Commit 5ff3b30a authored by Andrey Konovalov's avatar Andrey Konovalov Committed by Linus Torvalds

kcov: collect coverage from interrupts

This change extends kcov remote coverage support to allow collecting
coverage from soft interrupts in addition to kernel background threads.

To collect coverage from code that is executed in softirq context, a part
of that code has to be annotated with kcov_remote_start/stop() in a
similar way as how it is done for global kernel background threads.  Then
the handle used for the annotations has to be passed to the
KCOV_REMOTE_ENABLE ioctl.

Internally this patch adjusts the __sanitizer_cov_trace_pc() compiler
inserted callback to not bail out when called from softirq context.
kcov_remote_start/stop() are updated to save/restore the current per task
kcov state in a per-cpu area (in case the softirq came when the kernel was
already collecting coverage in task context).  Coverage from softirqs is
collected into pre-allocated per-cpu areas, whose size is controlled by
the new CONFIG_KCOV_IRQ_AREA_SIZE.

[andreyknvl@google.com: turn current->kcov_softirq into unsigned int to fix objtool warning]
  Link: http://lkml.kernel.org/r/841c778aa3849c5cb8c3761f56b87ce653a88671.1585233617.git.andreyknvl@google.comSigned-off-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Reviewed-by: default avatarDmitry Vyukov <dvyukov@google.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Konovalov <andreyknvl@gmail.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Marco Elver <elver@google.com>
Link: http://lkml.kernel.org/r/469bd385c431d050bc38a593296eff4baae50666.1584655448.git.andreyknvl@google.comSigned-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 5fe7042d
...@@ -217,14 +217,15 @@ This allows to collect coverage from two types of kernel background ...@@ -217,14 +217,15 @@ This allows to collect coverage from two types of kernel background
threads: the global ones, that are spawned during kernel boot in a limited threads: the global ones, that are spawned during kernel boot in a limited
number of instances (e.g. one USB hub_event() worker thread is spawned per number of instances (e.g. one USB hub_event() worker thread is spawned per
USB HCD); and the local ones, that are spawned when a user interacts with USB HCD); and the local ones, that are spawned when a user interacts with
some kernel interface (e.g. vhost workers). some kernel interface (e.g. vhost workers); as well as from soft
interrupts.
To enable collecting coverage from a global background thread, a unique To enable collecting coverage from a global background thread or from a
global handle must be assigned and passed to the corresponding softirq, a unique global handle must be assigned and passed to the
kcov_remote_start() call. Then a userspace process can pass a list of such corresponding kcov_remote_start() call. Then a userspace process can pass
handles to the KCOV_REMOTE_ENABLE ioctl in the handles array field of the a list of such handles to the KCOV_REMOTE_ENABLE ioctl in the handles
kcov_remote_arg struct. This will attach the used kcov device to the code array field of the kcov_remote_arg struct. This will attach the used kcov
sections, that are referenced by those handles. device to the code sections, that are referenced by those handles.
Since there might be many local background threads spawned from different Since there might be many local background threads spawned from different
userspace processes, we can't use a single global handle per annotation. userspace processes, we can't use a single global handle per annotation.
...@@ -242,7 +243,7 @@ handles as they don't belong to a particular subsystem. The bytes 4-7 are ...@@ -242,7 +243,7 @@ handles as they don't belong to a particular subsystem. The bytes 4-7 are
currently reserved and must be zero. In the future the number of bytes currently reserved and must be zero. In the future the number of bytes
used for the subsystem or handle ids might be increased. used for the subsystem or handle ids might be increased.
When a particular userspace proccess collects coverage by via a common When a particular userspace proccess collects coverage via a common
handle, kcov will collect coverage for each code section that is annotated handle, kcov will collect coverage for each code section that is annotated
to use the common handle obtained as kcov_handle from the current to use the common handle obtained as kcov_handle from the current
task_struct. However non common handles allow to collect coverage task_struct. However non common handles allow to collect coverage
......
...@@ -1247,6 +1247,9 @@ struct task_struct { ...@@ -1247,6 +1247,9 @@ struct task_struct {
/* KCOV sequence number: */ /* KCOV sequence number: */
int kcov_sequence; int kcov_sequence;
/* Collect coverage from softirq context: */
unsigned int kcov_softirq;
#endif #endif
#ifdef CONFIG_MEMCG #ifdef CONFIG_MEMCG
......
This diff is collapsed.
...@@ -1774,6 +1774,15 @@ config KCOV_INSTRUMENT_ALL ...@@ -1774,6 +1774,15 @@ config KCOV_INSTRUMENT_ALL
filesystem fuzzing with AFL) then you will want to enable coverage filesystem fuzzing with AFL) then you will want to enable coverage
for more specific subsets of files, and should say n here. for more specific subsets of files, and should say n here.
config KCOV_IRQ_AREA_SIZE
hex "Size of interrupt coverage collection area in words"
depends on KCOV
default 0x40000
help
KCOV uses preallocated per-cpu areas to collect coverage from
soft interrupts. This specifies the size of those areas in the
number of unsigned long words.
menuconfig RUNTIME_TESTING_MENU menuconfig RUNTIME_TESTING_MENU
bool "Runtime Testing" bool "Runtime Testing"
def_bool y def_bool y
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment