[PATCH] kcov: update documentation on remote coverage collection

1 view
Skip to first unread message

Jann Horn

unread,
May 19, 2026, 12:06:18 PMMay 19
to Alexander Potapenko, Dmitry Vyukov, Andrey Konovalov, kasa...@googlegroups.com, Andrew Morton, linux-...@vger.kernel.org, Jann Horn
Adjust the docs on remote coverage collection to reflect the changes made
in "kcov: refactor common handle ID into kcov_common_handle_id" and
"kcov: allow simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE".

Suggested-by: Alexander Potapenko <gli...@google.com>
Signed-off-by: Jann Horn <ja...@google.com>
---
Documentation/dev-tools/kcov.rst | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kcov.rst
index 8127849d40f5..54a0baeb917a 100644
--- a/Documentation/dev-tools/kcov.rst
+++ b/Documentation/dev-tools/kcov.rst
@@ -246,6 +246,8 @@ KCOV supports collecting remote coverage from the following contexts:
2. Local kernel background tasks. These are spawned when a userspace process
interacts with some kernel interface and are usually killed when the process
exits (e.g. vhost workers).
+ This can be combined with another KCOV instance that is configured for normal
+ coverage collection.

3. Soft interrupts.

@@ -262,6 +264,9 @@ gets saved to the ``kcov_handle`` field in the current ``task_struct`` and
needs to be passed to the newly spawned local tasks via custom kernel code
modifications. Those tasks should in turn use the passed handle in their
``kcov_remote_start`` and ``kcov_remote_stop`` annotations.
+In the kernel, common handles are wrapped in a ``kcov_common_handle_id``, which
+consumes no space in builds without ``CONFIG_KCOV``; subsystems that integrate
+with this mechanism should not need to use any ``#ifdef CONFIG_KCOV`` or such.

KCOV follows a predefined format for both global and common handles. Each
handle is a ``u64`` integer. Currently, only the one top and the lower 4 bytes

---
base-commit: ab5fce87a778cb780a05984a2ca448f2b41aafbf
change-id: 20260519-kcov-docs-15feabfb10aa

--
Jann Horn <ja...@google.com>

Alexander Potapenko

unread,
May 20, 2026, 4:28:23 AMMay 20
to Jann Horn, Dmitry Vyukov, Andrey Konovalov, kasa...@googlegroups.com, Andrew Morton, linux-...@vger.kernel.org
On Tue, May 19, 2026 at 6:06 PM Jann Horn <ja...@google.com> wrote:
>
> Adjust the docs on remote coverage collection to reflect the changes made
> in "kcov: refactor common handle ID into kcov_common_handle_id" and
> "kcov: allow simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE".
>
> Suggested-by: Alexander Potapenko <gli...@google.com>
> Signed-off-by: Jann Horn <ja...@google.com>
Reviewed-by: Alexander Potapenko <gli...@google.com>

Andrey Konovalov

unread,
May 20, 2026, 1:51:41 PMMay 20
to Jann Horn, Alexander Potapenko, Dmitry Vyukov, kasa...@googlegroups.com, Andrew Morton, linux-...@vger.kernel.org
On Tue, May 19, 2026 at 6:06 PM Jann Horn <ja...@google.com> wrote:
>
> Adjust the docs on remote coverage collection to reflect the changes made
> in "kcov: refactor common handle ID into kcov_common_handle_id" and
> "kcov: allow simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE".
>
> Suggested-by: Alexander Potapenko <gli...@google.com>
> Signed-off-by: Jann Horn <ja...@google.com>

Hi Jann,

> ---
> Documentation/dev-tools/kcov.rst | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kcov.rst
> index 8127849d40f5..54a0baeb917a 100644
> --- a/Documentation/dev-tools/kcov.rst
> +++ b/Documentation/dev-tools/kcov.rst
> @@ -246,6 +246,8 @@ KCOV supports collecting remote coverage from the following contexts:
> 2. Local kernel background tasks. These are spawned when a userspace process
> interacts with some kernel interface and are usually killed when the process
> exits (e.g. vhost workers).
> + This can be combined with another KCOV instance that is configured for normal
> + coverage collection.

But does your change only work for collecting coverage from these
local tasks, or from global ones as well? If the latter is allowed as
well, this sentence need to be moved.

