From nobody Fri Jun 12 13:56:05 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C9B352737FC for ; Thu, 14 May 2026 15:21:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772083; cv=none; b=Cqt14uVr4175hDc/Dzg9Vj8k+ruiuTxqa7/DNFP8s4G6F1c2utkN9zuwrfZhfQTXakt4Xe7PoQeyvneDX0Gfxwnb2ufS2MNbktwJK65BTECg1EdgNatBvt+PB7cyq3L5uaLs5dPkdonwzBWJ/aZwTMVs7Y9Wz5cj/D87skTq/9E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772083; c=relaxed/simple; bh=s8nFJ+2JWsR835hCjxv/sjajTJVR5mTrLIXZa6+KMFo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nyGSjxXUzfkx3C/KhO/yET47Iq/69sB2wKoNVLmg/lEfZL3d5MzfTeLB/8z0rC9nO2wduLDLC1RzkQGOGYJ1pYfeDlp9wGCcyIooEx7nrIRH5pZIa1L9mEFLyhIekbqdO/FPgh9hbt3498N3KB1RyGorZuoUqGkt6/5lj6aJdWg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=DttLUqr1; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="DttLUqr1" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778772081; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hoIyt76b7jqnRvNU6b8a3WX34nlOmKB7uW+1jd9CVSs=; b=DttLUqr1q4wEV45ykimvEB9X+o5Xm2cvnFd3yMj1j0G4GmftvQDBH9X7yo1r/NpuM/KdKf dxd6EC1bWcolUtEEP3L0FF9Y2cVtZuTj6vgi6t1Z7Op9yATM/0h2qi5vzhB45sSsEOb303 NHs9L4tbFTMRxaGHuC2xW0ZkAheEwKo= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-113-AyK_rq60PeS6y1Cb_swzog-1; Thu, 14 May 2026 11:21:18 -0400 X-MC-Unique: AyK_rq60PeS6y1Cb_swzog-1 X-Mimecast-MFC-AGG-ID: AyK_rq60PeS6y1Cb_swzog_1778772077 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 62C431800372; Thu, 14 May 2026 15:21:17 +0000 (UTC) Received: from gmonaco-thinkpadt14gen3.rmtit.csb (unknown [10.44.48.32]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 53FF230001A2; Thu, 14 May 2026 15:21:14 +0000 (UTC) From: Gabriele Monaco To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Steven Rostedt , Gabriele Monaco Cc: Nam Cao , Thomas Weissschuh , Tomas Glozar , John Kacur , Wen Yang Subject: [PATCH v2 01/14] tools/rv: Fix substring match bug in monitor name search Date: Thu, 14 May 2026 17:20:42 +0200 Message-ID: <20260514152055.229162-2-gmonaco@redhat.com> In-Reply-To: <20260514152055.229162-1-gmonaco@redhat.com> References: <20260514152055.229162-1-gmonaco@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" __ikm_find_monitor_name() relies on strstr() to find a monitor by name, which fails if the target monitor is a substring of a previously listed monitor. Fix it by tokenizing the available_monitors file and matching full tokens instead. Signed-off-by: Gabriele Monaco Reviewed-by: Nam Cao --- tools/verification/rv/src/in_kernel.c | 48 ++++++++++++++------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/tools/verification/rv/src/in_kernel.c b/tools/verification/rv/= src/in_kernel.c index 4bb746ea6e17..a200b63f4509 100644 --- a/tools/verification/rv/src/in_kernel.c +++ b/tools/verification/rv/src/in_kernel.c @@ -58,38 +58,40 @@ static int __ikm_read_enable(char *monitor_name) */ static int __ikm_find_monitor_name(char *monitor_name, char *out_name) { - char *available_monitors, container[MAX_DA_NAME_LEN+1], *cursor, *end; - int retval =3D 1; + char *available_monitors, *cursor, *line; + int len =3D strlen(monitor_name); + int found =3D 0; =20 available_monitors =3D tracefs_instance_file_read(NULL, "rv/available_mon= itors", NULL); if (!available_monitors) return -1; =20 - cursor =3D strstr(available_monitors, monitor_name); - if (!cursor) { - retval =3D 0; - goto out_free; - } + config_is_container =3D 0; + cursor =3D available_monitors; + while ((line =3D strsep(&cursor, "\n"))) { + char *colon =3D strchr(line, ':'); =20 - for (; cursor > available_monitors; cursor--) - if (*(cursor-1) =3D=3D '\n') - break; - end =3D strstr(cursor, "\n"); - memcpy(out_name, cursor, end-cursor); - out_name[end-cursor] =3D '\0'; - - cursor =3D strstr(out_name, ":"); - if (cursor) - *cursor =3D '/'; - else { - sprintf(container, "%s:", monitor_name); - if (strstr(available_monitors, container)) - config_is_container =3D 1; + if (strcmp(line, monitor_name) && (!colon || strcmp(colon + 1, monitor_n= ame))) + continue; + + strncpy(out_name, line, 2 * MAX_DA_NAME_LEN); + out_name[2 * MAX_DA_NAME_LEN - 1] =3D '\0'; + + if (colon) { + out_name[colon - line] =3D '/'; + } else { + /* If there are children, they are on the next line. */ + line =3D strsep(&cursor, "\n"); + if (line && !strncmp(line, monitor_name, len) && line[len] =3D=3D ':') + config_is_container =3D 1; + } + + found =3D 1; + break; } =20 -out_free: free(available_monitors); - return retval; + return found; } =20 /* --=20 2.54.0 From nobody Fri Jun 12 13:56:05 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6FF3E3016E3 for ; Thu, 14 May 2026 15:21:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772088; cv=none; b=G6xYpCqivSyurFRpxYbjv6I5m7TCEhahwZVDBipX6Q3Nr1jTLZUkcGZ3r9CQtSLrVawn4OoDT1Ll721mxUdu8dx5PESFN0hXDzAmmg6/yIcx5PsScs11+Gc4huJQP4LcBVzgij30DBNoMoNXL1ns5+eN3ZVro3qdRakAl8xDWIg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772088; c=relaxed/simple; bh=E+DSAUBgHEQsfyxM6Knh3+4qtmmADUuWkGc6CuPvfUI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=soYepQ/vvoabzUlmsEKDzTuwlYvUFx8wrBdc43PNWK5hZlPKsWVhRabkxIPoINddRl43T1U+5swZKEuk8a7tD92bbG0Zb5ESJP03kR99Ef97lg+KC0IuyKTN6C8Pv4/Wmj/OvAqykSW9RkbkHUu80X93uVb/10trHrFyBodPQZk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=OPSnLKe+; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="OPSnLKe+" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778772086; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vd1fF6aAyPNOBNzcj+Y3eMBsL+QM4FlzHARfaZk0mQE=; b=OPSnLKe+owvAcLBhDMuL5FLUcL5efczNmZFPfgMQGDJ8Ci4+ey+59hfuJZ0Kg98zqzw5nX 451dnUDeZA3AaQNumGR2TBBQ1aYWWGoSc5fWWo2P7ghdl7Io7/qu+LMS3++XKOmDU89kp6 FrQW29Y9sXeD2tLzksbDTnLXr2LIlFs= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-670-RIula7KAOriklGyC7KJDAQ-1; Thu, 14 May 2026 11:21:23 -0400 X-MC-Unique: RIula7KAOriklGyC7KJDAQ-1 X-Mimecast-MFC-AGG-ID: RIula7KAOriklGyC7KJDAQ_1778772081 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 895A61956089; Thu, 14 May 2026 15:21:21 +0000 (UTC) Received: from gmonaco-thinkpadt14gen3.rmtit.csb (unknown [10.44.48.32]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 51D7C30001A2; Thu, 14 May 2026 15:21:18 +0000 (UTC) From: Gabriele Monaco To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Steven Rostedt , Gabriele Monaco Cc: Nam Cao , Thomas Weissschuh , Tomas Glozar , John Kacur , Wen Yang Subject: [PATCH v2 02/14] tools/rv: Fix substring match when listing container monitors Date: Thu, 14 May 2026 17:20:43 +0200 Message-ID: <20260514152055.229162-3-gmonaco@redhat.com> In-Reply-To: <20260514152055.229162-1-gmonaco@redhat.com> References: <20260514152055.229162-1-gmonaco@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" When listing monitors within a specific container (rv list ), the tool incorrectly matched monitors if the requested container name was only a prefix of the actual container (e.g., 'rv list sche' would incorrectly list monitors from 'sched:'). Fix this by ensuring the container name is an exact match and is immediately followed by the ':' separator. Signed-off-by: Gabriele Monaco Reviewed-by: Nam Cao --- tools/verification/rv/src/in_kernel.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/verification/rv/src/in_kernel.c b/tools/verification/rv/= src/in_kernel.c index a200b63f4509..95adae321c11 100644 --- a/tools/verification/rv/src/in_kernel.c +++ b/tools/verification/rv/src/in_kernel.c @@ -193,8 +193,12 @@ static int ikm_fill_monitor_definition(char *name, str= uct monitor *ikm, char *co nested_name =3D strstr(name, ":"); if (nested_name) { /* it belongs in container if it starts with "container:" */ - if (container && strstr(name, container) !=3D name) - return 1; + if (container) { + int len =3D strlen(container); + + if (strncmp(name, container, len) || name[len] !=3D ':') + return 1; + } *nested_name =3D '/'; ++nested_name; ikm->nested =3D 1; --=20 2.54.0 From nobody Fri Jun 12 13:56:05 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 709C1311968 for ; Thu, 14 May 2026 15:21:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772093; cv=none; b=cr0fvBe1wULf+3Kdchi6rqipCm2zGVuDlVnA+6Um+Mo0Kdtd4srgCtxjeTVoXQ87WA43GsMtzWc6UyWySFTBrCz62N3khhl62noWeRvmQm2RhDRD0rIVHZs/94cgZlRAXJqO4B0rX+uScJdSk/eAFfbOIZEg5FzXS8HvhyewUl4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772093; c=relaxed/simple; bh=xlWOjX0aHeizYtQTWJbs4ac9HzSAz6/MExRXYVfRgBM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VXMvpPyaGmvgZ6eIR6srwXvMzaJYKyv++a5Xo9kXGyaJYVw1AJ0YgmccXy71fEJOrtSPKjpRvVgLLHX5rxR2wC6+zCG2xUXD1XUbDE15qjSKYvi9ex+mczfda1JlNNESB4pLoCeOkolSQyd6S3O/lLWjGqZsrOh5ReZfV5T0SZw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=D54w2wN+; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="D54w2wN+" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778772091; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0pd0Ym91wNaAacYPIZyKvEsUJqDPL6I4ObunAePv9rc=; b=D54w2wN+Ddi/JP3g0mY4kisQdkT0BypbN14IrobIcPT1QOPZDpxIfol/5TFH8+8teDtX3S kL6CtsgmI08FmUmnF8dm0K2aZ5x7zghO+YDSy5MDIquEh0RKQFjoKw8xueDiljtQWdiDuh ANK3QPPTbeYkJz9HGOhRXIahTFBEJTo= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-205-RH8v-XwrMxSpTSoXZMjW0Q-1; Thu, 14 May 2026 11:21:27 -0400 X-MC-Unique: RH8v-XwrMxSpTSoXZMjW0Q-1 X-Mimecast-MFC-AGG-ID: RH8v-XwrMxSpTSoXZMjW0Q_1778772086 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D4E5D19560B4; Thu, 14 May 2026 15:21:25 +0000 (UTC) Received: from gmonaco-thinkpadt14gen3.rmtit.csb (unknown [10.44.48.32]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 971C830001A2; Thu, 14 May 2026 15:21:22 +0000 (UTC) From: Gabriele Monaco To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Steven Rostedt , Gabriele Monaco Cc: Nam Cao , Thomas Weissschuh , Tomas Glozar , John Kacur , Wen Yang Subject: [PATCH v2 03/14] tools/rv: Fix exit status when monitor execution fails Date: Thu, 14 May 2026 17:20:44 +0200 Message-ID: <20260514152055.229162-4-gmonaco@redhat.com> In-Reply-To: <20260514152055.229162-1-gmonaco@redhat.com> References: <20260514152055.229162-1-gmonaco@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" When running "rv mon" on a monitor that is already enabled, the tool fails to start but incorrectly exits with a success status (0). Fix the exit condition to ensure it returns a failure code on any execution error. Signed-off-by: Gabriele Monaco Reviewed-by: Nam Cao --- tools/verification/rv/src/rv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/verification/rv/src/rv.c b/tools/verification/rv/src/rv.c index b8fe24a87d97..6d65f4037581 100644 --- a/tools/verification/rv/src/rv.c +++ b/tools/verification/rv/src/rv.c @@ -127,7 +127,7 @@ static void rv_mon(int argc, char **argv) =20 if (!run) err_msg("rv: monitor %s does not exist\n", monitor_name); - exit(!run); + exit(run <=3D 0); } =20 static void usage(int exit_val, const char *fmt, ...) --=20 2.54.0 From nobody Fri Jun 12 13:56:05 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 18D78423A81 for ; Thu, 14 May 2026 15:21:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772097; cv=none; b=r4VJpkbrcW4UTjKrISDAs6D1k35Eb8UV+kq/LSS1cFElEJZnElPu8u9qvWmS5y4oPR4xQiHs0NuV8QA38L4yLSNE4NgMoL+auvPW075baiAHU/CkC39bwmUYDSWXKaQvv47dW8V7i9pkQmXfkuBYavmLQ+9HeM698F/6YJJ3IKk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772097; c=relaxed/simple; bh=DjEBjyCMRzL53cgYQ3iYI0MjtVctDAlByOGTPZPrsEk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ry894B1A+1pxYpRG42rSqbttgkRLKP13FyoXRvWpTojqSsfXT/u64Pgvz92FBOiIwc9yIyIoXylbEvqlqwt33DFoLVfe6Va0XdBeQ/jw6JE/x+U/wJeKjkIudblLdt13OlYlMe9thnm8BdZJJPlCvAeRHgZYS9sJms9KEXkCuac= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=dZ0kU+7A; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="dZ0kU+7A" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778772094; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MUv6oVqF8gdTbH+ZaqH3yLjz7+6Xw90KPRafZ0fhMDg=; b=dZ0kU+7AEtn2hRJUCsJ8buKBKQ6BUzKHxtbtKoEFqduRq7WiH1tIbQ9JQk0RmI/2VYJE6/ lyIfq2x8mGD/pvRvQVs6m7zVjnUM9rEiIHDWuYzuaj1yfJVo1RX5E8xgt4rrPa4+twEUB+ +8yp7geyGcurQ8Y1Bn3sOgdMbOTAE68= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-553-tBLpXCzsPIuA5qkzeROTaA-1; Thu, 14 May 2026 11:21:31 -0400 X-MC-Unique: tBLpXCzsPIuA5qkzeROTaA-1 X-Mimecast-MFC-AGG-ID: tBLpXCzsPIuA5qkzeROTaA_1778772090 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id DE7B01800359; Thu, 14 May 2026 15:21:29 +0000 (UTC) Received: from gmonaco-thinkpadt14gen3.rmtit.csb (unknown [10.44.48.32]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id CB7E430001A2; Thu, 14 May 2026 15:21:26 +0000 (UTC) From: Gabriele Monaco To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Steven Rostedt , Gabriele Monaco Cc: Nam Cao , Thomas Weissschuh , Tomas Glozar , John Kacur , Wen Yang Subject: [PATCH v2 04/14] tools/rv: Fix cleanup after failed trace setup Date: Thu, 14 May 2026 17:20:45 +0200 Message-ID: <20260514152055.229162-5-gmonaco@redhat.com> In-Reply-To: <20260514152055.229162-1-gmonaco@redhat.com> References: <20260514152055.229162-1-gmonaco@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Currently if ikm_setup_trace_instance() fails, the tool returns without any cleanup, if rv was called with both -t and -r, this means the reactor is not going to be cleared. Jump to the cleanup label to restore the reactor if necessary. Signed-off-by: Gabriele Monaco Reviewed-by: Nam Cao --- tools/verification/rv/src/in_kernel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/verification/rv/src/in_kernel.c b/tools/verification/rv/= src/in_kernel.c index 95adae321c11..131a6787d639 100644 --- a/tools/verification/rv/src/in_kernel.c +++ b/tools/verification/rv/src/in_kernel.c @@ -809,7 +809,7 @@ int ikm_run_monitor(char *monitor_name, int argc, char = **argv) if (config_trace) { inst =3D ikm_setup_trace_instance(nested_name); if (!inst) - return -1; + goto out_free_instance; } =20 retval =3D ikm_enable(full_name); --=20 2.54.0 From nobody Fri Jun 12 13:56:05 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0F5C03FB05B for ; Thu, 14 May 2026 15:21:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772102; cv=none; b=gRHYqagA7Z1SI7nXtTwWAGxAEL1GpEh26TvWI1qNJ6qjrJAZoK1cz3Lzie/rwWgaSRjKIXvoRqzxgzKkHjh1tU2GHsVKQ9CY4USdaY2JmlUPD95jOVRw7wOxrp9VlQcxb1HrWfOL2FKhTkKT/L/F2GEyKE38yTcOreGtjfLF3AM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772102; c=relaxed/simple; bh=HIwTNmHr/mUUzeONwyUfSj5lTrhJX2vZdPSYaXJOegs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Szz/iIC6AwWKF3dcb70z7VPMW0HZP6l7Snxn1zMkuF7tlZQ76DXWk4YbSbnU2uAIUr/CCthxyonO98ZRIMM1gSX1OmB4laF2g4CGuB6cobKZt9KrtWkpM6k1+2GmGBUHtMaXyQjg0Vy/6L74JhjZ6WNlj+Xqe76p45OHFWdv4Ss= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=WYlADQ30; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="WYlADQ30" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778772100; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6q6wHBeLTOKd0n0LfaPwnZR6rAtjkqjt6Rg6aPkjJvo=; b=WYlADQ30uwMmsItyuWgEc2uUkffU5GSQGGhAQBVaS+olSz97mQ+EKsF2m1zNp4vchqpDjf d5IUybcGd56Fv2tipBNOOOm570lNCNkcbCB+4uW3eKr4xe8Z43wwjm7QmDNDkjCFEvRYMS tGFUffbGm192mOD3ZL3H4+nCIapRjXU= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-624-jPanFLOYMomjInosgAbTfA-1; Thu, 14 May 2026 11:21:37 -0400 X-MC-Unique: jPanFLOYMomjInosgAbTfA-1 X-Mimecast-MFC-AGG-ID: jPanFLOYMomjInosgAbTfA_1778772094 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 868B6195609E; Thu, 14 May 2026 15:21:34 +0000 (UTC) Received: from gmonaco-thinkpadt14gen3.rmtit.csb (unknown [10.44.48.32]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 6B93230002DA; Thu, 14 May 2026 15:21:31 +0000 (UTC) From: Gabriele Monaco To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Steven Rostedt , Gabriele Monaco Cc: Nam Cao , Thomas Weissschuh , Tomas Glozar , John Kacur , Wen Yang Subject: [PATCH v2 05/14] tools/rv: Add selftests Date: Thu, 14 May 2026 17:20:46 +0200 Message-ID: <20260514152055.229162-6-gmonaco@redhat.com> In-Reply-To: <20260514152055.229162-1-gmonaco@redhat.com> References: <20260514152055.229162-1-gmonaco@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" The rv tool needs automated testing to catch regressions and verify correct functionality across different usage scenarios. Add selftests that validate monitor listing (including containers and nested monitors), monitor execution with different configurations (reactors, verbose output, tracing), and trace output format for both per-task and per-cpu monitors. Error handling paths are also tested. Tests use a shared engine for common patterns. Signed-off-by: Gabriele Monaco Acked-by: Nam Cao --- tools/verification/rv/Makefile | 5 +- tools/verification/rv/tests/rv_list.t | 48 ++++++++++ tools/verification/rv/tests/rv_mon.t | 95 ++++++++++++++++++ tools/verification/tests/engine.sh | 132 ++++++++++++++++++++++++++ 4 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 tools/verification/rv/tests/rv_list.t create mode 100644 tools/verification/rv/tests/rv_mon.t create mode 100644 tools/verification/tests/engine.sh diff --git a/tools/verification/rv/Makefile b/tools/verification/rv/Makefile index 5b898360ba48..8ae5fc0d1d17 100644 --- a/tools/verification/rv/Makefile +++ b/tools/verification/rv/Makefile @@ -78,4 +78,7 @@ clean: doc_clean fixdep-clean $(Q)rm -f rv rv-static fixdep FEATURE-DUMP rv-* $(Q)rm -rf feature =20 -.PHONY: FORCE clean +check: $(RV) + RV=3D$(RV) prove -o --directives -f tests/ + +.PHONY: FORCE clean check diff --git a/tools/verification/rv/tests/rv_list.t b/tools/verification/rv/= tests/rv_list.t new file mode 100644 index 000000000000..201af33a52cc --- /dev/null +++ b/tools/verification/rv/tests/rv_list.t @@ -0,0 +1,48 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +source ../tests/engine.sh +test_begin + +set_timeout 30s + +RVDIR=3D/sys/kernel/tracing/rv/ + +# Help and basic tests +check "verify help page" \ + "$RV --help" 0 "usage: rv command" + +check "verify list subcommand help" \ + "$RV list --help" 0 "list all available monitors" + +all_nested=3D$(grep : $RVDIR/available_monitors | cut -d: -f2 | paste -s |= sed 's/\t/\\|/g') +all_non_nested=3D$(grep -v : $RVDIR/available_monitors | cut -d: -f2 | pas= te -s | sed 's/\t/\\|/g') +sched_monitors=3D$(grep sched: $RVDIR/available_monitors | cut -d: -f2 | p= aste -s | sed 's/\t/\\|/g') +description_state=3D"[[:space:]]\+[[:print:]]\+\[\(OFF\|ON\)\]" +line_nested=3D" - \($all_nested\)${description_state}" +line_non_nested=3D"\($all_non_nested\)${description_state}" + +# List monitors and containers +check "list all monitors" \ + "$RV list" 0 "" "" "^\($line_nested\|$line_non_nested\)$" + +check_if_exists "list container" \ + "$RV list sched" "$RVDIR/monitors/sched" \ + "" "-- No monitor found in container sched --" \ + "^\($sched_monitors\)${description_state}$" + +check_if_exists "list non-container" \ + "$RV list wwnr" "$RVDIR/monitors/wwnr" \ + "-- No monitor found in container wwnr --" \ + "^\( - \)\?[[:alnum:]]\+${description_state}$" + +check "list incomplete container name" \ + "$RV list s" 0 "-- No monitor found in container s --" + +# Error handling tests +check "no command" \ + "$RV" 1 "rv requires a command" + +check "invalid command" \ + "$RV invalid" 1 "rv does not know the invalid command" + +test_end diff --git a/tools/verification/rv/tests/rv_mon.t b/tools/verification/rv/t= ests/rv_mon.t new file mode 100644 index 000000000000..cbc346c74c71 --- /dev/null +++ b/tools/verification/rv/tests/rv_mon.t @@ -0,0 +1,95 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +source ../tests/engine.sh +test_begin + +set_timeout 30s + +RVDIR=3D/sys/kernel/tracing/rv/ + +# Help and basic tests +check "verify mon subcommand help" \ + "$RV mon --help" 0 "run a monitor" + +# Error handling tests +check "mon without monitor name" \ + "$RV mon" 1 "usage: rv mon" + +check "invalid monitor name" \ + "$RV mon invalid" 1 "monitor invalid does not exist" + +if [ -d $RVDIR/monitors/wwnr ]; then + +check "invalid reactor name" \ + "$RV mon wwnr -r invalid" 1 "failed to set invalid reactor, is it availab= le?" + +check "monitor name is substring of another monitor" \ + "$RV mon nr" 1 "monitor nr does not exist" + +check "already enabled monitor returns error" \ + "echo 1 > $RVDIR/monitors/wwnr/enable; $RV mon wwnr" 1 \ + "monitor wwnr (in-kernel) is already enabled" +echo 0 > $RVDIR/monitors/wwnr/enable + +fi + +# rv mon runs until terminated +set_expected_timeout 2s + +# Run monitors with different configurations +check_if_exists "run the monitor without parameters" \ + "$RV mon wwnr" "$RVDIR/monitors/wwnr" "" "." + +check_if_exists "run the monitor as verbose" \ + "$RV mon wwnr -v" "$RVDIR/monitors/wwnr" \ + "my pid is \$pid" "\(event\|error\)" + +check_if_exists "run the monitor with a reactor" \ + "$RV mon wwnr -r printk & sleep .5 && cat $RVDIR/monitors/wwnr/reactors &= & wait" \ + "$RVDIR/monitors/wwnr/reactors" "\[printk\]" + +check_if_exists "reactor is restored after exit" \ + "cat $RVDIR/monitors/wwnr/reactors" \ + "$RVDIR/monitors/wwnr/reactors" "\[nop\]" + +check_if_exists "run a nested monitor with a reactor" \ + "$RV mon snroc -r printk & sleep .5 && cat $RVDIR/monitors/sched/snroc/re= actors && wait" \ + "$RVDIR/monitors/sched/snroc/reactors" "\[printk\]" + +check_if_exists "run an explicitly nested monitor with a reactor" \ + "$RV mon sched:sssw -r printk & sleep .5 && cat $RVDIR/monitors/sched/sss= w/reactors && wait" \ + "$RVDIR/monitors/sched/sssw/reactors" "\[printk\]" + +check_if_exists "run container monitor" \ + "$RV mon sched & sleep .5 && cat $RVDIR/monitors/sched/{sssw,sco}/enable = && wait" \ + "$RVDIR/monitors/sched" "1" "0" "^1$" + +# Regexes for the trace +header=3D"^[[:space:]]\+\(\([][A-Z_x<>-]\+\||\)[[:space:]]*\)\+$" +type=3D"\(event\|error\)[[:space:]]\+" +genpid=3D"[0-9]\+[[:space:]]\+" +selfpid=3D"\$pid[[:space:]]\+" +cpu=3D"\[[0-9]\{3\}\][[:space:]]\+" +state=3D"[a-z_]\+ " +trace_task=3D"${genpid}${cpu}${type}${genpid}${state}" +trace_task_self=3D"${genpid}${cpu}${type}${selfpid}${state}" +trace_cpu=3D"${genpid}${cpu}${type}${state}" +trace_cpu_self=3D"${selfpid}${cpu}${type}${state}" + +check_if_exists "run per-task monitor with tracing" \ + "$RV mon sssw -t" "$RVDIR/monitors/sched/sssw" \ + "$header" "$trace_task_self" "\($header\|$trace_task\)" + +check_if_exists "run per-task monitor tracing also self" \ + "$RV mon sched:sssw -t -s" "$RVDIR/monitors/sched/sssw" \ + "$trace_task_self" "" "\($header\|$trace_task\)" + +check_if_exists "run per-cpu monitor with tracing" \ + "$RV mon sched:sco -t" "$RVDIR/monitors/sched/sco" \ + "$header" "$trace_cpu_self" "\($header\|$trace_cpu\)" + +check_if_exists "run per-cpu monitor tracing also self" \ + "$RV mon sco -t -s" "$RVDIR/monitors/sched/sco" \ + "$trace_cpu_self" "" "\($header\|$trace_cpu\)" + +test_end diff --git a/tools/verification/tests/engine.sh b/tools/verification/tests/= engine.sh new file mode 100644 index 000000000000..76cc254ff94c --- /dev/null +++ b/tools/verification/tests/engine.sh @@ -0,0 +1,132 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +test_begin() { + # Count tests to allow the test harness to double-check if all were + # included correctly. + ctr=3D0 + [ -z "$RV" ] && RV=3D"../rv/rv" + [ -n "$TEST_COUNT" ] && echo "1..$TEST_COUNT" +} + +failure() { + fail=3D1 + if [ $# -gt 0 ]; then + failbuf+=3D"$1" + failbuf+=3D$'\n' + fi +} + +report() { + local desc=3D"$1" + + if [ "$fail" -eq 0 ]; then + echo "ok $ctr - $desc" + else + # Add output and exit code as comments in case of failure + echo "not ok $ctr - $desc" + echo -n "$failbuf" + echo "$result" | col -b | while read -r line; do echo "# $line"; done + printf "#\n# exit code %s\n" "$exitcode" + fi +} + +_check() { + local command=3D$2 + local expected_exitcode=3D${3:-0} + local expected_output=3D$4 + local unexpected_output=3D$5 + local all_lines_pattern=3D$6 + local patterns=3D"$expected_output $unexpected_output $all_lines_pattern" + + eval "$TIMEOUT" "$command" &> check_output.$$ & + bgpid=3D$! + pid=3D$(pgrep -f "${command%%[|;&>]*}" | tail -n1) + wait $bgpid + exitcode=3D$? + result=3D$(tr -d '\0' < check_output.$$) + rm -f check_output.$$ + + failbuf=3D'' + fail=3D0 + + # Suppress any other error if a needed pid is empty + if [ -z "$pid" ] && grep -q "\$pid" <<< "$patterns"; then + result=3D'' + failure "# Empty pid for $command" + return 1 + fi + + expected_output=3D"${expected_output//\$pid/$pid}" + unexpected_output=3D"${unexpected_output//\$pid/$pid}" + all_lines_pattern=3D"${all_lines_pattern//\$pid/$pid}" + + # Test if the results matches if requested + if [ -n "$expected_output" ] && ! grep -qe "$expected_output" <<< "$resul= t"; then + failure "# Output match failed: \"$expected_output\"" + fi + + if [ -n "$unexpected_output" ] && grep -qe "$unexpected_output" <<< "$res= ult"; then + failure "# Output non-match failed: \"$unexpected_output\"" + fi + + if [ -n "$all_lines_pattern" ] && grep -vqe "$all_lines_pattern" <<< "$re= sult"; then + failure "# All-lines pattern failed: \"$all_lines_pattern\"" + fi + + if [ $exitcode -ne "$expected_exitcode" ]; then + failure "# Expected exit code $expected_exitcode" + fi +} + +check() { + # Simple check: run the command with given arguments and test exit code. + # If TEST_COUNT is set, run the test. Otherwise, just count. + ctr=3D$((ctr + 1)) + if [ -n "$TEST_COUNT" ]; then + _check "$@" + report "$1" + fi +} + +check_if_exists() { + # Conditional check that skips if a file or folder doesn't exist + local desc=3D$1 + local command=3D$2 + local file=3D$3 + local expected_output=3D$4 + local unexpected_output=3D$5 + local all_lines_pattern=3D$6 + + ctr=3D$((ctr + 1)) + if [ -n "$TEST_COUNT" ]; then + if [ ! -e "$file" ]; then + echo "ok $ctr - $desc # SKIP file not found: $file" + else + _check "$desc" "$command" 0 "$expected_output" \ + "$unexpected_output" "$all_lines_pattern" + report "$desc" + fi + fi +} + +set_timeout() { + TIMEOUT=3D"timeout -v -k 15s $1" +} + +set_expected_timeout() { + TIMEOUT=3D"timeout --preserve-status -k 15s $1" +} + +unset_timeout() { + unset TIMEOUT +} + +test_end() { + # If running without TEST_COUNT, tests are not actually run, just + # counted. In that case, re-run the test with the correct count. + [ -z "$TEST_COUNT" ] && TEST_COUNT=3D$ctr exec bash "$0" || true +} + +# Avoid any environmental discrepancies +export LC_ALL=3DC +unset_timeout --=20 2.54.0 From nobody Fri Jun 12 13:56:05 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E0B7125B0B7 for ; Thu, 14 May 2026 15:21:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772107; cv=none; b=mhb0l7ve9uNY3dJR1ongpXSFV/b6CEURlVP7XVTKWNU6RZp7OFOifwuOt1/Q0wx94n9xJa+CcQyJQyh6faQlMSyKk3iqGmgySiW0Wr76z0ofBAXeA8YtJ3U+v11iMkAYfA+YeP8uhVguevgU5Wma1MEpp0AfiNiM5TBoWJXp3wE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772107; c=relaxed/simple; bh=t4pf0tnESEA/39/+VmiJIbTN5OWd2wrRcu4MCbnbWEk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DM4n+rewd8fdQo+Rbu52S9vH80vrBDe+/aGz+9MXSBe10Ve6Uft7ic3tMp+tA6DsSjcF1dCu4fKSIw6lTvt0i9EnIxWsdk68Ic3vfpDz9mqUSmHIjT+aKTjk+uzxaPdku5ShOv63Ipavuc+nG+n8KIoeYk4kQUCyggit3f0rLTg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=QKYdMdBG; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="QKYdMdBG" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778772104; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Ri7ot+VccVROE2i09PVPZkiJRxbE0JkHy/+alxHnvTM=; b=QKYdMdBGZI999udAvajJkNqYB1v0305qnhkjSztJblffmp8cBnOq2wkU7UBWKHfTeFJH+u q3ErYX24Rh4yS+rZVyINCFzJVCKdAIgsIMksAc+9d+znFicfwQhM+W0GuresRvG70LBohK CH8KKQWQ+otPrmc6haPuN2NG2AhmwzE= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-654-LVeZs8IEMZifofwOARVfWw-1; Thu, 14 May 2026 11:21:39 -0400 X-MC-Unique: LVeZs8IEMZifofwOARVfWw-1 X-Mimecast-MFC-AGG-ID: LVeZs8IEMZifofwOARVfWw_1778772098 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 39ECA195608C; Thu, 14 May 2026 15:21:38 +0000 (UTC) Received: from gmonaco-thinkpadt14gen3.rmtit.csb (unknown [10.44.48.32]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 713FD30001A2; Thu, 14 May 2026 15:21:35 +0000 (UTC) From: Gabriele Monaco To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Steven Rostedt , Gabriele Monaco Cc: Nam Cao , Thomas Weissschuh , Tomas Glozar , John Kacur , Wen Yang Subject: [PATCH v2 06/14] verification/rvgen: Fix options shared among commands Date: Thu, 14 May 2026 17:20:47 +0200 Message-ID: <20260514152055.229162-7-gmonaco@redhat.com> In-Reply-To: <20260514152055.229162-1-gmonaco@redhat.com> References: <20260514152055.229162-1-gmonaco@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" After rvgen was refactored to use subparsers, the common options (-a and -D) were left in the main parser. This meant that they needed to be called /before/ the subcommand and using them without subcommand was allowed. This is not the original intent. rvgen -D "some description" container -n name Define the options as parent in the subparsers to allow them to be used from both subcommands together with other options. rvgen container -n name -D "some description" Signed-off-by: Gabriele Monaco Reviewed-by: Nam Cao --- tools/verification/rvgen/__main__.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/verification/rvgen/__main__.py b/tools/verification/rvge= n/__main__.py index 3be7f85fe37b..5c923dc10d0f 100644 --- a/tools/verification/rvgen/__main__.py +++ b/tools/verification/rvgen/__main__.py @@ -18,14 +18,16 @@ if __name__ =3D=3D '__main__': import sys =20 parser =3D argparse.ArgumentParser(description=3D'Generate kernel rv m= onitor') - parser.add_argument("-D", "--description", dest=3D"description", requi= red=3DFalse) - parser.add_argument("-a", "--auto_patch", dest=3D"auto_patch", + + parent_parser =3D argparse.ArgumentParser(add_help=3DFalse) + parent_parser.add_argument("-D", "--description", dest=3D"description"= , required=3DFalse) + parent_parser.add_argument("-a", "--auto_patch", dest=3D"auto_patch", action=3D"store_true", required=3DFalse, help=3D"Patch the kernel in place") =20 subparsers =3D parser.add_subparsers(dest=3D"subcmd", required=3DTrue) =20 - monitor_parser =3D subparsers.add_parser("monitor") + monitor_parser =3D subparsers.add_parser("monitor", parents=3D[parent_= parser]) monitor_parser.add_argument('-n', "--model_name", dest=3D"model_name") monitor_parser.add_argument("-p", "--parent", dest=3D"parent", required=3DFalse, help=3D"Create a monitor= nested to parent") @@ -36,7 +38,7 @@ if __name__ =3D=3D '__main__': monitor_parser.add_argument('-t', "--monitor_type", dest=3D"monitor_ty= pe", required=3DTrue, help=3Df"Available options: {', '.join(Mon= itor.monitor_types.keys())}") =20 - container_parser =3D subparsers.add_parser("container") + container_parser =3D subparsers.add_parser("container", parents=3D[par= ent_parser]) container_parser.add_argument('-n', "--model_name", dest=3D"model_name= ", required=3DTrue) =20 params =3D parser.parse_args() --=20 2.54.0 From nobody Fri Jun 12 13:56:05 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 807C942846E for ; Thu, 14 May 2026 15:21:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772110; cv=none; b=GbPcRMb6ZiuuNK/hDs06KfeqsIZdoWhLzo2+ray4RrDkF4rVaELuYtXY7cpTQS0No+WUiGkfQvz3AQR9z53zWyuI8DtEi6CoGjOtqsP1ZFC+l5t/mjo4xaFaayhnQmOal+958hwrxv/GgmuxCLLp9W7617pfkcDwhdz+SS8ylmo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772110; c=relaxed/simple; bh=0C6RfvaonJpqY5+r3oZmoyYaaprqQ+dSZ/HR09CNLNc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rwdVqxJJz8hNuwKew14TARHcn4b+zBxFYeo5giV6tpmMjfYcMEabWH+5qBZdE7EJvoMpLOLf0dv0Pr9xQe01g5cbuSq3wn/ZP3KFKFQnnAQajy4ewWDS3O2jC4ZolENK/nyZvE71NTLKrf4X64nAkeJNYRvYYkTYmLqEK9BD33k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=HyqNOGub; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="HyqNOGub" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778772106; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Yr0V9/34qco1aQYqxDHUIvyNht8oHMlUR7CJ+DlzE58=; b=HyqNOGubndsAnI1LGasmbJT8ZNdsjssWRptfXVoKO4wu5N31JoOnO0RMALP3gt4xg27TEW p20hw7z0ujHhAgHVwenJpjJtT/jIP91oPukGljUJK7hfgTr2cVSiEnQjynKOisCS26Lyqd MrzQ1Auz3QuH4WpHZwdQyql8cuGJUiM= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-43-Y5-WadFFM_6U8Dhj7q9lNA-1; Thu, 14 May 2026 11:21:43 -0400 X-MC-Unique: Y5-WadFFM_6U8Dhj7q9lNA-1 X-Mimecast-MFC-AGG-ID: Y5-WadFFM_6U8Dhj7q9lNA_1778772102 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2FC40180061D; Thu, 14 May 2026 15:21:42 +0000 (UTC) Received: from gmonaco-thinkpadt14gen3.rmtit.csb (unknown [10.44.48.32]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 20F6430001A2; Thu, 14 May 2026 15:21:38 +0000 (UTC) From: Gabriele Monaco To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Steven Rostedt , Gabriele Monaco , Nam Cao Cc: Thomas Weissschuh , Tomas Glozar , John Kacur , Wen Yang Subject: [PATCH v2 07/14] verification/rvgen: Fix ltl2k writing True as a literal Date: Thu, 14 May 2026 17:20:48 +0200 Message-ID: <20260514152055.229162-8-gmonaco@redhat.com> In-Reply-To: <20260514152055.229162-1-gmonaco@redhat.com> References: <20260514152055.229162-1-gmonaco@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" The rvgen parser for LTL stores literal true values in the python representation (capitalised True), this doesn't build in C. The Literal class should already handle this case but ASTNode skips its strigification method and converts the value (true/false) directly. Fix by delegating ASTNode stringification to the Literal and Variable classes instead of bypassing them. Fixes: 97ffa4ce6ab32 ("verification/rvgen: Add support for linear temporal = logic") Signed-off-by: Gabriele Monaco Reviewed-by: Nam Cao --- tools/verification/rvgen/rvgen/ltl2ba.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/verification/rvgen/rvgen/ltl2ba.py b/tools/verification/= rvgen/rvgen/ltl2ba.py index 7f538598a868..016e7cf93bbb 100644 --- a/tools/verification/rvgen/rvgen/ltl2ba.py +++ b/tools/verification/rvgen/rvgen/ltl2ba.py @@ -122,10 +122,8 @@ class ASTNode: return self.op.expand(self, node, node_set) =20 def __str__(self): - if isinstance(self.op, Literal): - return str(self.op.value) - if isinstance(self.op, Variable): - return self.op.name.lower() + if isinstance(self.op, (Literal, Variable)): + return str(self.op) return "val" + str(self.id) =20 def normalize(self): @@ -382,6 +380,9 @@ class Variable: def __iter__(self): yield from () =20 + def __str__(self): + return self.name.lower() + def negate(self): new =3D ASTNode(self) return NotOp(new) --=20 2.54.0 From nobody Fri Jun 12 13:56:05 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 54FAC31987D for ; Thu, 14 May 2026 15:21:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772123; cv=none; b=o5kJ/0PF195M84JdcPzN0wl6V4rDqDRlmlNblGje/HE/It9hUqcGKd7aI1/ZsfOjY3JJgQR5yC8r8bqspoGi+76hbCXfbuWkGYJ/aYGLiSz3n+romL8akywtmY61mh02+VDhgH3ilgnKehUxmj4IxmD1MBZ2ghHq3j3mXwQ8d2s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772123; c=relaxed/simple; bh=DuHH3/zvhkF3+z9nt7gsvhgnK9P4tR/SCAHM7nXH9No=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BuUR39z1gEJIRjUUIhxT19P+qYEjN9J2YpzyX7eRMiiHmt9Useo93uIz9drkoxhTh7YmhcvtXfrTyOyBeTtPFwVnlmC3zqj2d5M1yf8bv8HhDwsw9M1asM0jvwfG40aFD+sKHwMkZUNHSmRXTzLdkYD62PFqkRhsr0QLJXzlGNE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=AM+8CHgt; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="AM+8CHgt" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778772118; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uargouw4f+gnnmY1auj4yYsHT24DI/5K5rBccehTc1w=; b=AM+8CHgtl/GkqC8hi2bjlrD5DhgRMNRyWf4P6blRl6atWKdLWFmokMFkVKEWBgjIY+RFsb hzrD+s5ZaMO2Rg/WNDXaoVKH2qzas9yrfCznHhKGFCrPLO4juUSGZouNZov9HuIyxfRU5a jWmoayfCj87/Z6J6Ip/9bQHNZp4YRPA= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-394-PjUX6i9ePrG_ce3gasFLSA-1; Thu, 14 May 2026 11:21:54 -0400 X-MC-Unique: PjUX6i9ePrG_ce3gasFLSA-1 X-Mimecast-MFC-AGG-ID: PjUX6i9ePrG_ce3gasFLSA_1778772113 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 77922195608E; Thu, 14 May 2026 15:21:53 +0000 (UTC) Received: from gmonaco-thinkpadt14gen3.rmtit.csb (unknown [10.44.48.32]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D94F830001A2; Thu, 14 May 2026 15:21:49 +0000 (UTC) From: Gabriele Monaco To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Steven Rostedt , Gabriele Monaco Cc: Nam Cao , Thomas Weissschuh , Tomas Glozar , John Kacur , Wen Yang Subject: [PATCH v2 08/14] verification/rvgen: Add golden and spec folders for tests Date: Thu, 14 May 2026 17:20:49 +0200 Message-ID: <20260514152055.229162-9-gmonaco@redhat.com> In-Reply-To: <20260514152055.229162-1-gmonaco@redhat.com> References: <20260514152055.229162-1-gmonaco@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Create reference models specifications and generated files in the golded folder. Those can be used as reference to validate rvgen still generates files as expected in automated tests. Signed-off-by: Gabriele Monaco Reviewed-by: Nam Cao --- .../rvgen/tests/golden/da_global/Kconfig | 9 + .../rvgen/tests/golden/da_global/da_global.c | 95 +++++++ .../rvgen/tests/golden/da_global/da_global.h | 47 ++++ .../tests/golden/da_global/da_global_trace.h | 15 ++ .../tests/golden/da_perobj_parent/Kconfig | 11 + .../da_perobj_parent/da_perobj_parent.c | 110 ++++++++ .../da_perobj_parent/da_perobj_parent.h | 64 +++++ .../da_perobj_parent/da_perobj_parent_trace.h | 15 ++ .../tests/golden/da_pertask_desc/Kconfig | 9 + .../golden/da_pertask_desc/da_pertask_desc.c | 105 ++++++++ .../golden/da_pertask_desc/da_pertask_desc.h | 64 +++++ .../da_pertask_desc/da_pertask_desc_trace.h | 15 ++ .../rvgen/tests/golden/ha_percpu/Kconfig | 9 + .../rvgen/tests/golden/ha_percpu/ha_percpu.c | 244 +++++++++++++++++ .../rvgen/tests/golden/ha_percpu/ha_percpu.h | 72 +++++ .../tests/golden/ha_percpu/ha_percpu_trace.h | 19 ++ .../rvgen/tests/golden/ltl_pertask/Kconfig | 9 + .../tests/golden/ltl_pertask/ltl_pertask.c | 107 ++++++++ .../tests/golden/ltl_pertask/ltl_pertask.h | 108 ++++++++ .../golden/ltl_pertask/ltl_pertask_trace.h | 14 + .../rvgen/tests/golden/test_container/Kconfig | 5 + .../golden/test_container/test_container.c | 35 +++ .../golden/test_container/test_container.h | 3 + .../rvgen/tests/golden/test_da/Kconfig | 9 + .../rvgen/tests/golden/test_da/test_da.c | 95 +++++++ .../rvgen/tests/golden/test_da/test_da.h | 47 ++++ .../tests/golden/test_da/test_da_trace.h | 15 ++ .../rvgen/tests/golden/test_ha/Kconfig | 9 + .../rvgen/tests/golden/test_ha/test_ha.c | 247 ++++++++++++++++++ .../rvgen/tests/golden/test_ha/test_ha.h | 72 +++++ .../tests/golden/test_ha/test_ha_trace.h | 19 ++ .../rvgen/tests/golden/test_ltl/Kconfig | 11 + .../rvgen/tests/golden/test_ltl/test_ltl.c | 108 ++++++++ .../rvgen/tests/golden/test_ltl/test_ltl.h | 108 ++++++++ .../tests/golden/test_ltl/test_ltl_trace.h | 14 + .../rvgen/tests/specs/test_da.dot | 16 ++ .../rvgen/tests/specs/test_da2.dot | 19 ++ .../rvgen/tests/specs/test_ha.dot | 27 ++ .../rvgen/tests/specs/test_invalid.dot | 8 + .../rvgen/tests/specs/test_invalid.ltl | 1 + .../rvgen/tests/specs/test_invalid_ha.dot | 16 ++ .../rvgen/tests/specs/test_ltl.ltl | 1 + 42 files changed, 2026 insertions(+) create mode 100644 tools/verification/rvgen/tests/golden/da_global/Kconfig create mode 100644 tools/verification/rvgen/tests/golden/da_global/da_glob= al.c create mode 100644 tools/verification/rvgen/tests/golden/da_global/da_glob= al.h create mode 100644 tools/verification/rvgen/tests/golden/da_global/da_glob= al_trace.h create mode 100644 tools/verification/rvgen/tests/golden/da_perobj_parent/= Kconfig create mode 100644 tools/verification/rvgen/tests/golden/da_perobj_parent/= da_perobj_parent.c create mode 100644 tools/verification/rvgen/tests/golden/da_perobj_parent/= da_perobj_parent.h create mode 100644 tools/verification/rvgen/tests/golden/da_perobj_parent/= da_perobj_parent_trace.h create mode 100644 tools/verification/rvgen/tests/golden/da_pertask_desc/K= config create mode 100644 tools/verification/rvgen/tests/golden/da_pertask_desc/d= a_pertask_desc.c create mode 100644 tools/verification/rvgen/tests/golden/da_pertask_desc/d= a_pertask_desc.h create mode 100644 tools/verification/rvgen/tests/golden/da_pertask_desc/d= a_pertask_desc_trace.h create mode 100644 tools/verification/rvgen/tests/golden/ha_percpu/Kconfig create mode 100644 tools/verification/rvgen/tests/golden/ha_percpu/ha_perc= pu.c create mode 100644 tools/verification/rvgen/tests/golden/ha_percpu/ha_perc= pu.h create mode 100644 tools/verification/rvgen/tests/golden/ha_percpu/ha_perc= pu_trace.h create mode 100644 tools/verification/rvgen/tests/golden/ltl_pertask/Kconf= ig create mode 100644 tools/verification/rvgen/tests/golden/ltl_pertask/ltl_p= ertask.c create mode 100644 tools/verification/rvgen/tests/golden/ltl_pertask/ltl_p= ertask.h create mode 100644 tools/verification/rvgen/tests/golden/ltl_pertask/ltl_p= ertask_trace.h create mode 100644 tools/verification/rvgen/tests/golden/test_container/Kc= onfig create mode 100644 tools/verification/rvgen/tests/golden/test_container/te= st_container.c create mode 100644 tools/verification/rvgen/tests/golden/test_container/te= st_container.h create mode 100644 tools/verification/rvgen/tests/golden/test_da/Kconfig create mode 100644 tools/verification/rvgen/tests/golden/test_da/test_da.c create mode 100644 tools/verification/rvgen/tests/golden/test_da/test_da.h create mode 100644 tools/verification/rvgen/tests/golden/test_da/test_da_t= race.h create mode 100644 tools/verification/rvgen/tests/golden/test_ha/Kconfig create mode 100644 tools/verification/rvgen/tests/golden/test_ha/test_ha.c create mode 100644 tools/verification/rvgen/tests/golden/test_ha/test_ha.h create mode 100644 tools/verification/rvgen/tests/golden/test_ha/test_ha_t= race.h create mode 100644 tools/verification/rvgen/tests/golden/test_ltl/Kconfig create mode 100644 tools/verification/rvgen/tests/golden/test_ltl/test_ltl= .c create mode 100644 tools/verification/rvgen/tests/golden/test_ltl/test_ltl= .h create mode 100644 tools/verification/rvgen/tests/golden/test_ltl/test_ltl= _trace.h create mode 100644 tools/verification/rvgen/tests/specs/test_da.dot create mode 100644 tools/verification/rvgen/tests/specs/test_da2.dot create mode 100644 tools/verification/rvgen/tests/specs/test_ha.dot create mode 100644 tools/verification/rvgen/tests/specs/test_invalid.dot create mode 100644 tools/verification/rvgen/tests/specs/test_invalid.ltl create mode 100644 tools/verification/rvgen/tests/specs/test_invalid_ha.dot create mode 100644 tools/verification/rvgen/tests/specs/test_ltl.ltl diff --git a/tools/verification/rvgen/tests/golden/da_global/Kconfig b/tool= s/verification/rvgen/tests/golden/da_global/Kconfig new file mode 100644 index 000000000000..799fbf11c3ac --- /dev/null +++ b/tools/verification/rvgen/tests/golden/da_global/Kconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_DA_GLOBAL + depends on RV + # XXX: add dependencies if there + select DA_MON_EVENTS_IMPLICIT + bool "da_global monitor" + help + auto-generated diff --git a/tools/verification/rvgen/tests/golden/da_global/da_global.c b/= tools/verification/rvgen/tests/golden/da_global/da_global.c new file mode 100644 index 000000000000..ad4b939d2323 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/da_global/da_global.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "da_global" + +/* + * XXX: include required tracepoint headers, e.g., + * #include + */ +#include + +/* + * This is the self-generated part of the monitor. Generally, there is no = need + * to touch this section. + */ +#define RV_MON_TYPE RV_MON_GLOBAL +#include "da_global.h" +#include + +/* + * This is the instrumentation part of the monitor. + * + * This is the section where manual work is required. Here the kernel even= ts + * are translated into model's event. + * + */ +static void handle_event_1(void *data, /* XXX: fill header */) +{ + da_handle_event(event_1_da_global); +} + +static void handle_event_2(void *data, /* XXX: fill header */) +{ + /* XXX: validate that this event always leads to the initial state */ + da_handle_start_event(event_2_da_global); +} + +static int enable_da_global(void) +{ + int retval; + + retval =3D da_monitor_init(); + if (retval) + return retval; + + rv_attach_trace_probe("da_global", /* XXX: tracepoint */, handle_event_1); + rv_attach_trace_probe("da_global", /* XXX: tracepoint */, handle_event_2); + + return 0; +} + +static void disable_da_global(void) +{ + rv_this.enabled =3D 0; + + rv_detach_trace_probe("da_global", /* XXX: tracepoint */, handle_event_1); + rv_detach_trace_probe("da_global", /* XXX: tracepoint */, handle_event_2); + + da_monitor_destroy(); +} + +/* + * This is the monitor register section. + */ +static struct rv_monitor rv_this =3D { + .name =3D "da_global", + .description =3D "auto-generated", + .enable =3D enable_da_global, + .disable =3D disable_da_global, + .reset =3D da_monitor_reset_all, + .enabled =3D 0, +}; + +static int __init register_da_global(void) +{ + return rv_register_monitor(&rv_this, NULL); +} + +static void __exit unregister_da_global(void) +{ + rv_unregister_monitor(&rv_this); +} + +module_init(register_da_global); +module_exit(unregister_da_global); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("dot2k: auto-generated"); +MODULE_DESCRIPTION("da_global: auto-generated"); diff --git a/tools/verification/rvgen/tests/golden/da_global/da_global.h b/= tools/verification/rvgen/tests/golden/da_global/da_global.h new file mode 100644 index 000000000000..40b1f1c0c681 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/da_global/da_global.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Automatically generated C representation of da_global automaton + * For further information about this format, see kernel documentation: + * Documentation/trace/rv/deterministic_automata.rst + */ + +#define MONITOR_NAME da_global + +enum states_da_global { + state_a_da_global, + state_b_da_global, + state_max_da_global, +}; + +#define INVALID_STATE state_max_da_global + +enum events_da_global { + event_1_da_global, + event_2_da_global, + event_max_da_global, +}; + +struct automaton_da_global { + char *state_names[state_max_da_global]; + char *event_names[event_max_da_global]; + unsigned char function[state_max_da_global][event_max_da_global]; + unsigned char initial_state; + bool final_states[state_max_da_global]; +}; + +static const struct automaton_da_global automaton_da_global =3D { + .state_names =3D { + "state_a", + "state_b", + }, + .event_names =3D { + "event_1", + "event_2", + }, + .function =3D { + { state_b_da_global, state_a_da_global }, + { INVALID_STATE, state_a_da_global }, + }, + .initial_state =3D state_a_da_global, + .final_states =3D { 1, 0 }, +}; diff --git a/tools/verification/rvgen/tests/golden/da_global/da_global_trac= e.h b/tools/verification/rvgen/tests/golden/da_global/da_global_trace.h new file mode 100644 index 000000000000..4d2730b71dd0 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/da_global/da_global_trace.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_DA_GLOBAL +DEFINE_EVENT(event_da_monitor, event_da_global, + 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_da_global, + TP_PROTO(char *state, char *event), + TP_ARGS(state, event)); +#endif /* CONFIG_RV_MON_DA_GLOBAL */ diff --git a/tools/verification/rvgen/tests/golden/da_perobj_parent/Kconfig= b/tools/verification/rvgen/tests/golden/da_perobj_parent/Kconfig new file mode 100644 index 000000000000..249ba3aee8d7 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/da_perobj_parent/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_DA_PEROBJ_PARENT + depends on RV + # XXX: add dependencies if there + depends on RV_MON_PARENT_MON + default y + select DA_MON_EVENTS_ID + bool "da_perobj_parent monitor" + help + auto-generated diff --git a/tools/verification/rvgen/tests/golden/da_perobj_parent/da_pero= bj_parent.c b/tools/verification/rvgen/tests/golden/da_perobj_parent/da_per= obj_parent.c new file mode 100644 index 000000000000..66f3a010876a --- /dev/null +++ b/tools/verification/rvgen/tests/golden/da_perobj_parent/da_perobj_pare= nt.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "da_perobj_parent" + +/* + * XXX: include required tracepoint headers, e.g., + * #include + */ +#include +#include + +/* + * This is the self-generated part of the monitor. Generally, there is no = need + * to touch this section. + */ +#define RV_MON_TYPE RV_MON_PER_OBJ +typedef /* XXX: define the target type */ *monitor_target; +#include "da_perobj_parent.h" +#include + +/* + * This is the instrumentation part of the monitor. + * + * This is the section where manual work is required. Here the kernel even= ts + * are translated into model's event. + * + */ +static void handle_event_1(void *data, /* XXX: fill header */) +{ + /* XXX: validate that this event is only valid in the initial state */ + int id =3D /* XXX: how do I get the id? */; + monitor_target t =3D /* XXX: how do I get t? */; + da_handle_start_run_event(id, t, event_1_da_perobj_parent); +} + +static void handle_event_2(void *data, /* XXX: fill header */) +{ + int id =3D /* XXX: how do I get the id? */; + monitor_target t =3D /* XXX: how do I get t? */; + da_handle_event(id, t, event_2_da_perobj_parent); +} + +static void handle_event_3(void *data, /* XXX: fill header */) +{ + int id =3D /* XXX: how do I get the id? */; + monitor_target t =3D /* XXX: how do I get t? */; + da_handle_event(id, t, event_3_da_perobj_parent); +} + +static int enable_da_perobj_parent(void) +{ + int retval; + + retval =3D da_monitor_init(); + if (retval) + return retval; + + rv_attach_trace_probe("da_perobj_parent", /* XXX: tracepoint */, handle_e= vent_1); + rv_attach_trace_probe("da_perobj_parent", /* XXX: tracepoint */, handle_e= vent_2); + rv_attach_trace_probe("da_perobj_parent", /* XXX: tracepoint */, handle_e= vent_3); + + return 0; +} + +static void disable_da_perobj_parent(void) +{ + rv_this.enabled =3D 0; + + rv_detach_trace_probe("da_perobj_parent", /* XXX: tracepoint */, handle_e= vent_1); + rv_detach_trace_probe("da_perobj_parent", /* XXX: tracepoint */, handle_e= vent_2); + rv_detach_trace_probe("da_perobj_parent", /* XXX: tracepoint */, handle_e= vent_3); + + da_monitor_destroy(); +} + +/* + * This is the monitor register section. + */ +static struct rv_monitor rv_this =3D { + .name =3D "da_perobj_parent", + .description =3D "auto-generated", + .enable =3D enable_da_perobj_parent, + .disable =3D disable_da_perobj_parent, + .reset =3D da_monitor_reset_all, + .enabled =3D 0, +}; + +static int __init register_da_perobj_parent(void) +{ + return rv_register_monitor(&rv_this, &rv_parent_mon); +} + +static void __exit unregister_da_perobj_parent(void) +{ + rv_unregister_monitor(&rv_this); +} + +module_init(register_da_perobj_parent); +module_exit(unregister_da_perobj_parent); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("dot2k: auto-generated"); +MODULE_DESCRIPTION("da_perobj_parent: auto-generated"); diff --git a/tools/verification/rvgen/tests/golden/da_perobj_parent/da_pero= bj_parent.h b/tools/verification/rvgen/tests/golden/da_perobj_parent/da_per= obj_parent.h new file mode 100644 index 000000000000..3c8dc3b22443 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/da_perobj_parent/da_perobj_pare= nt.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Automatically generated C representation of da_perobj_parent automaton + * For further information about this format, see kernel documentation: + * Documentation/trace/rv/deterministic_automata.rst + */ + +#define MONITOR_NAME da_perobj_parent + +enum states_da_perobj_parent { + state_a_da_perobj_parent, + state_b_da_perobj_parent, + state_c_da_perobj_parent, + state_max_da_perobj_parent, +}; + +#define INVALID_STATE state_max_da_perobj_parent + +enum events_da_perobj_parent { + event_1_da_perobj_parent, + event_2_da_perobj_parent, + event_3_da_perobj_parent, + event_max_da_perobj_parent, +}; + +struct automaton_da_perobj_parent { + char *state_names[state_max_da_perobj_parent]; + char *event_names[event_max_da_perobj_parent]; + unsigned char function[state_max_da_perobj_parent][event_max_da_perobj_pa= rent]; + unsigned char initial_state; + bool final_states[state_max_da_perobj_parent]; +}; + +static const struct automaton_da_perobj_parent automaton_da_perobj_parent = =3D { + .state_names =3D { + "state_a", + "state_b", + "state_c", + }, + .event_names =3D { + "event_1", + "event_2", + "event_3", + }, + .function =3D { + { + state_b_da_perobj_parent, + state_c_da_perobj_parent, + INVALID_STATE, + }, + { + INVALID_STATE, + state_a_da_perobj_parent, + state_c_da_perobj_parent, + }, + { + INVALID_STATE, + INVALID_STATE, + INVALID_STATE, + }, + }, + .initial_state =3D state_a_da_perobj_parent, + .final_states =3D { 1, 0, 0 }, +}; diff --git a/tools/verification/rvgen/tests/golden/da_perobj_parent/da_pero= bj_parent_trace.h b/tools/verification/rvgen/tests/golden/da_perobj_parent/= da_perobj_parent_trace.h new file mode 100644 index 000000000000..59bfca8f73d2 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/da_perobj_parent/da_perobj_pare= nt_trace.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_DA_PEROBJ_PARENT +DEFINE_EVENT(event_da_monitor_id, event_da_perobj_parent, + 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_da_perobj_parent, + TP_PROTO(int id, char *state, char *event), + TP_ARGS(id, state, event)); +#endif /* CONFIG_RV_MON_DA_PEROBJ_PARENT */ diff --git a/tools/verification/rvgen/tests/golden/da_pertask_desc/Kconfig = b/tools/verification/rvgen/tests/golden/da_pertask_desc/Kconfig new file mode 100644 index 000000000000..c6f350179098 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/da_pertask_desc/Kconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_DA_PERTASK_DESC + depends on RV + # XXX: add dependencies if there + select DA_MON_EVENTS_ID + bool "da_pertask_desc monitor" + help + Custom description for testing diff --git a/tools/verification/rvgen/tests/golden/da_pertask_desc/da_perta= sk_desc.c b/tools/verification/rvgen/tests/golden/da_pertask_desc/da_pertas= k_desc.c new file mode 100644 index 000000000000..bd76ecc3a998 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/da_pertask_desc/da_pertask_desc= .c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "da_pertask_desc" + +/* + * XXX: include required tracepoint headers, e.g., + * #include + */ +#include + +/* + * This is the self-generated part of the monitor. Generally, there is no = need + * to touch this section. + */ +#define RV_MON_TYPE RV_MON_PER_TASK +#include "da_pertask_desc.h" +#include + +/* + * This is the instrumentation part of the monitor. + * + * This is the section where manual work is required. Here the kernel even= ts + * are translated into model's event. + * + */ +static void handle_event_1(void *data, /* XXX: fill header */) +{ + /* XXX: validate that this event is only valid in the initial state */ + struct task_struct *p =3D /* XXX: how do I get p? */; + da_handle_start_run_event(p, event_1_da_pertask_desc); +} + +static void handle_event_2(void *data, /* XXX: fill header */) +{ + struct task_struct *p =3D /* XXX: how do I get p? */; + da_handle_event(p, event_2_da_pertask_desc); +} + +static void handle_event_3(void *data, /* XXX: fill header */) +{ + struct task_struct *p =3D /* XXX: how do I get p? */; + da_handle_event(p, event_3_da_pertask_desc); +} + +static int enable_da_pertask_desc(void) +{ + int retval; + + retval =3D da_monitor_init(); + if (retval) + return retval; + + rv_attach_trace_probe("da_pertask_desc", /* XXX: tracepoint */, handle_ev= ent_1); + rv_attach_trace_probe("da_pertask_desc", /* XXX: tracepoint */, handle_ev= ent_2); + rv_attach_trace_probe("da_pertask_desc", /* XXX: tracepoint */, handle_ev= ent_3); + + return 0; +} + +static void disable_da_pertask_desc(void) +{ + rv_this.enabled =3D 0; + + rv_detach_trace_probe("da_pertask_desc", /* XXX: tracepoint */, handle_ev= ent_1); + rv_detach_trace_probe("da_pertask_desc", /* XXX: tracepoint */, handle_ev= ent_2); + rv_detach_trace_probe("da_pertask_desc", /* XXX: tracepoint */, handle_ev= ent_3); + + da_monitor_destroy(); +} + +/* + * This is the monitor register section. + */ +static struct rv_monitor rv_this =3D { + .name =3D "da_pertask_desc", + .description =3D "Custom description for testing", + .enable =3D enable_da_pertask_desc, + .disable =3D disable_da_pertask_desc, + .reset =3D da_monitor_reset_all, + .enabled =3D 0, +}; + +static int __init register_da_pertask_desc(void) +{ + return rv_register_monitor(&rv_this, NULL); +} + +static void __exit unregister_da_pertask_desc(void) +{ + rv_unregister_monitor(&rv_this); +} + +module_init(register_da_pertask_desc); +module_exit(unregister_da_pertask_desc); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("dot2k: auto-generated"); +MODULE_DESCRIPTION("da_pertask_desc: Custom description for testing"); diff --git a/tools/verification/rvgen/tests/golden/da_pertask_desc/da_perta= sk_desc.h b/tools/verification/rvgen/tests/golden/da_pertask_desc/da_pertas= k_desc.h new file mode 100644 index 000000000000..837b238754b0 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/da_pertask_desc/da_pertask_desc= .h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Automatically generated C representation of da_pertask_desc automaton + * For further information about this format, see kernel documentation: + * Documentation/trace/rv/deterministic_automata.rst + */ + +#define MONITOR_NAME da_pertask_desc + +enum states_da_pertask_desc { + state_a_da_pertask_desc, + state_b_da_pertask_desc, + state_c_da_pertask_desc, + state_max_da_pertask_desc, +}; + +#define INVALID_STATE state_max_da_pertask_desc + +enum events_da_pertask_desc { + event_1_da_pertask_desc, + event_2_da_pertask_desc, + event_3_da_pertask_desc, + event_max_da_pertask_desc, +}; + +struct automaton_da_pertask_desc { + char *state_names[state_max_da_pertask_desc]; + char *event_names[event_max_da_pertask_desc]; + unsigned char function[state_max_da_pertask_desc][event_max_da_pertask_de= sc]; + unsigned char initial_state; + bool final_states[state_max_da_pertask_desc]; +}; + +static const struct automaton_da_pertask_desc automaton_da_pertask_desc = =3D { + .state_names =3D { + "state_a", + "state_b", + "state_c", + }, + .event_names =3D { + "event_1", + "event_2", + "event_3", + }, + .function =3D { + { + state_b_da_pertask_desc, + state_c_da_pertask_desc, + INVALID_STATE, + }, + { + INVALID_STATE, + state_a_da_pertask_desc, + state_c_da_pertask_desc, + }, + { + INVALID_STATE, + INVALID_STATE, + INVALID_STATE, + }, + }, + .initial_state =3D state_a_da_pertask_desc, + .final_states =3D { 1, 0, 0 }, +}; diff --git a/tools/verification/rvgen/tests/golden/da_pertask_desc/da_perta= sk_desc_trace.h b/tools/verification/rvgen/tests/golden/da_pertask_desc/da_= pertask_desc_trace.h new file mode 100644 index 000000000000..4e6086c4d86e --- /dev/null +++ b/tools/verification/rvgen/tests/golden/da_pertask_desc/da_pertask_desc= _trace.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_DA_PERTASK_DESC +DEFINE_EVENT(event_da_monitor_id, event_da_pertask_desc, + 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_da_pertask_desc, + TP_PROTO(int id, char *state, char *event), + TP_ARGS(id, state, event)); +#endif /* CONFIG_RV_MON_DA_PERTASK_DESC */ diff --git a/tools/verification/rvgen/tests/golden/ha_percpu/Kconfig b/tool= s/verification/rvgen/tests/golden/ha_percpu/Kconfig new file mode 100644 index 000000000000..0cc185ccfddf --- /dev/null +++ b/tools/verification/rvgen/tests/golden/ha_percpu/Kconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_HA_PERCPU + depends on RV + # XXX: add dependencies if there + select HA_MON_EVENTS_IMPLICIT + bool "ha_percpu monitor" + help + auto-generated diff --git a/tools/verification/rvgen/tests/golden/ha_percpu/ha_percpu.c b/= tools/verification/rvgen/tests/golden/ha_percpu/ha_percpu.c new file mode 100644 index 000000000000..ba7a02a18f81 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/ha_percpu/ha_percpu.c @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "ha_percpu" + +/* + * XXX: include required tracepoint headers, e.g., + * #include + */ +#include + +/* + * This is the self-generated part of the monitor. Generally, there is no = need + * to touch this section. + */ +#define RV_MON_TYPE RV_MON_PER_CPU +/* XXX: If the monitor has several instances, consider HA_TIMER_WHEEL */ +#define HA_TIMER_TYPE HA_TIMER_HRTIMER +#include "ha_percpu.h" +#include + +/* + * This is the instrumentation part of the monitor. + * + * This is the section where manual work is required. Here the kernel even= ts + * are translated into model's event. + * + */ +#define BAR_NS(ha_mon) /* XXX: what is BAR_NS(ha_mon)? */ + +#define FOO_NS /* XXX: what is FOO_NS? */ + +static inline u64 bar_ns(struct ha_monitor *ha_mon) +{ + return /* XXX: what is bar_ns(ha_mon)? */; +} + +static u64 foo_ns =3D /* XXX: default value */; +module_param(foo_ns, ullong, 0644); + +/* + * These functions define how to read and reset the environment variable. + * + * Common environment variables like ns-based and jiffy-based clocks have + * pre-define getters and resetters you can use. The parser can infer the = type + * of the environment variable if you supply a measure unit in the constra= int. + * If you define your own functions, make sure to add appropriate memory + * barriers if required. + * Some environment variables don't require a storage as they read a system + * state (e.g. preemption count). Those variables are never reset, so we d= on't + * define a reset function on monitors only relying on this type of variab= les. + */ +static u64 ha_get_env(struct ha_monitor *ha_mon, enum envs_ha_percpu env, = u64 time_ns) +{ + if (env =3D=3D clk_ha_percpu) + return ha_get_clk_ns(ha_mon, env, time_ns); + else if (env =3D=3D env1_ha_percpu) + return /* XXX: how do I read env1? */ + else if (env =3D=3D env2_ha_percpu) + return /* XXX: how do I read env2? */ + return ENV_INVALID_VALUE; +} + +static void ha_reset_env(struct ha_monitor *ha_mon, enum envs_ha_percpu en= v, u64 time_ns) +{ + if (env =3D=3D clk_ha_percpu) + ha_reset_clk_ns(ha_mon, env, time_ns); +} + +/* + * These functions are used to validate state transitions. + * + * They are generated by parsing the model, there is usually no need to ch= ange them. + * If the monitor requires a timer, there are functions responsible to arm= it when + * the next state has a constraint, cancel it in any other case and to che= ck + * that it didn't expire before the callback run. Transitions to the same = state + * without a reset never affect timers. + * Due to the different representations between invariants and guards, the= re is + * a function to convert it in case invariants or guards are reachable from + * another invariant without reset. Those are not present if not required = in + * the model. This is all automatic but is worth checking because it may s= how + * errors in the model (e.g. missing resets). + */ +static inline bool ha_verify_invariants(struct ha_monitor *ha_mon, + enum states curr_state, enum events event, + enum states next_state, u64 time_ns) +{ + if (curr_state =3D=3D S0_ha_percpu) + return ha_check_invariant_ns(ha_mon, clk_ha_percpu, time_ns); + else if (curr_state =3D=3D S2_ha_percpu) + return ha_check_invariant_ns(ha_mon, clk_ha_percpu, time_ns); + return true; +} + +static inline void ha_convert_inv_guard(struct ha_monitor *ha_mon, + enum states curr_state, enum events event, + enum states next_state, u64 time_ns) +{ + if (curr_state =3D=3D next_state) + return; + if (curr_state =3D=3D S2_ha_percpu) + ha_inv_to_guard(ha_mon, clk_ha_percpu, BAR_NS(ha_mon), time_ns); +} + +static inline bool ha_verify_guards(struct ha_monitor *ha_mon, + enum states curr_state, enum events event, + enum states next_state, u64 time_ns) +{ + bool res =3D true; + + if (curr_state =3D=3D S0_ha_percpu && event =3D=3D event0_ha_percpu) + ha_reset_env(ha_mon, clk_ha_percpu, time_ns); + else if (curr_state =3D=3D S0_ha_percpu && event =3D=3D event1_ha_percpu) + ha_reset_env(ha_mon, clk_ha_percpu, time_ns); + else if (curr_state =3D=3D S1_ha_percpu && event =3D=3D event0_ha_percpu) + ha_reset_env(ha_mon, clk_ha_percpu, time_ns); + else if (curr_state =3D=3D S1_ha_percpu && event =3D=3D event2_ha_percpu)= { + res =3D ha_get_env(ha_mon, env1_ha_percpu, time_ns) =3D=3D 0ull; + ha_reset_env(ha_mon, clk_ha_percpu, time_ns); + } else if (curr_state =3D=3D S2_ha_percpu && event =3D=3D event1_ha_percp= u) + res =3D ha_monitor_env_invalid(ha_mon, clk_ha_percpu) || + ha_get_env(ha_mon, clk_ha_percpu, time_ns) < foo_ns; + else if (curr_state =3D=3D S3_ha_percpu && event =3D=3D event0_ha_percpu) + res =3D ha_monitor_env_invalid(ha_mon, clk_ha_percpu) || + (ha_get_env(ha_mon, clk_ha_percpu, time_ns) < FOO_NS && + ha_get_env(ha_mon, env2_ha_percpu, time_ns) =3D=3D 0ull); + else if (curr_state =3D=3D S3_ha_percpu && event =3D=3D event1_ha_percpu)= { + res =3D ha_monitor_env_invalid(ha_mon, clk_ha_percpu) || + (ha_get_env(ha_mon, clk_ha_percpu, time_ns) < foo_ns && + ha_get_env(ha_mon, env1_ha_percpu, time_ns) =3D=3D 1ull); + ha_reset_env(ha_mon, clk_ha_percpu, time_ns); + } + return res; +} + +static inline void ha_setup_invariants(struct ha_monitor *ha_mon, + enum states curr_state, enum events event, + enum states next_state, u64 time_ns) +{ + if (next_state =3D=3D curr_state && event !=3D event0_ha_percpu) + return; + if (next_state =3D=3D S0_ha_percpu) + ha_start_timer_ns(ha_mon, clk_ha_percpu, bar_ns(ha_mon), time_ns); + else if (next_state =3D=3D S2_ha_percpu) + ha_start_timer_ns(ha_mon, clk_ha_percpu, BAR_NS(ha_mon), time_ns); + else if (curr_state =3D=3D S0_ha_percpu) + ha_cancel_timer(ha_mon); + else if (curr_state =3D=3D S2_ha_percpu) + ha_cancel_timer(ha_mon); +} + +static bool ha_verify_constraint(struct ha_monitor *ha_mon, + enum states curr_state, enum events event, + enum states next_state, u64 time_ns) +{ + if (!ha_verify_invariants(ha_mon, curr_state, event, next_state, time_ns)) + return false; + + ha_convert_inv_guard(ha_mon, curr_state, event, next_state, time_ns); + + if (!ha_verify_guards(ha_mon, curr_state, event, next_state, time_ns)) + return false; + + ha_setup_invariants(ha_mon, curr_state, event, next_state, time_ns); + + return true; +} + +static void handle_event0(void *data, /* XXX: fill header */) +{ + /* XXX: validate that this event always leads to the initial state */ + da_handle_start_event(event0_ha_percpu); +} + +static void handle_event1(void *data, /* XXX: fill header */) +{ + da_handle_event(event1_ha_percpu); +} + +static void handle_event2(void *data, /* XXX: fill header */) +{ + da_handle_event(event2_ha_percpu); +} + +static int enable_ha_percpu(void) +{ + int retval; + + retval =3D da_monitor_init(); + if (retval) + return retval; + + rv_attach_trace_probe("ha_percpu", /* XXX: tracepoint */, handle_event0); + rv_attach_trace_probe("ha_percpu", /* XXX: tracepoint */, handle_event1); + rv_attach_trace_probe("ha_percpu", /* XXX: tracepoint */, handle_event2); + + return 0; +} + +static void disable_ha_percpu(void) +{ + rv_this.enabled =3D 0; + + rv_detach_trace_probe("ha_percpu", /* XXX: tracepoint */, handle_event0); + rv_detach_trace_probe("ha_percpu", /* XXX: tracepoint */, handle_event1); + rv_detach_trace_probe("ha_percpu", /* XXX: tracepoint */, handle_event2); + + da_monitor_destroy(); +} + +/* + * This is the monitor register section. + */ +static struct rv_monitor rv_this =3D { + .name =3D "ha_percpu", + .description =3D "auto-generated", + .enable =3D enable_ha_percpu, + .disable =3D disable_ha_percpu, + .reset =3D da_monitor_reset_all, + .enabled =3D 0, +}; + +static int __init register_ha_percpu(void) +{ + return rv_register_monitor(&rv_this, NULL); +} + +static void __exit unregister_ha_percpu(void) +{ + rv_unregister_monitor(&rv_this); +} + +module_init(register_ha_percpu); +module_exit(unregister_ha_percpu); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("dot2k: auto-generated"); +MODULE_DESCRIPTION("ha_percpu: auto-generated"); diff --git a/tools/verification/rvgen/tests/golden/ha_percpu/ha_percpu.h b/= tools/verification/rvgen/tests/golden/ha_percpu/ha_percpu.h new file mode 100644 index 000000000000..2538db4f6a26 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/ha_percpu/ha_percpu.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Automatically generated C representation of ha_percpu automaton + * For further information about this format, see kernel documentation: + * Documentation/trace/rv/deterministic_automata.rst + */ + +#define MONITOR_NAME ha_percpu + +enum states_ha_percpu { + S0_ha_percpu, + S1_ha_percpu, + S2_ha_percpu, + S3_ha_percpu, + state_max_ha_percpu, +}; + +#define INVALID_STATE state_max_ha_percpu + +enum events_ha_percpu { + event0_ha_percpu, + event1_ha_percpu, + event2_ha_percpu, + event_max_ha_percpu, +}; + +enum envs_ha_percpu { + clk_ha_percpu, + env1_ha_percpu, + env2_ha_percpu, + env_max_ha_percpu, + env_max_stored_ha_percpu =3D env1_ha_percpu, +}; + +_Static_assert(env_max_stored_ha_percpu <=3D MAX_HA_ENV_LEN, "Not enough s= lots"); +#define HA_CLK_NS + +struct automaton_ha_percpu { + char *state_names[state_max_ha_percpu]; + char *event_names[event_max_ha_percpu]; + char *env_names[env_max_ha_percpu]; + unsigned char function[state_max_ha_percpu][event_max_ha_percpu]; + unsigned char initial_state; + bool final_states[state_max_ha_percpu]; +}; + +static const struct automaton_ha_percpu automaton_ha_percpu =3D { + .state_names =3D { + "S0", + "S1", + "S2", + "S3", + }, + .event_names =3D { + "event0", + "event1", + "event2", + }, + .env_names =3D { + "clk", + "env1", + "env2", + }, + .function =3D { + { S0_ha_percpu, S1_ha_percpu, INVALID_ST= ATE }, + { S0_ha_percpu, INVALID_STATE, S2_ha_per= cpu }, + { INVALID_STATE, S2_ha_percpu, S3_ha_per= cpu }, + { S0_ha_percpu, S1_ha_percpu, INVALID_ST= ATE }, + }, + .initial_state =3D S0_ha_percpu, + .final_states =3D { 1, 0, 0, 0 }, +}; diff --git a/tools/verification/rvgen/tests/golden/ha_percpu/ha_percpu_trac= e.h b/tools/verification/rvgen/tests/golden/ha_percpu/ha_percpu_trace.h new file mode 100644 index 000000000000..074ddff6a60d --- /dev/null +++ b/tools/verification/rvgen/tests/golden/ha_percpu/ha_percpu_trace.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_HA_PERCPU +DEFINE_EVENT(event_da_monitor, event_ha_percpu, + 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_ha_percpu, + TP_PROTO(char *state, char *event), + TP_ARGS(state, event)); + +DEFINE_EVENT(error_env_da_monitor, error_env_ha_percpu, + TP_PROTO(char *state, char *event, char *env), + TP_ARGS(state, event, env)); +#endif /* CONFIG_RV_MON_HA_PERCPU */ diff --git a/tools/verification/rvgen/tests/golden/ltl_pertask/Kconfig b/to= ols/verification/rvgen/tests/golden/ltl_pertask/Kconfig new file mode 100644 index 000000000000..b37f46670bfd --- /dev/null +++ b/tools/verification/rvgen/tests/golden/ltl_pertask/Kconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_LTL_PERTASK + depends on RV + # XXX: add dependencies if there + select LTL_MON_EVENTS_ID + bool "ltl_pertask monitor" + help + auto-generated diff --git a/tools/verification/rvgen/tests/golden/ltl_pertask/ltl_pertask.= c b/tools/verification/rvgen/tests/golden/ltl_pertask/ltl_pertask.c new file mode 100644 index 000000000000..1b6897200e4b --- /dev/null +++ b/tools/verification/rvgen/tests/golden/ltl_pertask/ltl_pertask.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "ltl_pertask" + +/* + * XXX: include required tracepoint headers, e.g., + * #include + */ +#include + + +/* + * This is the self-generated part of the monitor. Generally, there is no = need + * to touch this section. + */ +#include "ltl_pertask.h" +#include + +static void ltl_atoms_fetch(struct task_struct *task, struct ltl_monitor *= mon) +{ + /* + * This is called everytime the Buchi automaton is triggered. + * + * This function could be used to fetch the atomic propositions which + * are expensive to trace. It is possible only if the atomic proposition + * does not need to be updated at precise time. + * + * It is recommended to use tracepoints and ltl_atom_update() instead. + */ +} + +static void ltl_atoms_init(struct task_struct *task, struct ltl_monitor *m= on, bool task_creation) +{ + /* + * This should initialize as many atomic propositions as possible. + * + * @task_creation indicates whether the task is being created. This is + * false if the task is already running before the monitor is enabled. + */ + ltl_atom_set(mon, LTL_EVENT_A, true/false); + ltl_atom_set(mon, LTL_EVENT_B, true/false); +} + +/* + * This is the instrumentation part of the monitor. + * + * This is the section where manual work is required. Here the kernel even= ts + * are translated into model's event. + */ +static void handle_example_event(void *data, /* XXX: fill header */) +{ + ltl_atom_update(task, LTL_EVENT_A, true/false); +} + +static int enable_ltl_pertask(void) +{ + int retval; + + retval =3D ltl_monitor_init(); + if (retval) + return retval; + + rv_attach_trace_probe("ltl_pertask", /* XXX: tracepoint */, handle_exampl= e_event); + + return 0; +} + +static void disable_ltl_pertask(void) +{ + rv_detach_trace_probe("ltl_pertask", /* XXX: tracepoint */, handle_sample= _event); + + ltl_monitor_destroy(); +} + +/* + * This is the monitor register section. + */ +static struct rv_monitor rv_ltl_pertask =3D { + .name =3D "ltl_pertask", + .description =3D "auto-generated", + .enable =3D enable_ltl_pertask, + .disable =3D disable_ltl_pertask, +}; + +static int __init register_ltl_pertask(void) +{ + return rv_register_monitor(&rv_ltl_pertask, NULL); +} + +static void __exit unregister_ltl_pertask(void) +{ + rv_unregister_monitor(&rv_ltl_pertask); +} + +module_init(register_ltl_pertask); +module_exit(unregister_ltl_pertask); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR(/* TODO */); +MODULE_DESCRIPTION("ltl_pertask: auto-generated"); diff --git a/tools/verification/rvgen/tests/golden/ltl_pertask/ltl_pertask.= h b/tools/verification/rvgen/tests/golden/ltl_pertask/ltl_pertask.h new file mode 100644 index 000000000000..7e5de351b8fa --- /dev/null +++ b/tools/verification/rvgen/tests/golden/ltl_pertask/ltl_pertask.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * C implementation of Buchi automaton, automatically generated by + * tools/verification/rvgen from the linear temporal logic specification. + * For further information, see kernel documentation: + * Documentation/trace/rv/linear_temporal_logic.rst + */ + +#include + +#define MONITOR_NAME ltl_pertask + +enum ltl_atom { + LTL_EVENT_A, + LTL_EVENT_B, + LTL_NUM_ATOM +}; +static_assert(LTL_NUM_ATOM <=3D RV_MAX_LTL_ATOM); + +static const char *ltl_atom_str(enum ltl_atom atom) +{ + static const char *const names[] =3D { + "ev_a", + "ev_b", + }; + + return names[atom]; +} + +enum ltl_buchi_state { + S0, + S1, + S2, + S3, + S4, + RV_NUM_BA_STATES +}; +static_assert(RV_NUM_BA_STATES <=3D RV_MAX_BA_STATES); + +static void ltl_start(struct task_struct *task, struct ltl_monitor *mon) +{ + bool event_b =3D test_bit(LTL_EVENT_B, mon->atoms); + bool event_a =3D test_bit(LTL_EVENT_A, mon->atoms); + bool val1 =3D !event_a; + + if (val1) + __set_bit(S0, mon->states); + if (true) + __set_bit(S1, mon->states); + if (event_b) + __set_bit(S4, mon->states); +} + +static void +ltl_possible_next_states(struct ltl_monitor *mon, unsigned int state, unsi= gned long *next) +{ + bool event_b =3D test_bit(LTL_EVENT_B, mon->atoms); + bool event_a =3D test_bit(LTL_EVENT_A, mon->atoms); + bool val1 =3D !event_a; + + switch (state) { + case S0: + if (val1) + __set_bit(S0, next); + if (true) + __set_bit(S1, next); + if (event_b) + __set_bit(S4, next); + break; + case S1: + if (true) + __set_bit(S1, next); + if (true && val1) + __set_bit(S2, next); + if (event_b && val1) + __set_bit(S3, next); + if (event_b) + __set_bit(S4, next); + break; + case S2: + if (true) + __set_bit(S1, next); + if (true && val1) + __set_bit(S2, next); + if (event_b && val1) + __set_bit(S3, next); + if (event_b) + __set_bit(S4, next); + break; + case S3: + if (val1) + __set_bit(S0, next); + if (true) + __set_bit(S1, next); + if (event_b) + __set_bit(S4, next); + break; + case S4: + if (val1) + __set_bit(S0, next); + if (true) + __set_bit(S1, next); + if (event_b) + __set_bit(S4, next); + break; + } +} diff --git a/tools/verification/rvgen/tests/golden/ltl_pertask/ltl_pertask_= trace.h b/tools/verification/rvgen/tests/golden/ltl_pertask/ltl_pertask_tra= ce.h new file mode 100644 index 000000000000..ebd53621a5b1 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/ltl_pertask/ltl_pertask_trace.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_LTL_PERTASK +DEFINE_EVENT(event_ltl_monitor_id, event_ltl_pertask, + TP_PROTO(struct task_struct *task, char *states, char *atoms, char *= next), + TP_ARGS(task, states, atoms, next)); +DEFINE_EVENT(error_ltl_monitor_id, error_ltl_pertask, + TP_PROTO(struct task_struct *task), + TP_ARGS(task)); +#endif /* CONFIG_RV_MON_LTL_PERTASK */ diff --git a/tools/verification/rvgen/tests/golden/test_container/Kconfig b= /tools/verification/rvgen/tests/golden/test_container/Kconfig new file mode 100644 index 000000000000..2becb65dddad --- /dev/null +++ b/tools/verification/rvgen/tests/golden/test_container/Kconfig @@ -0,0 +1,5 @@ +config RV_MON_TEST_CONTAINER + depends on RV + bool "test_container monitor" + help + Test container for grouping monitors diff --git a/tools/verification/rvgen/tests/golden/test_container/test_cont= ainer.c b/tools/verification/rvgen/tests/golden/test_container/test_contain= er.c new file mode 100644 index 000000000000..984e2eac7196 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/test_container/test_container.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include + +#define MODULE_NAME "test_container" + +#include "test_container.h" + +struct rv_monitor rv_test_container =3D { + .name =3D "test_container", + .description =3D "Test container for grouping monitors", + .enable =3D NULL, + .disable =3D NULL, + .reset =3D NULL, + .enabled =3D 0, +}; + +static int __init register_test_container(void) +{ + return rv_register_monitor(&rv_test_container, NULL); +} + +static void __exit unregister_test_container(void) +{ + rv_unregister_monitor(&rv_test_container); +} + +module_init(register_test_container); +module_exit(unregister_test_container); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("dot2k: auto-generated"); +MODULE_DESCRIPTION("test_container: Test container for grouping monitors"); diff --git a/tools/verification/rvgen/tests/golden/test_container/test_cont= ainer.h b/tools/verification/rvgen/tests/golden/test_container/test_contain= er.h new file mode 100644 index 000000000000..83e434432650 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/test_container/test_container.h @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +extern struct rv_monitor rv_test_container; diff --git a/tools/verification/rvgen/tests/golden/test_da/Kconfig b/tools/= verification/rvgen/tests/golden/test_da/Kconfig new file mode 100644 index 000000000000..0143a148ef34 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/test_da/Kconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_TEST_DA + depends on RV + # XXX: add dependencies if there + select DA_MON_EVENTS_IMPLICIT + bool "test_da monitor" + help + auto-generated diff --git a/tools/verification/rvgen/tests/golden/test_da/test_da.c b/tool= s/verification/rvgen/tests/golden/test_da/test_da.c new file mode 100644 index 000000000000..b63bbf4e35c5 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/test_da/test_da.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "test_da" + +/* + * XXX: include required tracepoint headers, e.g., + * #include + */ +#include + +/* + * This is the self-generated part of the monitor. Generally, there is no = need + * to touch this section. + */ +#define RV_MON_TYPE RV_MON_PER_CPU +#include "test_da.h" +#include + +/* + * This is the instrumentation part of the monitor. + * + * This is the section where manual work is required. Here the kernel even= ts + * are translated into model's event. + * + */ +static void handle_event_1(void *data, /* XXX: fill header */) +{ + da_handle_event(event_1_test_da); +} + +static void handle_event_2(void *data, /* XXX: fill header */) +{ + /* XXX: validate that this event always leads to the initial state */ + da_handle_start_event(event_2_test_da); +} + +static int enable_test_da(void) +{ + int retval; + + retval =3D da_monitor_init(); + if (retval) + return retval; + + rv_attach_trace_probe("test_da", /* XXX: tracepoint */, handle_event_1); + rv_attach_trace_probe("test_da", /* XXX: tracepoint */, handle_event_2); + + return 0; +} + +static void disable_test_da(void) +{ + rv_this.enabled =3D 0; + + rv_detach_trace_probe("test_da", /* XXX: tracepoint */, handle_event_1); + rv_detach_trace_probe("test_da", /* XXX: tracepoint */, handle_event_2); + + da_monitor_destroy(); +} + +/* + * This is the monitor register section. + */ +static struct rv_monitor rv_this =3D { + .name =3D "test_da", + .description =3D "auto-generated", + .enable =3D enable_test_da, + .disable =3D disable_test_da, + .reset =3D da_monitor_reset_all, + .enabled =3D 0, +}; + +static int __init register_test_da(void) +{ + return rv_register_monitor(&rv_this, NULL); +} + +static void __exit unregister_test_da(void) +{ + rv_unregister_monitor(&rv_this); +} + +module_init(register_test_da); +module_exit(unregister_test_da); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("dot2k: auto-generated"); +MODULE_DESCRIPTION("test_da: auto-generated"); diff --git a/tools/verification/rvgen/tests/golden/test_da/test_da.h b/tool= s/verification/rvgen/tests/golden/test_da/test_da.h new file mode 100644 index 000000000000..d55795efbb61 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/test_da/test_da.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Automatically generated C representation of test_da automaton + * For further information about this format, see kernel documentation: + * Documentation/trace/rv/deterministic_automata.rst + */ + +#define MONITOR_NAME test_da + +enum states_test_da { + state_a_test_da, + state_b_test_da, + state_max_test_da, +}; + +#define INVALID_STATE state_max_test_da + +enum events_test_da { + event_1_test_da, + event_2_test_da, + event_max_test_da, +}; + +struct automaton_test_da { + char *state_names[state_max_test_da]; + char *event_names[event_max_test_da]; + unsigned char function[state_max_test_da][event_max_test_da]; + unsigned char initial_state; + bool final_states[state_max_test_da]; +}; + +static const struct automaton_test_da automaton_test_da =3D { + .state_names =3D { + "state_a", + "state_b", + }, + .event_names =3D { + "event_1", + "event_2", + }, + .function =3D { + { state_b_test_da, state_a_test_da }, + { INVALID_STATE, state_a_test_da }, + }, + .initial_state =3D state_a_test_da, + .final_states =3D { 1, 0 }, +}; diff --git a/tools/verification/rvgen/tests/golden/test_da/test_da_trace.h = b/tools/verification/rvgen/tests/golden/test_da/test_da_trace.h new file mode 100644 index 000000000000..8bd67115d244 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/test_da/test_da_trace.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_TEST_DA +DEFINE_EVENT(event_da_monitor, event_test_da, + 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_test_da, + TP_PROTO(char *state, char *event), + TP_ARGS(state, event)); +#endif /* CONFIG_RV_MON_TEST_DA */ diff --git a/tools/verification/rvgen/tests/golden/test_ha/Kconfig b/tools/= verification/rvgen/tests/golden/test_ha/Kconfig new file mode 100644 index 000000000000..f4048290c774 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/test_ha/Kconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_TEST_HA + depends on RV + # XXX: add dependencies if there + select HA_MON_EVENTS_ID + bool "test_ha monitor" + help + auto-generated diff --git a/tools/verification/rvgen/tests/golden/test_ha/test_ha.c b/tool= s/verification/rvgen/tests/golden/test_ha/test_ha.c new file mode 100644 index 000000000000..485fcd0259b6 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/test_ha/test_ha.c @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "test_ha" + +/* + * XXX: include required tracepoint headers, e.g., + * #include + */ +#include + +/* + * This is the self-generated part of the monitor. Generally, there is no = need + * to touch this section. + */ +#define RV_MON_TYPE RV_MON_PER_TASK +/* XXX: If the monitor has several instances, consider HA_TIMER_WHEEL */ +#define HA_TIMER_TYPE HA_TIMER_HRTIMER +#include "test_ha.h" +#include + +/* + * This is the instrumentation part of the monitor. + * + * This is the section where manual work is required. Here the kernel even= ts + * are translated into model's event. + * + */ +#define BAR_NS(ha_mon) /* XXX: what is BAR_NS(ha_mon)? */ + +#define FOO_NS /* XXX: what is FOO_NS? */ + +static inline u64 bar_ns(struct ha_monitor *ha_mon) +{ + return /* XXX: what is bar_ns(ha_mon)? */; +} + +static u64 foo_ns =3D /* XXX: default value */; +module_param(foo_ns, ullong, 0644); + +/* + * These functions define how to read and reset the environment variable. + * + * Common environment variables like ns-based and jiffy-based clocks have + * pre-define getters and resetters you can use. The parser can infer the = type + * of the environment variable if you supply a measure unit in the constra= int. + * If you define your own functions, make sure to add appropriate memory + * barriers if required. + * Some environment variables don't require a storage as they read a system + * state (e.g. preemption count). Those variables are never reset, so we d= on't + * define a reset function on monitors only relying on this type of variab= les. + */ +static u64 ha_get_env(struct ha_monitor *ha_mon, enum envs_test_ha env, u6= 4 time_ns) +{ + if (env =3D=3D clk_test_ha) + return ha_get_clk_ns(ha_mon, env, time_ns); + else if (env =3D=3D env1_test_ha) + return /* XXX: how do I read env1? */ + else if (env =3D=3D env2_test_ha) + return /* XXX: how do I read env2? */ + return ENV_INVALID_VALUE; +} + +static void ha_reset_env(struct ha_monitor *ha_mon, enum envs_test_ha env,= u64 time_ns) +{ + if (env =3D=3D clk_test_ha) + ha_reset_clk_ns(ha_mon, env, time_ns); +} + +/* + * These functions are used to validate state transitions. + * + * They are generated by parsing the model, there is usually no need to ch= ange them. + * If the monitor requires a timer, there are functions responsible to arm= it when + * the next state has a constraint, cancel it in any other case and to che= ck + * that it didn't expire before the callback run. Transitions to the same = state + * without a reset never affect timers. + * Due to the different representations between invariants and guards, the= re is + * a function to convert it in case invariants or guards are reachable from + * another invariant without reset. Those are not present if not required = in + * the model. This is all automatic but is worth checking because it may s= how + * errors in the model (e.g. missing resets). + */ +static inline bool ha_verify_invariants(struct ha_monitor *ha_mon, + enum states curr_state, enum events event, + enum states next_state, u64 time_ns) +{ + if (curr_state =3D=3D S0_test_ha) + return ha_check_invariant_ns(ha_mon, clk_test_ha, time_ns); + else if (curr_state =3D=3D S2_test_ha) + return ha_check_invariant_ns(ha_mon, clk_test_ha, time_ns); + return true; +} + +static inline void ha_convert_inv_guard(struct ha_monitor *ha_mon, + enum states curr_state, enum events event, + enum states next_state, u64 time_ns) +{ + if (curr_state =3D=3D next_state) + return; + if (curr_state =3D=3D S2_test_ha) + ha_inv_to_guard(ha_mon, clk_test_ha, BAR_NS(ha_mon), time_ns); +} + +static inline bool ha_verify_guards(struct ha_monitor *ha_mon, + enum states curr_state, enum events event, + enum states next_state, u64 time_ns) +{ + bool res =3D true; + + if (curr_state =3D=3D S0_test_ha && event =3D=3D event0_test_ha) + ha_reset_env(ha_mon, clk_test_ha, time_ns); + else if (curr_state =3D=3D S0_test_ha && event =3D=3D event1_test_ha) + ha_reset_env(ha_mon, clk_test_ha, time_ns); + else if (curr_state =3D=3D S1_test_ha && event =3D=3D event0_test_ha) + ha_reset_env(ha_mon, clk_test_ha, time_ns); + else if (curr_state =3D=3D S1_test_ha && event =3D=3D event2_test_ha) { + res =3D ha_get_env(ha_mon, env1_test_ha, time_ns) =3D=3D 0ull; + ha_reset_env(ha_mon, clk_test_ha, time_ns); + } else if (curr_state =3D=3D S2_test_ha && event =3D=3D event1_test_ha) + res =3D ha_monitor_env_invalid(ha_mon, clk_test_ha) || + ha_get_env(ha_mon, clk_test_ha, time_ns) < foo_ns; + else if (curr_state =3D=3D S3_test_ha && event =3D=3D event0_test_ha) + res =3D ha_monitor_env_invalid(ha_mon, clk_test_ha) || + (ha_get_env(ha_mon, clk_test_ha, time_ns) < FOO_NS && + ha_get_env(ha_mon, env2_test_ha, time_ns) =3D=3D 0ull); + else if (curr_state =3D=3D S3_test_ha && event =3D=3D event1_test_ha) { + res =3D ha_monitor_env_invalid(ha_mon, clk_test_ha) || + (ha_get_env(ha_mon, clk_test_ha, time_ns) < foo_ns && + ha_get_env(ha_mon, env1_test_ha, time_ns) =3D=3D 1ull); + ha_reset_env(ha_mon, clk_test_ha, time_ns); + } + return res; +} + +static inline void ha_setup_invariants(struct ha_monitor *ha_mon, + enum states curr_state, enum events event, + enum states next_state, u64 time_ns) +{ + if (next_state =3D=3D curr_state && event !=3D event0_test_ha) + return; + if (next_state =3D=3D S0_test_ha) + ha_start_timer_ns(ha_mon, clk_test_ha, bar_ns(ha_mon), time_ns); + else if (next_state =3D=3D S2_test_ha) + ha_start_timer_ns(ha_mon, clk_test_ha, BAR_NS(ha_mon), time_ns); + else if (curr_state =3D=3D S0_test_ha) + ha_cancel_timer(ha_mon); + else if (curr_state =3D=3D S2_test_ha) + ha_cancel_timer(ha_mon); +} + +static bool ha_verify_constraint(struct ha_monitor *ha_mon, + enum states curr_state, enum events event, + enum states next_state, u64 time_ns) +{ + if (!ha_verify_invariants(ha_mon, curr_state, event, next_state, time_ns)) + return false; + + ha_convert_inv_guard(ha_mon, curr_state, event, next_state, time_ns); + + if (!ha_verify_guards(ha_mon, curr_state, event, next_state, time_ns)) + return false; + + ha_setup_invariants(ha_mon, curr_state, event, next_state, time_ns); + + return true; +} + +static void handle_event0(void *data, /* XXX: fill header */) +{ + /* XXX: validate that this event always leads to the initial state */ + struct task_struct *p =3D /* XXX: how do I get p? */; + da_handle_start_event(p, event0_test_ha); +} + +static void handle_event1(void *data, /* XXX: fill header */) +{ + struct task_struct *p =3D /* XXX: how do I get p? */; + da_handle_event(p, event1_test_ha); +} + +static void handle_event2(void *data, /* XXX: fill header */) +{ + struct task_struct *p =3D /* XXX: how do I get p? */; + da_handle_event(p, event2_test_ha); +} + +static int enable_test_ha(void) +{ + int retval; + + retval =3D da_monitor_init(); + if (retval) + return retval; + + rv_attach_trace_probe("test_ha", /* XXX: tracepoint */, handle_event0); + rv_attach_trace_probe("test_ha", /* XXX: tracepoint */, handle_event1); + rv_attach_trace_probe("test_ha", /* XXX: tracepoint */, handle_event2); + + return 0; +} + +static void disable_test_ha(void) +{ + rv_this.enabled =3D 0; + + rv_detach_trace_probe("test_ha", /* XXX: tracepoint */, handle_event0); + rv_detach_trace_probe("test_ha", /* XXX: tracepoint */, handle_event1); + rv_detach_trace_probe("test_ha", /* XXX: tracepoint */, handle_event2); + + da_monitor_destroy(); +} + +/* + * This is the monitor register section. + */ +static struct rv_monitor rv_this =3D { + .name =3D "test_ha", + .description =3D "auto-generated", + .enable =3D enable_test_ha, + .disable =3D disable_test_ha, + .reset =3D da_monitor_reset_all, + .enabled =3D 0, +}; + +static int __init register_test_ha(void) +{ + return rv_register_monitor(&rv_this, NULL); +} + +static void __exit unregister_test_ha(void) +{ + rv_unregister_monitor(&rv_this); +} + +module_init(register_test_ha); +module_exit(unregister_test_ha); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("dot2k: auto-generated"); +MODULE_DESCRIPTION("test_ha: auto-generated"); diff --git a/tools/verification/rvgen/tests/golden/test_ha/test_ha.h b/tool= s/verification/rvgen/tests/golden/test_ha/test_ha.h new file mode 100644 index 000000000000..949fa4453403 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/test_ha/test_ha.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Automatically generated C representation of test_ha automaton + * For further information about this format, see kernel documentation: + * Documentation/trace/rv/deterministic_automata.rst + */ + +#define MONITOR_NAME test_ha + +enum states_test_ha { + S0_test_ha, + S1_test_ha, + S2_test_ha, + S3_test_ha, + state_max_test_ha, +}; + +#define INVALID_STATE state_max_test_ha + +enum events_test_ha { + event0_test_ha, + event1_test_ha, + event2_test_ha, + event_max_test_ha, +}; + +enum envs_test_ha { + clk_test_ha, + env1_test_ha, + env2_test_ha, + env_max_test_ha, + env_max_stored_test_ha =3D env1_test_ha, +}; + +_Static_assert(env_max_stored_test_ha <=3D MAX_HA_ENV_LEN, "Not enough slo= ts"); +#define HA_CLK_NS + +struct automaton_test_ha { + char *state_names[state_max_test_ha]; + char *event_names[event_max_test_ha]; + char *env_names[env_max_test_ha]; + unsigned char function[state_max_test_ha][event_max_test_ha]; + unsigned char initial_state; + bool final_states[state_max_test_ha]; +}; + +static const struct automaton_test_ha automaton_test_ha =3D { + .state_names =3D { + "S0", + "S1", + "S2", + "S3", + }, + .event_names =3D { + "event0", + "event1", + "event2", + }, + .env_names =3D { + "clk", + "env1", + "env2", + }, + .function =3D { + { S0_test_ha, S1_test_ha, INVALID_STATE }, + { S0_test_ha, INVALID_STATE, S2_test_ha }, + { INVALID_STATE, S2_test_ha, S3_test_ha }, + { S0_test_ha, S1_test_ha, INVALID_STATE }, + }, + .initial_state =3D S0_test_ha, + .final_states =3D { 1, 0, 0, 0 }, +}; diff --git a/tools/verification/rvgen/tests/golden/test_ha/test_ha_trace.h = b/tools/verification/rvgen/tests/golden/test_ha/test_ha_trace.h new file mode 100644 index 000000000000..381bafcb3322 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/test_ha/test_ha_trace.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_TEST_HA +DEFINE_EVENT(event_da_monitor_id, event_test_ha, + 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_test_ha, + TP_PROTO(int id, char *state, char *event), + TP_ARGS(id, state, event)); + +DEFINE_EVENT(error_env_da_monitor_id, error_env_test_ha, + TP_PROTO(int id, char *state, char *event, char *env), + TP_ARGS(id, state, event, env)); +#endif /* CONFIG_RV_MON_TEST_HA */ diff --git a/tools/verification/rvgen/tests/golden/test_ltl/Kconfig b/tools= /verification/rvgen/tests/golden/test_ltl/Kconfig new file mode 100644 index 000000000000..e2d0e721f180 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/test_ltl/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_TEST_LTL + depends on RV + # XXX: add dependencies if there + depends on RV_MON_LTL_PARENT + default y + select LTL_MON_EVENTS_ID + bool "test_ltl monitor" + help + Simple description diff --git a/tools/verification/rvgen/tests/golden/test_ltl/test_ltl.c b/to= ols/verification/rvgen/tests/golden/test_ltl/test_ltl.c new file mode 100644 index 000000000000..92c69b9d9a41 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/test_ltl/test_ltl.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "test_ltl" + +/* + * XXX: include required tracepoint headers, e.g., + * #include + */ +#include +#include + + +/* + * This is the self-generated part of the monitor. Generally, there is no = need + * to touch this section. + */ +#include "test_ltl.h" +#include + +static void ltl_atoms_fetch(struct task_struct *task, struct ltl_monitor *= mon) +{ + /* + * This is called everytime the Buchi automaton is triggered. + * + * This function could be used to fetch the atomic propositions which + * are expensive to trace. It is possible only if the atomic proposition + * does not need to be updated at precise time. + * + * It is recommended to use tracepoints and ltl_atom_update() instead. + */ +} + +static void ltl_atoms_init(struct task_struct *task, struct ltl_monitor *m= on, bool task_creation) +{ + /* + * This should initialize as many atomic propositions as possible. + * + * @task_creation indicates whether the task is being created. This is + * false if the task is already running before the monitor is enabled. + */ + ltl_atom_set(mon, LTL_EVENT_A, true/false); + ltl_atom_set(mon, LTL_EVENT_B, true/false); +} + +/* + * This is the instrumentation part of the monitor. + * + * This is the section where manual work is required. Here the kernel even= ts + * are translated into model's event. + */ +static void handle_example_event(void *data, /* XXX: fill header */) +{ + ltl_atom_update(task, LTL_EVENT_A, true/false); +} + +static int enable_test_ltl(void) +{ + int retval; + + retval =3D ltl_monitor_init(); + if (retval) + return retval; + + rv_attach_trace_probe("test_ltl", /* XXX: tracepoint */, handle_example_e= vent); + + return 0; +} + +static void disable_test_ltl(void) +{ + rv_detach_trace_probe("test_ltl", /* XXX: tracepoint */, handle_sample_ev= ent); + + ltl_monitor_destroy(); +} + +/* + * This is the monitor register section. + */ +static struct rv_monitor rv_test_ltl =3D { + .name =3D "test_ltl", + .description =3D "Simple description", + .enable =3D enable_test_ltl, + .disable =3D disable_test_ltl, +}; + +static int __init register_test_ltl(void) +{ + return rv_register_monitor(&rv_test_ltl, &rv_ltl_parent); +} + +static void __exit unregister_test_ltl(void) +{ + rv_unregister_monitor(&rv_test_ltl); +} + +module_init(register_test_ltl); +module_exit(unregister_test_ltl); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR(/* TODO */); +MODULE_DESCRIPTION("test_ltl: Simple description"); diff --git a/tools/verification/rvgen/tests/golden/test_ltl/test_ltl.h b/to= ols/verification/rvgen/tests/golden/test_ltl/test_ltl.h new file mode 100644 index 000000000000..7895f2e233e8 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/test_ltl/test_ltl.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * C implementation of Buchi automaton, automatically generated by + * tools/verification/rvgen from the linear temporal logic specification. + * For further information, see kernel documentation: + * Documentation/trace/rv/linear_temporal_logic.rst + */ + +#include + +#define MONITOR_NAME test_ltl + +enum ltl_atom { + LTL_EVENT_A, + LTL_EVENT_B, + LTL_NUM_ATOM +}; +static_assert(LTL_NUM_ATOM <=3D RV_MAX_LTL_ATOM); + +static const char *ltl_atom_str(enum ltl_atom atom) +{ + static const char *const names[] =3D { + "ev_a", + "ev_b", + }; + + return names[atom]; +} + +enum ltl_buchi_state { + S0, + S1, + S2, + S3, + S4, + RV_NUM_BA_STATES +}; +static_assert(RV_NUM_BA_STATES <=3D RV_MAX_BA_STATES); + +static void ltl_start(struct task_struct *task, struct ltl_monitor *mon) +{ + bool event_b =3D test_bit(LTL_EVENT_B, mon->atoms); + bool event_a =3D test_bit(LTL_EVENT_A, mon->atoms); + bool val1 =3D !event_a; + + if (val1) + __set_bit(S0, mon->states); + if (true) + __set_bit(S1, mon->states); + if (event_b) + __set_bit(S4, mon->states); +} + +static void +ltl_possible_next_states(struct ltl_monitor *mon, unsigned int state, unsi= gned long *next) +{ + bool event_b =3D test_bit(LTL_EVENT_B, mon->atoms); + bool event_a =3D test_bit(LTL_EVENT_A, mon->atoms); + bool val1 =3D !event_a; + + switch (state) { + case S0: + if (val1) + __set_bit(S0, next); + if (true) + __set_bit(S1, next); + if (event_b) + __set_bit(S4, next); + break; + case S1: + if (true) + __set_bit(S1, next); + if (true && val1) + __set_bit(S2, next); + if (event_b && val1) + __set_bit(S3, next); + if (event_b) + __set_bit(S4, next); + break; + case S2: + if (true) + __set_bit(S1, next); + if (true && val1) + __set_bit(S2, next); + if (event_b && val1) + __set_bit(S3, next); + if (event_b) + __set_bit(S4, next); + break; + case S3: + if (val1) + __set_bit(S0, next); + if (true) + __set_bit(S1, next); + if (event_b) + __set_bit(S4, next); + break; + case S4: + if (val1) + __set_bit(S0, next); + if (true) + __set_bit(S1, next); + if (event_b) + __set_bit(S4, next); + break; + } +} diff --git a/tools/verification/rvgen/tests/golden/test_ltl/test_ltl_trace.= h b/tools/verification/rvgen/tests/golden/test_ltl/test_ltl_trace.h new file mode 100644 index 000000000000..3571b004c114 --- /dev/null +++ b/tools/verification/rvgen/tests/golden/test_ltl/test_ltl_trace.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_TEST_LTL +DEFINE_EVENT(event_ltl_monitor_id, event_test_ltl, + TP_PROTO(struct task_struct *task, char *states, char *atoms, char *= next), + TP_ARGS(task, states, atoms, next)); +DEFINE_EVENT(error_ltl_monitor_id, error_test_ltl, + TP_PROTO(struct task_struct *task), + TP_ARGS(task)); +#endif /* CONFIG_RV_MON_TEST_LTL */ diff --git a/tools/verification/rvgen/tests/specs/test_da.dot b/tools/verif= ication/rvgen/tests/specs/test_da.dot new file mode 100644 index 000000000000..e555c239b221 --- /dev/null +++ b/tools/verification/rvgen/tests/specs/test_da.dot @@ -0,0 +1,16 @@ +digraph state_automaton { + {node [shape =3D circle] "state_b"}; + {node [shape =3D plaintext, style=3Dinvis, label=3D""] "__init_state_a"}; + {node [shape =3D doublecircle] "state_a"}; + {node [shape =3D circle] "state_a"}; + "__init_state_a" -> "state_a"; + "state_a" [label =3D "state_a"]; + "state_a" -> "state_a" [ label =3D "event_2" ]; + "state_a" -> "state_b" [ label =3D "event_1" ]; + "state_b" [label =3D "state_b"]; + "state_b" -> "state_a" [ label =3D "event_2" ]; + { rank =3D min ; + "__init_state_a"; + "state_a"; + } +} diff --git a/tools/verification/rvgen/tests/specs/test_da2.dot b/tools/veri= fication/rvgen/tests/specs/test_da2.dot new file mode 100644 index 000000000000..cdd4192f58ae --- /dev/null +++ b/tools/verification/rvgen/tests/specs/test_da2.dot @@ -0,0 +1,19 @@ +digraph state_automaton { + {node [shape =3D circle] "state_b"}; + {node [shape =3D circle] "state_c"}; + {node [shape =3D plaintext, style=3Dinvis, label=3D""] "__init_state_a"}; + {node [shape =3D doublecircle] "state_a"}; + {node [shape =3D circle] "state_a"}; + "__init_state_a" -> "state_a"; + "state_a" [label =3D "state_a"]; + "state_a" -> "state_b" [ label =3D "event_1" ]; + "state_a" -> "state_c" [ label =3D "event_2" ]; + "state_b" [label =3D "state_b"]; + "state_b" -> "state_a" [ label =3D "event_2" ]; + "state_b" -> "state_c" [ label =3D "event_3" ]; + "state_c" [label =3D "state_c"]; + { rank =3D min ; + "__init_state_a"; + "state_a"; + } +} diff --git a/tools/verification/rvgen/tests/specs/test_ha.dot b/tools/verif= ication/rvgen/tests/specs/test_ha.dot new file mode 100644 index 000000000000..786aa8b22098 --- /dev/null +++ b/tools/verification/rvgen/tests/specs/test_ha.dot @@ -0,0 +1,27 @@ +digraph state_automaton { + center =3D true; + size =3D "7,11"; + {node [shape =3D circle] "S1"}; + {node [shape =3D plaintext, style=3Dinvis, label=3D""] "__init_S0"}; + {node [shape =3D doublecircle] "S0"}; + {node [shape =3D circle] "S0"}; + {node [shape =3D circle] "S2"}; + {node [shape =3D circle] "S3"}; + "__init_S0" -> "S0"; + "S0" [label =3D "S0\nclk < bar_ns()", color =3D green3]; + "S1" [label =3D "S1"]; + "S2" [label =3D "S2\nclk < BAR_NS()"]; + "S3" [label =3D "S3"]; + "S1" -> "S0" [ label =3D "event0;reset(clk)" ]; + "S0" -> "S1" [ label =3D "event1;reset(clk)" ]; + "S0" -> "S0" [ label =3D "event0;reset(clk)" ]; + "S1" -> "S2" [ label =3D "event2;env1 =3D=3D 0;reset(clk)" ]; + "S2" -> "S3" [ label =3D "event2" ]; + "S2" -> "S2" [ label =3D "event1;clk < foo_ns" ]; + "S3" -> "S0" [ label =3D "event0;clk < FOO_NS && env2 =3D=3D 0" ]; + "S3" -> "S1" [ label =3D "event1;clk < foo_ns && env1 =3D=3D 1;reset(clk)= " ]; + { rank =3D min ; + "__init_S0"; + "S0"; + } +} diff --git a/tools/verification/rvgen/tests/specs/test_invalid.dot b/tools/= verification/rvgen/tests/specs/test_invalid.dot new file mode 100644 index 000000000000..17c63fc57f17 --- /dev/null +++ b/tools/verification/rvgen/tests/specs/test_invalid.dot @@ -0,0 +1,8 @@ +digraph invalid { + {node [shape =3D circle] "init"}; + {node [shape =3D circle] "state1"}; + "init" [label =3D "init"]; + "init" -> "state1" [ label =3D "event_a" ]; + "state1" [label =3D "state1"]; + "state1" -> "init" [ label =3D "event_b" ]; +} diff --git a/tools/verification/rvgen/tests/specs/test_invalid.ltl b/tools/= verification/rvgen/tests/specs/test_invalid.ltl new file mode 100644 index 000000000000..cf36307e003c --- /dev/null +++ b/tools/verification/rvgen/tests/specs/test_invalid.ltl @@ -0,0 +1 @@ +RULE =3D A invalid B diff --git a/tools/verification/rvgen/tests/specs/test_invalid_ha.dot b/too= ls/verification/rvgen/tests/specs/test_invalid_ha.dot new file mode 100644 index 000000000000..06de6aa8709f --- /dev/null +++ b/tools/verification/rvgen/tests/specs/test_invalid_ha.dot @@ -0,0 +1,16 @@ +digraph state_automaton { + {node [shape =3D circle] "state_b"}; + {node [shape =3D plaintext, style=3Dinvis, label=3D""] "__init_state_a"}; + {node [shape =3D doublecircle] "state_a"}; + {node [shape =3D circle] "state_a"}; + "__init_state_a" -> "state_a"; + "state_a" [label =3D "state_a;clk < 1"]; + "state_a" -> "state_a" [ label =3D "event_2;reset(clk)" ]; + "state_a" -> "state_b" [ label =3D "event_1;wrong_constraint" ]; + "state_b" [label =3D "state_b"]; + "state_b" -> "state_a" [ label =3D "event_2" ]; + { rank =3D min ; + "__init_state_a"; + "state_a"; + } +} diff --git a/tools/verification/rvgen/tests/specs/test_ltl.ltl b/tools/veri= fication/rvgen/tests/specs/test_ltl.ltl new file mode 100644 index 000000000000..5ed658abd69c --- /dev/null +++ b/tools/verification/rvgen/tests/specs/test_ltl.ltl @@ -0,0 +1 @@ +RULE =3D always (EVENT_A imply eventually EVENT_B) --=20 2.54.0 From nobody Fri Jun 12 13:56:05 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3283C3A0E8A for ; Thu, 14 May 2026 15:22:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772129; cv=none; b=NAx8aWssFCysDq8z3Oc76qRJ6tLoS5w9J3HtVZL4uyLh7U7URo+8IerPmS11nONbgUmQrrTAsQ6tb7KMO4vwG3DIa6eOzpl3pud3rnBwY0eBMmalwnRddIO2Tyg/Tixy0Hh113lkcSBNrb/7UG17vupNoBwBPDzzmFPJppOn0FY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772129; c=relaxed/simple; bh=XMMEG7UqTwK3DMw0IThursZ2BiR/6FtH2DlPAM/ZTEM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JH3H8XMbqhIPC7II3roKY9aZRK3tBOkJEC+hoQ8bDmM+BrcFpZn1j6sLeFdUeMbctaZxPyPlkXlAtgZiD+hrB8k3Qyy4NvTcLyPemBegXGFrwkW1KW+rTjXHS3c9OwBOHaoFaWIqV3fVJRkA2q1g/GlkATf/8BnvwLKatqKKo3I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=O8v6JTkw; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="O8v6JTkw" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778772124; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DhrQpblyteM574X+wOshM6TPUFSbWsgLKOX0WosKIow=; b=O8v6JTkw2bUr7F0lWwJ4h1ghvULUTkj9cHau7uTux/jiu6+/UqVQ618VgLCTVZ+mwj4EFs 9LclzqZCvUjXnFXZknNq8v5B03Kph1zEKO5P3n/S/21hrwHlDff0NbhPTVYvz+r5RyEret 7F7K6i4aXL1M4A7Aw4SPAP73lNt5gKU= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-675-k9P8wOfxN4GM4mdkJr_eWA-1; Thu, 14 May 2026 11:21:59 -0400 X-MC-Unique: k9P8wOfxN4GM4mdkJr_eWA-1 X-Mimecast-MFC-AGG-ID: k9P8wOfxN4GM4mdkJr_eWA_1778772118 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 222471956095; Thu, 14 May 2026 15:21:58 +0000 (UTC) Received: from gmonaco-thinkpadt14gen3.rmtit.csb (unknown [10.44.48.32]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 1798930002DC; Thu, 14 May 2026 15:21:54 +0000 (UTC) From: Gabriele Monaco To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Steven Rostedt , Gabriele Monaco Cc: Nam Cao , Thomas Weissschuh , Tomas Glozar , John Kacur , Wen Yang Subject: [PATCH v2 09/14] verification/rvgen: Add selftests Date: Thu, 14 May 2026 17:20:50 +0200 Message-ID: <20260514152055.229162-10-gmonaco@redhat.com> In-Reply-To: <20260514152055.229162-1-gmonaco@redhat.com> References: <20260514152055.229162-1-gmonaco@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" The rvgen code generator needs validation to ensure it produces correct monitor implementations from input specifications. Add selftests with golden reference outputs covering all monitor classes (DA, HA, LTL) and types (global, per_cpu, per_task, per_obj), including optional features like descriptions and parent monitors. Container generation and error handling (missing files, invalid specifications, missing arguments) are also validated against expected output. Signed-off-by: Gabriele Monaco Acked-by: Nam Cao --- tools/verification/rvgen/Makefile | 4 + .../rvgen/tests/rvgen_container.t | 20 +++++ .../verification/rvgen/tests/rvgen_monitor.t | 87 +++++++++++++++++++ tools/verification/tests/engine.sh | 34 ++++++++ 4 files changed, 145 insertions(+) create mode 100644 tools/verification/rvgen/tests/rvgen_container.t create mode 100644 tools/verification/rvgen/tests/rvgen_monitor.t diff --git a/tools/verification/rvgen/Makefile b/tools/verification/rvgen/M= akefile index cfc4056c1e87..2a2b9e64ea42 100644 --- a/tools/verification/rvgen/Makefile +++ b/tools/verification/rvgen/Makefile @@ -13,6 +13,10 @@ all: .PHONY: clean clean: =20 +.PHONY: check +check: + prove -o --directives -f tests/ + .PHONY: install install: $(INSTALL) rvgen/automata.py -D -m 644 $(DESTDIR)$(PYLIB)/rvgen/automata.= py diff --git a/tools/verification/rvgen/tests/rvgen_container.t b/tools/verif= ication/rvgen/tests/rvgen_container.t new file mode 100644 index 000000000000..fa4fb3db8288 --- /dev/null +++ b/tools/verification/rvgen/tests/rvgen_container.t @@ -0,0 +1,20 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +source ../tests/engine.sh +test_begin + +set_timeout 30s + +# Help tests +check "verify container subcommand help" \ + "$RVGEN container -h" 0 "model_name" "class" + +check_and_compare_folder "container with description" \ + "$RVGEN container -n test_container -D 'Test container for grouping monit= ors'" \ + "test_container" "Writing the monitor into the directory test_container" + +# Error handling tests +check "missing required model_name" \ + "$RVGEN container" 2 "the following arguments are required: -n/--model_na= me" + +test_end diff --git a/tools/verification/rvgen/tests/rvgen_monitor.t b/tools/verific= ation/rvgen/tests/rvgen_monitor.t new file mode 100644 index 000000000000..261476504eee --- /dev/null +++ b/tools/verification/rvgen/tests/rvgen_monitor.t @@ -0,0 +1,87 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +source ../tests/engine.sh +test_begin + +set_timeout 30s + +# Help and basic tests +check "verify help page" \ + "$RVGEN --help" 0 "Generate kernel rv monitor" + +check "verify monitor subcommand help" \ + "$RVGEN monitor --help" 0 "Monitor class" + +# DA monitor tests - test all monitor types +check_and_compare_folder "DA per_cpu (default name)" \ + "$RVGEN monitor -c da -s tests/specs/test_da.dot -t per_cpu" \ + "test_da" "obj-\$(CONFIG_RV_MON_TEST_DA) +=3D monitors/test_da/test_da.o" + +check_and_compare_folder "DA global type" \ + "$RVGEN monitor -c da -s tests/specs/test_da.dot -t global -n da_global" \ + "da_global" "DA_MON_EVENTS_IMPLICIT" + +check_and_compare_folder "DA per_task with description" \ + "$RVGEN monitor -c da -s tests/specs/test_da2.dot -t per_task -n da_perta= sk_desc -D 'Custom description for testing'" \ + "da_pertask_desc" "#include " + +check_and_compare_folder "DA per_obj with parent" \ + "$RVGEN monitor -c da -s tests/specs/test_da2.dot -t per_obj -n da_perobj= _parent -p parent_mon" \ + "da_perobj_parent" "DA_MON_EVENTS_ID" + +# HA monitor tests +check_and_compare_folder "HA per_task (default name)" \ + "$RVGEN monitor -c ha -s tests/specs/test_ha.dot -t per_task" \ + "test_ha" "HA_MON_EVENTS_ID" + +check_and_compare_folder "HA per_cpu type" \ + "$RVGEN monitor -c ha -s tests/specs/test_ha.dot -t per_cpu -n ha_percpu"= \ + "ha_percpu" "HA_MON_EVENTS_IMPLICIT" + +# LTL monitor test +check_and_compare_folder "LTL per_task" \ + "$RVGEN monitor -c ltl -s tests/specs/test_ltl.ltl -t per_task -n ltl_per= task" \ + "ltl_pertask" "source \"kernel/trace/rv/monitors/ltl_pertask/Kconfig\"" + +check_and_compare_folder "LTL per_task with parent and description (defaul= t name)" \ + "$RVGEN monitor -c ltl -s tests/specs/test_ltl.ltl -t per_task -p ltl_par= ent -D 'Simple description'" \ + "test_ltl" "LTL_MON_EVENTS_ID" + +# Error handling tests +check "missing required spec argument" \ + "$RVGEN monitor -c da -t per_cpu" 2 \ + "the following arguments are required: -s/--spec" "Traceback (most recent= call last)" + +check "missing required monitor type" \ + "$RVGEN monitor -c da -s tests/specs/test_da.dot" 2 \ + "the following arguments are required: -t/--monitor_type" "Traceback (mos= t recent call last)" + +check "missing required monitor class" \ + "$RVGEN monitor -s tests/specs/test_da.dot -t per_cpu" 2 \ + "the following arguments are required: -c/--class" "Traceback (most recen= t call last)" + +check "invalid monitor class" \ + "$RVGEN monitor -c invalid -s tests/specs/test_da.dot -t per_cpu" 1 \ + "Unknown monitor class" "Traceback (most recent call last)" + +check "missing dot file" \ + "$RVGEN monitor -c da -s tests/specs/nonexistent.dot -t per_cpu" 1 \ + "No such file or directory" "Traceback (most recent call last)" + +check "missing ltl file" \ + "$RVGEN monitor -c ltl -s tests/specs/nonexistent.ltl -t per_task" 1 \ + "No such file or directory" "Traceback (most recent call last)" + +check "invalid dot file syntax" \ + "$RVGEN monitor -c da -s tests/specs/test_invalid.dot -t per_cpu" 1 \ + "Not a valid .dot format" "Traceback (most recent call last)" + +check "invalid ha file syntax" \ + "$RVGEN monitor -c ha -s tests/specs/test_invalid_ha.dot -t per_obj" 1 \ + "Unrecognised event constraint" "Traceback (most recent call last)" + +check "invalid ltl file syntax" \ + "$RVGEN monitor -c ltl -s tests/specs/test_invalid.ltl -t per_task" 1 \ + "Illegal character 'i'" "Traceback (most recent call last)" + +test_end diff --git a/tools/verification/tests/engine.sh b/tools/verification/tests/= engine.sh index 76cc254ff94c..f86d44460895 100644 --- a/tools/verification/tests/engine.sh +++ b/tools/verification/tests/engine.sh @@ -5,6 +5,8 @@ test_begin() { # included correctly. ctr=3D0 [ -z "$RV" ] && RV=3D"../rv/rv" + [ -z "$RVGEN" ] && RVGEN=3D"python3 ../rvgen" + [ -z "$GOLDEN_DIR" ] && GOLDEN_DIR=3D"tests/golden" [ -n "$TEST_COUNT" ] && echo "1..$TEST_COUNT" } =20 @@ -109,6 +111,38 @@ check_if_exists() { fi } =20 +check_and_compare_folder() { + # Run command, compare generated folder to golden, and cleanup + local desc=3D$1 + local command=3D$2 + local generated_dir=3D$3 + local expected_output=3D$4 + local unexpected_output=3D$5 + local golden_dir=3D"$GOLDEN_DIR/$generated_dir" + + ctr=3D$((ctr + 1)) + if [ -n "$TEST_COUNT" ]; then + rm -rf "$generated_dir" + _check "$desc" "$command" 0 "$expected_output" "$unexpected_output" + + if [ "$fail" -eq 0 ] && [ ! -d "$generated_dir" ]; then + failure "# Generated directory not found: $generated_dir" + fi + + if [ "$fail" -ne 0 ]; then + : + elif ! diff -r "$generated_dir" "$golden_dir" &> /dev/null; then + failure "# Directories differ:" + failbuf+=3D$(diff -r "$generated_dir" "$golden_dir" 2>&1 | sed 's/^/# = /') + failbuf+=3D$'\n' + fi + + report "$1" + + rm -rf "$generated_dir" + fi +} + set_timeout() { TIMEOUT=3D"timeout -v -k 15s $1" } --=20 2.54.0 From nobody Fri Jun 12 13:56:05 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D3BE53DFC9C for ; Thu, 14 May 2026 15:22:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772129; cv=none; b=qExQ8d9DTwMoCNSajYpO2tqFWXHRqcyfwHowYSYI4qkf8ZGrVWFv8Dw0FTymiW4vn9RMVOkjQQjliZo+erNumrxx+pJQ9bWNjfqPZUGpc1c0DofcOsKmOvNNor9eloqtY0zu3BDKGzvDFTwBf+AK2ogY7BX/sMegE4LAWS3BzLE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772129; c=relaxed/simple; bh=pmOAGe2/dKAM04j7AO3NBZ7mElAJOEn2l8Xcwj9rons=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=O6GFJZ0s4ahW7QtC9sfpw1STTTSWbAZ7QfI6sm3jeQHng5zXXunJ1UzOS0DO3ACODB467cgONpwk2oR6Xae4IjpMHKrXjOHE1MrUPEO5NXuuDcwTqm98+LFNMQ8sRJRH5k0yE9tnzehjkWWLOPaW7cqjbN7Tmezqyg61PAAaPtw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=L/C/BO2/; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="L/C/BO2/" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778772126; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=r7WGOCgehfq4wxKxQkvMM756/S2J/BObUI/5cdc840M=; b=L/C/BO2/iWgva1aTtv8ZLGSXy1QcRzFy0mgCyUqeeIkXt5Py1C2zC+L5F+tZPIK6pqegrj n9Bx9qU1AltS97fJlxMUjEaGhFsWOLVWgm+pzyhV0GV8CtyVdJuLl3DhP1UME9V0POjihq OB7xefgMOrb6gV/3Dcf0StG7kn4D9Eg= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-507-cSjYZmE7NDaO0uQk-MT_nw-1; Thu, 14 May 2026 11:22:04 -0400 X-MC-Unique: cSjYZmE7NDaO0uQk-MT_nw-1 X-Mimecast-MFC-AGG-ID: cSjYZmE7NDaO0uQk-MT_nw_1778772122 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8C03C1800371; Thu, 14 May 2026 15:22:02 +0000 (UTC) Received: from gmonaco-thinkpadt14gen3.rmtit.csb (unknown [10.44.48.32]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 47DA730001A2; Thu, 14 May 2026 15:21:58 +0000 (UTC) From: Gabriele Monaco To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Steven Rostedt , Gabriele Monaco , Masami Hiramatsu Cc: Nam Cao , Thomas Weissschuh , Tomas Glozar , John Kacur , Wen Yang Subject: [PATCH v2 10/14] rv: Add KUnit stub to rv_react() and rv_*_task_monitor_slot() Date: Thu, 14 May 2026 17:20:51 +0200 Message-ID: <20260514152055.229162-11-gmonaco@redhat.com> In-Reply-To: <20260514152055.229162-1-gmonaco@redhat.com> References: <20260514152055.229162-1-gmonaco@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Add KUNIT_STATIC_STUB_REDIRECT to allow those functions to be stubbed in a KUnit test. This is useful to catch reaction without creating a custom reactor and going through the effort of setting it from a test. rv_{get/put}_task_monitor_slot() rely on a lock, but this isn't necessary during a unit test, so simply skip the calls. Signed-off-by: Gabriele Monaco Reviewed-by: Nam Cao --- kernel/trace/rv/rv.c | 5 +++++ kernel/trace/rv/rv_reactors.c | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/kernel/trace/rv/rv.c b/kernel/trace/rv/rv.c index ee4e68102f17..f59385a24fa1 100644 --- a/kernel/trace/rv/rv.c +++ b/kernel/trace/rv/rv.c @@ -142,6 +142,7 @@ #include #include #include +#include =20 #ifdef CONFIG_RV_MON_EVENTS #define CREATE_TRACE_POINTS @@ -171,6 +172,8 @@ int rv_get_task_monitor_slot(void) { int i; =20 + KUNIT_STATIC_STUB_REDIRECT(rv_get_task_monitor_slot); + lockdep_assert_held(&rv_interface_lock); =20 if (task_monitor_count =3D=3D CONFIG_RV_PER_TASK_MONITORS) @@ -192,6 +195,8 @@ int rv_get_task_monitor_slot(void) =20 void rv_put_task_monitor_slot(int slot) { + KUNIT_STATIC_STUB_REDIRECT(rv_put_task_monitor_slot, slot); + lockdep_assert_held(&rv_interface_lock); =20 if (slot < 0 || slot >=3D CONFIG_RV_PER_TASK_MONITORS) { diff --git a/kernel/trace/rv/rv_reactors.c b/kernel/trace/rv/rv_reactors.c index 460af07f7aba..3435dcedc7ee 100644 --- a/kernel/trace/rv/rv_reactors.c +++ b/kernel/trace/rv/rv_reactors.c @@ -63,6 +63,7 @@ =20 #include #include +#include =20 #include "rv.h" =20 @@ -468,6 +469,12 @@ void rv_react(struct rv_monitor *monitor, const char *= msg, ...) static DEFINE_WAIT_OVERRIDE_MAP(rv_react_map, LD_WAIT_FREE); va_list args; =20 + __diag_push(); + __diag_ignore(GCC, all, "-Wsuggest-attribute=3Dformat", + "Not a valid __printf() conversion candidate."); + KUNIT_STATIC_STUB_REDIRECT(rv_react, monitor, msg); + __diag_pop(); + if (!rv_reacting_on() || !monitor->react) return; =20 --=20 2.54.0 From nobody Fri Jun 12 13:56:05 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C282E40FDA8 for ; Thu, 14 May 2026 15:22:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772145; cv=none; b=BVOF4oFj9HzPDkp+LZi92XuYozAXe6i0MQ9B8Br3RZ6UvWSMZjPC1vgZZy4uD7dZQrvmPjc6EX9Aa3BBIIQ59PixWSwFRItidjk999rjEo6iJ3M3ZwAHKnBlVSRrQiO3v9haIFAYF+PMcmmgFC82sjH0OI2M+vkPBE/FG7s0PHU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772145; c=relaxed/simple; bh=yED5GptCBeJvjyG7GR3JJ+4/syeDt8ge3n2csFZNFq4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WQPFY2F7VazUEIqx0Z9wxZEOcTNm9nllBW1FAwXU7JJhUqxGFWX8U9ruP8bCcIwyva7hx+Czp5+KfFb31V0alhYZqs4GTpMoY9UbbCYN9AaUjgSpYE4FNhyACcqAm//C3k2VXAjuLHfO46VbOZVeYJckv8cGB0FFYLyx54vbwU8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=c6CDIuOv; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="c6CDIuOv" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778772141; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=kv4F8za0V9Kpcwtw3XsSLhuVZ6m6LjaQMH64pRuS7dM=; b=c6CDIuOvCBPMRcqGEhsW//sX7r5E93CPJO3U6mWCrCLDFT94JeP2jfMAD3qevemLfk/s6J NcgJr9W5bRihrVtRJYGqObvi8oCzZ3fjXopRwGqvGhDBanVZsrPaqEG4h1dvyefe24r931 b2gsYrF3SCkYFtTvKg+MJxHYXIOjTPg= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-215-nwVYFCz1NJOVsbuKHJbeyg-1; Thu, 14 May 2026 11:22:12 -0400 X-MC-Unique: nwVYFCz1NJOVsbuKHJbeyg-1 X-Mimecast-MFC-AGG-ID: nwVYFCz1NJOVsbuKHJbeyg_1778772128 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 54C2E19560A7; Thu, 14 May 2026 15:22:08 +0000 (UTC) Received: from gmonaco-thinkpadt14gen3.rmtit.csb (unknown [10.44.48.32]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 0795230001A2; Thu, 14 May 2026 15:22:04 +0000 (UTC) From: Gabriele Monaco To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Steven Rostedt , Gabriele Monaco , Masami Hiramatsu Cc: Nam Cao , Thomas Weissschuh , Tomas Glozar , John Kacur , Wen Yang Subject: [PATCH v2 11/14] rv: Add KUnit tests for some DA/HA monitors Date: Thu, 14 May 2026 17:20:52 +0200 Message-ID: <20260514152055.229162-12-gmonaco@redhat.com> In-Reply-To: <20260514152055.229162-1-gmonaco@redhat.com> References: <20260514152055.229162-1-gmonaco@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Validate the functionality of DA monitors by injecting events in a controlled environment (KUnit) and expecting reactions. Events handlers are called directly from the monitor source files without using system events and with dummy arguments (e.g. no real tasks). If the provided sequence of events incurs a violation, the test expects the stub version of rv_react() to be called. This testing method can validate the entire monitor implementation since it sits between the monitor and the system (in place of the tracepoints). All sorts of system and timing events can be emulated without affecting the running kernel. Signed-off-by: Gabriele Monaco Reviewed-by: Nam Cao --- include/rv/da_monitor.h | 38 +++++++ include/rv/kunit.h | 41 ++++++++ kernel/trace/rv/Kconfig | 11 ++ kernel/trace/rv/Makefile | 1 + kernel/trace/rv/monitors/nomiss/nomiss.c | 44 ++++++++ kernel/trace/rv/monitors/opid/opid.c | 26 +++++ kernel/trace/rv/monitors/sco/sco.c | 24 +++++ kernel/trace/rv/monitors/sssw/sssw.c | 29 ++++++ kernel/trace/rv/monitors/sts/sts.c | 35 +++++++ kernel/trace/rv/rv_monitors_test.c | 126 +++++++++++++++++++++++ 10 files changed, 375 insertions(+) create mode 100644 include/rv/kunit.h create mode 100644 kernel/trace/rv/rv_monitors_test.c diff --git a/include/rv/da_monitor.h b/include/rv/da_monitor.h index 39765ff6f098..d16a55292f3f 100644 --- a/include/rv/da_monitor.h +++ b/include/rv/da_monitor.h @@ -15,6 +15,7 @@ #define _RV_DA_MONITOR_H =20 #include +#include #include #include #include @@ -817,4 +818,41 @@ static inline void da_reset(da_id_type id, monitor_tar= get target) } #endif /* RV_MON_TYPE */ =20 +#ifdef CONFIG_RV_MONITORS_KUNIT_TEST + +/* + * da_teardown_test - Disable the monitor for a kunit test + */ +static inline void da_teardown_test(void *arg) +{ + struct rv_monitor *rv_this =3D arg; + struct kunit *test =3D kunit_get_current_test(); + + if (test) { + struct rv_kunit_ctx *ctx =3D test->priv; + + RV_KUNIT_EXPECT_NO_REACTION(test, ctx); + } + + rv_this->enabled =3D 0; + da_monitor_destroy(); +} + +/* + * da_prepare_test - Enable the monitor for a kunit test + * + * Do the bare minimum to set up the monitor, make sure it is not active a= nd + * real tracepoint handlers are NOT attached. + */ +static inline void da_prepare_test(struct kunit *test, struct rv_monitor *= rv_this) +{ + KUNIT_ASSERT_FALSE(test, rv_this->enabled); + da_monitor_init(); + rv_this->enabled =3D 1; + + KUNIT_ASSERT_EQ(test, 0, + kunit_add_action_or_reset(test, da_teardown_test, rv_this)); +} +#endif /* CONFIG_RV_MONITORS_KUNIT_TEST */ + #endif diff --git a/include/rv/kunit.h b/include/rv/kunit.h new file mode 100644 index 000000000000..67f6057bd5b1 --- /dev/null +++ b/include/rv/kunit.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2026-2029 Red Hat, Inc. Gabriele Monaco + * + * Declaration of utilities to run KUnit tests. + */ + +#ifndef _RV_KUNIT_H +#define _RV_KUNIT_H + +#ifdef CONFIG_RV_MONITORS_KUNIT_TEST + +#include +#include +#include + +struct rv_kunit_ctx { + int reactions, expected; +}; + +#define RV_KUNIT_EXPECT_REACTION(test, ctx) \ + do { \ + KUNIT_EXPECT_EQ(test, ctx->reactions, ++ctx->expected); \ + if (ctx->reactions !=3D ctx->expected) \ + ctx->expected =3D ctx->reactions; \ + } while (0) + +#define RV_KUNIT_EXPECT_NO_REACTION(test, ctx) \ + do { \ + KUNIT_EXPECT_EQ(test, ctx->reactions, ctx->expected); \ + if (ctx->reactions !=3D ctx->expected) \ + ctx->expected =3D ctx->reactions; \ + } while (0) + +#define RV_KUNIT_EXPECT_REACTION_HERE(test, ctx) = \ + for (int __done =3D ({ RV_KUNIT_EXPECT_NO_REACTION(test, ctx); 0; }); \ + !__done; \ + __done =3D ({ RV_KUNIT_EXPECT_REACTION(test, ctx); 1; })) + +#endif /* CONFIG_RV_MONITORS_KUNIT_TEST */ +#endif /* _RV_KUNIT_H */ diff --git a/kernel/trace/rv/Kconfig b/kernel/trace/rv/Kconfig index 3884b14df375..d7dba4453bd3 100644 --- a/kernel/trace/rv/Kconfig +++ b/kernel/trace/rv/Kconfig @@ -111,3 +111,14 @@ config RV_REACT_PANIC help Enables the panic reactor. The panic reactor emits a printk() message if an exception is found and panic()s the system. + +config RV_MONITORS_KUNIT_TEST + bool "KUnit tests for RV monitors" if !KUNIT_ALL_TESTS + depends on KUNIT=3Dy && RV + default KUNIT_ALL_TESTS + help + Enable KUnit tests for the RV (Runtime Verification) monitors. + These tests verify that monitors correctly detect violations by + triggering fake events and validating the expected reactions. + + If unsure, say N. diff --git a/kernel/trace/rv/Makefile b/kernel/trace/rv/Makefile index 94498da35b37..a3502b7fe7f2 100644 --- a/kernel/trace/rv/Makefile +++ b/kernel/trace/rv/Makefile @@ -24,3 +24,4 @@ obj-$(CONFIG_RV_MON_NOMISS) +=3D monitors/nomiss/nomiss.o obj-$(CONFIG_RV_REACTORS) +=3D rv_reactors.o obj-$(CONFIG_RV_REACT_PRINTK) +=3D reactor_printk.o obj-$(CONFIG_RV_REACT_PANIC) +=3D reactor_panic.o +obj-$(CONFIG_RV_MONITORS_KUNIT_TEST) +=3D rv_monitors_test.o diff --git a/kernel/trace/rv/monitors/nomiss/nomiss.c b/kernel/trace/rv/mon= itors/nomiss/nomiss.c index 31f90f3638d8..a0b5641a1858 100644 --- a/kernel/trace/rv/monitors/nomiss/nomiss.c +++ b/kernel/trace/rv/monitors/nomiss/nomiss.c @@ -291,3 +291,47 @@ module_exit(unregister_nomiss); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Gabriele Monaco "); MODULE_DESCRIPTION("nomiss: dl entities run to completion before their dea= dline."); + +#ifdef CONFIG_RV_MONITORS_KUNIT_TEST +void rv_test_nomiss(struct kunit *test); + +void rv_test_nomiss(struct kunit *test) +{ + struct task_struct *target, *other; + struct rv_kunit_ctx *ctx =3D test->priv; + + da_prepare_test(test, &rv_this); + target =3D kunit_kzalloc(test, sizeof(struct task_struct), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, target); + other =3D kunit_kzalloc(test, sizeof(struct task_struct), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, other); + + if (IS_ENABLED(CONFIG_SMP)) { + if (!IS_ENABLED(CONFIG_THREAD_INFO_IN_TASK)) { + target->stack =3D kunit_kzalloc(test, sizeof(struct thread_info), GFP_K= ERNEL); + KUNIT_ASSERT_NOT_NULL(test, target->stack); + other->stack =3D kunit_kzalloc(test, sizeof(struct thread_info), GFP_KE= RNEL); + KUNIT_ASSERT_NOT_NULL(test, other->stack); + } + task_thread_info(target)->cpu =3D 0; + task_thread_info(other)->cpu =3D 0; + } + + target->pid =3D 99; + target->policy =3D SCHED_DEADLINE; + target->dl.runtime =3D 10000; + target->dl.dl_deadline =3D 20000; + + handle_newtask(NULL, target, 0); + + /* Task gets preempted and can't terminate before deadline */ + handle_sched_switch(NULL, 0, other, target, TASK_RUNNING); + handle_dl_replenish(NULL, &target->dl, 0, DL_TASK); + udelay(10); + handle_sched_switch(NULL, 0, target, other, TASK_RUNNING); + udelay(10 + deadline_thresh / 1000); + RV_KUNIT_EXPECT_REACTION_HERE(test, ctx) + handle_sched_switch(NULL, 0, other, target, TASK_RUNNING); +} +EXPORT_SYMBOL_GPL(rv_test_nomiss); +#endif diff --git a/kernel/trace/rv/monitors/opid/opid.c b/kernel/trace/rv/monitor= s/opid/opid.c index 4594c7c46601..124dd043999f 100644 --- a/kernel/trace/rv/monitors/opid/opid.c +++ b/kernel/trace/rv/monitors/opid/opid.c @@ -121,3 +121,29 @@ module_exit(unregister_opid); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Gabriele Monaco "); MODULE_DESCRIPTION("opid: operations with preemption and irq disabled."); + +#ifdef CONFIG_RV_MONITORS_KUNIT_TEST +void rv_test_opid(struct kunit *test); + +void rv_test_opid(struct kunit *test) +{ + struct rv_kunit_ctx *ctx =3D test->priv; + + da_prepare_test(test, &rv_this); + + /* Ensure we keep the same per-cpu monitor */ + guard(migrate)(); + KUNIT_EXPECT_TRUE(test, preemptible()); + + /* Wakeup with preemption and interrupts enabled */ + RV_KUNIT_EXPECT_REACTION_HERE(test, ctx) + handle_sched_waking(NULL, NULL); + + /* Need resched with interrupts enabled */ + RV_KUNIT_EXPECT_REACTION_HERE(test, ctx) { + scoped_guard(preempt) + handle_sched_need_resched(NULL, NULL, 0, TIF_NEED_RESCHED); + } +} +EXPORT_SYMBOL_GPL(rv_test_opid); +#endif diff --git a/kernel/trace/rv/monitors/sco/sco.c b/kernel/trace/rv/monitors/= sco/sco.c index 5a3bd5e16e62..40eab946574b 100644 --- a/kernel/trace/rv/monitors/sco/sco.c +++ b/kernel/trace/rv/monitors/sco/sco.c @@ -83,3 +83,27 @@ module_exit(unregister_sco); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Gabriele Monaco "); MODULE_DESCRIPTION("sco: scheduling context operations."); + +#ifdef CONFIG_RV_MONITORS_KUNIT_TEST +void rv_test_sco(struct kunit *test); + +void rv_test_sco(struct kunit *test) +{ + struct task_struct *target; + struct rv_kunit_ctx *ctx =3D test->priv; + + da_prepare_test(test, &rv_this); + target =3D kunit_kzalloc(test, sizeof(struct task_struct), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, target); + + /* Ensure we keep the same per-cpu monitor */ + guard(migrate)(); + + /* Set state while scheduling */ + handle_sched_set_state(NULL, target, TASK_INTERRUPTIBLE); + handle_schedule_entry(NULL, false); + RV_KUNIT_EXPECT_REACTION_HERE(test, ctx) + handle_sched_set_state(NULL, target, TASK_INTERRUPTIBLE); +} +EXPORT_SYMBOL_GPL(rv_test_sco); +#endif diff --git a/kernel/trace/rv/monitors/sssw/sssw.c b/kernel/trace/rv/monitor= s/sssw/sssw.c index a91321c890cd..6d33b740474c 100644 --- a/kernel/trace/rv/monitors/sssw/sssw.c +++ b/kernel/trace/rv/monitors/sssw/sssw.c @@ -112,3 +112,32 @@ module_exit(unregister_sssw); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Gabriele Monaco "); MODULE_DESCRIPTION("sssw: set state sleep and wakeup."); + +#ifdef CONFIG_RV_MONITORS_KUNIT_TEST +void rv_test_sssw(struct kunit *test); + +void rv_test_sssw(struct kunit *test) +{ + struct task_struct *target, *other; + struct rv_kunit_ctx *ctx =3D test->priv; + + da_prepare_test(test, &rv_this); + target =3D kunit_kzalloc(test, sizeof(struct task_struct), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, target); + other =3D kunit_kzalloc(test, sizeof(struct task_struct), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, other); + + /* Suspend without setting to sleepable */ + handle_sched_set_state(NULL, target, TASK_RUNNING); + RV_KUNIT_EXPECT_REACTION_HERE(test, ctx) + handle_sched_switch(NULL, 0, target, other, TASK_INTERRUPTIBLE); + + /* Switch in after suspension without wakeup */ + handle_sched_wakeup(NULL, target); + handle_sched_set_state(NULL, target, TASK_INTERRUPTIBLE); + handle_sched_switch(NULL, 0, target, other, TASK_INTERRUPTIBLE); + RV_KUNIT_EXPECT_REACTION_HERE(test, ctx) + handle_sched_switch(NULL, 0, other, target, TASK_RUNNING); +} +EXPORT_SYMBOL_GPL(rv_test_sssw); +#endif diff --git a/kernel/trace/rv/monitors/sts/sts.c b/kernel/trace/rv/monitors/= sts/sts.c index ce031cbf202a..587ec44fb509 100644 --- a/kernel/trace/rv/monitors/sts/sts.c +++ b/kernel/trace/rv/monitors/sts/sts.c @@ -152,3 +152,38 @@ module_exit(unregister_sts); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Gabriele Monaco "); MODULE_DESCRIPTION("sts: schedule implies task switch."); + +#ifdef CONFIG_RV_MONITORS_KUNIT_TEST +void rv_test_sts(struct kunit *test); + +void rv_test_sts(struct kunit *test) +{ + struct task_struct *target, *other; + struct rv_kunit_ctx *ctx =3D test->priv; + + da_prepare_test(test, &rv_this); + target =3D kunit_kzalloc(test, sizeof(struct task_struct), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, target); + other =3D kunit_kzalloc(test, sizeof(struct task_struct), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, other); + /* Per-CPU monitor, make sure we don't change CPU mid-test */ + guard(migrate)(); + + /* Switch without disabling interrupts */ + handle_schedule_exit(NULL, false); + handle_schedule_entry(NULL, false); + RV_KUNIT_EXPECT_REACTION_HERE(test, ctx) + handle_sched_switch(NULL, 0, target, other, TASK_RUNNING); + + handle_schedule_exit(NULL, false); + + /* Schedule from interrupt context */ + handle_schedule_entry(NULL, false); + handle_irq_disable(NULL, 0, 0); + handle_irq_entry(NULL, 0, NULL); + RV_KUNIT_EXPECT_REACTION_HERE(test, ctx) + handle_sched_switch(NULL, 0, target, other, TASK_RUNNING); + handle_irq_enable(NULL, 0, 0); +} +EXPORT_SYMBOL_GPL(rv_test_sts); +#endif diff --git a/kernel/trace/rv/rv_monitors_test.c b/kernel/trace/rv/rv_monito= rs_test.c new file mode 100644 index 000000000000..5a12a109c1ed --- /dev/null +++ b/kernel/trace/rv/rv_monitors_test.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2026-2029 Red Hat, Inc. Gabriele Monaco + * + * RV monitor kunit tests: + * Tests the RV monitors by triggering fake events to verify monitor + * behavior and reactions. Tests start from the first defined event and + * trigger events in order to verify error detection. + */ +#include +#include +#include +#include +#include +#include "rv.h" + +__printf(2, 3) +static void stub_rv_react(struct rv_monitor *monitor, const char *msg, ...) +{ + struct rv_kunit_ctx *ctx =3D kunit_get_current_test()->priv; + + ++ctx->reactions; +} + +static int stub_rv_get_task_monitor_slot(void) +{ + return 0; +} + +static void stub_rv_put_task_monitor_slot(int slot) +{ +} + +static int rv_mon_test_init(struct kunit *test) +{ + struct rv_kunit_ctx *ctx; + + ctx =3D kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + test->priv =3D ctx; + + __diag_push(); + __diag_ignore(GCC, all, "-Wsuggest-attribute=3Dformat", + "Not a valid __printf() conversion candidate."); + kunit_activate_static_stub(test, rv_react, stub_rv_react); + __diag_pop(); + kunit_activate_static_stub(test, rv_get_task_monitor_slot, + stub_rv_get_task_monitor_slot); + kunit_activate_static_stub(test, rv_put_task_monitor_slot, + stub_rv_put_task_monitor_slot); + + return 0; +} + +/* + * rv_set_testing - ensure mutual exclusion between KUnit tests and real m= onitors + * + * KUnit tests for RV monitors rely on stubs that are incompatible with + * the execution of real monitors. Ensure mutual exclusion by acquiring + * the rv_interface_lock for the duration of the suite. + * + * Returns 0 on success, -EBUSY if any real monitor is already enabled. + */ +static int rv_set_testing(struct kunit_suite *suite) +{ + struct rv_monitor *mon; + + mutex_lock(&rv_interface_lock); + + list_for_each_entry(mon, &rv_monitors_list, list) { + if (mon->enabled) { + mutex_unlock(&rv_interface_lock); + return -EBUSY; + } + } + + rv_mon_test_running =3D true; + + return 0; +} + +/* + * rv_clear_testing - allow real monitors to run again after KUnit tests + */ +static void rv_clear_testing(struct kunit_suite *suite) +{ + mutex_unlock(&rv_interface_lock); +} + +static void rv_test_stub(struct kunit *test) +{ + kunit_skip(test, "Monitor not enabled\n"); +} + +#define DECLARE_RV_TEST(name) \ + void name(struct kunit *test) __weak __alias(rv_test_stub) + +DECLARE_RV_TEST(rv_test_sco); +DECLARE_RV_TEST(rv_test_sssw); +DECLARE_RV_TEST(rv_test_sts); +DECLARE_RV_TEST(rv_test_opid); +DECLARE_RV_TEST(rv_test_nomiss); + +static struct kunit_case rv_mon_test_cases[] =3D { + KUNIT_CASE(rv_test_sco), + KUNIT_CASE(rv_test_sssw), + KUNIT_CASE(rv_test_sts), + KUNIT_CASE(rv_test_opid), + KUNIT_CASE(rv_test_nomiss), + {} +}; + +static struct kunit_suite rv_mon_test_suite =3D { + .name =3D "rv_mon", + .suite_init =3D rv_set_testing, + .suite_exit =3D rv_clear_testing, + .init =3D rv_mon_test_init, + .test_cases =3D rv_mon_test_cases, +}; + +kunit_test_suites(&rv_mon_test_suite); + +MODULE_AUTHOR("Gabriele Monaco "); +MODULE_DESCRIPTION("RV monitor kunit tests: test monitors by triggering re= actions"); +MODULE_LICENSE("GPL"); --=20 2.54.0 From nobody Fri Jun 12 13:56:05 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A054931987D for ; Thu, 14 May 2026 15:22:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772146; cv=none; b=ED6x71PJB2MKAe8xO2BGHlfi1k0B/Iwn5eRP4/wjN5g85E5woOR8IN8/LGre2suHAP47Wr93Qy2CHMCANVGPaLbWLmo90V0sDaJjPQpJ2gpRsrGEXh31VKR/AtV/DSkCJkk2fudlcgNWoRADNeFgeEAZiboWwVVAiYSXaDs6KI4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772146; c=relaxed/simple; bh=rIR3orqeq30/B2cWeDokb1/lUwP3UL81WE4O8yn1hrs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OxWWc44ift5Pb3M74qnvkSuN5OibevWVF9Ul75TxTpJHk+4PW4CFv8Y5WHJpWPw0hgGVP7HpZFXfnASfUe/XOu7XWuAi6BaP9U/JWK7wffRQMEjyJhiFX/c/CDMmkvMx9tBng+OnRboGE9Izo/34KENvSV1RieEuVaPnVuDNLpM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=BbrMLbq3; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="BbrMLbq3" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778772143; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cQ1EmTIT9OQO80HWrb/E3MPx3//XTk3Mk07UYKCdZFQ=; b=BbrMLbq33lmqG69C7GHNGjpZ45ttVBauL7Aq86STfcqMckt25fHuiCXSsiF+lEbrZTeGlE KayVtBqwRmn9bKpZ46DNM4upg7wZHNmRot3jxt/d8WorTYR+s+7EJ1QIp6qoU5Gky17kr1 HNvVinY2y+p886PY3mMbF1YfidBWv7Y= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-547-JyoqaI7MNCWoP3JMxS8RDA-1; Thu, 14 May 2026 11:22:20 -0400 X-MC-Unique: JyoqaI7MNCWoP3JMxS8RDA-1 X-Mimecast-MFC-AGG-ID: JyoqaI7MNCWoP3JMxS8RDA_1778772134 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 1151218002F0; Thu, 14 May 2026 15:22:14 +0000 (UTC) Received: from gmonaco-thinkpadt14gen3.rmtit.csb (unknown [10.44.48.32]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 0BB9730002DA; Thu, 14 May 2026 15:22:09 +0000 (UTC) From: Gabriele Monaco To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Steven Rostedt , Gabriele Monaco , Masami Hiramatsu Cc: Nam Cao , Thomas Weissschuh , Tomas Glozar , John Kacur , Wen Yang Subject: [PATCH v2 12/14] rv: Add KUnit stubs for current and smp_processor_id() Date: Thu, 14 May 2026 17:20:53 +0200 Message-ID: <20260514152055.229162-13-gmonaco@redhat.com> In-Reply-To: <20260514152055.229162-1-gmonaco@redhat.com> References: <20260514152055.229162-1-gmonaco@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Some monitors do not only rely on tracepoint arguments but also on the currently executing task and current processor. This makes it more challenging to mock events in KUnit. Define wrapper functions around current and smp_processor_id(), the functionality is stubbed only during KUnit, however the additional function call is necessary whenever the KUnit tests are built in. Signed-off-by: Gabriele Monaco Reviewed-by: Nam Cao --- include/rv/kunit.h | 18 ++++++++++++- include/rv/ltl_monitor.h | 1 + kernel/trace/rv/Kconfig | 3 +++ .../trace/rv/monitors/pagefault/pagefault.c | 2 +- kernel/trace/rv/monitors/sleep/sleep.c | 24 ++++++++--------- kernel/trace/rv/rv_monitors_test.c | 26 +++++++++++++++++++ 6 files changed, 60 insertions(+), 14 deletions(-) diff --git a/include/rv/kunit.h b/include/rv/kunit.h index 67f6057bd5b1..3ef83d337880 100644 --- a/include/rv/kunit.h +++ b/include/rv/kunit.h @@ -2,7 +2,10 @@ /* * Copyright (C) 2026-2029 Red Hat, Inc. Gabriele Monaco * - * Declaration of utilities to run KUnit tests. + * Declaration of wrappers to allow stubbing core functionality, like curr= ent + * and smp_processor_id(), and other testing utilities. + * Necessary only when mocking may be needed. If the RV KUnit test is + * enabled, the wrappers incur an additional function call overhead. */ =20 #ifndef _RV_KUNIT_H @@ -14,8 +17,13 @@ #include #include =20 +struct task_struct *rv_get_current(void); +int rv_current_cpu(void); + struct rv_kunit_ctx { int reactions, expected; + int cpu; + struct task_struct *curr; }; =20 #define RV_KUNIT_EXPECT_REACTION(test, ctx) \ @@ -37,5 +45,13 @@ struct rv_kunit_ctx { !__done; \ __done =3D ({ RV_KUNIT_EXPECT_REACTION(test, ctx); 1; })) =20 +#define rv_mock_current(ctx, task) (ctx->curr =3D task) +#define rv_mock_cpu(ctx, cpu) (ctx->cpu =3D cpu) + +#else /* !CONFIG_RV_MONITORS_KUNIT_TEST */ + +#define rv_get_current() current +#define rv_current_cpu() smp_processor_id() + #endif /* CONFIG_RV_MONITORS_KUNIT_TEST */ #endif /* _RV_KUNIT_H */ diff --git a/include/rv/ltl_monitor.h b/include/rv/ltl_monitor.h index eff60cd61106..35bc870d808a 100644 --- a/include/rv/ltl_monitor.h +++ b/include/rv/ltl_monitor.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include =20 diff --git a/kernel/trace/rv/Kconfig b/kernel/trace/rv/Kconfig index d7dba4453bd3..702349e1ddd4 100644 --- a/kernel/trace/rv/Kconfig +++ b/kernel/trace/rv/Kconfig @@ -121,4 +121,7 @@ config RV_MONITORS_KUNIT_TEST These tests verify that monitors correctly detect violations by triggering fake events and validating the expected reactions. =20 + Enabling this may slightly increase overhead of some monitors even + when the KUnit test is not running. + If unsure, say N. diff --git a/kernel/trace/rv/monitors/pagefault/pagefault.c b/kernel/trace/= rv/monitors/pagefault/pagefault.c index 9fe6123b2200..56abe5079676 100644 --- a/kernel/trace/rv/monitors/pagefault/pagefault.c +++ b/kernel/trace/rv/monitors/pagefault/pagefault.c @@ -38,7 +38,7 @@ static void ltl_atoms_init(struct task_struct *task, stru= ct ltl_monitor *mon, bo static void handle_page_fault(void *data, unsigned long address, struct pt= _regs *regs, unsigned long error_code) { - ltl_atom_pulse(current, LTL_PAGEFAULT, true); + ltl_atom_pulse(rv_get_current(), LTL_PAGEFAULT, true); } =20 static int enable_pagefault(void) diff --git a/kernel/trace/rv/monitors/sleep/sleep.c b/kernel/trace/rv/monit= ors/sleep/sleep.c index 8dfe5ec13e19..8b44161d47d3 100644 --- a/kernel/trace/rv/monitors/sleep/sleep.c +++ b/kernel/trace/rv/monitors/sleep/sleep.c @@ -102,7 +102,7 @@ static void handle_sched_waking(void *data, struct task= _struct *task) if (this_cpu_read(hardirq_context)) { ltl_atom_pulse(task, LTL_WOKEN_BY_HARDIRQ, true); } else if (in_task()) { - if (current->prio <=3D task->prio) + if (rv_get_current()->prio <=3D task->prio) ltl_atom_pulse(task, LTL_WOKEN_BY_EQUAL_OR_HIGHER_PRIO, true); } else if (in_nmi()) { ltl_atom_pulse(task, LTL_WOKEN_BY_NMI, true); @@ -112,12 +112,12 @@ static void handle_sched_waking(void *data, struct ta= sk_struct *task) static void handle_contention_begin(void *data, void *lock, unsigned int f= lags) { if (flags & LCB_F_RT) - ltl_atom_update(current, LTL_BLOCK_ON_RT_MUTEX, true); + ltl_atom_update(rv_get_current(), LTL_BLOCK_ON_RT_MUTEX, true); } =20 static void handle_contention_end(void *data, void *lock, int ret) { - ltl_atom_update(current, LTL_BLOCK_ON_RT_MUTEX, false); + ltl_atom_update(rv_get_current(), LTL_BLOCK_ON_RT_MUTEX, false); } =20 static void handle_sys_enter(void *data, struct pt_regs *regs, long id) @@ -126,7 +126,7 @@ static void handle_sys_enter(void *data, struct pt_regs= *regs, long id) unsigned long args[6]; int op, cmd; =20 - mon =3D ltl_get_monitor(current); + mon =3D ltl_get_monitor(rv_get_current()); =20 switch (id) { #ifdef __NR_clock_nanosleep @@ -135,11 +135,11 @@ static void handle_sys_enter(void *data, struct pt_re= gs *regs, long id) #ifdef __NR_clock_nanosleep_time64 case __NR_clock_nanosleep_time64: #endif - syscall_get_arguments(current, regs, args); + syscall_get_arguments(rv_get_current(), regs, args); ltl_atom_set(mon, LTL_NANOSLEEP_CLOCK_MONOTONIC, args[0] =3D=3D CLOCK_MO= NOTONIC); ltl_atom_set(mon, LTL_NANOSLEEP_CLOCK_TAI, args[0] =3D=3D CLOCK_TAI); ltl_atom_set(mon, LTL_NANOSLEEP_TIMER_ABSTIME, args[1] =3D=3D TIMER_ABST= IME); - ltl_atom_update(current, LTL_CLOCK_NANOSLEEP, true); + ltl_atom_update(rv_get_current(), LTL_CLOCK_NANOSLEEP, true); break; =20 #ifdef __NR_futex @@ -148,25 +148,25 @@ static void handle_sys_enter(void *data, struct pt_re= gs *regs, long id) #ifdef __NR_futex_time64 case __NR_futex_time64: #endif - syscall_get_arguments(current, regs, args); + syscall_get_arguments(rv_get_current(), regs, args); op =3D args[1]; cmd =3D op & FUTEX_CMD_MASK; =20 switch (cmd) { case FUTEX_LOCK_PI: case FUTEX_LOCK_PI2: - ltl_atom_update(current, LTL_FUTEX_LOCK_PI, true); + ltl_atom_update(rv_get_current(), LTL_FUTEX_LOCK_PI, true); break; case FUTEX_WAIT: case FUTEX_WAIT_BITSET: case FUTEX_WAIT_REQUEUE_PI: - ltl_atom_update(current, LTL_FUTEX_WAIT, true); + ltl_atom_update(rv_get_current(), LTL_FUTEX_WAIT, true); break; } break; #ifdef __NR_epoll_wait case __NR_epoll_wait: - ltl_atom_update(current, LTL_EPOLL_WAIT, true); + ltl_atom_update(rv_get_current(), LTL_EPOLL_WAIT, true); break; #endif } @@ -174,7 +174,7 @@ static void handle_sys_enter(void *data, struct pt_regs= *regs, long id) =20 static void handle_sys_exit(void *data, struct pt_regs *regs, long ret) { - struct ltl_monitor *mon =3D ltl_get_monitor(current); + struct ltl_monitor *mon =3D ltl_get_monitor(rv_get_current()); =20 ltl_atom_set(mon, LTL_FUTEX_LOCK_PI, false); ltl_atom_set(mon, LTL_FUTEX_WAIT, false); @@ -182,7 +182,7 @@ static void handle_sys_exit(void *data, struct pt_regs = *regs, long ret) ltl_atom_set(mon, LTL_NANOSLEEP_CLOCK_TAI, false); ltl_atom_set(mon, LTL_NANOSLEEP_TIMER_ABSTIME, false); ltl_atom_set(mon, LTL_EPOLL_WAIT, false); - ltl_atom_update(current, LTL_CLOCK_NANOSLEEP, false); + ltl_atom_update(rv_get_current(), LTL_CLOCK_NANOSLEEP, false); } =20 static void handle_kthread_stop(void *data, struct task_struct *task) diff --git a/kernel/trace/rv/rv_monitors_test.c b/kernel/trace/rv/rv_monito= rs_test.c index 5a12a109c1ed..3dbe562f00c1 100644 --- a/kernel/trace/rv/rv_monitors_test.c +++ b/kernel/trace/rv/rv_monitors_test.c @@ -31,6 +31,30 @@ static void stub_rv_put_task_monitor_slot(int slot) { } =20 +struct task_struct *rv_get_current(void) +{ + KUNIT_STATIC_STUB_REDIRECT(rv_get_current); + return current; +} +int rv_current_cpu(void) +{ + KUNIT_STATIC_STUB_REDIRECT(rv_current_cpu); + return smp_processor_id(); +} + +static struct task_struct *stub_rv_get_current(void) +{ + struct rv_kunit_ctx *ctx =3D kunit_get_current_test()->priv; + + return ctx->curr ?: current; +} +static int stub_rv_current_cpu(void) +{ + struct rv_kunit_ctx *ctx =3D kunit_get_current_test()->priv; + + return ctx->cpu; +} + static int rv_mon_test_init(struct kunit *test) { struct rv_kunit_ctx *ctx; @@ -49,6 +73,8 @@ static int rv_mon_test_init(struct kunit *test) stub_rv_get_task_monitor_slot); kunit_activate_static_stub(test, rv_put_task_monitor_slot, stub_rv_put_task_monitor_slot); + kunit_activate_static_stub(test, rv_get_current, stub_rv_get_current); + kunit_activate_static_stub(test, rv_current_cpu, stub_rv_current_cpu); =20 return 0; } --=20 2.54.0 From nobody Fri Jun 12 13:56:05 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9C44242315D for ; Thu, 14 May 2026 15:22:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772146; cv=none; b=D76cfOV04RAAoxBcUH3sfml2gSDN2bLDZc0fTnwgObgve9xCJjsqg86M+PVQ6mIh4y0GCpz81fkUTGrI7Utv2DDI6ZEHxLR7KXOO3ws2ePRGIG5SCUBaw5vj6OCQZcLrMURj9UcjIX85aLc2gh9vkOsRmQpKxvfgXaw2jxfaMV0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772146; c=relaxed/simple; bh=a7E6bNQ7dz1N4RXdiqY6zukq4q8+j7ikFLUQ41WJkHI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=udSTepqJkgd0KDOWOZMA9ku5Ko3L0KfDOIMEA+6XWFm2Diop3mnZlqVgSQujbZhyC7BFhokwCh/Fc2nsxnHLdjR0uqCbh0WJZCq0GarcQMWHXC7/hiZ/NOFUlDAbK7kfn+OVOfwNDXMKKY+xWA6yHr/NFSLfveDQKlkTr7esPR4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=jP1zPFnz; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="jP1zPFnz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778772143; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=aZGfHfNLg7GxzHHU+nQbUU/OieYElwK43G1qeeynGNQ=; b=jP1zPFnzNGgmx/RtVCpJ3deFRmUWurnTo4ECfRJyFhiftDDydbfc6bc8Sk1DzugEBNoQL/ OlujQX2XTMT0QzBwExkb03rIIm6jfpzZZJuCplRtk+BWq5KSoKY/rBEQvGtWNL0xBBbIg3 vNnKqauhYU8U5YWsaQBG5OGXWM+agD4= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-270-F69KfIhKPYi-bXMtszLY4g-1; Thu, 14 May 2026 11:22:20 -0400 X-MC-Unique: F69KfIhKPYi-bXMtszLY4g-1 X-Mimecast-MFC-AGG-ID: F69KfIhKPYi-bXMtszLY4g_1778772139 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D715C18005BB; Thu, 14 May 2026 15:22:18 +0000 (UTC) Received: from gmonaco-thinkpadt14gen3.rmtit.csb (unknown [10.44.48.32]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 515FE30001A2; Thu, 14 May 2026 15:22:15 +0000 (UTC) From: Gabriele Monaco To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Steven Rostedt , Gabriele Monaco , Masami Hiramatsu Cc: Nam Cao , Thomas Weissschuh , Tomas Glozar , John Kacur , Wen Yang Subject: [PATCH v2 13/14] rv: Prevent unintentional tracepoints during KUnit tests Date: Thu, 14 May 2026 17:20:54 +0200 Message-ID: <20260514152055.229162-14-gmonaco@redhat.com> In-Reply-To: <20260514152055.229162-1-gmonaco@redhat.com> References: <20260514152055.229162-1-gmonaco@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Monitor initialisation also called during KUnit tests may register some tracepoints, this can lead to issues since we don't expect real monitor events running during KUnit tests. Prevent tracepoint registration if an RV KUnit test is running. Signed-off-by: Gabriele Monaco Reviewed-by: Nam Cao --- include/rv/instrumentation.h | 5 +++++ include/rv/kunit.h | 2 ++ kernel/trace/rv/rv_monitors_test.c | 10 ++++++++++ 3 files changed, 17 insertions(+) diff --git a/include/rv/instrumentation.h b/include/rv/instrumentation.h index d4e7a02ede1a..761f8f147dac 100644 --- a/include/rv/instrumentation.h +++ b/include/rv/instrumentation.h @@ -9,12 +9,15 @@ */ =20 #include +#include =20 /* * rv_attach_trace_probe - check and attach a handler function to a tracep= oint */ #define rv_attach_trace_probe(monitor, tp, rv_handler) \ do { \ + if (rv_mon_test_is_running()) \ + break; \ check_trace_callback_type_##tp(rv_handler); \ WARN_ONCE(register_trace_##tp(rv_handler, NULL), \ "fail attaching " #monitor " " #tp "handler"); \ @@ -25,5 +28,7 @@ */ #define rv_detach_trace_probe(monitor, tp, rv_handler) \ do { \ + if (rv_mon_test_is_running()) \ + break; \ unregister_trace_##tp(rv_handler, NULL); \ } while (0) diff --git a/include/rv/kunit.h b/include/rv/kunit.h index 3ef83d337880..9daaebacfc7e 100644 --- a/include/rv/kunit.h +++ b/include/rv/kunit.h @@ -19,6 +19,7 @@ =20 struct task_struct *rv_get_current(void); int rv_current_cpu(void); +bool rv_mon_test_is_running(void); =20 struct rv_kunit_ctx { int reactions, expected; @@ -52,6 +53,7 @@ struct rv_kunit_ctx { =20 #define rv_get_current() current #define rv_current_cpu() smp_processor_id() +#define rv_mon_test_is_running() false =20 #endif /* CONFIG_RV_MONITORS_KUNIT_TEST */ #endif /* _RV_KUNIT_H */ diff --git a/kernel/trace/rv/rv_monitors_test.c b/kernel/trace/rv/rv_monito= rs_test.c index 3dbe562f00c1..01cbee9ac6c0 100644 --- a/kernel/trace/rv/rv_monitors_test.c +++ b/kernel/trace/rv/rv_monitors_test.c @@ -14,6 +14,8 @@ #include #include "rv.h" =20 +static bool rv_mon_test_running; + __printf(2, 3) static void stub_rv_react(struct rv_monitor *monitor, const char *msg, ...) { @@ -55,6 +57,11 @@ static int stub_rv_current_cpu(void) return ctx->cpu; } =20 +bool rv_mon_test_is_running(void) +{ + return rv_mon_test_running; +} + static int rv_mon_test_init(struct kunit *test) { struct rv_kunit_ctx *ctx; @@ -94,6 +101,8 @@ static int rv_set_testing(struct kunit_suite *suite) =20 mutex_lock(&rv_interface_lock); =20 + rv_mon_test_running =3D true; + list_for_each_entry(mon, &rv_monitors_list, list) { if (mon->enabled) { mutex_unlock(&rv_interface_lock); @@ -111,6 +120,7 @@ static int rv_set_testing(struct kunit_suite *suite) */ static void rv_clear_testing(struct kunit_suite *suite) { + rv_mon_test_running =3D false; mutex_unlock(&rv_interface_lock); } =20 --=20 2.54.0 From nobody Fri Jun 12 13:56:05 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7432742B73A for ; Thu, 14 May 2026 15:22:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772152; cv=none; b=okU73L8mM/Mb3qWObjyAYvEHjpBRy95CHJuuCVCSrs5YqS2kQ2WRMbjZ/aA9lw45a7qVAEhxkhT5S5XOMRE1XtUhcy+FxOjrwPj/tWuCqEWwmd5eE/a8kIyOWIFZZKA0SItqTam5sx5jrSXZsyDN484yweqbN3IjKJnv1keaEIU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778772152; c=relaxed/simple; bh=GZpCkzriGvjreliX2NExP+KurHWU6689xE4PmTd9NXo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uKH891ZBnzbN298SuNqz66SNCQ79035o4Sa6X4erDRLXzMEIPlSgoQxwb2paCwGVGeK4bYPdHB2Lu+ydTOMpH1iqXZML89uvnY4wntKR1DnvG430tsqlkPEj+JHFaCjPkU6yeztuMzWvmJnRobSCNN7ITap834m5xRKIRusQHFs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=RwY/rbRg; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="RwY/rbRg" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778772149; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cChOR4WDN1ePG+G6GSE+5i1NpzN8hqKtv2EbJv0L3Rc=; b=RwY/rbRgk97LXUQRu0jk9Zy4uuqBjhBZdnRx8z4fvmxErc0QzlNQ+fjv0ML2LmlwkJ62Gh 7Kd6uuBR0fsPGMtBr0VqaWL8i/ptyZ2vp5I+4vfRA4YmW7EVNOdbAVwNCuir/XDvwFs37d OuhfLEfPNQHS4rGFjeUCNsoooBmoOU4= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-638-_n2Jyx-rPz2LkDdsCx9dvw-1; Thu, 14 May 2026 11:22:25 -0400 X-MC-Unique: _n2Jyx-rPz2LkDdsCx9dvw-1 X-Mimecast-MFC-AGG-ID: _n2Jyx-rPz2LkDdsCx9dvw_1778772143 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 977B41956089; Thu, 14 May 2026 15:22:23 +0000 (UTC) Received: from gmonaco-thinkpadt14gen3.rmtit.csb (unknown [10.44.48.32]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2C7D230002DA; Thu, 14 May 2026 15:22:19 +0000 (UTC) From: Gabriele Monaco To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Steven Rostedt , Gabriele Monaco , Masami Hiramatsu Cc: Nam Cao , Thomas Weissschuh , Tomas Glozar , John Kacur , Wen Yang Subject: [PATCH v2 14/14] rv: Add KUnit tests for some LTL monitors Date: Thu, 14 May 2026 17:20:55 +0200 Message-ID: <20260514152055.229162-15-gmonaco@redhat.com> In-Reply-To: <20260514152055.229162-1-gmonaco@redhat.com> References: <20260514152055.229162-1-gmonaco@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Validate the functionality of LTL monitors by injecting events in a controlled environment (KUnit) and expecting reactions, just like it is done in DA monitors. Signed-off-by: Gabriele Monaco Reviewed-by: Nam Cao --- include/rv/ltl_monitor.h | 37 +++++++++++++ .../trace/rv/monitors/pagefault/pagefault.c | 25 +++++++++ kernel/trace/rv/monitors/sleep/sleep.c | 52 +++++++++++++++++++ kernel/trace/rv/rv_monitors_test.c | 4 ++ 4 files changed, 118 insertions(+) diff --git a/include/rv/ltl_monitor.h b/include/rv/ltl_monitor.h index 35bc870d808a..75c9c6230dae 100644 --- a/include/rv/ltl_monitor.h +++ b/include/rv/ltl_monitor.h @@ -172,3 +172,40 @@ static void __maybe_unused ltl_atom_pulse(struct task_= struct *task, enum ltl_ato ltl_atom_set(mon, atom, !value); ltl_validate(task, mon); } + +#ifdef CONFIG_RV_MONITORS_KUNIT_TEST + +/* + * ltl_teardown_test - Disable the monitor for a kunit test + */ +static inline void ltl_teardown_test(void *arg) +{ + struct rv_monitor *rv_this =3D arg; + struct kunit *test =3D kunit_get_current_test(); + + if (test) { + struct rv_kunit_ctx *ctx =3D test->priv; + + RV_KUNIT_EXPECT_NO_REACTION(test, ctx); + } + + rv_this->enabled =3D 0; + ltl_monitor_destroy(); +} + +/* + * ltl_prepare_test - Enable the monitor for a kunit test + * + * Do the bare minimum to set up the monitor, make sure it is not active a= nd + * real tracepoint handlers are NOT attached. + */ +static inline void ltl_prepare_test(struct kunit *test, struct rv_monitor = *rv_this) +{ + KUNIT_ASSERT_FALSE(test, rv_this->enabled); + ltl_monitor_init(); + rv_this->enabled =3D 1; + + KUNIT_ASSERT_EQ(test, 0, + kunit_add_action_or_reset(test, ltl_teardown_test, rv_this)); +} +#endif /* CONFIG_RV_MONITORS_KUNIT_TEST */ diff --git a/kernel/trace/rv/monitors/pagefault/pagefault.c b/kernel/trace/= rv/monitors/pagefault/pagefault.c index 56abe5079676..28c3382eabb0 100644 --- a/kernel/trace/rv/monitors/pagefault/pagefault.c +++ b/kernel/trace/rv/monitors/pagefault/pagefault.c @@ -86,3 +86,28 @@ module_exit(unregister_pagefault); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Nam Cao "); MODULE_DESCRIPTION("pagefault: Monitor that RT tasks do not raise page fau= lts"); + +#ifdef CONFIG_RV_MONITORS_KUNIT_TEST +void rv_test_pagefault(struct kunit *test); + +void rv_test_pagefault(struct kunit *test) +{ + struct task_struct *target; + struct rv_kunit_ctx *ctx =3D test->priv; + + ltl_prepare_test(test, &rv_pagefault); + target =3D kunit_kzalloc(test, sizeof(struct task_struct), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, target); + target->policy =3D SCHED_FIFO; + target->prio =3D MAX_RT_PRIO - 1; + handle_task_newtask(NULL, target, 0); + + ltl_attempt_start(target, ltl_get_monitor(target)); + + /* RT task has a page fault */ + rv_mock_current(ctx, target); + RV_KUNIT_EXPECT_REACTION_HERE(test, ctx) + handle_page_fault(NULL, 0, NULL, 0); +} +EXPORT_SYMBOL_GPL(rv_test_pagefault); +#endif diff --git a/kernel/trace/rv/monitors/sleep/sleep.c b/kernel/trace/rv/monit= ors/sleep/sleep.c index 8b44161d47d3..76e70e2db992 100644 --- a/kernel/trace/rv/monitors/sleep/sleep.c +++ b/kernel/trace/rv/monitors/sleep/sleep.c @@ -247,3 +247,55 @@ module_exit(unregister_sleep); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Nam Cao "); MODULE_DESCRIPTION("sleep: Monitor that RT tasks do not undesirably sleep"= ); + +#ifdef CONFIG_RV_MONITORS_KUNIT_TEST +void rv_test_sleep(struct kunit *test); + +void rv_test_sleep(struct kunit *test) +{ + struct task_struct *target, *other; + struct rv_kunit_ctx *ctx =3D test->priv; + unsigned long args[6] =3D {0}; + struct pt_regs regs; + + ltl_prepare_test(test, &rv_sleep); + target =3D kunit_kzalloc(test, sizeof(struct task_struct), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, target); + target->policy =3D SCHED_FIFO; + target->prio =3D MAX_RT_PRIO - 2; + other =3D kunit_kzalloc(test, sizeof(struct task_struct), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, other); + other->policy =3D SCHED_FIFO; + other->prio =3D MAX_RT_PRIO - 1; + handle_task_newtask(NULL, target, 0); + + /* RT task sleeps on a non RT-friendly nanosleep */ + rv_mock_current(ctx, target); + args[0] =3D CLOCK_REALTIME; + syscall_set_arguments(target, ®s, args); +#ifdef __NR_clock_nanosleep + handle_sys_enter(NULL, ®s, __NR_clock_nanosleep); +#elif defined(__NR_clock_nanosleep_time64) + handle_sys_enter(NULL, ®s, __NR_clock_nanosleep_time64); +#endif + RV_KUNIT_EXPECT_REACTION_HERE(test, ctx) + handle_sched_set_state(NULL, target, TASK_INTERRUPTIBLE); + handle_sys_exit(NULL, NULL, 0); + + /* RT task woken up by lower priority task */ + args[1] =3D FUTEX_WAIT; + syscall_set_arguments(target, ®s, args); + rv_mock_current(ctx, target); +#ifdef __NR_futex + handle_sys_enter(NULL, ®s, __NR_futex); +#elif defined(__NR_futex_time64) + handle_sys_enter(NULL, ®s, __NR_futex_time64); +#endif + handle_sched_set_state(NULL, target, TASK_INTERRUPTIBLE); + rv_mock_current(ctx, other); + handle_sched_waking(NULL, target); + RV_KUNIT_EXPECT_REACTION_HERE(test, ctx) + handle_sched_wakeup(NULL, target); +} +EXPORT_SYMBOL_GPL(rv_test_sleep); +#endif diff --git a/kernel/trace/rv/rv_monitors_test.c b/kernel/trace/rv/rv_monito= rs_test.c index 01cbee9ac6c0..d3e3aa1ac4ec 100644 --- a/kernel/trace/rv/rv_monitors_test.c +++ b/kernel/trace/rv/rv_monitors_test.c @@ -137,6 +137,8 @@ DECLARE_RV_TEST(rv_test_sssw); DECLARE_RV_TEST(rv_test_sts); DECLARE_RV_TEST(rv_test_opid); DECLARE_RV_TEST(rv_test_nomiss); +DECLARE_RV_TEST(rv_test_pagefault); +DECLARE_RV_TEST(rv_test_sleep); =20 static struct kunit_case rv_mon_test_cases[] =3D { KUNIT_CASE(rv_test_sco), @@ -144,6 +146,8 @@ static struct kunit_case rv_mon_test_cases[] =3D { KUNIT_CASE(rv_test_sts), KUNIT_CASE(rv_test_opid), KUNIT_CASE(rv_test_nomiss), + KUNIT_CASE(rv_test_pagefault), + KUNIT_CASE(rv_test_sleep), {} }; =20 --=20 2.54.0