From: Jann Horn <jannh@google.com>
To: Dmitry Vyukov <dvyukov@google.com>,
Andrey Konovalov <andreyknvl@gmail.com>,
Alexander Potapenko <glider@google.com>
Cc: Nathan Chancellor <nathan@kernel.org>,
Nick Desaulniers <nick.desaulniers+lkml@gmail.com>,
Bill Wendling <morbo@google.com>,
Justin Stitt <justinstitt@google.com>,
linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com,
llvm@lists.linux.dev, Jann Horn <jannh@google.com>
Subject: [PATCH RFC v3 04/12] kcov: summarize entry/exit while disabled
Date: Tue, 08 Sep 2026 18:54:44 +0200 [thread overview]
Message-ID: <20260908-kcov-extrecord-v3-4-dcbc11593e88@google.com> (raw)
In-Reply-To: <20260908-kcov-extrecord-v3-0-dcbc11593e88@google.com>
In case kcov is re-enabled with a different call stack than the one it
was disabled with, emit events that summarize changes to the call stack
so that userspace can continue tracking the call stack across context
switches.
Signed-off-by: Jann Horn <jannh@google.com>
---
include/linux/kcov.h | 11 ++---------
include/uapi/linux/kcov.h | 2 ++
kernel/kcov.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 50 insertions(+), 11 deletions(-)
diff --git a/include/linux/kcov.h b/include/linux/kcov.h
index 6c9f0373022f..357f4de8790a 100644
--- a/include/linux/kcov.h
+++ b/include/linux/kcov.h
@@ -35,15 +35,8 @@ enum kcov_mode {
void kcov_task_init(struct task_struct *t);
void kcov_task_exit(struct task_struct *t);
-#define kcov_prepare_switch(t) \
-do { \
- (t)->kcov_mode |= KCOV_IN_CTXSW; \
-} while (0)
-
-#define kcov_finish_switch(t) \
-do { \
- (t)->kcov_mode &= ~KCOV_IN_CTXSW; \
-} while (0)
+void kcov_prepare_switch(struct task_struct *cur);
+void kcov_finish_switch(struct task_struct *cur);
/* See Documentation/dev-tools/kcov.rst for usage details. */
void kcov_remote_start(u64 handle);
diff --git a/include/uapi/linux/kcov.h b/include/uapi/linux/kcov.h
index 8d8a233bd61f..75c582784055 100644
--- a/include/uapi/linux/kcov.h
+++ b/include/uapi/linux/kcov.h
@@ -48,6 +48,8 @@ enum {
#define KCOV_RECORDFLAG_TYPE_NORMAL 0xf000000000000000
#define KCOV_RECORDFLAG_TYPE_ENTRY 0x0000000000000000
#define KCOV_RECORDFLAG_TYPE_EXIT 0x1000000000000000
+/* Summarized entry/exit events that occurred in an untraced region. */
+#define KCOV_RECORDFLAG_TYPE_EESUM 0x2000000000000000
/*
* The format for the types of collected comparisons.
diff --git a/kernel/kcov.c b/kernel/kcov.c
index 701ad69493bf..712f0f744ec5 100644
--- a/kernel/kcov.c
+++ b/kernel/kcov.c
@@ -76,6 +76,8 @@ struct kcov {
* kcov_remote_stop(), see the comment there.
*/
int sequence;
+ int suppressed_stack_delta;
+ int suppressed_stack_mindelta;
};
struct kcov_remote_area {
@@ -256,8 +258,12 @@ void notrace __sanitizer_cov_trace_pc_entry(void)
* This hook replaces __sanitizer_cov_trace_pc() for the function entry
* basic block; it should still emit a record even in classic kcov mode.
*/
- if ((kcov_mode & ~KCOV_EXT_FORMAT) != KCOV_MODE_TRACE_PC)
+ if ((kcov_mode & ~(KCOV_EXT_FORMAT|KCOV_IN_CTXSW)) != KCOV_MODE_TRACE_PC)
return;
+ if (kcov_mode & KCOV_IN_CTXSW) {
+ cur->kcov->suppressed_stack_delta++;
+ return;
+ }
if ((kcov_mode & KCOV_EXT_FORMAT) != 0)
record = (record & KCOV_RECORD_IP_MASK) | KCOV_RECORDFLAG_TYPE_ENTRY;
kcov_add_pc_record(cur, record);
@@ -266,6 +272,7 @@ void notrace __sanitizer_cov_trace_pc_exit(void)
{
struct task_struct *cur = current;
unsigned long record;
+ unsigned int kcov_mode = READ_ONCE(cur->kcov_mode);
/*
* This hook is not called at the beginning of a basic block; the basic
@@ -274,8 +281,16 @@ void notrace __sanitizer_cov_trace_pc_exit(void)
* So unlike __sanitizer_cov_trace_pc_entry(), this PC should only be
* reported in extended mode, where function exit events are recorded.
*/
- if (READ_ONCE(cur->kcov_mode) != KCOV_MODE_TRACE_PC_EXT)
+ if ((kcov_mode & ~KCOV_IN_CTXSW) != KCOV_MODE_TRACE_PC_EXT)
return;
+ if (kcov_mode & KCOV_IN_CTXSW) {
+ struct kcov *kcov = cur->kcov;
+
+ if (kcov->suppressed_stack_mindelta == kcov->suppressed_stack_delta)
+ kcov->suppressed_stack_mindelta--;
+ kcov->suppressed_stack_delta--;
+ return;
+ }
record = (canonicalize_ip(_RET_IP_) & KCOV_RECORD_IP_MASK) | KCOV_RECORDFLAG_TYPE_EXIT;
kcov_add_pc_record(cur, record);
}
@@ -399,6 +414,35 @@ void notrace __sanitizer_cov_trace_switch(kcov_u64 val, void *arg)
EXPORT_SYMBOL(__sanitizer_cov_trace_switch);
#endif /* ifdef CONFIG_KCOV_ENABLE_COMPARISONS */
+void kcov_prepare_switch(struct task_struct *cur)
+{
+#ifdef CONFIG_KCOV_EXT_RECORDS
+ struct kcov *kcov = cur->kcov;
+
+ if (kcov) {
+ kcov->suppressed_stack_mindelta = 0;
+ kcov->suppressed_stack_delta = 0;
+ }
+#endif
+ cur->kcov_mode |= KCOV_IN_CTXSW;
+}
+
+void kcov_finish_switch(struct task_struct *cur)
+{
+ struct kcov *kcov = cur->kcov;
+ unsigned long record;
+
+ cur->kcov_mode &= ~KCOV_IN_CTXSW;
+ if (!IS_ENABLED(CONFIG_KCOV_EXT_RECORDS))
+ return;
+ if ((cur->kcov_mode & KCOV_EXT_FORMAT) == 0)
+ return;
+ record = KCOV_RECORDFLAG_TYPE_EESUM |
+ (((u16)(s16)kcov->suppressed_stack_mindelta)<<16) |
+ (((u16)(s16)kcov->suppressed_stack_delta)<<16);
+ kcov_add_pc_record(cur, record);
+}
+
static void kcov_start(struct task_struct *t, struct kcov *kcov,
unsigned int size, void *area, unsigned int mode,
int sequence)
--
2.55.0.979.g7e5102b832-goog
next prev parent reply other threads:[~2026-09-08 16:55 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-08 16:54 [PATCH RFC v3 00/12] KCOV: entry/exit records, memory access records, and delay injection Jann Horn
2026-09-08 16:54 ` [PATCH RFC v3 01/12] kcov: wire up compiler instrumentation for CONFIG_KCOV_EXT_RECORDS Jann Horn
2026-09-08 16:54 ` [PATCH RFC v3 02/12] kcov: refactor mode check out of check_kcov_mode() Jann Horn
2026-09-08 16:54 ` [PATCH RFC v3 03/12] kcov: introduce extended PC coverage collection mode Jann Horn
2026-09-08 16:54 ` Jann Horn [this message]
2026-09-08 16:54 ` [PATCH RFC v3 05/12] kasan: refactor write/is_write arguments to flags Jann Horn
2026-09-08 16:54 ` [PATCH RFC v3 06/12] kcov: introduce memory access tracing Jann Horn
2026-09-08 16:54 ` [PATCH RFC v3 07/12] kasan: provide memory access information to KCOV Jann Horn
2026-09-08 16:54 ` [PATCH RFC v3 08/12] kcov: log freeing of SLUB objects and pages Jann Horn
2026-09-08 17:04 ` Jann Horn
2026-09-08 16:54 ` [PATCH RFC v3 09/12] kcov: record return address on function entry Jann Horn
2026-09-08 16:54 ` [PATCH RFC v3 10/12] kcov: log old value Jann Horn
2026-09-08 16:54 ` [PATCH RFC v3 11/12] kcov: introduce delay injection Jann Horn
2026-09-08 16:54 ` [PATCH RFC v3 12/12] Documentation/kcov: add documentation for EXT_RECORDS and KCOV_MEMORY Jann Horn
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260908-kcov-extrecord-v3-4-dcbc11593e88@google.com \
--to=jannh@google.com \
--cc=andreyknvl@gmail.com \
--cc=dvyukov@google.com \
--cc=glider@google.com \
--cc=justinstitt@google.com \
--cc=kasan-dev@googlegroups.com \
--cc=linux-kernel@vger.kernel.org \
--cc=llvm@lists.linux.dev \
--cc=morbo@google.com \
--cc=nathan@kernel.org \
--cc=nick.desaulniers+lkml@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®