From nobody Sun Oct 5 23:40:18 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 BA5B180B for ; Mon, 28 Jul 2025 20:49:45 +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=1753735785; cv=none; b=Jb/c8dM697gZIOX1p7gNXE9FhPugDBLErSGG29GjpD/1yzaLllkjj3PJNWEUGjCDPBg8wNbW9rblib1gY58k3q5lyFHTiSw1QyiiQf3VuzBLIawuPjHWn6MROabDtqY+etYPzAiX6zGc7jaUilVVR6ftt1RpQ1WgrDsHPFqjne8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753735785; c=relaxed/simple; bh=1h/ccd7mYSdeiigRgNASidHz3AmZ4bQvdOjtLEyasG4=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=DbbhCo8CcsNPZsZeFSW8Qi7EXWJnQc//RKJhRzP0hVhwGVieJTOqSKoGQgIV8UfB1kQd1u3na+g24aHOPO4phQlIRwoJ2LQsLfk5kxhVVnJ8Wbmjxk6xuuwg4T+qKxDy0OG62G3WKt+GkdbfdIzq7MUksmma65p2f0ZoDvmnDvM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KN+udngU; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KN+udngU" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 44C6CC4CEE7; Mon, 28 Jul 2025 20:49:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753735785; bh=1h/ccd7mYSdeiigRgNASidHz3AmZ4bQvdOjtLEyasG4=; h=Date:From:To:Cc:Subject:References:From; b=KN+udngUojK25D3ptPKH3/MdgUtOU4sQt0W21bBzkrYw0BQ8V6RMesxtGQJN4u8r3 041NDvyh7PiFqflI/Jnbjubkasy1buu8sikTI3fJmPkdb91OovAap/Ip0988oWG2UT bfnARZC4IZqZV+do6WdyNuJ3GvxguRRkAPpIZJWxj826BiB6rIl6ZIVv7FfCrpVU7U iEmXy9AHHO6ZkJZhzpnjD8BdE6Hxubxbkt/R/kJ26UWUrCZrsQgv/zFJOW6nqguuan wGe4Ggr1g6zxd2t2Bi/+iqfRlVrmA7lrXA1Rb79bplLAM6dIF+UN8Stdjkcg1XT+si Xok4aOXdyvs/Q== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1ugUnG-000000042uJ-0KKb; Mon, 28 Jul 2025 16:49:58 -0400 Message-ID: <20250728204957.930076277@kernel.org> User-Agent: quilt/0.68 Date: Mon, 28 Jul 2025 16:49:35 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Masami Hiramatsu , Mathieu Desnoyers , Nam Cao , Gabriele Monaco Subject: [for-next][PATCH 01/11] rv: Fix wrong type cast in monitors_show() References: <20250728204934.281385756@kernel.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: Nam Cao Argument 'p' of monitors_show() is not a pointer to struct rv_monitor, it is actually a pointer to the list_head inside struct rv_monitor. Therefore it is wrong to cast 'p' to struct rv_monitor *. This wrong type cast has been there since the beginning. But it still worked because the list_head was the first field in struct rv_monitor_def. This is no longer true since commit 24cbfe18d55a ("rv: Merge struct rv_monitor_def into struct rv_monitor") moved the list_head, and this wrong type cast became a functional problem. Properly use container_of() instead. Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Link: https://lore.kernel.org/35e49e97696007919ceacf73796487a2e15a3d02.1753= 625621.git.namcao@linutronix.de Fixes: 24cbfe18d55a ("rv: Merge struct rv_monitor_def into struct rv_monito= r") Signed-off-by: Nam Cao Reviewed-by: Gabriele Monaco Signed-off-by: Steven Rostedt (Google) --- kernel/trace/rv/rv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/rv/rv.c b/kernel/trace/rv/rv.c index 6c8498743b98..bd7d56dbf6c2 100644 --- a/kernel/trace/rv/rv.c +++ b/kernel/trace/rv/rv.c @@ -458,7 +458,7 @@ static int create_monitor_dir(struct rv_monitor *mon, s= truct rv_monitor *parent) */ static int monitors_show(struct seq_file *m, void *p) { - struct rv_monitor *mon =3D p; + struct rv_monitor *mon =3D container_of(p, struct rv_monitor, list); =20 if (mon->parent) seq_printf(m, "%s:%s\n", mon->parent->name, mon->name); --=20 2.47.2 From nobody Sun Oct 5 23:40:18 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 3539322156C for ; Mon, 28 Jul 2025 20:49:45 +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=1753735786; cv=none; b=gy+5qPf9XUBeD/wW9ZNJZcfE6WFuIgtrNHZuPbBQ+G54b2kczBX6y5o6XadBk6UO1EKDs+99vZYyTeWbDNlHxyZiFqDI4MLudZgtyUQ51q9X/e99e7TxzQkm8MXqERbxuAo9kNLRxZpUa2VXd3oGIowmDLeaARswLa389gz14pQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753735786; c=relaxed/simple; bh=xA9EdT2HycZIor0fvG3GFQWsXgKP+tp2pwkHaU1rJq8=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=EUnJB+BPEl8EPCGQ+WGDnANjPXPsB+vG1rXGshxGRme7tVv/jWZNb+FN3fgUF9vuNRujm0xkZzsfskejJqTgY+bX0fmPVYh2qjSOMguFNMiIblY9Qmg1z3otpRfILtK3urRG9sY2iDIDmKV2nws1hRj6uyacK0nl9cp9Yte8LDg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SbXcRV+w; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="SbXcRV+w" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 742CBC4CEF7; Mon, 28 Jul 2025 20:49:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753735785; bh=xA9EdT2HycZIor0fvG3GFQWsXgKP+tp2pwkHaU1rJq8=; h=Date:From:To:Cc:Subject:References:From; b=SbXcRV+w+ge8BFYBMXzAE52LvU1iAdz6wmURnebMTGoJLJtOnNUbrtKhIHS15eVIf qwI25zzAvU2Kmx8SUsUBp9WhAmWDWxIY43eTyTXWgV6lOjLiE1xCk+U0kTSKgoOOHW polqiTGPcn3W0MAlpuyzTBELlkK+OkF7frQ5djI8FReV+GyBnlTWKuO8/3zSXF14xW IG9a4jOJ8MWHBhCGDAvahyyJh2TmfeEy5A39z9sPTHs808K4NbpKadbjVbdqiTfWH7 uuQDXTyhdz/PC2b9/2HyY+rSwle0/eTQon8yVZzpVEQ4gTYT7AsP01mnT2KWoi/8Ui 3grON71lSGl6Q== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1ugUnG-000000042up-12As; Mon, 28 Jul 2025 16:49:58 -0400 Message-ID: <20250728204958.099222690@kernel.org> User-Agent: quilt/0.68 Date: Mon, 28 Jul 2025 16:49:36 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Masami Hiramatsu , Mathieu Desnoyers , Gabriele Monaco , Nam Cao Subject: [for-next][PATCH 02/11] rv: Fix wrong type cast in reactors_show() and monitor_reactor_show() References: <20250728204934.281385756@kernel.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: Nam Cao Argument 'p' of reactors_show() and monitor_reactor_show() is not a pointer to struct rv_reactor, it is actually a pointer to the list_head inside struct rv_reactor. Therefore it's wrong to cast 'p' to struct rv_reactor *. This wrong type cast has been there since the beginning. But it still worked because the list_head was the first field in struct rv_reactor_def. This is no longer true since commit 3d3c376118b5 ("rv: Merge struct rv_reactor_def into struct rv_reactor") moved the list_head, and this wrong type cast became a functional problem. Properly use container_of() instead. Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Cc: Gabriele Monaco Link: https://lore.kernel.org/b4febbd6844311209e4c8768b65d508b81bd8c9b.1753= 625621.git.namcao@linutronix.de Fixes: 3d3c376118b5 ("rv: Merge struct rv_reactor_def into struct rv_reacto= r") Signed-off-by: Nam Cao Signed-off-by: Steven Rostedt (Google) --- kernel/trace/rv/rv_reactors.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/trace/rv/rv_reactors.c b/kernel/trace/rv/rv_reactors.c index 106f2c4740f2..d32859fec238 100644 --- a/kernel/trace/rv/rv_reactors.c +++ b/kernel/trace/rv/rv_reactors.c @@ -86,7 +86,7 @@ static struct rv_reactor *get_reactor_rdef_by_name(char *= name) */ static int reactors_show(struct seq_file *m, void *p) { - struct rv_reactor *reactor =3D p; + struct rv_reactor *reactor =3D container_of(p, struct rv_reactor, list); =20 seq_printf(m, "%s\n", reactor->name); return 0; @@ -139,7 +139,7 @@ static const struct file_operations available_reactors_= ops =3D { static int monitor_reactor_show(struct seq_file *m, void *p) { struct rv_monitor *mon =3D m->private; - struct rv_reactor *reactor =3D p; + struct rv_reactor *reactor =3D container_of(p, struct rv_reactor, list); =20 if (mon->reactor =3D=3D reactor) seq_printf(m, "[%s]\n", reactor->name); --=20 2.47.2 From nobody Sun Oct 5 23:40:18 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 3533921CA00 for ; Mon, 28 Jul 2025 20:49:45 +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=1753735786; cv=none; b=gOlItAAsqusRP2j07/jBT8G9McgwffykydtLCHll6Gl8XTslq6G/VJsF/CUvsfXn0y72NbAoZ39T9c79S5T0J6pKZfqI9v/cpYwJqdaz7/OMYxfSOnNbQeJVWdmVpZ1ipZ3BCOOu36H+S37xEiadJD9B78XLiYtdGlLpkmWzSWM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753735786; c=relaxed/simple; bh=CZ8NU2b5BJTwvMm3Ohi9pTiahzYRLV29sPFfQFmKRNk=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=pOhmvihIOBd0duJ9+zPVoPdX/sUjbAH2wk9Kx8/oCnCe3EqMtmsQIA6S213m0g6bjhR/Ugpz3YAvK48MTAJe2f7OfGQBQ8yYzY3ICY0Rvg4wP8Kys12BSYfnmlBi3rfFRx77jbTz5ebA+VL2lFJ4FKgd+W4tmqKfV+BBN0Ypi8E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=skVBZXub; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="skVBZXub" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ACFA0C4CEF8; Mon, 28 Jul 2025 20:49:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753735785; bh=CZ8NU2b5BJTwvMm3Ohi9pTiahzYRLV29sPFfQFmKRNk=; h=Date:From:To:Cc:Subject:References:From; b=skVBZXubxxPVRjoollTysa9t9yZ3uNlyvDZ69oZzCMNpovQQjmMHDlKItsfBpWjft XKDIvLdmQMj+wAmKboe7261lwgT6XrR5Z/T1n4yIUM3fmzJvRG7hGbuGCQlfx4GJbO n6A8miCLKFBgIuIp08A3koTDU+aS21ff6DhsfVUEMxjvfwm5t5b7izI0Evmn1g+Bi9 CiH6j8mCUzrQY61chUjSkj8WzEZKj3fJmiCZWJw8q8FVLtbrYaz7I8VSdBpnMqoAUu m6/nYi+Y94/zxEAEa/Yw/uAgY+iUkyD3BtY7BKonYSe+oflwLM5lDdQ+/7eGglkk+J Ii/RPCBa7uoew== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1ugUnG-000000042vJ-1gxk; Mon, 28 Jul 2025 16:49:58 -0400 Message-ID: <20250728204958.267161508@kernel.org> User-Agent: quilt/0.68 Date: Mon, 28 Jul 2025 16:49:37 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Ingo Molnar , Peter Zijlstra , Juri Lelli , Clark Williams , Nam Cao , Gabriele Monaco Subject: [for-next][PATCH 03/11] rv: Add da_handle_start_run_event_ to per-task monitors References: <20250728204934.281385756@kernel.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 The RV da_monitor API allows to start monitors in two ways: da_handle_start_event_NAME and da_handle_start_run_event_NAME. The former is used when the event is followed by the initial state of the module, so we ignore the event but we know the monitor is in the initial state and can start monitoring, the latter can be used if the event can only occur in the initial state, so we do handle the event as if the monitor was in the initial state. This latter API is defined for implicit monitors but not per-task ones. Define da_handle_start_run_event_NAME macro also for per-task monitors. Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Tomas Glozar Cc: Juri Lelli Cc: Clark Williams Cc: John Kacur Link: https://lore.kernel.org/20250728135022.255578-2-gmonaco@redhat.com Reviewed-by: Nam Cao Signed-off-by: Gabriele Monaco Signed-off-by: Steven Rostedt (Google) --- include/rv/da_monitor.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/include/rv/da_monitor.h b/include/rv/da_monitor.h index 15f9ed4e4bb6..ed3c34fe18d6 100644 --- a/include/rv/da_monitor.h +++ b/include/rv/da_monitor.h @@ -487,6 +487,30 @@ da_handle_start_event_##name(struct task_struct *tsk, = enum events_##name event) __da_handle_event_##name(da_mon, tsk, event); \ \ return 1; \ +} \ + \ +/* \ + * da_handle_start_run_event_##name - start monitoring and handle event = \ + * \ + * This function is used to notify the monitor that the system is in the = \ + * initial state, so the monitor can start monitoring and handling event. = \ + */ \ +static inline bool \ +da_handle_start_run_event_##name(struct task_struct *tsk, enum events_##na= me event) \ +{ \ + struct da_monitor *da_mon; \ + \ + if (!da_monitor_enabled_##name()) \ + return 0; \ + \ + da_mon =3D da_get_monitor_##name(tsk); \ + \ + if (unlikely(!da_monitoring_##name(da_mon))) \ + da_monitor_start_##name(da_mon); \ + \ + __da_handle_event_##name(da_mon, tsk, event); \ + \ + return 1; \ } =20 /* --=20 2.47.2 From nobody Sun Oct 5 23:40:18 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 54F7722539E for ; Mon, 28 Jul 2025 20:49:45 +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=1753735786; cv=none; b=FxJvXzHGyM4bCoEQveO1hjOSWGCOMnKXXLyv0sR45HUC4fCF8OxsumxYli4eXb5bY3dUQRz5s15+eauFypAiPcx4eVAyOP2XTK/elpVvca7WpkLnM/kHuG+9MpaMy11HjXlXKlZrSXe+eOKeijXUesBtzLRDfh+E16vb78C57Uc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753735786; c=relaxed/simple; bh=2ZP0KPw+xXpyUaKWcjsbvXzDO+nB0WA5dPt/uWOQM/w=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=LHMjgjnClWS74WEx4vfResFcR0+VVOLX7HtvjcdqmEU8ZL97nIZUCRn4RVz9gETWQwwr4opRFFpQfAOHybqsRNFv9nIPGBsEU5oO/sgug+sVXxMeocTKU7+5ZHpwzhrQTPjYAYE3b36jVHjdGOVhR4nJRqaTwefyuNL9X3IOD2U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CJgChVq1; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CJgChVq1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CC933C4CEF9; Mon, 28 Jul 2025 20:49:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753735785; bh=2ZP0KPw+xXpyUaKWcjsbvXzDO+nB0WA5dPt/uWOQM/w=; h=Date:From:To:Cc:Subject:References:From; b=CJgChVq1ppz0UxpOkxdZXQnt12EvLOn1i9o0l+flUmnU8vlhcWUUDaoP2eHMQjxJR eKkBJN5yY+x2Tbp7vBrh9mYeNExpjBK7LXxUMUxT5m2WsUT60PY+ZtRCZBYTIc/i5Y 3/QtXy5GU2UV+L9+P0CjetvSHBkX7Soo8wtDYoMjrXYxHjYcatmHvebU41lrN05w12 XG74RMDU1T5dJuSyN9yERpI5PUBGj60mmWtIPCSPLSwPHVg8mGcmy0FwT1iGzfMHWK kQs0jPWx/N23g21zwtSCr7QEFSjUh7lXXi90TdUrQdvgSqb5Jhk5o3eUovCUFa4dOO YrOjBHs7usjzA== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1ugUnG-000000042vo-2NiZ; Mon, 28 Jul 2025 16:49:58 -0400 Message-ID: <20250728204958.425213297@kernel.org> User-Agent: quilt/0.68 Date: Mon, 28 Jul 2025 16:49:38 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Masami Hiramatsu , Ingo Molnar , Peter Zijlstra , Juri Lelli , Clark Williams , Nam Cao , Gabriele Monaco Subject: [for-next][PATCH 04/11] rv: Remove trailing whitespace from tracepoint string References: <20250728204934.281385756@kernel.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 event tracepoints print a line with the format: "event_xyz: S0 x event -> S1 " "event_xyz: S1 x event -> S0 (final)" While printing an event leading to a non-final state, the line has a trailing white space (visible above before the closing "). Adapt the format string not to print the trailing whitespace if we are not printing "(final)". Cc: Masami Hiramatsu Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Tomas Glozar Cc: Juri Lelli Cc: Clark Williams Cc: John Kacur Link: https://lore.kernel.org/20250728135022.255578-3-gmonaco@redhat.com Reviewed-by: Nam Cao Signed-off-by: Gabriele Monaco Signed-off-by: Steven Rostedt (Google) --- kernel/trace/rv/rv_trace.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/trace/rv/rv_trace.h b/kernel/trace/rv/rv_trace.h index b6f310498466..17ba07329b67 100644 --- a/kernel/trace/rv/rv_trace.h +++ b/kernel/trace/rv/rv_trace.h @@ -29,11 +29,11 @@ DECLARE_EVENT_CLASS(event_da_monitor, __entry->final_state =3D final_state; ), =20 - TP_printk("%s x %s -> %s %s", + TP_printk("%s x %s -> %s%s", __entry->state, __entry->event, __entry->next_state, - __entry->final_state ? "(final)" : "") + __entry->final_state ? " (final)" : "") ); =20 DECLARE_EVENT_CLASS(error_da_monitor, @@ -90,12 +90,12 @@ DECLARE_EVENT_CLASS(event_da_monitor_id, __entry->final_state =3D final_state; ), =20 - TP_printk("%d: %s x %s -> %s %s", + TP_printk("%d: %s x %s -> %s%s", __entry->id, __entry->state, __entry->event, __entry->next_state, - __entry->final_state ? "(final)" : "") + __entry->final_state ? " (final)" : "") ); =20 DECLARE_EVENT_CLASS(error_da_monitor_id, --=20 2.47.2 From nobody Sun Oct 5 23:40:18 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 54FDC2253A1 for ; Mon, 28 Jul 2025 20:49:46 +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=1753735786; cv=none; b=E/vDxRkL88quU3eWMWNwP0O42xRnIQMxVikai7H/M069ub/lc8PZDxXzEfZHGfytoxijQSLQipPgcAW5VvBn3qyn0Fcs0WXmZG7rbBHPYwhWpvdsW95WSimnqVnXb6k5ykgrpF4Z0WQsmhf98lef4EyEuR9C1Rjqz+aUEfXSkTk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753735786; c=relaxed/simple; bh=+z/vQdXbmjGgcEzFQFAAtCAqyXFrb/QCsWewWeQ+OU0=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=FlsaECyiUKXEpAJDxuYhMRJSy1hRFXnD4z+WVb++Ex428BuaSr9qSgqVjE4MTAbkeCsGpNCW+1S1JhVB0jC/+sQjaeSJkP2MXGUyMytSwYjeDaNEXYUTbsPXe06y8duiiSTkaM+MucPf6Og6gORnZEflhLKbNM3Sl+sDi2X8OzM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Xspgf/hy; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Xspgf/hy" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EC61BC4CEF4; Mon, 28 Jul 2025 20:49:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753735786; bh=+z/vQdXbmjGgcEzFQFAAtCAqyXFrb/QCsWewWeQ+OU0=; h=Date:From:To:Cc:Subject:References:From; b=Xspgf/hyXUCUZ78mwpyf2QSZ5kJ8o6d1t6o4R3sxYd7XOQ1RdQp0TCQDJkqyLDfzd Xx9cqTz4E9QBB9DmhZforGYnLQ3opz/K9wQL2Z/VhcDC0kvyeJZd8jB6JL2DRJM9pc mieKh38pgMJTyRoL6rBmeKJ5TgPiOmB09QJSmCQJZbW8GKjzrKn61J3MqhckciOG5L FNtfwHE+ddhEnXmq3OlVHHPaLLME5OyUaLywxB11ouTqfiKY5rwBRPDxfOEjxRnAoK Kaf2+QQiAMR3FvfBpKJggqJePFvzW5S/7RPT5sQvDdJm/nSOOMoiHG3WAAADifdVWA cSVhg9uVmf+Mw== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1ugUnG-000000042wI-35F7; Mon, 28 Jul 2025 16:49:58 -0400 Message-ID: <20250728204958.587985378@kernel.org> User-Agent: quilt/0.68 Date: Mon, 28 Jul 2025 16:49:39 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Masami Hiramatsu , Ingo Molnar , Peter Zijlstra , Juri Lelli , Clark Williams , Nam Cao , Gabriele Monaco Subject: [for-next][PATCH 05/11] rv: Use strings in da monitors tracepoints References: <20250728204934.281385756@kernel.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 Using DA monitors tracepoints with KASAN enabled triggers the following warning: BUG: KASAN: global-out-of-bounds in do_trace_event_raw_event_event_da_moni= tor+0xd6/0x1a0 Read of size 32 at addr ffffffffaada8980 by task ... Call Trace: [...] do_trace_event_raw_event_event_da_monitor+0xd6/0x1a0 ? __pfx_do_trace_event_raw_event_event_da_monitor+0x10/0x10 ? trace_event_sncid+0x83/0x200 trace_event_sncid+0x163/0x200 [...] The buggy address belongs to the variable: automaton_snep+0x4e0/0x5e0 This is caused by the tracepoints reading 32 bytes __array instead of __string from the automata definition. Such strings are literals and reading 32 bytes ends up in out of bound memory accesses (e.g. the next automaton's data in this case). The error is harmless as, while printing the string, we stop at the null terminator, but it should still be fixed. Use the __string facilities while defining the tracepoints to avoid reading out of bound memory. Cc: Masami Hiramatsu Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Tomas Glozar Cc: Juri Lelli Cc: Clark Williams Cc: John Kacur Link: https://lore.kernel.org/20250728135022.255578-4-gmonaco@redhat.com Fixes: 792575348ff7 ("rv/include: Add deterministic automata monitor defini= tion via C macros") Reviewed-by: Nam Cao Signed-off-by: Gabriele Monaco Signed-off-by: Steven Rostedt (Google) --- kernel/trace/rv/rv_trace.h | 76 +++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/kernel/trace/rv/rv_trace.h b/kernel/trace/rv/rv_trace.h index 17ba07329b67..d38e0d3abdfd 100644 --- a/kernel/trace/rv/rv_trace.h +++ b/kernel/trace/rv/rv_trace.h @@ -16,23 +16,23 @@ DECLARE_EVENT_CLASS(event_da_monitor, TP_ARGS(state, event, next_state, final_state), =20 TP_STRUCT__entry( - __array( char, state, MAX_DA_NAME_LEN ) - __array( char, event, MAX_DA_NAME_LEN ) - __array( char, next_state, MAX_DA_NAME_LEN ) - __field( bool, final_state ) + __string( state, state ) + __string( event, event ) + __string( next_state, next_state ) + __field( bool, final_state ) ), =20 TP_fast_assign( - memcpy(__entry->state, state, MAX_DA_NAME_LEN); - memcpy(__entry->event, event, MAX_DA_NAME_LEN); - memcpy(__entry->next_state, next_state, MAX_DA_NAME_LEN); - __entry->final_state =3D final_state; + __assign_str(state); + __assign_str(event); + __assign_str(next_state); + __entry->final_state =3D final_state; ), =20 TP_printk("%s x %s -> %s%s", - __entry->state, - __entry->event, - __entry->next_state, + __get_str(state), + __get_str(event), + __get_str(next_state), __entry->final_state ? " (final)" : "") ); =20 @@ -43,18 +43,18 @@ DECLARE_EVENT_CLASS(error_da_monitor, TP_ARGS(state, event), =20 TP_STRUCT__entry( - __array( char, state, MAX_DA_NAME_LEN ) - __array( char, event, MAX_DA_NAME_LEN ) + __string( state, state ) + __string( event, event ) ), =20 TP_fast_assign( - memcpy(__entry->state, state, MAX_DA_NAME_LEN); - memcpy(__entry->event, event, MAX_DA_NAME_LEN); + __assign_str(state); + __assign_str(event); ), =20 TP_printk("event %s not expected in the state %s", - __entry->event, - __entry->state) + __get_str(event), + __get_str(state)) ); =20 #include @@ -75,26 +75,26 @@ DECLARE_EVENT_CLASS(event_da_monitor_id, TP_ARGS(id, state, event, next_state, final_state), =20 TP_STRUCT__entry( - __field( int, id ) - __array( char, state, MAX_DA_NAME_LEN ) - __array( char, event, MAX_DA_NAME_LEN ) - __array( char, next_state, MAX_DA_NAME_LEN ) - __field( bool, final_state ) + __field( int, id ) + __string( state, state ) + __string( event, event ) + __string( next_state, next_state ) + __field( bool, final_state ) ), =20 TP_fast_assign( - memcpy(__entry->state, state, MAX_DA_NAME_LEN); - memcpy(__entry->event, event, MAX_DA_NAME_LEN); - memcpy(__entry->next_state, next_state, MAX_DA_NAME_LEN); - __entry->id =3D id; - __entry->final_state =3D final_state; + __assign_str(state); + __assign_str(event); + __assign_str(next_state); + __entry->id =3D id; + __entry->final_state =3D final_state; ), =20 TP_printk("%d: %s x %s -> %s%s", __entry->id, - __entry->state, - __entry->event, - __entry->next_state, + __get_str(state), + __get_str(event), + __get_str(next_state), __entry->final_state ? " (final)" : "") ); =20 @@ -105,21 +105,21 @@ DECLARE_EVENT_CLASS(error_da_monitor_id, TP_ARGS(id, state, event), =20 TP_STRUCT__entry( - __field( int, id ) - __array( char, state, MAX_DA_NAME_LEN ) - __array( char, event, MAX_DA_NAME_LEN ) + __field( int, id ) + __string( state, state ) + __string( event, event ) ), =20 TP_fast_assign( - memcpy(__entry->state, state, MAX_DA_NAME_LEN); - memcpy(__entry->event, event, MAX_DA_NAME_LEN); - __entry->id =3D id; + __assign_str(state); + __assign_str(event); + __entry->id =3D id; ), =20 TP_printk("%d: event %s not expected in the state %s", __entry->id, - __entry->event, - __entry->state) + __get_str(event), + __get_str(state)) ); =20 #include --=20 2.47.2 From nobody Sun Oct 5 23:40:18 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 54F1F225390 for ; Mon, 28 Jul 2025 20:49:46 +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=1753735786; cv=none; b=nWWyZ4vS2hpZyqDoFO5qEJyYdhJnQX4HTfzRB8I2f8OXxQi/BH82fABSDY+SgXduNSfPC6IP7KRMPJtokHgoeoTa62P5vPWVoiU/TqaJd88tOkH3UXvLmmfUQ7GJKTrs0uF0LxsoCeGgJd9AEVwqTU1nvpirkD/TJArfi7A1Dco= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753735786; c=relaxed/simple; bh=ZoZCZAaJhfgRL7NP5HYJOF2Pkwdg1aDsh+deeurCy4c=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=jM9EMAgffTG1I4JTErIjHwGMi4MNVuOO945Pc2s1EMwSN9YqCdufUTyfxztra8WkEC6N9uVR9MU53Uszz+v6r708PhNVJLJ4Iuag1miN7hLuaSS5IJlZ1/uMmKgyKdm3W0sA10RJapGz4TVHhzj7k1mXcUr1HmNlS2JxB9FskUQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GqUEkT3h; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GqUEkT3h" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0C188C4CEE7; Mon, 28 Jul 2025 20:49:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753735786; bh=ZoZCZAaJhfgRL7NP5HYJOF2Pkwdg1aDsh+deeurCy4c=; h=Date:From:To:Cc:Subject:References:From; b=GqUEkT3h5dv60F/Pscrd2cKrQAtHU3O5Dr8ZXKATGLMDdBsOJx3dKIzfm9YrIaRdZ vQWYCHZiUiKfTPyM5TPO2wuo+/ENHwGOR3F1TOaB45iNesQxILfzWfcEKhR70+RXo3 vjfGHLOnnWP4tZwwSHjIVT2pD98JZKgRKglCv25D1tcRpe8ZyTt4mdDtuzZp55PgDB D9xKctzBlIWna7uzb+4UqT1INOPupU+QwNkHC+RVj/5woJzskr/xaIkZsL5LRHx0Lw YNN7N/uZRayyxAQnwQ2GbVHerSdNt3831dacE5cuiH2uIeqpVpK+GrBgotSNeYCkcl VhqfPTI3ypSwQ== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1ugUnG-000000042wm-3mCg; Mon, 28 Jul 2025 16:49:58 -0400 Message-ID: <20250728204958.754817582@kernel.org> User-Agent: quilt/0.68 Date: Mon, 28 Jul 2025 16:49:40 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Masami Hiramatsu , Ingo Molnar , Peter Zijlstra , Juri Lelli , Clark Williams , Nam Cao , Gabriele Monaco Subject: [for-next][PATCH 06/11] rv: Adjust monitor dependencies References: <20250728204934.281385756@kernel.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 monitors relying on the preemptirqs tracepoints are set as dependent on PREEMPT_TRACER and IRQSOFF_TRACER. In fact, those configurations do enable the tracepoints but are not the minimal configurations enabling them, which are TRACE_PREEMPT_TOGGLE and TRACE_IRQFLAGS (not selectable manually). Set TRACE_PREEMPT_TOGGLE and TRACE_IRQFLAGS as dependencies for monitors. Cc: Masami Hiramatsu Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Tomas Glozar Cc: Juri Lelli Cc: Clark Williams Cc: John Kacur Link: https://lore.kernel.org/20250728135022.255578-5-gmonaco@redhat.com Fixes: fbe6c09b7eb4 ("rv: Add scpd, snep and sncid per-cpu monitors") Acked-by: Nam Cao Signed-off-by: Gabriele Monaco Signed-off-by: Steven Rostedt (Google) --- kernel/trace/rv/monitors/scpd/Kconfig | 2 +- kernel/trace/rv/monitors/sncid/Kconfig | 2 +- kernel/trace/rv/monitors/snep/Kconfig | 2 +- kernel/trace/rv/monitors/wip/Kconfig | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/trace/rv/monitors/scpd/Kconfig b/kernel/trace/rv/monito= rs/scpd/Kconfig index b9114fbf680f..682d0416188b 100644 --- a/kernel/trace/rv/monitors/scpd/Kconfig +++ b/kernel/trace/rv/monitors/scpd/Kconfig @@ -2,7 +2,7 @@ # config RV_MON_SCPD depends on RV - depends on PREEMPT_TRACER + depends on TRACE_PREEMPT_TOGGLE depends on RV_MON_SCHED default y select DA_MON_EVENTS_IMPLICIT diff --git a/kernel/trace/rv/monitors/sncid/Kconfig b/kernel/trace/rv/monit= ors/sncid/Kconfig index 76bcfef4fd10..3a5639feaaaf 100644 --- a/kernel/trace/rv/monitors/sncid/Kconfig +++ b/kernel/trace/rv/monitors/sncid/Kconfig @@ -2,7 +2,7 @@ # config RV_MON_SNCID depends on RV - depends on IRQSOFF_TRACER + depends on TRACE_IRQFLAGS depends on RV_MON_SCHED default y select DA_MON_EVENTS_IMPLICIT diff --git a/kernel/trace/rv/monitors/snep/Kconfig b/kernel/trace/rv/monito= rs/snep/Kconfig index 77527f971232..7dd54f434ff7 100644 --- a/kernel/trace/rv/monitors/snep/Kconfig +++ b/kernel/trace/rv/monitors/snep/Kconfig @@ -2,7 +2,7 @@ # config RV_MON_SNEP depends on RV - depends on PREEMPT_TRACER + depends on TRACE_PREEMPT_TOGGLE depends on RV_MON_SCHED default y select DA_MON_EVENTS_IMPLICIT diff --git a/kernel/trace/rv/monitors/wip/Kconfig b/kernel/trace/rv/monitor= s/wip/Kconfig index e464b9294865..87a26195792b 100644 --- a/kernel/trace/rv/monitors/wip/Kconfig +++ b/kernel/trace/rv/monitors/wip/Kconfig @@ -2,7 +2,7 @@ # config RV_MON_WIP depends on RV - depends on PREEMPT_TRACER + depends on TRACE_PREEMPT_TOGGLE select DA_MON_EVENTS_IMPLICIT bool "wip monitor" help --=20 2.47.2 From nobody Sun Oct 5 23:40:18 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 C690624BD04 for ; Mon, 28 Jul 2025 20:49:46 +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=1753735787; cv=none; b=f0t2e1tRhfcZJ2eGbET3Teo+ybJ5Xs8CssNfwJhBgZ89r5WPhMp9hKWdRIhlZXQXYzHtvRHHHcQ/M/zZnzyWQxUEuom0WrXO4+gwSDylXO8mLGPFSiDE6RWUaSctNAkzTYv1i7xIwVdCiOUJ1SFmUUDGWRmk4KHNHMZ4AxazzAE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753735787; c=relaxed/simple; bh=9YGKh50GtwHPpbC/Wepnr2POH1NKu0X7MUW8JpJaOGI=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=CArCsB4LyIE6Dvc0uE8lNmz1WQWbx3L8+clZu/lEBYf/EjWhDYXZ/gKMZruoSG0unXgK90kyf4Ogd11aTNhWRgrsNLH1+KybDldwMwfXkDRNJs7uRpBpVk7I6DwC051XMf0xCamn+1aM+rq4WqVHOFGZtQ+TF8H8VpXQb+TfB1M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IsaBNAV4; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IsaBNAV4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4423EC4CEF6; Mon, 28 Jul 2025 20:49:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753735786; bh=9YGKh50GtwHPpbC/Wepnr2POH1NKu0X7MUW8JpJaOGI=; h=Date:From:To:Cc:Subject:References:From; b=IsaBNAV4REztse1y0UZ8PuUVEW4xABK1rQ7OfkREoar7bWcK3zVjqePt0gedD9ztn hhXZhG+hjEX7uU4hbp+U9ETpCm6ueC7SO9DFmjiispCvnvtEOhdZWxJHAWDSsTzMRw BpNAXLL85jqkiVV+92nAcqD0nisL3YL27fpeoeEo812erVTdkrjypEU4QtnPJpkiC0 ncDkA40ARM0nNqm0TuGSm3rUw++gYwFHXyx22Vqo/8ag83OZyndODkb2fh7MyrrUYx IhDKDDW7yNq+c4Cm06ibDfhxNXs0TGbrg/o28kbbQQ4qoqKJQ536UsLoKpdXsGkXKJ XsZe5gP1Es6nQ== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1ugUnH-000000042xG-0I1z; Mon, 28 Jul 2025 16:49:59 -0400 Message-ID: <20250728204958.921448608@kernel.org> User-Agent: quilt/0.68 Date: Mon, 28 Jul 2025 16:49:41 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Ingo Molnar , Masami Hiramatsu , Juri Lelli , Clark Williams , Peter Zijlstra , Gabriele Monaco , Nam Cao Subject: [for-next][PATCH 07/11] rv: Retry when da monitor detects race conditions References: <20250728204934.281385756@kernel.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 DA monitor can be accessed from multiple cores simultaneously, this is likely, for instance when dealing with per-task monitors reacting on events that do not always occur on the CPU where the task is running. This can cause race conditions where two events change the next state and we see inconsistent values. E.g.: [62] event_srs: 27: sleepable x sched_wakeup -> running (final) [63] event_srs: 27: sleepable x sched_set_state_sleepable -> sleepable [63] error_srs: 27: event sched_switch_suspend not expected in the state = running In this case the monitor fails because the event on CPU 62 wins against the one on CPU 63, although the correct state should have been sleepable, since the task get suspended. Detect if the current state was modified by using try_cmpxchg while storing the next value. If it was, try again reading the current state. After a maximum number of failed retries, react by calling a special tracepoint, print on the console and reset the monitor. Remove the functions da_monitor_curr_state() and da_monitor_set_state() as they only hide the underlying implementation in this case. Monitors where this type of condition can occur must be able to account for racing events in any possible order, as we cannot know the winner. Cc: Ingo Molnar Cc: Masami Hiramatsu Cc: Tomas Glozar Cc: Juri Lelli Cc: Clark Williams Cc: John Kacur Cc: Peter Zijlstra Link: https://lore.kernel.org/20250728135022.255578-6-gmonaco@redhat.com Signed-off-by: Gabriele Monaco Reviewed-by: Nam Cao Signed-off-by: Steven Rostedt (Google) --- include/linux/rv.h | 3 +- include/rv/da_monitor.h | 107 +++++++++++++++++++------------------ kernel/trace/rv/Kconfig | 5 ++ kernel/trace/rv/rv_trace.h | 24 +++++++++ 4 files changed, 85 insertions(+), 54 deletions(-) diff --git a/include/linux/rv.h b/include/linux/rv.h index 80731242fe60..14410a42faef 100644 --- a/include/linux/rv.h +++ b/include/linux/rv.h @@ -10,7 +10,8 @@ #include #include =20 -#define MAX_DA_NAME_LEN 32 +#define MAX_DA_NAME_LEN 32 +#define MAX_DA_RETRY_RACING_EVENTS 3 =20 #ifdef CONFIG_RV #include diff --git a/include/rv/da_monitor.h b/include/rv/da_monitor.h index ed3c34fe18d6..17fa4f6e5ea6 100644 --- a/include/rv/da_monitor.h +++ b/include/rv/da_monitor.h @@ -54,23 +54,6 @@ static inline void da_monitor_reset_##name(struct da_mon= itor *da_mon) \ da_mon->curr_state =3D model_get_initial_state_##name(); \ } \ \ -/* \ - * da_monitor_curr_state_##name - return the current state \ - */ \ -static inline type da_monitor_curr_state_##name(struct da_monitor *da_mon)= \ -{ \ - return da_mon->curr_state; \ -} \ - \ -/* \ - * da_monitor_set_state_##name - set the new current state \ - */ \ -static inline void \ -da_monitor_set_state_##name(struct da_monitor *da_mon, enum states_##name = state) \ -{ \ - da_mon->curr_state =3D state; \ -} \ - \ /* \ * da_monitor_start_##name - start monitoring \ * \ @@ -127,63 +110,81 @@ static inline bool da_monitor_handling_event_##name(s= truct da_monitor *da_mon) * Event handler for implicit monitors. Implicit monitor is the one which = the * handler does not need to specify which da_monitor to manipulate. Exampl= es * of implicit monitor are the per_cpu or the global ones. + * + * Retry in case there is a race between getting and setting the next stat= e, + * warn and reset the monitor if it runs out of retries. The monitor shoul= d be + * able to handle various orders. */ #define DECLARE_DA_MON_MODEL_HANDLER_IMPLICIT(name, type) \ \ static inline bool \ da_event_##name(struct da_monitor *da_mon, enum events_##name event) \ { \ - type curr_state =3D da_monitor_curr_state_##name(da_mon); \ - type next_state =3D model_get_next_state_##name(curr_state, event); \ - \ - if (next_state !=3D INVALID_STATE) { \ - da_monitor_set_state_##name(da_mon, next_state); \ - \ - trace_event_##name(model_get_state_name_##name(curr_state), \ - model_get_event_name_##name(event), \ - model_get_state_name_##name(next_state), \ - model_is_final_state_##name(next_state)); \ - \ - return true; \ + enum states_##name curr_state, next_state; \ + \ + curr_state =3D READ_ONCE(da_mon->curr_state); \ + for (int i =3D 0; i < MAX_DA_RETRY_RACING_EVENTS; i++) { \ + next_state =3D model_get_next_state_##name(curr_state, event); \ + if (next_state =3D=3D INVALID_STATE) { \ + cond_react_##name(curr_state, event); \ + trace_error_##name(model_get_state_name_##name(curr_state), \ + model_get_event_name_##name(event)); \ + return false; \ + } \ + if (likely(try_cmpxchg(&da_mon->curr_state, &curr_state, next_state))) {= \ + trace_event_##name(model_get_state_name_##name(curr_state), \ + model_get_event_name_##name(event), \ + model_get_state_name_##name(next_state), \ + model_is_final_state_##name(next_state)); \ + return true; \ + } \ } \ \ - cond_react_##name(curr_state, event); \ - \ - trace_error_##name(model_get_state_name_##name(curr_state), \ - model_get_event_name_##name(event)); \ - \ + trace_rv_retries_error(#name, model_get_event_name_##name(event)); \ + pr_warn("rv: " __stringify(MAX_DA_RETRY_RACING_EVENTS) \ + " retries reached for event %s, resetting monitor %s", \ + model_get_event_name_##name(event), #name); \ return false; \ } \ =20 /* * Event handler for per_task monitors. + * + * Retry in case there is a race between getting and setting the next stat= e, + * warn and reset the monitor if it runs out of retries. The monitor shoul= d be + * able to handle various orders. */ #define DECLARE_DA_MON_MODEL_HANDLER_PER_TASK(name, type) \ \ static inline bool da_event_##name(struct da_monitor *da_mon, struct task_= struct *tsk, \ enum events_##name event) \ { \ - type curr_state =3D da_monitor_curr_state_##name(da_mon); \ - type next_state =3D model_get_next_state_##name(curr_state, event); \ - \ - if (next_state !=3D INVALID_STATE) { \ - da_monitor_set_state_##name(da_mon, next_state); \ - \ - trace_event_##name(tsk->pid, \ - model_get_state_name_##name(curr_state), \ - model_get_event_name_##name(event), \ - model_get_state_name_##name(next_state), \ - model_is_final_state_##name(next_state)); \ - \ - return true; \ + enum states_##name curr_state, next_state; \ + \ + curr_state =3D READ_ONCE(da_mon->curr_state); \ + for (int i =3D 0; i < MAX_DA_RETRY_RACING_EVENTS; i++) { \ + next_state =3D model_get_next_state_##name(curr_state, event); \ + if (next_state =3D=3D INVALID_STATE) { \ + cond_react_##name(curr_state, event); \ + trace_error_##name(tsk->pid, \ + model_get_state_name_##name(curr_state), \ + model_get_event_name_##name(event)); \ + return false; \ + } \ + if (likely(try_cmpxchg(&da_mon->curr_state, &curr_state, next_state))) {= \ + trace_event_##name(tsk->pid, \ + model_get_state_name_##name(curr_state), \ + model_get_event_name_##name(event), \ + model_get_state_name_##name(next_state), \ + model_is_final_state_##name(next_state)); \ + return true; \ + } \ } \ \ - cond_react_##name(curr_state, event); \ - \ - trace_error_##name(tsk->pid, \ - model_get_state_name_##name(curr_state), \ - model_get_event_name_##name(event)); \ - \ + trace_rv_retries_error(#name, model_get_event_name_##name(event)); \ + pr_warn("rv: " __stringify(MAX_DA_RETRY_RACING_EVENTS) \ + " retries reached for event %s, resetting monitor %s", \ + model_get_event_name_##name(event), #name); \ return false; \ } =20 diff --git a/kernel/trace/rv/Kconfig b/kernel/trace/rv/Kconfig index 26017378f79b..34164eb4ec91 100644 --- a/kernel/trace/rv/Kconfig +++ b/kernel/trace/rv/Kconfig @@ -3,12 +3,17 @@ config RV_MON_EVENTS bool =20 +config RV_MON_MAINTENANCE_EVENTS + bool + config DA_MON_EVENTS_IMPLICIT select RV_MON_EVENTS + select RV_MON_MAINTENANCE_EVENTS bool =20 config DA_MON_EVENTS_ID select RV_MON_EVENTS + select RV_MON_MAINTENANCE_EVENTS bool =20 config LTL_MON_EVENTS_ID diff --git a/kernel/trace/rv/rv_trace.h b/kernel/trace/rv/rv_trace.h index d38e0d3abdfd..3af46cd185b3 100644 --- a/kernel/trace/rv/rv_trace.h +++ b/kernel/trace/rv/rv_trace.h @@ -176,6 +176,30 @@ DECLARE_EVENT_CLASS(error_ltl_monitor_id, #include // Add new monitors based on CONFIG_LTL_MON_EVENTS_ID here #endif /* CONFIG_LTL_MON_EVENTS_ID */ + +#ifdef CONFIG_RV_MON_MAINTENANCE_EVENTS +/* Tracepoint useful for monitors development, currenly only used in DA */ +TRACE_EVENT(rv_retries_error, + + TP_PROTO(char *name, char *event), + + TP_ARGS(name, event), + + TP_STRUCT__entry( + __string( name, name ) + __string( event, event ) + ), + + TP_fast_assign( + __assign_str(name); + __assign_str(event); + ), + + TP_printk(__stringify(MAX_DA_RETRY_RACING_EVENTS) + " retries reached for event %s, resetting monitor %s", + __get_str(event), __get_str(name)) +); +#endif /* CONFIG_RV_MON_MAINTENANCE_EVENTS */ #endif /* _TRACE_RV_H */ =20 /* This part must be outside protection */ --=20 2.47.2 From nobody Sun Oct 5 23:40:18 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 8CE8C22A4EB for ; Mon, 28 Jul 2025 20:49:46 +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=1753735786; cv=none; b=LJyvWBHNn+TPAP8TqAg7u3fLN6U7X8H7aC/2DuZ65t1yT6/Qu8sdXFXL7FJDi1xz7DgkALP/HbnhYSWGKLYt+ub4R5G5tEDDJ7wKZzPlMwP94F+zQX8PPJAH3YcTdFYFIRcBYmgKtZBqof3UJonbF93cOCOWP5Wwog/wLvMxBLo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753735786; c=relaxed/simple; bh=FGd6uP//wL11kLSl1PdCcAAVYZSczd25hHGCi590xPw=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=ok89Ti9PVPGteezWendkThA6aQf61++T8qI+dsbD0tbTUIAPIIfOpV/WiO2I8leNsyefCmYALd8xO5YZCo1jYNzOVL2NaufaOxRtxsf0vTL0RWnptDhFSmAHVdglu0RISOL5cNvk9jiZPlh4NndafAaVauId9xzg09gIFWCZ+BM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SJ0B6VaK; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="SJ0B6VaK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 61BC7C4CEF7; Mon, 28 Jul 2025 20:49:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753735786; bh=FGd6uP//wL11kLSl1PdCcAAVYZSczd25hHGCi590xPw=; h=Date:From:To:Cc:Subject:References:From; b=SJ0B6VaK+WTX9Le2/5IuCvGjugtu7ooT+pqyHFGKSbfneqfn7EK5Z+g8ZDmUYm731 kggtnYwf1UkVAHo3I9G6ylAwxA+Til1SAc9NWlK7rZtvknuxHIYm6YTnWexTDiCtfD 3FIw6BQVcjJfwcwY08gQOYWLGXzOLTTvng0qbyE1qBwux+DPYoi4enTP6mQsmKPe1c Vwe9ym5dzVgQf5RMb/q9svxnb9mE/M3fY0ISMfowZFJr8et6P6Oc5fJ5AT+89vCGoq 9ns07pk5NOCSf51uWuNhFuerW7nrwtWLKafBzROxyQ83XTbZAFJ0g5s5iyFLv0hQ4g bL/EikSCh3LlA== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1ugUnH-000000042xm-0zzZ; Mon, 28 Jul 2025 16:49:59 -0400 Message-ID: <20250728204959.088532429@kernel.org> User-Agent: quilt/0.68 Date: Mon, 28 Jul 2025 16:49:42 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Ingo Molnar , Peter Zijlstra , Masami Hiramatsu , Nam Cao , Juri Lelli , Clark Williams , Gabriele Monaco Subject: [for-next][PATCH 08/11] sched: Adapt sched tracepoints for RV task model References: <20250728204934.281385756@kernel.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 tracepoint: * sched_set_need_resched(tsk, cpu, tif) Called when a task is set the need resched [lazy] flag Remove the unused ip parameter from sched_entry and sched_exit and alter sched_entry to have a value of preempt consistent with the one used in sched_switch. Also adapt all monitors using sched_{entry,exit} to avoid breaking build. 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: Peter Zijlstra Cc: Masami Hiramatsu Cc: Nam Cao Cc: Tomas Glozar Cc: Juri Lelli Cc: Clark Williams Cc: John Kacur Link: https://lore.kernel.org/20250728135022.255578-7-gmonaco@redhat.com Signed-off-by: Gabriele Monaco Signed-off-by: Steven Rostedt (Google) --- include/linux/sched.h | 7 ++++++- include/trace/events/sched.h | 12 ++++++++---- kernel/sched/core.c | 13 ++++++++++--- kernel/trace/rv/monitors/sco/sco.c | 4 ++-- kernel/trace/rv/monitors/scpd/scpd.c | 4 ++-- kernel/trace/rv/monitors/sncid/sncid.c | 4 ++-- kernel/trace/rv/monitors/snep/snep.c | 4 ++-- kernel/trace/rv/monitors/tss/tss.c | 4 ++-- 8 files changed, 34 insertions(+), 18 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index fabd7fe1a07a..91d1fdbc2f56 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -339,9 +339,11 @@ 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 */ +/* wrapper functions to trace from this header file */ DECLARE_TRACEPOINT(sched_set_state_tp); extern void __trace_set_current_state(int state_value); +DECLARE_TRACEPOINT(sched_set_need_resched_tp); +extern void __trace_set_need_resched(struct task_struct *curr, int tif); =20 /** * struct prev_cputime - snapshot of system and user cputime @@ -2063,6 +2065,9 @@ static inline int test_tsk_thread_flag(struct task_st= ruct *tsk, int flag) =20 static inline void set_tsk_need_resched(struct task_struct *tsk) { + if (tracepoint_enabled(sched_set_need_resched_tp) && + !test_tsk_thread_flag(tsk, TIF_NEED_RESCHED)) + __trace_set_need_resched(tsk, TIF_NEED_RESCHED); set_tsk_thread_flag(tsk,TIF_NEED_RESCHED); } =20 diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h index 4e6b2910cec3..c08893bde255 100644 --- a/include/trace/events/sched.h +++ b/include/trace/events/sched.h @@ -882,18 +882,22 @@ DECLARE_TRACE(sched_compute_energy, TP_ARGS(p, dst_cpu, energy, max_util, busy_time)); =20 DECLARE_TRACE(sched_entry, - TP_PROTO(bool preempt, unsigned long ip), - TP_ARGS(preempt, ip)); + TP_PROTO(bool preempt), + TP_ARGS(preempt)); =20 DECLARE_TRACE(sched_exit, - TP_PROTO(bool is_switch, unsigned long ip), - TP_ARGS(is_switch, ip)); + TP_PROTO(bool is_switch), + TP_ARGS(is_switch)); =20 DECLARE_TRACE_CONDITION(sched_set_state, TP_PROTO(struct task_struct *tsk, int state), TP_ARGS(tsk, state), TP_CONDITION(!!(tsk->__state) !=3D !!state)); =20 +DECLARE_TRACE(sched_set_need_resched, + TP_PROTO(struct task_struct *tsk, int cpu, int tif), + TP_ARGS(tsk, cpu, tif)); + #endif /* _TRACE_SCHED_H */ =20 /* This part must be outside protection */ diff --git a/kernel/sched/core.c b/kernel/sched/core.c index ec68fc686bd7..b485e0639616 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1110,6 +1110,7 @@ static void __resched_curr(struct rq *rq, int tif) =20 cpu =3D cpu_of(rq); =20 + trace_sched_set_need_resched_tp(curr, cpu, tif); if (cpu =3D=3D smp_processor_id()) { set_ti_thread_flag(cti, tif); if (tif =3D=3D TIF_NEED_RESCHED) @@ -1125,6 +1126,11 @@ static void __resched_curr(struct rq *rq, int tif) } } =20 +void __trace_set_need_resched(struct task_struct *curr, int tif) +{ + trace_sched_set_need_resched_tp(curr, smp_processor_id(), tif); +} + void resched_curr(struct rq *rq) { __resched_curr(rq, TIF_NEED_RESCHED); @@ -5329,7 +5335,7 @@ asmlinkage __visible void schedule_tail(struct task_s= truct *prev) * 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); + trace_sched_exit_tp(true); preempt_enable(); =20 if (current->set_child_tid) @@ -6678,7 +6684,8 @@ static void __sched notrace __schedule(int sched_mode) struct rq *rq; int cpu; =20 - trace_sched_entry_tp(preempt, CALLER_ADDR0); + /* Trace preemptions consistently with task switches */ + trace_sched_entry_tp(sched_mode =3D=3D SM_PREEMPT); =20 cpu =3D smp_processor_id(); rq =3D cpu_rq(cpu); @@ -6793,7 +6800,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); + trace_sched_exit_tp(is_switch); } =20 void __noreturn do_task_dead(void) diff --git a/kernel/trace/rv/monitors/sco/sco.c b/kernel/trace/rv/monitors/= sco/sco.c index 66f4639d46ac..04c36405e2e3 100644 --- a/kernel/trace/rv/monitors/sco/sco.c +++ b/kernel/trace/rv/monitors/sco/sco.c @@ -24,12 +24,12 @@ static void handle_sched_set_state(void *data, struct t= ask_struct *tsk, int stat da_handle_start_event_sco(sched_set_state_sco); } =20 -static void handle_schedule_entry(void *data, bool preempt, unsigned long = ip) +static void handle_schedule_entry(void *data, bool preempt) { da_handle_event_sco(schedule_entry_sco); } =20 -static void handle_schedule_exit(void *data, bool is_switch, unsigned long= ip) +static void handle_schedule_exit(void *data, bool is_switch) { da_handle_start_event_sco(schedule_exit_sco); } diff --git a/kernel/trace/rv/monitors/scpd/scpd.c b/kernel/trace/rv/monitor= s/scpd/scpd.c index 299703cd72b0..1e351ba52fee 100644 --- a/kernel/trace/rv/monitors/scpd/scpd.c +++ b/kernel/trace/rv/monitors/scpd/scpd.c @@ -30,12 +30,12 @@ static void handle_preempt_enable(void *data, unsigned = long ip, unsigned long pa da_handle_start_event_scpd(preempt_enable_scpd); } =20 -static void handle_schedule_entry(void *data, bool preempt, unsigned long = ip) +static void handle_schedule_entry(void *data, bool preempt) { da_handle_event_scpd(schedule_entry_scpd); } =20 -static void handle_schedule_exit(void *data, bool is_switch, unsigned long= ip) +static void handle_schedule_exit(void *data, bool is_switch) { da_handle_event_scpd(schedule_exit_scpd); } diff --git a/kernel/trace/rv/monitors/sncid/sncid.c b/kernel/trace/rv/monit= ors/sncid/sncid.c index 3e1ee715a0fb..c8491f426365 100644 --- a/kernel/trace/rv/monitors/sncid/sncid.c +++ b/kernel/trace/rv/monitors/sncid/sncid.c @@ -30,12 +30,12 @@ static void handle_irq_enable(void *data, unsigned long= ip, unsigned long parent da_handle_start_event_sncid(irq_enable_sncid); } =20 -static void handle_schedule_entry(void *data, bool preempt, unsigned long = ip) +static void handle_schedule_entry(void *data, bool preempt) { da_handle_start_event_sncid(schedule_entry_sncid); } =20 -static void handle_schedule_exit(void *data, bool is_switch, unsigned long= ip) +static void handle_schedule_exit(void *data, bool is_switch) { da_handle_start_event_sncid(schedule_exit_sncid); } diff --git a/kernel/trace/rv/monitors/snep/snep.c b/kernel/trace/rv/monitor= s/snep/snep.c index 2adc3108d60c..558950f524a5 100644 --- a/kernel/trace/rv/monitors/snep/snep.c +++ b/kernel/trace/rv/monitors/snep/snep.c @@ -30,12 +30,12 @@ static void handle_preempt_enable(void *data, unsigned = long ip, unsigned long pa da_handle_start_event_snep(preempt_enable_snep); } =20 -static void handle_schedule_entry(void *data, bool preempt, unsigned long = ip) +static void handle_schedule_entry(void *data, bool preempt) { da_handle_event_snep(schedule_entry_snep); } =20 -static void handle_schedule_exit(void *data, bool is_switch, unsigned long= ip) +static void handle_schedule_exit(void *data, bool is_switch) { da_handle_start_event_snep(schedule_exit_snep); } diff --git a/kernel/trace/rv/monitors/tss/tss.c b/kernel/trace/rv/monitors/= tss/tss.c index 0452fcd9edcf..95ebd15131f5 100644 --- a/kernel/trace/rv/monitors/tss/tss.c +++ b/kernel/trace/rv/monitors/tss/tss.c @@ -27,12 +27,12 @@ static void handle_sched_switch(void *data, bool preemp= t, da_handle_event_tss(sched_switch_tss); } =20 -static void handle_schedule_entry(void *data, bool preempt, unsigned long = ip) +static void handle_schedule_entry(void *data, bool preempt) { da_handle_event_tss(schedule_entry_tss); } =20 -static void handle_schedule_exit(void *data, bool is_switch, unsigned long= ip) +static void handle_schedule_exit(void *data, bool is_switch) { da_handle_start_event_tss(schedule_exit_tss); } --=20 2.47.2 From nobody Sun Oct 5 23:40:18 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 E190122FDE6 for ; Mon, 28 Jul 2025 20:49:46 +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=1753735787; cv=none; b=CGz76Yj/VU6Re5FSWn2jggp0qKKuGiphfXfICGCLyx5TTDo8T8iyXxaR6sZlgNpEEPWg5LrZEFTyiJmpYmPrmO02zfl/SqMxjUQ+iRPv9OTgDZIulCKuviAKgl6kXqn6+jIjgphlU8+T8RtN2wYqpkYCrEXvgEcVALH4SCnmJlE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753735787; c=relaxed/simple; bh=HTTn0gtcrrZx9SzRKRbbP/AJwa/FfRT+WzBhPwNbJn4=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=HcD2m+uhxSoc6WAVDVLWDUpU+MolXf20maEpVuWua2g5xqlXpQhXhMSs8YqDGPIwBgpb/3eJCT/4TgbzCHxA8FUqGHsmcxJP3c4OdB7Xoor6JmSMRMhakUg6KSi6qNZfaUeqGXnSK7NMHF2mi4yqkFB7HyyowI3A+icbZT2lQVQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QRWPiPZ2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QRWPiPZ2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9B95EC4CEE7; Mon, 28 Jul 2025 20:49:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753735786; bh=HTTn0gtcrrZx9SzRKRbbP/AJwa/FfRT+WzBhPwNbJn4=; h=Date:From:To:Cc:Subject:References:From; b=QRWPiPZ23NNMAagYdgRLioFa89nMQROx3TwBHoiB2BbYt/sHUyWnomF+o9OFuazCv UgW9z/Gh/YcNPaZJU44wV/ZvVQg57W5wyV9sWcqIxgKxzBMUUx11QTYYodc4gnGJCU tu4CJtnqduadvx1tRxg4w7TCm7E0M7Nd9E7VmuxAeROxnMpPbtZEFmlZD03mCN6T9B cHQZzejFYZs6q257UTCB7UQnbzVJnut3BOTAINkLnTugPP22mVRx7rQADHUD58zlN1 Kag26H8LuLDOOW9yalocIkp3Z1Syn6JBQ5j27hZpBq4OzLacIkc5KFyMjew8vmcpfy y1JT0Z3MgQo5Q== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1ugUnH-000000042yH-1h3M; Mon, 28 Jul 2025 16:49:59 -0400 Message-ID: <20250728204959.259938900@kernel.org> User-Agent: quilt/0.68 Date: Mon, 28 Jul 2025 16:49:43 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Ingo Molnar , Jonathan Corbet , Masami Hiramatsu , Nam Cao , Juri Lelli , Clark Williams , Peter Zijlstra , Gabriele Monaco Subject: [for-next][PATCH 09/11] rv: Replace tss and sncid monitors with more complete sts References: <20250728204934.281385756@kernel.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 The tss monitor currently guarantees task switches can happen only while scheduling, whereas the sncid monitor enforces scheduling occurs with interrupt disabled. Replace the monitors with a more comprehensive specification which implies both but also ensures that: * each scheduler call disable interrupts to switch * each task switch happens with interrupts disabled Cc: Ingo Molnar Cc: Jonathan Corbet Cc: Masami Hiramatsu Cc: Nam Cao Cc: Tomas Glozar Cc: Juri Lelli Cc: Clark Williams Cc: John Kacur Cc: Peter Zijlstra Link: https://lore.kernel.org/20250728135022.255578-8-gmonaco@redhat.com Signed-off-by: Gabriele Monaco Signed-off-by: Steven Rostedt (Google) --- Documentation/trace/rv/monitor_sched.rst | 87 +++++----- kernel/trace/rv/Kconfig | 3 +- kernel/trace/rv/Makefile | 3 +- kernel/trace/rv/monitors/sncid/Kconfig | 15 -- kernel/trace/rv/monitors/sncid/sncid.c | 95 ----------- kernel/trace/rv/monitors/sncid/sncid.h | 49 ------ kernel/trace/rv/monitors/sncid/sncid_trace.h | 15 -- kernel/trace/rv/monitors/sts/Kconfig | 19 +++ kernel/trace/rv/monitors/sts/sts.c | 156 ++++++++++++++++++ kernel/trace/rv/monitors/sts/sts.h | 117 +++++++++++++ .../{tss/tss_trace.h =3D> sts/sts_trace.h} | 8 +- kernel/trace/rv/monitors/tss/Kconfig | 14 -- kernel/trace/rv/monitors/tss/tss.c | 90 ---------- kernel/trace/rv/monitors/tss/tss.h | 47 ------ kernel/trace/rv/rv_trace.h | 3 +- tools/verification/models/sched/sncid.dot | 18 -- tools/verification/models/sched/sts.dot | 38 +++++ tools/verification/models/sched/tss.dot | 18 -- 18 files changed, 385 insertions(+), 410 deletions(-) delete mode 100644 kernel/trace/rv/monitors/sncid/Kconfig delete mode 100644 kernel/trace/rv/monitors/sncid/sncid.c delete mode 100644 kernel/trace/rv/monitors/sncid/sncid.h delete mode 100644 kernel/trace/rv/monitors/sncid/sncid_trace.h create mode 100644 kernel/trace/rv/monitors/sts/Kconfig create mode 100644 kernel/trace/rv/monitors/sts/sts.c create mode 100644 kernel/trace/rv/monitors/sts/sts.h rename kernel/trace/rv/monitors/{tss/tss_trace.h =3D> sts/sts_trace.h} (67= %) delete mode 100644 kernel/trace/rv/monitors/tss/Kconfig delete mode 100644 kernel/trace/rv/monitors/tss/tss.c delete mode 100644 kernel/trace/rv/monitors/tss/tss.h delete mode 100644 tools/verification/models/sched/sncid.dot create mode 100644 tools/verification/models/sched/sts.dot delete mode 100644 tools/verification/models/sched/tss.dot diff --git a/Documentation/trace/rv/monitor_sched.rst b/Documentation/trace= /rv/monitor_sched.rst index 24b2c62a3bc2..6c4c00216c07 100644 --- a/Documentation/trace/rv/monitor_sched.rst +++ b/Documentation/trace/rv/monitor_sched.rst @@ -40,26 +40,6 @@ defined in by Daniel Bristot in [1]. =20 Currently we included the following: =20 -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 ~~~~~~~~~~~ =20 @@ -144,26 +124,55 @@ does not enable preemption:: | scheduling_contex -+ =20 -Monitor sncid -~~~~~~~~~~~~~ - -The schedule not called with interrupt disabled (sncid) monitor ensures -schedule is not called with interrupt disabled:: +Monitor sts +~~~~~~~~~~~ =20 - | - | - v - schedule_entry +--------------+ - schedule_exit | | - +----------------- | can_sched | - | | | - +----------------> | | <+ - +--------------+ | - | | - | irq_disable | irq_enable - v | - | - cant_sched -+ +The schedule implies task switch (sts) monitor ensures a task switch happe= ns +only in scheduling context and up to once, as well as scheduling occurs wi= th +interrupts enabled but no task switch can happen before interrupts are +disabled. When the next task picked for execution is the same as the previ= ously +running one, no real task switch occurs but interrupts are disabled noneth= eless:: + + irq_entry | + +----+ | + v | v + +------------+ irq_enable #=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D# irq_disable + | | ------------> H H irq_entry + | cant_sched | <------------ H H irq_enable + | | irq_disable H can_sched H --------------+ + +------------+ H H | + H H | + +---------------> H H <-------------+ + | #=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D# + | | + schedule_exit | schedule_entry + | v + | +-------------------+ irq_enable + | | scheduling | <---------------+ + | +-------------------+ | + | | | + | | irq_disable +--------+ irq_entry + | v | | --------+ + | +-------------------+ irq_entry | in_irq | | + | | | -----------> | | <-------+ + | | disable_to_switch | +--------+ + | | | --+ + | +-------------------+ | + | | | + | | sched_switch | + | v | + | +-------------------+ | + | | switching | | irq_enable + | +-------------------+ | + | | | + | | irq_enable | + | v | + | +-------------------+ | + +-- | enable_to_exit | <-+ + +-------------------+ + ^ | irq_disable + | | irq_entry + +---------------+ irq_enable =20 References ---------- diff --git a/kernel/trace/rv/Kconfig b/kernel/trace/rv/Kconfig index 34164eb4ec91..b688b24081c8 100644 --- a/kernel/trace/rv/Kconfig +++ b/kernel/trace/rv/Kconfig @@ -50,12 +50,11 @@ source "kernel/trace/rv/monitors/wip/Kconfig" source "kernel/trace/rv/monitors/wwnr/Kconfig" =20 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" +source "kernel/trace/rv/monitors/sts/Kconfig" # Add new sched monitors here =20 source "kernel/trace/rv/monitors/rtapp/Kconfig" diff --git a/kernel/trace/rv/Makefile b/kernel/trace/rv/Makefile index 13ec2944c665..1939d3d7621c 100644 --- a/kernel/trace/rv/Makefile +++ b/kernel/trace/rv/Makefile @@ -6,15 +6,14 @@ 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 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 obj-$(CONFIG_RV_MON_RTAPP) +=3D monitors/rtapp/rtapp.o obj-$(CONFIG_RV_MON_PAGEFAULT) +=3D monitors/pagefault/pagefault.o obj-$(CONFIG_RV_MON_SLEEP) +=3D monitors/sleep/sleep.o +obj-$(CONFIG_RV_MON_STS) +=3D monitors/sts/sts.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/sncid/Kconfig b/kernel/trace/rv/monit= ors/sncid/Kconfig deleted file mode 100644 index 3a5639feaaaf..000000000000 --- a/kernel/trace/rv/monitors/sncid/Kconfig +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -config RV_MON_SNCID - depends on RV - depends on TRACE_IRQFLAGS - 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 deleted file mode 100644 index c8491f426365..000000000000 --- a/kernel/trace/rv/monitors/sncid/sncid.c +++ /dev/null @@ -1,95 +0,0 @@ -// 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) -{ - da_handle_start_event_sncid(schedule_entry_sncid); -} - -static void handle_schedule_exit(void *data, bool is_switch) -{ - 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) -{ - return rv_register_monitor(&rv_sncid, &rv_sched); -} - -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 deleted file mode 100644 index 21304725142b..000000000000 --- a/kernel/trace/rv/monitors/sncid/sncid.h +++ /dev/null @@ -1,49 +0,0 @@ -/* 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 deleted file mode 100644 index 3ce42a57671d..000000000000 --- a/kernel/trace/rv/monitors/sncid/sncid_trace.h +++ /dev/null @@ -1,15 +0,0 @@ -/* 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/sts/Kconfig b/kernel/trace/rv/monitor= s/sts/Kconfig new file mode 100644 index 000000000000..7d1ff0f6fc91 --- /dev/null +++ b/kernel/trace/rv/monitors/sts/Kconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_STS + depends on RV + depends on TRACE_IRQFLAGS + depends on RV_MON_SCHED + default y + select DA_MON_EVENTS_IMPLICIT + bool "sts monitor" + help + Monitor to ensure relationships between scheduler and task switches + * the scheduler is called and returns with interrupts disabled + * each call to the scheduler has up to one switch + * switches only happen inside the scheduler + * each call to the scheduler disables interrupts to switch + 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/sts/sts.c b/kernel/trace/rv/monitors/= sts/sts.c new file mode 100644 index 000000000000..c4a9cd67c1d2 --- /dev/null +++ b/kernel/trace/rv/monitors/sts/sts.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "sts" + +#include +#include +#include +#include +#include + +#include "sts.h" + +static struct rv_monitor rv_sts; +DECLARE_DA_MON_PER_CPU(sts, unsigned char); + +#ifdef CONFIG_X86_LOCAL_APIC +#include + +static void handle_vector_irq_entry(void *data, int vector) +{ + da_handle_event_sts(irq_entry_sts); +} + +static void attach_vector_irq(void) +{ + rv_attach_trace_probe("sts", local_timer_entry, handle_vector_irq_entry); + if (IS_ENABLED(CONFIG_IRQ_WORK)) + rv_attach_trace_probe("sts", irq_work_entry, handle_vector_irq_entry); + if (IS_ENABLED(CONFIG_SMP)) { + rv_attach_trace_probe("sts", reschedule_entry, handle_vector_irq_entry); + rv_attach_trace_probe("sts", call_function_entry, handle_vector_irq_entr= y); + rv_attach_trace_probe("sts", call_function_single_entry, handle_vector_i= rq_entry); + } +} + +static void detach_vector_irq(void) +{ + rv_detach_trace_probe("sts", local_timer_entry, handle_vector_irq_entry); + if (IS_ENABLED(CONFIG_IRQ_WORK)) + rv_detach_trace_probe("sts", irq_work_entry, handle_vector_irq_entry); + if (IS_ENABLED(CONFIG_SMP)) { + rv_detach_trace_probe("sts", reschedule_entry, handle_vector_irq_entry); + rv_detach_trace_probe("sts", call_function_entry, handle_vector_irq_entr= y); + rv_detach_trace_probe("sts", call_function_single_entry, handle_vector_i= rq_entry); + } +} + +#else +/* We assume irq_entry tracepoints are sufficient on other architectures */ +static void attach_vector_irq(void) { } +static void detach_vector_irq(void) { } +#endif + +static void handle_irq_disable(void *data, unsigned long ip, unsigned long= parent_ip) +{ + da_handle_event_sts(irq_disable_sts); +} + +static void handle_irq_enable(void *data, unsigned long ip, unsigned long = parent_ip) +{ + da_handle_event_sts(irq_enable_sts); +} + +static void handle_irq_entry(void *data, int irq, struct irqaction *action) +{ + da_handle_event_sts(irq_entry_sts); +} + +static void handle_sched_switch(void *data, bool preempt, + struct task_struct *prev, + struct task_struct *next, + unsigned int prev_state) +{ + da_handle_event_sts(sched_switch_sts); +} + +static void handle_schedule_entry(void *data, bool preempt) +{ + da_handle_event_sts(schedule_entry_sts); +} + +static void handle_schedule_exit(void *data, bool is_switch) +{ + da_handle_start_event_sts(schedule_exit_sts); +} + +static int enable_sts(void) +{ + int retval; + + retval =3D da_monitor_init_sts(); + if (retval) + return retval; + + rv_attach_trace_probe("sts", irq_disable, handle_irq_disable); + rv_attach_trace_probe("sts", irq_enable, handle_irq_enable); + rv_attach_trace_probe("sts", irq_handler_entry, handle_irq_entry); + rv_attach_trace_probe("sts", sched_switch, handle_sched_switch); + rv_attach_trace_probe("sts", sched_entry_tp, handle_schedule_entry); + rv_attach_trace_probe("sts", sched_exit_tp, handle_schedule_exit); + attach_vector_irq(); + + return 0; +} + +static void disable_sts(void) +{ + rv_sts.enabled =3D 0; + + rv_detach_trace_probe("sts", irq_disable, handle_irq_disable); + rv_detach_trace_probe("sts", irq_enable, handle_irq_enable); + rv_detach_trace_probe("sts", irq_handler_entry, handle_irq_entry); + rv_detach_trace_probe("sts", sched_switch, handle_sched_switch); + rv_detach_trace_probe("sts", sched_entry_tp, handle_schedule_entry); + rv_detach_trace_probe("sts", sched_exit_tp, handle_schedule_exit); + detach_vector_irq(); + + da_monitor_destroy_sts(); +} + +/* + * This is the monitor register section. + */ +static struct rv_monitor rv_sts =3D { + .name =3D "sts", + .description =3D "schedule implies task switch.", + .enable =3D enable_sts, + .disable =3D disable_sts, + .reset =3D da_monitor_reset_all_sts, + .enabled =3D 0, +}; + +static int __init register_sts(void) +{ + return rv_register_monitor(&rv_sts, &rv_sched); +} + +static void __exit unregister_sts(void) +{ + rv_unregister_monitor(&rv_sts); +} + +module_init(register_sts); +module_exit(unregister_sts); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gabriele Monaco "); +MODULE_DESCRIPTION("sts: schedule implies task switch."); diff --git a/kernel/trace/rv/monitors/sts/sts.h b/kernel/trace/rv/monitors/= sts/sts.h new file mode 100644 index 000000000000..3368b6599a00 --- /dev/null +++ b/kernel/trace/rv/monitors/sts/sts.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Automatically generated C representation of sts automaton + * For further information about this format, see kernel documentation: + * Documentation/trace/rv/deterministic_automata.rst + */ + +enum states_sts { + can_sched_sts =3D 0, + cant_sched_sts, + disable_to_switch_sts, + enable_to_exit_sts, + in_irq_sts, + scheduling_sts, + switching_sts, + state_max_sts +}; + +#define INVALID_STATE state_max_sts + +enum events_sts { + irq_disable_sts =3D 0, + irq_enable_sts, + irq_entry_sts, + sched_switch_sts, + schedule_entry_sts, + schedule_exit_sts, + event_max_sts +}; + +struct automaton_sts { + char *state_names[state_max_sts]; + char *event_names[event_max_sts]; + unsigned char function[state_max_sts][event_max_sts]; + unsigned char initial_state; + bool final_states[state_max_sts]; +}; + +static const struct automaton_sts automaton_sts =3D { + .state_names =3D { + "can_sched", + "cant_sched", + "disable_to_switch", + "enable_to_exit", + "in_irq", + "scheduling", + "switching" + }, + .event_names =3D { + "irq_disable", + "irq_enable", + "irq_entry", + "sched_switch", + "schedule_entry", + "schedule_exit" + }, + .function =3D { + { + cant_sched_sts, + INVALID_STATE, + INVALID_STATE, + INVALID_STATE, + scheduling_sts, + INVALID_STATE + }, + { + INVALID_STATE, + can_sched_sts, + cant_sched_sts, + INVALID_STATE, + INVALID_STATE, + INVALID_STATE + }, + { + INVALID_STATE, + enable_to_exit_sts, + in_irq_sts, + switching_sts, + INVALID_STATE, + INVALID_STATE + }, + { + enable_to_exit_sts, + enable_to_exit_sts, + enable_to_exit_sts, + INVALID_STATE, + INVALID_STATE, + can_sched_sts + }, + { + INVALID_STATE, + scheduling_sts, + in_irq_sts, + INVALID_STATE, + INVALID_STATE, + INVALID_STATE + }, + { + disable_to_switch_sts, + INVALID_STATE, + INVALID_STATE, + INVALID_STATE, + INVALID_STATE, + INVALID_STATE + }, + { + INVALID_STATE, + enable_to_exit_sts, + INVALID_STATE, + INVALID_STATE, + INVALID_STATE, + INVALID_STATE + }, + }, + .initial_state =3D can_sched_sts, + .final_states =3D { 1, 0, 0, 0, 0, 0, 0 }, +}; diff --git a/kernel/trace/rv/monitors/tss/tss_trace.h b/kernel/trace/rv/mon= itors/sts/sts_trace.h similarity index 67% rename from kernel/trace/rv/monitors/tss/tss_trace.h rename to kernel/trace/rv/monitors/sts/sts_trace.h index 4619dbb50cc0..d78beb58d5b3 100644 --- a/kernel/trace/rv/monitors/tss/tss_trace.h +++ b/kernel/trace/rv/monitors/sts/sts_trace.h @@ -4,12 +4,12 @@ * Snippet to be included in rv_trace.h */ =20 -#ifdef CONFIG_RV_MON_TSS -DEFINE_EVENT(event_da_monitor, event_tss, +#ifdef CONFIG_RV_MON_STS +DEFINE_EVENT(event_da_monitor, event_sts, TP_PROTO(char *state, char *event, char *next_state, bool final_stat= e), TP_ARGS(state, event, next_state, final_state)); =20 -DEFINE_EVENT(error_da_monitor, error_tss, +DEFINE_EVENT(error_da_monitor, error_sts, TP_PROTO(char *state, char *event), TP_ARGS(state, event)); -#endif /* CONFIG_RV_MON_TSS */ +#endif /* CONFIG_RV_MON_STS */ diff --git a/kernel/trace/rv/monitors/tss/Kconfig b/kernel/trace/rv/monitor= s/tss/Kconfig deleted file mode 100644 index 479f86f52e60..000000000000 --- a/kernel/trace/rv/monitors/tss/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -# 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 deleted file mode 100644 index 95ebd15131f5..000000000000 --- a/kernel/trace/rv/monitors/tss/tss.c +++ /dev/null @@ -1,90 +0,0 @@ -// 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) -{ - da_handle_event_tss(schedule_entry_tss); -} - -static void handle_schedule_exit(void *data, bool is_switch) -{ - 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) -{ - return rv_register_monitor(&rv_tss, &rv_sched); -} - -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 deleted file mode 100644 index f0a36fda1b87..000000000000 --- a/kernel/trace/rv/monitors/tss/tss.h +++ /dev/null @@ -1,47 +0,0 @@ -/* 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/rv_trace.h b/kernel/trace/rv/rv_trace.h index 3af46cd185b3..97b2f7e07f27 100644 --- a/kernel/trace/rv/rv_trace.h +++ b/kernel/trace/rv/rv_trace.h @@ -58,11 +58,10 @@ DECLARE_EVENT_CLASS(error_da_monitor, ); =20 #include -#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/sncid.dot b/tools/verification= /models/sched/sncid.dot deleted file mode 100644 index 072851721b50..000000000000 --- a/tools/verification/models/sched/sncid.dot +++ /dev/null @@ -1,18 +0,0 @@ -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/sts.dot b/tools/verification/m= odels/sched/sts.dot new file mode 100644 index 000000000000..8f5f38be04d5 --- /dev/null +++ b/tools/verification/models/sched/sts.dot @@ -0,0 +1,38 @@ +digraph state_automaton { + center =3D true; + size =3D "7,11"; + {node [shape =3D plaintext, style=3Dinvis, label=3D""] "__init_can_sched"= }; + {node [shape =3D doublecircle] "can_sched"}; + {node [shape =3D circle] "can_sched"}; + {node [shape =3D circle] "cant_sched"}; + {node [shape =3D circle] "disable_to_switch"}; + {node [shape =3D circle] "enable_to_exit"}; + {node [shape =3D circle] "in_irq"}; + {node [shape =3D circle] "scheduling"}; + {node [shape =3D circle] "switching"}; + "__init_can_sched" -> "can_sched"; + "can_sched" [label =3D "can_sched", color =3D green3]; + "can_sched" -> "cant_sched" [ label =3D "irq_disable" ]; + "can_sched" -> "scheduling" [ label =3D "schedule_entry" ]; + "cant_sched" [label =3D "cant_sched"]; + "cant_sched" -> "can_sched" [ label =3D "irq_enable" ]; + "cant_sched" -> "cant_sched" [ label =3D "irq_entry" ]; + "disable_to_switch" [label =3D "disable_to_switch"]; + "disable_to_switch" -> "enable_to_exit" [ label =3D "irq_enable" ]; + "disable_to_switch" -> "in_irq" [ label =3D "irq_entry" ]; + "disable_to_switch" -> "switching" [ label =3D "sched_switch" ]; + "enable_to_exit" [label =3D "enable_to_exit"]; + "enable_to_exit" -> "can_sched" [ label =3D "schedule_exit" ]; + "enable_to_exit" -> "enable_to_exit" [ label =3D "irq_disable\nirq_entry\= nirq_enable" ]; + "in_irq" [label =3D "in_irq"]; + "in_irq" -> "in_irq" [ label =3D "irq_entry" ]; + "in_irq" -> "scheduling" [ label =3D "irq_enable" ]; + "scheduling" [label =3D "scheduling"]; + "scheduling" -> "disable_to_switch" [ label =3D "irq_disable" ]; + "switching" [label =3D "switching"]; + "switching" -> "enable_to_exit" [ label =3D "irq_enable" ]; + { rank =3D min ; + "__init_can_sched"; + "can_sched"; + } +} diff --git a/tools/verification/models/sched/tss.dot b/tools/verification/m= odels/sched/tss.dot deleted file mode 100644 index 7dfa1d9121bb..000000000000 --- a/tools/verification/models/sched/tss.dot +++ /dev/null @@ -1,18 +0,0 @@ -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 Sun Oct 5 23:40:18 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 F355B230D35 for ; Mon, 28 Jul 2025 20:49:46 +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=1753735787; cv=none; b=LJAf0YbiwIXHZLutKtxLoOE8+cRK41lwWrbLZQM86tWW6ekGGHShh1no1Sh4Q5teRButFJKfMaZqjR9e546oNOjUvgjy3UjrR+Irq/W9mWhmL1BxnkMQAP2ckpJdp8Cbvg++NSPmF1SP3cUgAC+shZwpDzdB9LY2/5vymqpVnJU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753735787; c=relaxed/simple; bh=fa+oBSdbXiBeFKTWv7wlmZOfz7plss8MxuO4SWIzo5g=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=amMTHkeB16TgVclOKQpQiNQVBWNVKTd09rgrSnzZQGfdjtmCCBu4c5GkqDuv1leyXoK8oPFBR7DSZ+L9+J7DsT2Nj3IaLkks0sc549p4ltcPy9wjmWjtPtdRS6sEBeMwUVfoorkpV+BcSacAM4noPxmP4REak2n/CcRyyUnLBl0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JAe9MXSM; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="JAe9MXSM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AFE9BC4CEF7; Mon, 28 Jul 2025 20:49:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753735786; bh=fa+oBSdbXiBeFKTWv7wlmZOfz7plss8MxuO4SWIzo5g=; h=Date:From:To:Cc:Subject:References:From; b=JAe9MXSMx95sfven+beFr1MQPiYiQR5FvkkX6+4abuQIkwEFoHNnp7fz7TWS6LdSs PnCuMjaXUqnCxrcXW3Sr5viMzLUwsVaKjHRBHaca7qeQL0RJviwSNiszUPHoQ7wz/l yYtg/NC1u1wNw0oix9TwUK4jgF91pI8sc1yrswkAr0Bjq2knnukxgBwAm93DzwRoqg fz4lUQsAyrNc0KkAZxuw3qW+sE5HuPNnI2nz/Jkn3svl5sVDJQxFZBDAR6xsGsZ5Id 93MPhm00d+OBeNOrF75FlZJZAa4LRIFOVmE/RilUx2UeK6mO/bU0F7jYk2jJFvyWOE 6KvDepgT1onxw== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1ugUnH-000000042ym-2QUS; Mon, 28 Jul 2025 16:49:59 -0400 Message-ID: <20250728204959.425356272@kernel.org> User-Agent: quilt/0.68 Date: Mon, 28 Jul 2025 16:49:44 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Ingo Molnar , Jonathan Corbet , Masami Hiramatsu , Juri Lelli , Clark Williams , Peter Zijlstra , Gabriele Monaco , Nam Cao Subject: [for-next][PATCH 10/11] rv: Add nrp and sssw per-task monitors References: <20250728204934.281385756@kernel.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-task monitors as part of the sched model: * nrp: need-resched preempts Monitor to ensure preemption requires need resched. * sssw: set state sleep and wakeup Monitor to ensure sched_set_state to sleepable leads to sleeping and sleeping tasks require wakeup. Cc: Ingo Molnar Cc: Jonathan Corbet Cc: Masami Hiramatsu Cc: Tomas Glozar Cc: Juri Lelli Cc: Clark Williams Cc: John Kacur Cc: Peter Zijlstra Link: https://lore.kernel.org/20250728135022.255578-9-gmonaco@redhat.com Signed-off-by: Gabriele Monaco Acked-by: Nam Cao Tested-by: Nam Cao Signed-off-by: Steven Rostedt (Google) --- Documentation/trace/rv/monitor_sched.rst | 167 +++++++++++++++++++++ kernel/trace/rv/Kconfig | 2 + kernel/trace/rv/Makefile | 2 + kernel/trace/rv/monitors/nrp/Kconfig | 16 ++ kernel/trace/rv/monitors/nrp/nrp.c | 138 +++++++++++++++++ kernel/trace/rv/monitors/nrp/nrp.h | 75 +++++++++ kernel/trace/rv/monitors/nrp/nrp_trace.h | 15 ++ kernel/trace/rv/monitors/sched/Kconfig | 1 + kernel/trace/rv/monitors/sssw/Kconfig | 15 ++ kernel/trace/rv/monitors/sssw/sssw.c | 116 ++++++++++++++ kernel/trace/rv/monitors/sssw/sssw.h | 105 +++++++++++++ kernel/trace/rv/monitors/sssw/sssw_trace.h | 15 ++ kernel/trace/rv/rv_trace.h | 2 + tools/verification/models/sched/nrp.dot | 29 ++++ tools/verification/models/sched/sssw.dot | 30 ++++ 15 files changed, 728 insertions(+) create mode 100644 kernel/trace/rv/monitors/nrp/Kconfig create mode 100644 kernel/trace/rv/monitors/nrp/nrp.c create mode 100644 kernel/trace/rv/monitors/nrp/nrp.h create mode 100644 kernel/trace/rv/monitors/nrp/nrp_trace.h create mode 100644 kernel/trace/rv/monitors/sssw/Kconfig create mode 100644 kernel/trace/rv/monitors/sssw/sssw.c create mode 100644 kernel/trace/rv/monitors/sssw/sssw.h create mode 100644 kernel/trace/rv/monitors/sssw/sssw_trace.h create mode 100644 tools/verification/models/sched/nrp.dot create mode 100644 tools/verification/models/sched/sssw.dot diff --git a/Documentation/trace/rv/monitor_sched.rst b/Documentation/trace= /rv/monitor_sched.rst index 6c4c00216c07..11ef963cb578 100644 --- a/Documentation/trace/rv/monitor_sched.rst +++ b/Documentation/trace/rv/monitor_sched.rst @@ -174,6 +174,173 @@ running one, no real task switch occurs but interrupt= s are disabled nonetheless: | | irq_entry +---------------+ irq_enable =20 +Monitor nrp +----------- + +The need resched preempts (nrp) monitor ensures preemption requires +``need_resched``. Only kernel preemption is considered, since preemption +while returning to userspace, for this monitor, is indistinguishable from +``sched_switch_yield`` (described in the sssw monitor). +A kernel preemption is whenever ``__schedule`` is called with the preempti= on +flag set to true (e.g. from preempt_enable or exiting from interrupts). Th= is +type of preemption occurs after the need for ``rescheduling`` has been set. +This is not valid for the *lazy* variant of the flag, which causes only +userspace preemption. +A ``schedule_entry_preempt`` may involve a task switch or not, in the latt= er +case, a task goes through the scheduler from a preemption context but it is +picked as the next task to run. Since the scheduler runs, this clears the = need +to reschedule. The ``any_thread_running`` state does not imply the monitor= ed +task is not running as this monitor does not track the outcome of scheduli= ng. + +In theory, a preemption can only occur after the ``need_resched`` flag is = set. In +practice, however, it is possible to see a preemption where the flag is not +set. This can happen in one specific condition:: + + need_resched + preempt_schedule() + preempt_schedule_irq() + __schedule() + !need_resched + __schedule() + +In the situation above, standard preemption starts (e.g. from preempt_enab= le +when the flag is set), an interrupt occurs before scheduling and, on its e= xit +path, it schedules, which clears the ``need_resched`` flag. +When the preempted task runs again, the standard preemption started earlier +resumes, although the flag is no longer set. The monitor considers this a +``nested_preemption``, this allows another preemption without re-setting t= he +flag. This condition relaxes the monitor constraints and may catch false +negatives (i.e. no real ``nested_preemptions``) but makes the monitor more +robust and able to validate other scenarios. +For simplicity, the monitor starts in ``preempt_irq``, although no interru= pt +occurred, as the situation above is hard to pinpoint:: + + schedule_entry + irq_entry #=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 H + | H H + +-------------------------> H any_thread_running H + H H + +-------------------------> H 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# + | schedule_entry | ^ + | schedule_entry_preempt | sched_need_resched | schedule_entry + | | schedule_entry_pree= mpt + | v | + | +----------------------+ | + | +--- | | | + | sched_need_resched | | rescheduling | -+ + | +--> | | + | +----------------------+ + | | irq_entry + | v + | +----------------------+ + | | | ---+ + | ---> | | | sched_need_res= ched + | | preempt_irq | | irq_entry + | | | <--+ + | | | <--+ + | +----------------------+ | + | | schedule_entry | sched_need_res= ched + | | schedule_entry_preempt | + | v | + | +-----------------------+ | + +-------------------------- | nested_preempt | --+ + +-----------------------+ + ^ irq_entry | + +-------------------+ + +Due to how the ``need_resched`` flag on the preemption count works on arm6= 4, +this monitor is unstable on that architecture, as it often records preempt= ion +when the flag is not set, even in presence of the workaround above. +For the time being, the monitor is disabled by default on arm64. + +Monitor sssw +------------ + +The set state sleep and wakeup (sssw) monitor ensures ``set_state`` to +sleepable leads to sleeping and sleeping tasks require wakeup. It includes= the +following types of switch: + +* ``switch_suspend``: + a task puts itself to sleep, this can happen only after explicitly setti= ng + the task to ``sleepable``. After a task is suspended, it needs to be wok= en up + (``waking`` state) before being switched in again. + Setting the task's state to ``sleepable`` can be reverted before switchi= ng if it + is woken up or set to ``runnable``. +* ``switch_blocking``: + a special case of a ``switch_suspend`` where the task is waiting on a + sleeping RT lock (``PREEMPT_RT`` only), it is common to see wakeup and s= et + state events racing with each other and this leads the model to perceive= this + type of switch when the task is not set to sleepable. This is a limitati= on of + the model in SMP system and workarounds may slow down the system. +* ``switch_preempt``: + a task switch as a result of kernel preemption (``schedule_entry_preempt= `` in + the nrp model). +* ``switch_yield``: + a task explicitly calls the scheduler or is preempted while returning to + userspace. It can happen after a ``yield`` system call, from the idle ta= sk or + if the ``need_resched`` flag is set. By definition, a task cannot yield = while + ``sleepable`` as that would be a suspension. A special case of a yield o= ccurs + when a task in ``TASK_INTERRUPTIBLE`` calls the scheduler while a signal= is + pending. The task doesn't go through the usual blocking/waking and is set + back to runnable, the resulting switch (if there) looks like a yield to = the + ``signal_wakeup`` state and is followed by the signal delivery. From this + state, the monitor expects a signal even if it sees a wakeup event, alth= ough + not necessary, to rule out false negatives. + +This monitor doesn't include a running state, ``sleepable`` and ``runnable= `` +are only referring to the task's desired state, which could be scheduled o= ut +(e.g. due to preemption). However, it does include the event +``sched_switch_in`` to represent when a task is allowed to become running.= This +can be triggered also by preemption, but cannot occur after the task got to +``sleeping`` before a ``wakeup`` occurs:: + + +----------------------------------------------------------------------= ----+ + | = | + | = | + | switch_suspend | = | + | switch_blocking | = | + 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# set_state_runnable | + | | H H wakeup = | + | | H H switch_in = | + | | H H switch_yield = | + | sleeping | H H switch_preempt = | + | | H H signal_deliver = | + | | switch_ H H ------+ = | + | | _blocking H runnable H | = | + | | <----------- H H <-----+ = | + +----------+ H H = | + | wakeup H H = | + +---------------------> H H = | + H H = | + +---------> H 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# | + | | ^ = | + | | | set_state_runnable = | + | | | wakeup = | + | set_state_sleepable | +--------------------= ----+ + | v | | + | +--------------------------+ set_state_sleepab= le + | | | switch_in + | | | switch_preempt + signal_deliver | sleepable | signal_deliver + | | | ------+ + | | | | + | | | <-----+ + | +--------------------------+ + | | ^ + | switch_yield | set_state_sleepable + | v | + | +---------------+ | + +---------- | signal_wakeup | -+ + +---------------+ + ^ | switch_in + | | switch_preempt + | | switch_yield + +-----------+ wakeup + References ---------- =20 diff --git a/kernel/trace/rv/Kconfig b/kernel/trace/rv/Kconfig index b688b24081c8..59d0db898d4a 100644 --- a/kernel/trace/rv/Kconfig +++ b/kernel/trace/rv/Kconfig @@ -55,6 +55,8 @@ 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/sts/Kconfig" +source "kernel/trace/rv/monitors/nrp/Kconfig" +source "kernel/trace/rv/monitors/sssw/Kconfig" # Add new sched monitors here =20 source "kernel/trace/rv/monitors/rtapp/Kconfig" diff --git a/kernel/trace/rv/Makefile b/kernel/trace/rv/Makefile index 1939d3d7621c..2afac88539d3 100644 --- a/kernel/trace/rv/Makefile +++ b/kernel/trace/rv/Makefile @@ -14,6 +14,8 @@ obj-$(CONFIG_RV_MON_RTAPP) +=3D monitors/rtapp/rtapp.o obj-$(CONFIG_RV_MON_PAGEFAULT) +=3D monitors/pagefault/pagefault.o obj-$(CONFIG_RV_MON_SLEEP) +=3D monitors/sleep/sleep.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 # 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/nrp/Kconfig b/kernel/trace/rv/monitor= s/nrp/Kconfig new file mode 100644 index 000000000000..f5ec08f65535 --- /dev/null +++ b/kernel/trace/rv/monitors/nrp/Kconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_NRP + depends on RV + depends on RV_MON_SCHED + default y if !ARM64 + select DA_MON_EVENTS_ID + bool "nrp monitor" + help + Monitor to ensure preemption requires need resched. + This monitor is part of the sched monitors collection. + + This monitor is unstable on arm64, say N unless you are testing it. + + For further information, see: + Documentation/trace/rv/monitor_sched.rst diff --git a/kernel/trace/rv/monitors/nrp/nrp.c b/kernel/trace/rv/monitors/= nrp/nrp.c new file mode 100644 index 000000000000..5a83b7171432 --- /dev/null +++ b/kernel/trace/rv/monitors/nrp/nrp.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "nrp" + +#include +#include +#include +#include + +#include "nrp.h" + +static struct rv_monitor rv_nrp; +DECLARE_DA_MON_PER_TASK(nrp, unsigned char); + +#ifdef CONFIG_X86_LOCAL_APIC +#include + +static void handle_vector_irq_entry(void *data, int vector) +{ + da_handle_event_nrp(current, irq_entry_nrp); +} + +static void attach_vector_irq(void) +{ + rv_attach_trace_probe("nrp", local_timer_entry, handle_vector_irq_entry); + if (IS_ENABLED(CONFIG_IRQ_WORK)) + rv_attach_trace_probe("nrp", irq_work_entry, handle_vector_irq_entry); + if (IS_ENABLED(CONFIG_SMP)) { + rv_attach_trace_probe("nrp", reschedule_entry, handle_vector_irq_entry); + rv_attach_trace_probe("nrp", call_function_entry, handle_vector_irq_entr= y); + rv_attach_trace_probe("nrp", call_function_single_entry, handle_vector_i= rq_entry); + } +} + +static void detach_vector_irq(void) +{ + rv_detach_trace_probe("nrp", local_timer_entry, handle_vector_irq_entry); + if (IS_ENABLED(CONFIG_IRQ_WORK)) + rv_detach_trace_probe("nrp", irq_work_entry, handle_vector_irq_entry); + if (IS_ENABLED(CONFIG_SMP)) { + rv_detach_trace_probe("nrp", reschedule_entry, handle_vector_irq_entry); + rv_detach_trace_probe("nrp", call_function_entry, handle_vector_irq_entr= y); + rv_detach_trace_probe("nrp", call_function_single_entry, handle_vector_i= rq_entry); + } +} + +#else +/* We assume irq_entry tracepoints are sufficient on other architectures */ +static void attach_vector_irq(void) { } +static void detach_vector_irq(void) { } +#endif + +static void handle_irq_entry(void *data, int irq, struct irqaction *action) +{ + da_handle_event_nrp(current, irq_entry_nrp); +} + +static void handle_sched_need_resched(void *data, struct task_struct *tsk, + int cpu, int tif) +{ + /* + * Although need_resched leads to both the rescheduling and preempt_irq + * states, it is safer to start the monitor always in preempt_irq, + * which may not mirror the system state but makes the monitor simpler, + */ + if (tif =3D=3D TIF_NEED_RESCHED) + da_handle_start_event_nrp(tsk, sched_need_resched_nrp); +} + +static void handle_schedule_entry(void *data, bool preempt) +{ + if (preempt) + da_handle_event_nrp(current, schedule_entry_preempt_nrp); + else + da_handle_event_nrp(current, schedule_entry_nrp); +} + +static int enable_nrp(void) +{ + int retval; + + retval =3D da_monitor_init_nrp(); + if (retval) + return retval; + + rv_attach_trace_probe("nrp", irq_handler_entry, handle_irq_entry); + rv_attach_trace_probe("nrp", sched_set_need_resched_tp, handle_sched_need= _resched); + rv_attach_trace_probe("nrp", sched_entry_tp, handle_schedule_entry); + attach_vector_irq(); + + return 0; +} + +static void disable_nrp(void) +{ + rv_nrp.enabled =3D 0; + + rv_detach_trace_probe("nrp", irq_handler_entry, handle_irq_entry); + rv_detach_trace_probe("nrp", sched_set_need_resched_tp, handle_sched_need= _resched); + rv_detach_trace_probe("nrp", sched_entry_tp, handle_schedule_entry); + detach_vector_irq(); + + da_monitor_destroy_nrp(); +} + +static struct rv_monitor rv_nrp =3D { + .name =3D "nrp", + .description =3D "need resched preempts.", + .enable =3D enable_nrp, + .disable =3D disable_nrp, + .reset =3D da_monitor_reset_all_nrp, + .enabled =3D 0, +}; + +static int __init register_nrp(void) +{ + return rv_register_monitor(&rv_nrp, &rv_sched); +} + +static void __exit unregister_nrp(void) +{ + rv_unregister_monitor(&rv_nrp); +} + +module_init(register_nrp); +module_exit(unregister_nrp); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gabriele Monaco "); +MODULE_DESCRIPTION("nrp: need resched preempts."); diff --git a/kernel/trace/rv/monitors/nrp/nrp.h b/kernel/trace/rv/monitors/= nrp/nrp.h new file mode 100644 index 000000000000..c9f12207cbf6 --- /dev/null +++ b/kernel/trace/rv/monitors/nrp/nrp.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Automatically generated C representation of nrp automaton + * For further information about this format, see kernel documentation: + * Documentation/trace/rv/deterministic_automata.rst + */ + +enum states_nrp { + preempt_irq_nrp =3D 0, + any_thread_running_nrp, + nested_preempt_nrp, + rescheduling_nrp, + state_max_nrp +}; + +#define INVALID_STATE state_max_nrp + +enum events_nrp { + irq_entry_nrp =3D 0, + sched_need_resched_nrp, + schedule_entry_nrp, + schedule_entry_preempt_nrp, + event_max_nrp +}; + +struct automaton_nrp { + char *state_names[state_max_nrp]; + char *event_names[event_max_nrp]; + unsigned char function[state_max_nrp][event_max_nrp]; + unsigned char initial_state; + bool final_states[state_max_nrp]; +}; + +static const struct automaton_nrp automaton_nrp =3D { + .state_names =3D { + "preempt_irq", + "any_thread_running", + "nested_preempt", + "rescheduling" + }, + .event_names =3D { + "irq_entry", + "sched_need_resched", + "schedule_entry", + "schedule_entry_preempt" + }, + .function =3D { + { + preempt_irq_nrp, + preempt_irq_nrp, + nested_preempt_nrp, + nested_preempt_nrp + }, + { + any_thread_running_nrp, + rescheduling_nrp, + any_thread_running_nrp, + INVALID_STATE + }, + { + nested_preempt_nrp, + preempt_irq_nrp, + any_thread_running_nrp, + any_thread_running_nrp + }, + { + preempt_irq_nrp, + rescheduling_nrp, + any_thread_running_nrp, + any_thread_running_nrp + }, + }, + .initial_state =3D preempt_irq_nrp, + .final_states =3D { 0, 1, 0, 0 }, +}; diff --git a/kernel/trace/rv/monitors/nrp/nrp_trace.h b/kernel/trace/rv/mon= itors/nrp/nrp_trace.h new file mode 100644 index 000000000000..2e13497de3b6 --- /dev/null +++ b/kernel/trace/rv/monitors/nrp/nrp_trace.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_NRP +DEFINE_EVENT(event_da_monitor_id, event_nrp, + 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_nrp, + TP_PROTO(int id, char *state, char *event), + TP_ARGS(id, state, event)); +#endif /* CONFIG_RV_MON_NRP */ diff --git a/kernel/trace/rv/monitors/sched/Kconfig b/kernel/trace/rv/monit= ors/sched/Kconfig index ae3eb410abd7..aa16456da864 100644 --- a/kernel/trace/rv/monitors/sched/Kconfig +++ b/kernel/trace/rv/monitors/sched/Kconfig @@ -2,6 +2,7 @@ # config RV_MON_SCHED depends on RV + depends on RV_PER_TASK_MONITORS >=3D 3 bool "sched monitor" help Collection of monitors to check the scheduler behaves according to spec= ifications. diff --git a/kernel/trace/rv/monitors/sssw/Kconfig b/kernel/trace/rv/monito= rs/sssw/Kconfig new file mode 100644 index 000000000000..23b7eeb38bbf --- /dev/null +++ b/kernel/trace/rv/monitors/sssw/Kconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_SSSW + depends on RV + depends on RV_MON_SCHED + default y + select DA_MON_EVENTS_ID + bool "sssw monitor" + help + Monitor to ensure sched_set_state to sleepable leads to sleeping and + sleeping tasks require wakeup. + 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/sssw/sssw.c b/kernel/trace/rv/monitor= s/sssw/sssw.c new file mode 100644 index 000000000000..84b8d890d9d4 --- /dev/null +++ b/kernel/trace/rv/monitors/sssw/sssw.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "sssw" + +#include +#include +#include +#include + +#include "sssw.h" + +static struct rv_monitor rv_sssw; +DECLARE_DA_MON_PER_TASK(sssw, unsigned char); + +static void handle_sched_set_state(void *data, struct task_struct *tsk, in= t state) +{ + if (state =3D=3D TASK_RUNNING) + da_handle_start_event_sssw(tsk, sched_set_state_runnable_sssw); + else + da_handle_event_sssw(tsk, sched_set_state_sleepable_sssw); +} + +static void handle_sched_switch(void *data, bool preempt, + struct task_struct *prev, + struct task_struct *next, + unsigned int prev_state) +{ + if (preempt) + da_handle_event_sssw(prev, sched_switch_preempt_sssw); + else if (prev_state =3D=3D TASK_RUNNING) + da_handle_event_sssw(prev, sched_switch_yield_sssw); + else if (prev_state =3D=3D TASK_RTLOCK_WAIT) + /* special case of sleeping task with racy conditions */ + da_handle_event_sssw(prev, sched_switch_blocking_sssw); + else + da_handle_event_sssw(prev, sched_switch_suspend_sssw); + da_handle_event_sssw(next, sched_switch_in_sssw); +} + +static void handle_sched_wakeup(void *data, struct task_struct *p) +{ + /* + * Wakeup can also lead to signal_wakeup although the system is + * actually runnable. The monitor can safely start with this event. + */ + da_handle_start_event_sssw(p, sched_wakeup_sssw); +} + +static void handle_signal_deliver(void *data, int sig, + struct kernel_siginfo *info, + struct k_sigaction *ka) +{ + da_handle_event_sssw(current, signal_deliver_sssw); +} + +static int enable_sssw(void) +{ + int retval; + + retval =3D da_monitor_init_sssw(); + if (retval) + return retval; + + rv_attach_trace_probe("sssw", sched_set_state_tp, handle_sched_set_state); + rv_attach_trace_probe("sssw", sched_switch, handle_sched_switch); + rv_attach_trace_probe("sssw", sched_wakeup, handle_sched_wakeup); + rv_attach_trace_probe("sssw", signal_deliver, handle_signal_deliver); + + return 0; +} + +static void disable_sssw(void) +{ + rv_sssw.enabled =3D 0; + + rv_detach_trace_probe("sssw", sched_set_state_tp, handle_sched_set_state); + rv_detach_trace_probe("sssw", sched_switch, handle_sched_switch); + rv_detach_trace_probe("sssw", sched_wakeup, handle_sched_wakeup); + rv_detach_trace_probe("sssw", signal_deliver, handle_signal_deliver); + + da_monitor_destroy_sssw(); +} + +static struct rv_monitor rv_sssw =3D { + .name =3D "sssw", + .description =3D "set state sleep and wakeup.", + .enable =3D enable_sssw, + .disable =3D disable_sssw, + .reset =3D da_monitor_reset_all_sssw, + .enabled =3D 0, +}; + +static int __init register_sssw(void) +{ + return rv_register_monitor(&rv_sssw, &rv_sched); +} + +static void __exit unregister_sssw(void) +{ + rv_unregister_monitor(&rv_sssw); +} + +module_init(register_sssw); +module_exit(unregister_sssw); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gabriele Monaco "); +MODULE_DESCRIPTION("sssw: set state sleep and wakeup."); diff --git a/kernel/trace/rv/monitors/sssw/sssw.h b/kernel/trace/rv/monitor= s/sssw/sssw.h new file mode 100644 index 000000000000..243d54050c94 --- /dev/null +++ b/kernel/trace/rv/monitors/sssw/sssw.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Automatically generated C representation of sssw automaton + * For further information about this format, see kernel documentation: + * Documentation/trace/rv/deterministic_automata.rst + */ + +enum states_sssw { + runnable_sssw =3D 0, + signal_wakeup_sssw, + sleepable_sssw, + sleeping_sssw, + state_max_sssw +}; + +#define INVALID_STATE state_max_sssw + +enum events_sssw { + sched_set_state_runnable_sssw =3D 0, + sched_set_state_sleepable_sssw, + sched_switch_blocking_sssw, + sched_switch_in_sssw, + sched_switch_preempt_sssw, + sched_switch_suspend_sssw, + sched_switch_yield_sssw, + sched_wakeup_sssw, + signal_deliver_sssw, + event_max_sssw +}; + +struct automaton_sssw { + char *state_names[state_max_sssw]; + char *event_names[event_max_sssw]; + unsigned char function[state_max_sssw][event_max_sssw]; + unsigned char initial_state; + bool final_states[state_max_sssw]; +}; + +static const struct automaton_sssw automaton_sssw =3D { + .state_names =3D { + "runnable", + "signal_wakeup", + "sleepable", + "sleeping" + }, + .event_names =3D { + "sched_set_state_runnable", + "sched_set_state_sleepable", + "sched_switch_blocking", + "sched_switch_in", + "sched_switch_preempt", + "sched_switch_suspend", + "sched_switch_yield", + "sched_wakeup", + "signal_deliver" + }, + .function =3D { + { + runnable_sssw, + sleepable_sssw, + sleeping_sssw, + runnable_sssw, + runnable_sssw, + INVALID_STATE, + runnable_sssw, + runnable_sssw, + runnable_sssw + }, + { + INVALID_STATE, + sleepable_sssw, + INVALID_STATE, + signal_wakeup_sssw, + signal_wakeup_sssw, + INVALID_STATE, + signal_wakeup_sssw, + signal_wakeup_sssw, + runnable_sssw + }, + { + runnable_sssw, + sleepable_sssw, + sleeping_sssw, + sleepable_sssw, + sleepable_sssw, + sleeping_sssw, + signal_wakeup_sssw, + runnable_sssw, + sleepable_sssw + }, + { + INVALID_STATE, + INVALID_STATE, + INVALID_STATE, + INVALID_STATE, + INVALID_STATE, + INVALID_STATE, + INVALID_STATE, + runnable_sssw, + INVALID_STATE + }, + }, + .initial_state =3D runnable_sssw, + .final_states =3D { 1, 0, 0, 0 }, +}; diff --git a/kernel/trace/rv/monitors/sssw/sssw_trace.h b/kernel/trace/rv/m= onitors/sssw/sssw_trace.h new file mode 100644 index 000000000000..6c03cfc6960b --- /dev/null +++ b/kernel/trace/rv/monitors/sssw/sssw_trace.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_SSSW +DEFINE_EVENT(event_da_monitor_id, event_sssw, + 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_sssw, + TP_PROTO(int id, char *state, char *event), + TP_ARGS(id, state, event)); +#endif /* CONFIG_RV_MON_SSSW */ diff --git a/kernel/trace/rv/rv_trace.h b/kernel/trace/rv/rv_trace.h index 97b2f7e07f27..e4e78d23b7b0 100644 --- a/kernel/trace/rv/rv_trace.h +++ b/kernel/trace/rv/rv_trace.h @@ -123,6 +123,8 @@ DECLARE_EVENT_CLASS(error_da_monitor_id, =20 #include #include +#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/nrp.dot b/tools/verification/m= odels/sched/nrp.dot new file mode 100644 index 000000000000..77bb64669416 --- /dev/null +++ b/tools/verification/models/sched/nrp.dot @@ -0,0 +1,29 @@ +digraph state_automaton { + center =3D true; + size =3D "7,11"; + {node [shape =3D doublecircle] "any_thread_running"}; + {node [shape =3D circle] "any_thread_running"}; + {node [shape =3D circle] "nested_preempt"}; + {node [shape =3D plaintext, style=3Dinvis, label=3D""] "__init_preempt_ir= q"}; + {node [shape =3D circle] "preempt_irq"}; + {node [shape =3D circle] "rescheduling"}; + "__init_preempt_irq" -> "preempt_irq"; + "any_thread_running" [label =3D "any_thread_running", color =3D green3]; + "any_thread_running" -> "any_thread_running" [ label =3D "schedule_entry\= nirq_entry" ]; + "any_thread_running" -> "rescheduling" [ label =3D "sched_need_resched" ]; + "nested_preempt" [label =3D "nested_preempt"]; + "nested_preempt" -> "any_thread_running" [ label =3D "schedule_entry_pree= mpt\nschedule_entry" ]; + "nested_preempt" -> "nested_preempt" [ label =3D "irq_entry" ]; + "nested_preempt" -> "preempt_irq" [ label =3D "sched_need_resched" ]; + "preempt_irq" [label =3D "preempt_irq"]; + "preempt_irq" -> "nested_preempt" [ label =3D "schedule_entry_preempt\nsc= hedule_entry" ]; + "preempt_irq" -> "preempt_irq" [ label =3D "irq_entry\nsched_need_resched= " ]; + "rescheduling" [label =3D "rescheduling"]; + "rescheduling" -> "any_thread_running" [ label =3D "schedule_entry_preemp= t\nschedule_entry" ]; + "rescheduling" -> "preempt_irq" [ label =3D "irq_entry" ]; + "rescheduling" -> "rescheduling" [ label =3D "sched_need_resched" ]; + { rank =3D min ; + "__init_preempt_irq"; + "preempt_irq"; + } +} diff --git a/tools/verification/models/sched/sssw.dot b/tools/verification/= models/sched/sssw.dot new file mode 100644 index 000000000000..4994c3e876be --- /dev/null +++ b/tools/verification/models/sched/sssw.dot @@ -0,0 +1,30 @@ +digraph state_automaton { + center =3D true; + size =3D "7,11"; + {node [shape =3D plaintext, style=3Dinvis, label=3D""] "__init_runnable"}; + {node [shape =3D doublecircle] "runnable"}; + {node [shape =3D circle] "runnable"}; + {node [shape =3D circle] "signal_wakeup"}; + {node [shape =3D circle] "sleepable"}; + {node [shape =3D circle] "sleeping"}; + "__init_runnable" -> "runnable"; + "runnable" [label =3D "runnable", color =3D green3]; + "runnable" -> "runnable" [ label =3D "sched_set_state_runnable\nsched_wak= eup\nsched_switch_in\nsched_switch_yield\nsched_switch_preempt\nsignal_deli= ver" ]; + "runnable" -> "sleepable" [ label =3D "sched_set_state_sleepable" ]; + "runnable" -> "sleeping" [ label =3D "sched_switch_blocking" ]; + "signal_wakeup" [label =3D "signal_wakeup"]; + "signal_wakeup" -> "runnable" [ label =3D "signal_deliver" ]; + "signal_wakeup" -> "signal_wakeup" [ label =3D "sched_switch_in\nsched_sw= itch_preempt\nsched_switch_yield\nsched_wakeup" ]; + "signal_wakeup" -> "sleepable" [ label =3D "sched_set_state_sleepable" ]; + "sleepable" [label =3D "sleepable"]; + "sleepable" -> "runnable" [ label =3D "sched_set_state_runnable\nsched_wa= keup" ]; + "sleepable" -> "signal_wakeup" [ label =3D "sched_switch_yield" ]; + "sleepable" -> "sleepable" [ label =3D "sched_set_state_sleepable\nsched_= switch_in\nsched_switch_preempt\nsignal_deliver" ]; + "sleepable" -> "sleeping" [ label =3D "sched_switch_suspend\nsched_switch= _blocking" ]; + "sleeping" [label =3D "sleeping"]; + "sleeping" -> "runnable" [ label =3D "sched_wakeup" ]; + { rank =3D min ; + "__init_runnable"; + "runnable"; + } +} --=20 2.47.2 From nobody Sun Oct 5 23:40:18 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 2E79E233701 for ; Mon, 28 Jul 2025 20:49:47 +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=1753735787; cv=none; b=DAiQFz8gvw5LjyjrflU8MOcCe9N7v6HtMd8o7NSmwYFXTKZ0MHMgLL87K435HGubb4us2qDKce8P8WkMjLlfko0EesakSCXu6QYBV0ykqui0/6ZpH7dgDbKYQWp+3SEOax9v9+6E5YWSdr4wdvVnjoZUcBZFOv4gFQ8zokWymFM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753735787; c=relaxed/simple; bh=PdwENEoZ0HROQdM2uLsLhAg1Be9dF1miS6bYuTmdK+Q=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=IWjvUd6gC1j9E16DakRiHyqYc7VjCrsIIwq4Zr95X7p3bnzqHAmuaNKa1g95MWENFuCNCEaL0xA2O+i7dkaYGqCj8+remCfOk9crdXFBgGH3/Y52ssiVtctveQE9pcILwGQ0I14IBUEpcosT/e6o4FmaElg4OGAyRONlXPAuZoQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WPgj7DtC; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WPgj7DtC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DB7FCC4CEF9; Mon, 28 Jul 2025 20:49:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753735787; bh=PdwENEoZ0HROQdM2uLsLhAg1Be9dF1miS6bYuTmdK+Q=; h=Date:From:To:Cc:Subject:References:From; b=WPgj7DtCe3fxIl7dAIwZwlQnUkuFOfZCnSn7SUt0QWlU1vlnMRDl0QGX6YkJqxM+C VNn0EG2z74srgPRq5EyXy1cmGWJTe03S6Or1QorND7tRSoKxLqsh78AnFdKGjW72OE CAGeB0ziFNLk5qFXBJecbJYQ2vZDNEkIzC61+8cWNoPmGbRY73Lv9rlIqzXrsYoIoI URS+YouaLbVQkNxlBGstFqrDXhYXxiuI3Ngr1OkS9aynOr0KbcSvx6o1ymkloiZIkC 6r2ipVXyGU7zwq+0GCaajzPV3RreVPURiZeykQUuOlRcPs/3l39EEj2EWb7xlVM+js aA4PGOJVt2UJA== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1ugUnH-000000042zI-38SI; Mon, 28 Jul 2025 16:49:59 -0400 Message-ID: <20250728204959.600249463@kernel.org> User-Agent: quilt/0.68 Date: Mon, 28 Jul 2025 16:49:45 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Jonathan Corbet , Masami Hiramatsu , Ingo Molnar , Peter Zijlstra , Juri Lelli , Clark Williams , Gabriele Monaco , Nam Cao Subject: [for-next][PATCH 11/11] rv: Add opid per-cpu monitor References: <20250728204934.281385756@kernel.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-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. Cc: Jonathan Corbet Cc: Masami Hiramatsu Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Tomas Glozar Cc: Juri Lelli Cc: Clark Williams Cc: John Kacur Link: https://lore.kernel.org/20250728135022.255578-10-gmonaco@redhat.com Signed-off-by: Gabriele Monaco Acked-by: Nam Cao Tested-by: Nam Cao Signed-off-by: Steven Rostedt (Google) --- Documentation/trace/rv/monitor_sched.rst | 55 +++++++ kernel/trace/rv/Kconfig | 1 + kernel/trace/rv/Makefile | 1 + kernel/trace/rv/monitors/opid/Kconfig | 19 +++ kernel/trace/rv/monitors/opid/opid.c | 168 +++++++++++++++++++++ kernel/trace/rv/monitors/opid/opid.h | 104 +++++++++++++ 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, 399 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 11ef963cb578..3f8381ad9ec7 100644 --- a/Documentation/trace/rv/monitor_sched.rst +++ b/Documentation/trace/rv/monitor_sched.rst @@ -341,6 +341,61 @@ can be triggered also by preemption, but cannot occur = after the task got to | | switch_yield +-----------+ 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 interrupt context, in such case preemption m= ay +not be disabled 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 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 | -+ | + +------------------+ | + | | + +-------------------------------------------------------+ + +This monitor is designed to work on ``PREEMPT_RT`` kernels, the special ca= se of +events occurring in interrupt context is a shortcut to identify valid scen= arios +where the preemption tracepoints might not be visible, during interrupts +preemption is always disabled. On non- ``PREEMPT_RT`` kernels, the interru= pts +might invoke a softirq to set ``need_resched`` and wake up a task. This is +another special case that is currently not supported by the monitor. + References ---------- =20 diff --git a/kernel/trace/rv/Kconfig b/kernel/trace/rv/Kconfig index 59d0db898d4a..5b4be87ba59d 100644 --- a/kernel/trace/rv/Kconfig +++ b/kernel/trace/rv/Kconfig @@ -57,6 +57,7 @@ source "kernel/trace/rv/monitors/snep/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 sched monitors here =20 source "kernel/trace/rv/monitors/rtapp/Kconfig" diff --git a/kernel/trace/rv/Makefile b/kernel/trace/rv/Makefile index 2afac88539d3..750e4ad6fa0f 100644 --- a/kernel/trace/rv/Makefile +++ b/kernel/trace/rv/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_RV_MON_SLEEP) +=3D monitors/sleep/sleep.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..561d32da572b --- /dev/null +++ b/kernel/trace/rv/monitors/opid/Kconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_OPID + depends on RV + depends on TRACE_IRQFLAGS + depends on TRACE_PREEMPT_TOGGLE + depends on RV_MON_SCHED + default y if PREEMPT_RT + 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. + + This monitor is unstable on !PREEMPT_RT, say N unless you are testing i= t. + + 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..50d64e7fb8c4 --- /dev/null +++ b/kernel/trace/rv/monitors/opid/opid.c @@ -0,0 +1,168 @@ +// 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); + if (IS_ENABLED(CONFIG_IRQ_WORK)) + rv_attach_trace_probe("opid", irq_work_entry, handle_vector_irq_entry); + if (IS_ENABLED(CONFIG_SMP)) { + rv_attach_trace_probe("opid", reschedule_entry, handle_vector_irq_entry); + rv_attach_trace_probe("opid", call_function_entry, handle_vector_irq_ent= ry); + rv_attach_trace_probe("opid", call_function_single_entry, handle_vector_= irq_entry); + } +} + +static void detach_vector_irq(void) +{ + rv_detach_trace_probe("opid", local_timer_entry, handle_vector_irq_entry); + if (IS_ENABLED(CONFIG_IRQ_WORK)) + rv_detach_trace_probe("opid", irq_work_entry, handle_vector_irq_entry); + if (IS_ENABLED(CONFIG_SMP)) { + rv_detach_trace_probe("opid", reschedule_entry, handle_vector_irq_entry); + rv_detach_trace_probe("opid", call_function_entry, handle_vector_irq_ent= ry); + rv_detach_trace_probe("opid", call_function_single_entry, handle_vector_= irq_entry); + } +} + +#else +/* We assume irq_entry tracepoints are sufficient on other architectures */ +static void attach_vector_irq(void) { } +static void detach_vector_irq(void) { } +#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) +{ + /* The monitor's intitial state is not in_irq */ + if (this_cpu_read(hardirq_context)) + 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) +{ + /* The monitor's intitial state is not in_irq */ + if (this_cpu_read(hardirq_context)) + 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) +{ + return rv_register_monitor(&rv_opid, &rv_sched); +} + +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..b4b8c2ff7f64 --- /dev/null +++ b/kernel/trace/rv/monitors/opid/opid.h @@ -0,0 +1,104 @@ +/* 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, + preempt_disabled_opid, + enabled_opid, + INVALID_STATE, + INVALID_STATE + }, + { + INVALID_STATE, + enabled_opid, + in_irq_opid, + 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 e4e78d23b7b0..4a6faddac614 100644 --- a/kernel/trace/rv/rv_trace.h +++ b/kernel/trace/rv/rv_trace.h @@ -62,6 +62,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..840052f6952b --- /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\nirq_e= ntry" ]; + "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.47.2