Jann Horn

unread,
May 20, 2026, 2:15:57 PMMay 20
to Andrey Konovalov, Alexander Potapenko, Dmitry Vyukov, kasa...@googlegroups.com, Andrew Morton, linux-...@vger.kernel.org
On Wed, May 20, 2026 at 7:51 PM Andrey Konovalov <andre...@gmail.com> wrote:
> On Tue, May 19, 2026 at 6:06 PM Jann Horn <ja...@google.com> wrote:
> > diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kcov.rst
> > index 8127849d40f5..54a0baeb917a 100644
> > --- a/Documentation/dev-tools/kcov.rst
> > +++ b/Documentation/dev-tools/kcov.rst
> > @@ -246,6 +246,8 @@ KCOV supports collecting remote coverage from the following contexts:
> > 2. Local kernel background tasks. These are spawned when a userspace process
> > interacts with some kernel interface and are usually killed when the process
> > exits (e.g. vhost workers).
> > + This can be combined with another KCOV instance that is configured for normal
> > + coverage collection.
>
> But does your change only work for collecting coverage from these
> local tasks, or from global ones as well? If the latter is allowed as
> well, this sentence need to be moved.

It also works for collecting global coverage. When I was writing this,
I figured that anyone wanting to collect global coverage would
probably be doing it from a separate task anyway; but yeah, you're
right, it makes more sense to move this note. I'll send a v2.

Jann Horn

unread,
May 20, 2026, 2:21:39 PMMay 20
to Alexander Potapenko, Dmitry Vyukov, Andrey Konovalov, kasa...@googlegroups.com, Andrew Morton, linux-...@vger.kernel.org, Jann Horn
Adjust the docs on remote coverage collection to reflect the changes made
in "kcov: refactor common handle ID into kcov_common_handle_id" and
"kcov: allow simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE".

Suggested-by: Alexander Potapenko <gli...@google.com>
Signed-off-by: Jann Horn <ja...@google.com>
---
Changes in v2:
- move and reword sentence on simultaneous normal/remote collection (andreyknvl)
- Link to v1: https://lore.kernel.org/r/20260519-kcov-docs...@google.com
---
Documentation/dev-tools/kcov.rst | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kcov.rst
index 8127849d40f5..1a739290c8ec 100644
--- a/Documentation/dev-tools/kcov.rst
+++ b/Documentation/dev-tools/kcov.rst
@@ -237,6 +237,9 @@ Both ``kcov_remote_start`` and ``kcov_remote_stop`` annotations and the
collection sections. The way a handle is used depends on the context where the
matching code section executes.

+A thread can use two separate KCOV instances to collect remote coverage and
+normal coverage at the same time.
+
KCOV supports collecting remote coverage from the following contexts:

1. Global kernel background tasks. These are the tasks that are spawned during
@@ -262,6 +265,9 @@ gets saved to the ``kcov_handle`` field in the current ``task_struct`` and

Andrew Morton

unread,
May 21, 2026, 7:18:54 PMMay 21
to Jann Horn, Alexander Potapenko, Dmitry Vyukov, Andrey Konovalov, kasa...@googlegroups.com, linux-...@vger.kernel.org
On Wed, 20 May 2026 20:21:29 +0200 Jann Horn <ja...@google.com> wrote:

> Adjust the docs on remote coverage collection to reflect the changes made
> in "kcov: refactor common handle ID into kcov_common_handle_id" and
> "kcov: allow simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE".

This has all become rather confusing, with fixes and new versions of
fixes under different titles, etc.

I did my best to piece it all together then I joined everything into a
single patch, below. Please check it for accuracy, up-to-dateness and
changelog truthfulness, thanks.


From: Jann Horn <ja...@google.com>
Subject: kcov: allow simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE
Date: Tue, 05 May 2026 11:00:46 +0200

Allow the same userspace thread to simultaneously collect normal coverage
in syscall context (KCOV_ENABLE) and remote coverage of asynchronous work
created by the thread (KCOV_REMOTE_ENABLE). With this, remote KCOV
coverage becomes useful for generic fuzzing and not just fuzzing of
specific data injection interfaces.

This requires that the task_struct::kcov_* fields are separated into ones
that are used by the task that generates coverage, and ones that are used
by the task that requested remote coverage. To split this up:

- Split task_struct::kcov into kcov and kcov_remote. kcov_task_exit() now
has to clean up both separately.
- Only use task_struct::kcov_mode on the task that generates coverage.
- Only reset task_struct::kcov_handle on the task that requested remote
coverage.

After this change, fields used by the task that generates coverage are:

- kcov_mode
- kcov_size
- kcov_area
- kcov
- kcov_sequence
- kcov_softirq

Fields used by the task that requested remote coverage are:

- kcov_remote
- kcov_handle

[ja...@google.com: remove unused constant KCOV_MODE_REMOTE, per Dmitry]
Link: https://lore.kernel.org/20260515-kcov-simultaneou...@google.com
[ja...@google.com: update documentation on remote coverage collection]
Link: https://lore.kernel.org/20260519-kcov-docs...@google.com
[ja...@google.com: move and reword sentence on simultaneous normal/remote collection
Link: https://lore.kernel.org/20260520-kcov-docs...@google.com
Link: https://lore.kernel.org/20260505-kcov-simultaneou...@google.com
Signed-off-by: Jann Horn <ja...@google.com>
Reviewed-by: Dmitry Vyukov <dvy...@google.com>
Cc: Alexander Potapenko <gli...@google.com>
Cc: Andrey Konovalov <andre...@gmail.com>
Cc: Marco Elver <el...@google.com>
Signed-off-by: Andrew Morton <ak...@linux-foundation.org>
---

Documentation/dev-tools/kcov.rst | 6 +
include/linux/kcov.h | 2
include/linux/sched.h | 3
kernel/kcov.c | 94 ++++++++++++++++-------------
4 files changed, 61 insertions(+), 44 deletions(-)

--- a/include/linux/sched.h~kcov-allow-simultaneous-kcov_enable-kcov_remote_enable
+++ a/include/linux/sched.h
@@ -1517,6 +1517,9 @@ struct task_struct {
/* KCOV descriptor wired with this task or NULL: */
struct kcov *kcov;

+ /* KCOV descriptor for remote coverage collection from other tasks: */
+ struct kcov *kcov_remote;
+
/* KCOV common handle for remote coverage collection: */
u64 kcov_handle;

--- a/kernel/kcov.c~kcov-allow-simultaneous-kcov_enable-kcov_remote_enable
+++ a/kernel/kcov.c
@@ -368,6 +368,7 @@ static void kcov_start(struct task_struc
WRITE_ONCE(t->kcov_mode, mode);
}

+/* operates on coverage-generator-owned fields */
static void kcov_stop(struct task_struct *t)
{
WRITE_ONCE(t->kcov_mode, KCOV_MODE_DISABLED);
@@ -377,16 +378,17 @@ static void kcov_stop(struct task_struct
t->kcov_area = NULL;
}

+/* operates on coverage-generator-owned fields */
static void kcov_task_reset(struct task_struct *t)
{
kcov_stop(t);
t->kcov_sequence = 0;
- t->kcov_handle = 0;
}

void kcov_task_init(struct task_struct *t)
{
kcov_task_reset(t);
+ t->kcov_remote = NULL;
t->kcov_handle = current->kcov_handle;
}

@@ -423,11 +425,14 @@ static void kcov_remote_reset(struct kco
static void kcov_disable(struct task_struct *t, struct kcov *kcov)
__must_hold(&kcov->lock)
{
- kcov_task_reset(t);
- if (kcov->remote)
+ if (kcov->remote) {
+ t->kcov_handle = 0;
+ t->kcov_remote = NULL;
kcov_remote_reset(kcov);
- else
+ } else {
+ kcov_task_reset(t);
kcov_reset(kcov);
+ }
}

static void kcov_get(struct kcov *kcov)
@@ -453,41 +458,47 @@ void kcov_task_exit(struct task_struct *
unsigned long flags;

kcov = t->kcov;
- if (kcov == NULL)
- return;
-
- spin_lock_irqsave(&kcov->lock, flags);
- kcov_debug("t = %px, kcov->t = %px\n", t, kcov->t);
- /*
- * For KCOV_ENABLE devices we want to make sure that t->kcov->t == t,
- * which comes down to:
- * WARN_ON(!kcov->remote && kcov->t != t);
- *
- * For KCOV_REMOTE_ENABLE devices, the exiting task is either:
- *
- * 1. A remote task between kcov_remote_start() and kcov_remote_stop().
- * In this case we should print a warning right away, since a task
- * shouldn't be exiting when it's in a kcov coverage collection
- * section. Here t points to the task that is collecting remote
- * coverage, and t->kcov->t points to the thread that created the
- * kcov device. Which means that to detect this case we need to
- * check that t != t->kcov->t, and this gives us the following:
- * WARN_ON(kcov->remote && kcov->t != t);
- *
- * 2. The task that created kcov exiting without calling KCOV_DISABLE,
- * and then again we make sure that t->kcov->t == t:
- * WARN_ON(kcov->remote && kcov->t != t);
- *
- * By combining all three checks into one we get:
- */
- if (WARN_ON(kcov->t != t)) {
+ if (kcov) {
+ spin_lock_irqsave(&kcov->lock, flags);
+ kcov_debug("t = %px, kcov->t = %px\n", t, kcov->t);
+ /*
+ * This could be a remote task between kcov_remote_start() and
+ * kcov_remote_stop().
+ * In this case we should print a warning right away, since a
+ * task shouldn't be exiting when it's in a kcov coverage
+ * collection section.
+ *
+ * Otherwise, this should be a task that created a local
+ * kcov instance and hasn't called KCOV_DISABLE.
+ * Make sure that t->kcov->t is consistent.
+ */
+ if (WARN_ON(kcov->remote) || WARN_ON(kcov->t != t)) {
+ spin_unlock_irqrestore(&kcov->lock, flags);
+ return;
+ }
+ /* Just to not leave dangling references behind. */
+ kcov_disable(t, kcov);
spin_unlock_irqrestore(&kcov->lock, flags);
- return;
+ kcov_put(kcov);
+ }
+ kcov = t->kcov_remote;
+ if (kcov) {
+ spin_lock_irqsave(&kcov->lock, flags);
+ kcov_debug("t = %px, kcov->t = %px\n", t, kcov->t);
+ /*
+ * This is a KCOV_REMOTE_ENABLE device, and the task is the
+ * user task which has requested remote coverage collection.
+ * Make sure that t->kcov->t is consistent.
+ */
+ if (WARN_ON(!kcov->remote) || WARN_ON(kcov->t != t)) {
+ spin_unlock_irqrestore(&kcov->lock, flags);
+ return;
+ }
+ /* Just to not leave dangling references behind. */
+ kcov_disable(t, kcov);
+ spin_unlock_irqrestore(&kcov->lock, flags);
+ kcov_put(kcov);
}
- /* Just to not leave dangling references behind. */
- kcov_disable(t, kcov);
- spin_unlock_irqrestore(&kcov->lock, flags);
- kcov_put(kcov);
}

static int kcov_mmap(struct file *filep, struct vm_area_struct *vma)
@@ -629,9 +640,9 @@ static int kcov_ioctl_locked(struct kcov
case KCOV_DISABLE:
/* Disable coverage for the current task. */
unused = arg;
- if (unused != 0 || current->kcov != kcov)
- return -EINVAL;
t = current;
+ if (unused != 0 || (kcov != t->kcov && kcov != t->kcov_remote))
+ return -EINVAL;
if (WARN_ON(kcov->t != t))
return -EINVAL;
kcov_disable(t, kcov);
@@ -641,7 +652,7 @@ static int kcov_ioctl_locked(struct kcov
if (kcov->mode != KCOV_MODE_INIT || !kcov->area)
return -EINVAL;
t = current;
- if (kcov->t != NULL || t->kcov != NULL)
+ if (kcov->t != NULL || t->kcov_remote != NULL)
return -EBUSY;
remote_arg = (struct kcov_remote_arg *)arg;
mode = kcov_get_mode(remote_arg->trace_mode);
@@ -651,8 +662,7 @@ static int kcov_ioctl_locked(struct kcov
LONG_MAX / sizeof(unsigned long))
return -EINVAL;
kcov->mode = mode;
- t->kcov = kcov;
- t->kcov_mode = KCOV_MODE_REMOTE;
+ t->kcov_remote = kcov;
kcov->t = t;
kcov->remote = true;
kcov->remote_size = remote_arg->area_size;
--- a/include/linux/kcov.h~kcov-allow-simultaneous-kcov_enable-kcov_remote_enable
+++ a/include/linux/kcov.h
@@ -21,8 +21,6 @@ enum kcov_mode {
KCOV_MODE_TRACE_PC = 2,
/* Collecting comparison operands mode. */
KCOV_MODE_TRACE_CMP = 3,
- /* The process owns a KCOV remote reference. */
- KCOV_MODE_REMOTE = 4,
};

#define KCOV_IN_CTXSW (1 << 30)
--- a/Documentation/dev-tools/kcov.rst~kcov-allow-simultaneous-kcov_enable-kcov_remote_enable
+++ a/Documentation/dev-tools/kcov.rst
@@ -237,6 +237,9 @@ Both ``kcov_remote_start`` and ``kcov_re
collection sections. The way a handle is used depends on the context where the
matching code section executes.

+A thread can use two separate KCOV instances to collect remote coverage and
+normal coverage at the same time.
+
KCOV supports collecting remote coverage from the following contexts:

1. Global kernel background tasks. These are the tasks that are spawned during
@@ -262,6 +265,9 @@ gets saved to the ``kcov_handle`` field
needs to be passed to the newly spawned local tasks via custom kernel code
modifications. Those tasks should in turn use the passed handle in their
``kcov_remote_start`` and ``kcov_remote_stop`` annotations.
+In the kernel, common handles are wrapped in a ``kcov_common_handle_id``, which
+consumes no space in builds without ``CONFIG_KCOV``; subsystems that integrate
+with this mechanism should not need to use any ``#ifdef CONFIG_KCOV`` or such.

KCOV follows a predefined format for both global and common handles. Each
handle is a ``u64`` integer. Currently, only the one top and the lower 4 bytes
_

Jann Horn

unread,
May 26, 2026, 10:08:42 AMMay 26
to Andrew Morton, Alexander Potapenko, Dmitry Vyukov, Andrey Konovalov, kasa...@googlegroups.com, linux-...@vger.kernel.org
On Fri, May 22, 2026 at 1:18 AM Andrew Morton <ak...@linux-foundation.org> wrote:
> On Wed, 20 May 2026 20:21:29 +0200 Jann Horn <ja...@google.com> wrote:
> > Adjust the docs on remote coverage collection to reflect the changes made
> > in "kcov: refactor common handle ID into kcov_common_handle_id" and
> > "kcov: allow simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE".
>
> This has all become rather confusing, with fixes and new versions of
> fixes under different titles, etc.

glider@ suggested in
<https://lore.kernel.org/all/CAG_fn=U+V9wzvJJsRh3aB1uCm5zf...@mail.gmail.com/>:

| Could you also update Documentation/dev-tools/kcov.rst (a separate
| commit is also fine - it can cover the kcov_common_handle_id change as
| well)?

So that was my intent - to have these three separate patches:

"kcov: refactor common handle ID into kcov_common_handle_id"
"kcov: allow simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE"
"kcov: update documentation on remote coverage collection"

(where the documentation patch covers changes by both the other changes)

All the patches I sent were meant as full patches, not incremental fixups.

> I did my best to piece it all together then I joined everything into a
> single patch, below. Please check it for accuracy, up-to-dateness and
> changelog truthfulness, thanks.

Yes, that is an accurate combination of "[PATCH v2] kcov: allow
simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE" and "[PATCH v2] kcov:
update documentation on remote coverage collection", and it is
up-to-date, and the changelog looks accurate.

Alexander Potapenko

unread,
Jun 5, 2026, 9:47:30 AM (5 days ago) Jun 5
to Jann Horn, Dmitry Vyukov, Andrey Konovalov, kasa...@googlegroups.com, Andrew Morton, linux-...@vger.kernel.org
On Wed, May 20, 2026 at 8:21 PM Jann Horn <ja...@google.com> wrote:
>
> Adjust the docs on remote coverage collection to reflect the changes made
> in "kcov: refactor common handle ID into kcov_common_handle_id" and
> "kcov: allow simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE".
>
> Suggested-by: Alexander Potapenko <gli...@google.com>
> Signed-off-by: Jann Horn <ja...@google.com>
Reviewed-by: Alexander Potapenko <gli...@google.com>
Reply all
Reply to author
Forward
0 new messages