* [PATCH v2] selftests: harness: Support KCOV.
@ 2025-10-28 2:42 Kuniyuki Iwashima
2025-11-06 8:50 ` kernel test robot
2025-11-06 21:42 ` Shuah Khan
0 siblings, 2 replies; 4+ messages in thread
From: Kuniyuki Iwashima @ 2025-10-28 2:42 UTC (permalink / raw)
To: Shuah Khan; +Cc: Kuniyuki Iwashima, Kuniyuki Iwashima, linux-kselftest
While writing a selftest with kselftest_harness.h, I often want to
check which paths are actually exercised.
Let's support generating KCOV coverage data.
We can specify the output directory via the KCOV_OUTPUT environment
variable, and the number of instructions to collect via the KCOV_SLOTS
environment variable.
# KCOV_OUTPUT=$PWD/kcov KCOV_SLOTS=$((4096 * 2)) \
./tools/testing/selftests/net/af_unix/scm_inq
Both variables can also be specified as the make variable.
# make -C tools/testing/selftests/ \
KCOV_OUTPUT=$PWD/kcov KCOV_SLOTS=$((4096 * 4)) \
kselftest_override_timeout=60 TARGETS=net/af_unix run_tests
The coverage data can be simply decoded with addr2line:
$ cat kcov/* | sort | uniq | addr2line -e vmlinux | grep unix
net/unix/af_unix.c:1056
net/unix/af_unix.c:3138
net/unix/af_unix.c:3834
net/unix/af_unix.c:3838
net/unix/af_unix.c:311 (discriminator 2)
...
or more nicely with a script embedded in vock [0]:
$ cat kcov/* | sort | uniq > local.log
$ python3 ~/kernel/tools/vock/report.py \
--kernel-src ./ --vmlinux ./vmlinux \
--mode local --local-log local.log --filter unix
...
------------------------------- Coverage Report --------------------------------
📄 net/unix/af_unix.c (276 lines)
...
942 | static int unix_setsockopt(struct socket *sock, int level, int optname,
943 | sockptr_t optval, unsigned int optlen)
944 | {
...
961 | switch (optname) {
962 | case SO_INQ:
963 > if (sk->sk_type != SOCK_STREAM)
964 | return -EINVAL;
965 |
966 > if (val > 1 || val < 0)
967 | return -EINVAL;
968 |
969 > WRITE_ONCE(u->recvmsg_inq, val);
970 | break;
Link: https://github.com/kzall0c/vock/blob/f3d97de9954f9df758c0ab287ca7e24e654288c7/report.py #[0]
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
---
v2: Support TEST()
v1: https://lore.kernel.org/linux-kselftest/20251017084022.3721950-1-kuniyu@google.com/
---
Documentation/dev-tools/kselftest.rst | 41 ++++++
tools/testing/selftests/Makefile | 14 ++-
tools/testing/selftests/kselftest_harness.h | 133 +++++++++++++++++++-
3 files changed, 178 insertions(+), 10 deletions(-)
diff --git a/Documentation/dev-tools/kselftest.rst b/Documentation/dev-tools/kselftest.rst
index 18c2da67fae4..5c2b92ac4a30 100644
--- a/Documentation/dev-tools/kselftest.rst
+++ b/Documentation/dev-tools/kselftest.rst
@@ -200,6 +200,47 @@ You can look at the TAP output to see if you ran into the timeout. Test
runners which know a test must run under a specific time can then optionally
treat these timeouts then as fatal.
+KCOV for selftests
+==================
+
+Selftests built with `kselftest_harness.h` natively support generating
+KCOV coverage data. See :doc:`KCOV: code coverage for fuzzing </dev-tools/kcov>`
+for prerequisites.
+
+You can specify the output directory with the `KCOV_OUTPUT` environment
+variable. Additionally, you can specify the number of instructions to
+collect with the `KCOV_SLOTS` environment variable ::
+
+ # KCOV_OUTPUT=$PWD/kcov KCOV_SLOTS=$((4096 * 2)) \
+ ./tools/testing/selftests/net/af_unix/scm_inq
+
+In the output directory, a coverage file is generated for each test
+case in the selftest ::
+
+ $ ls kcov/
+ scm_inq.dgram.basic scm_inq.seqpacket.basic scm_inq.stream.basic
+
+The default value of `KCOV_SLOTS` is `4096`, and `KCOV_SLOTS` multiplied
+by `sizeof(unsigned long)` must be multiple of `4096`, so the smallest
+value is `512`.
+
+Both `KCOV_OUTPUT` and `KCOV_SLOTS` can be specified as the variables
+on the `make` command line ::
+
+ # make -C tools/testing/selftests/ \
+ kselftest_override_timeout=60 \
+ KCOV_OUTPUT=$PWD/kcov KCOV_SLOTS=$((4096 * 4)) \
+ TARGETS=net/af_unix run_tests
+
+The collected data can be decoded with `addr2line` ::
+
+ $ cat kcov/* | sort | uniq | addr2line -e vmlinux | grep unix
+ net/unix/af_unix.c:1056
+ net/unix/af_unix.c:3138
+ net/unix/af_unix.c:3834
+ net/unix/af_unix.c:3838
+ ...
+
Packaging selftests
===================
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index c46ebdb9b8ef..40e70fb1a347 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -218,12 +218,14 @@ all:
done; exit $$ret;
run_tests: all
- @for TARGET in $(TARGETS); do \
- BUILD_TARGET=$$BUILD/$$TARGET; \
- $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests \
- SRC_PATH=$(shell readlink -e $$(pwd)) \
- OBJ_PATH=$(BUILD) \
- O=$(abs_objtree); \
+ @for TARGET in $(TARGETS); do \
+ BUILD_TARGET=$$BUILD/$$TARGET; \
+ $(MAKE) OUTPUT=$$BUILD_TARGET \
+ KCOV_OUTPUT=$(abspath $(KCOV_OUTPUT)) \
+ -C $$TARGET run_tests \
+ SRC_PATH=$(shell readlink -e $$(pwd)) \
+ OBJ_PATH=$(BUILD) \
+ O=$(abs_objtree); \
done;
hotplug:
diff --git a/tools/testing/selftests/kselftest_harness.h b/tools/testing/selftests/kselftest_harness.h
index 3f66e862e83e..5b7a01722981 100644
--- a/tools/testing/selftests/kselftest_harness.h
+++ b/tools/testing/selftests/kselftest_harness.h
@@ -56,6 +56,8 @@
#include <asm/types.h>
#include <ctype.h>
#include <errno.h>
+#include <fcntl.h>
+#include <linux/kcov.h>
#include <linux/unistd.h>
#include <poll.h>
#include <stdbool.h>
@@ -63,7 +65,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/ioctl.h>
#include <sys/mman.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -175,9 +179,12 @@
static void test_name(struct __test_metadata *_metadata); \
static void wrapper_##test_name( \
struct __test_metadata *_metadata, \
- struct __fixture_variant_metadata __attribute__((unused)) *variant) \
+ struct __fixture_variant_metadata __attribute__((unused)) *variant, \
+ char *test_full_name) \
{ \
+ enable_kcov(_metadata); \
test_name(_metadata); \
+ disable_kcov(_metadata, test_full_name); \
} \
static struct __test_metadata _##test_name##_object = \
{ .name = #test_name, \
@@ -401,7 +408,8 @@
const FIXTURE_VARIANT(fixture_name) *variant); \
static void wrapper_##fixture_name##_##test_name( \
struct __test_metadata *_metadata, \
- struct __fixture_variant_metadata *variant) \
+ struct __fixture_variant_metadata *variant, \
+ char *test_full_name) \
{ \
/* fixture data is alloced, setup, and torn down per call. */ \
FIXTURE_DATA(fixture_name) self_private, *self = NULL; \
@@ -430,7 +438,9 @@
if (_metadata->exit_code) \
_exit(0); \
*_metadata->no_teardown = false; \
+ enable_kcov(_metadata); \
fixture_name##_##test_name(_metadata, self, variant->data); \
+ disable_kcov(_metadata, test_full_name); \
_metadata->teardown_fn(false, _metadata, self, variant->data); \
_exit(0); \
} else if (child < 0 || child != waitpid(child, &status, 0)) { \
@@ -470,6 +480,8 @@
object->teardown_fn = &wrapper_##fixture_name##_##test_name##_teardown; \
object->termsig = signal; \
object->timeout = tmout; \
+ object->kcov_fd = -1; \
+ object->kcov_slots = -1; \
_##fixture_name##_##test_name##_object = object; \
__register_test(object); \
} \
@@ -908,7 +920,8 @@ __register_fixture_variant(struct __fixture_metadata *f,
struct __test_metadata {
const char *name;
void (*fn)(struct __test_metadata *,
- struct __fixture_variant_metadata *);
+ struct __fixture_variant_metadata *,
+ char *test_name);
pid_t pid; /* pid of test when being run */
struct __fixture_metadata *fixture;
void (*teardown_fn)(bool in_parent, struct __test_metadata *_metadata,
@@ -923,6 +936,10 @@ struct __test_metadata {
const void *variant;
struct __test_results *results;
struct __test_metadata *prev, *next;
+ int kcov_fd;
+ int kcov_slots;
+ char *kcov_dir;
+ unsigned long *kcov_mem;
};
static inline bool __test_passed(struct __test_metadata *metadata)
@@ -1185,6 +1202,114 @@ static bool test_enabled(int argc, char **argv,
return !has_positive;
}
+#define KCOV_SLOTS 4096
+
+static void enable_kcov(struct __test_metadata *t)
+{
+ char *slots;
+ int err;
+
+ t->kcov_dir = getenv("KCOV_OUTPUT");
+ if (!t->kcov_dir || *t->kcov_dir == '\0')
+ return;
+
+ slots = getenv("KCOV_SLOTS");
+ if (slots && *slots != '\0')
+ sscanf(slots, "%d", &t->kcov_slots);
+ if (t->kcov_slots <= 0)
+ t->kcov_slots = KCOV_SLOTS;
+
+ t->kcov_fd = open("/sys/kernel/debug/kcov", O_RDWR);
+ if (t->kcov_fd < 0) {
+ ksft_print_msg("ERROR OPENING KCOV FD\n");
+ goto err;
+ }
+
+ err = ioctl(t->kcov_fd, KCOV_INIT_TRACE, t->kcov_slots);
+ if (err) {
+ ksft_print_msg("ERROR INITIALISING KCOV\n");
+ goto err;
+ }
+
+ t->kcov_mem = mmap(NULL, sizeof(unsigned long) * t->kcov_slots,
+ PROT_READ | PROT_WRITE, MAP_SHARED, t->kcov_fd, 0);
+ if ((void *)t->kcov_mem == MAP_FAILED) {
+ ksft_print_msg("ERROR ALLOCATING MEMORY FOR KCOV\n");
+ goto err;
+ }
+
+ err = ioctl(t->kcov_fd, KCOV_ENABLE, KCOV_TRACE_PC);
+ if (err) {
+ ksft_print_msg("ERROR ENABLING KCOV\n");
+ goto err;
+ }
+
+ __atomic_store_n(&t->kcov_mem[0], 0, __ATOMIC_RELAXED);
+ return;
+err:
+ t->exit_code = KSFT_FAIL;
+ _exit(KSFT_FAIL);
+}
+
+static void disable_kcov(struct __test_metadata *t, char *test_name)
+{
+ int slots, err, dir, fd, i;
+
+ if (t->kcov_fd == -1)
+ return;
+
+ slots = __atomic_load_n(&t->kcov_mem[0], __ATOMIC_RELAXED);
+ if (slots == t->kcov_slots - 1)
+ ksft_print_msg("Set KCOV_SLOTS to a value greater than %d\n", t->kcov_slots);
+
+ err = ioctl(t->kcov_fd, KCOV_DISABLE, 0);
+ if (err) {
+ ksft_print_msg("ERROR DISABLING KCOV\n");
+ goto out;
+ }
+
+ err = mkdir(t->kcov_dir, 0755);
+ if (err == -1 && errno != EEXIST) {
+ ksft_print_msg("ERROR CREATING '%s'\n", t->kcov_dir);
+ goto out;
+ }
+ err = 0;
+
+ dir = open(t->kcov_dir, O_DIRECTORY);
+ if (dir < 0) {
+ ksft_print_msg("ERROR OPENING %s\n", t->kcov_dir);
+ err = dir;
+ goto out;
+ }
+
+ fd = openat(dir, test_name, O_RDWR | O_CREAT | O_TRUNC);
+
+ close(dir);
+
+ if (fd == -1) {
+ ksft_print_msg("ERROR CREATING '%s' at '%s'\n", test_name, t->kcov_dir);
+ err = fd;
+ goto out;
+ }
+
+ for (i = 0; i < slots; i++) {
+ char buf[64];
+ int size;
+
+ size = snprintf(buf, 64, "0x%lx\n", t->kcov_mem[i + 1]);
+ write(fd, buf, size);
+ }
+
+out:
+ munmap(t->kcov_mem, sizeof(t->kcov_mem[0]) * t->kcov_slots);
+ close(t->kcov_fd);
+
+ if (err) {
+ t->exit_code = KSFT_FAIL;
+ _exit(KSFT_FAIL);
+ }
+}
+
static void __run_test(struct __fixture_metadata *f,
struct __fixture_variant_metadata *variant,
struct __test_metadata *t)
@@ -1216,7 +1341,7 @@ static void __run_test(struct __fixture_metadata *f,
t->exit_code = KSFT_FAIL;
} else if (child == 0) {
setpgrp();
- t->fn(t, variant);
+ t->fn(t, variant, test_name);
_exit(t->exit_code);
} else {
t->pid = child;
--
2.51.1.838.g19442a804e-goog
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH v2] selftests: harness: Support KCOV. 2025-10-28 2:42 [PATCH v2] selftests: harness: Support KCOV Kuniyuki Iwashima @ 2025-11-06 8:50 ` kernel test robot 2025-11-06 21:42 ` Shuah Khan 1 sibling, 0 replies; 4+ messages in thread From: kernel test robot @ 2025-11-06 8:50 UTC (permalink / raw) To: Kuniyuki Iwashima Cc: oe-lkp, lkp, linux-kselftest, Shuah Khan, Kuniyuki Iwashima, Kuniyuki Iwashima, oliver.sang Hello, kernel test robot noticed "segfault_at_ip_sp_error" on: commit: c849d8e404a7b145b33c184042234e903ce72c7c ("[PATCH v2] selftests: harness: Support KCOV.") url: https://github.com/intel-lab-lkp/linux/commits/Kuniyuki-Iwashima/selftests-harness-Support-KCOV/20251028-104538 base: https://git.kernel.org/cgit/linux/kernel/git/shuah/linux-kselftest.git next patch link: https://lore.kernel.org/all/20251028024339.2028774-1-kuniyu@google.com/ patch subject: [PATCH v2] selftests: harness: Support KCOV. in testcase: kernel-selftests version: kernel-selftests-x86_64-8bb886cb8f3a-1_20251104 with following parameters: group: syscall_user_dispatch config: x86_64-rhel-9.4-kselftests compiler: gcc-14 test machine: 36 threads 1 sockets Intel(R) Core(TM) i9-9980XE CPU @ 3.00GHz (Skylake) with 32G memory (please refer to attached dmesg/kmsg for entire log/backtrace) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <oliver.sang@intel.com> | Closes: https://lore.kernel.org/oe-lkp/202511061615.3c5824f3-lkp@intel.com kern :info : [ 72.507647] [ T2520] sud_test[2520]: segfault at 0 ip 0000558da6f1242c sp 00007fffd6f2faf0 error 4 in sud_test[342c,558da6f11000+5000] likely on CPU 23 (core 8, socket 0) kern :info : [ 72.508965] [ T2520] Code: 48 89 e5 48 83 ec 70 48 89 7d 98 48 89 75 90 48 8b 45 98 8b 40 70 83 f8 ff 0f 84 36 02 00 00 48 8b 45 98 48 8b 80 80 00 00 00 <48> 8b 00 89 45 f4 48 8b 45 98 8b 40 74 83 e8 01 39 45 f4 75 1d 48 All code ======== 0: 48 89 e5 mov %rsp,%rbp 3: 48 83 ec 70 sub $0x70,%rsp 7: 48 89 7d 98 mov %rdi,-0x68(%rbp) b: 48 89 75 90 mov %rsi,-0x70(%rbp) f: 48 8b 45 98 mov -0x68(%rbp),%rax 13: 8b 40 70 mov 0x70(%rax),%eax 16: 83 f8 ff cmp $0xffffffff,%eax 19: 0f 84 36 02 00 00 je 0x255 1f: 48 8b 45 98 mov -0x68(%rbp),%rax 23: 48 8b 80 80 00 00 00 mov 0x80(%rax),%rax 2a:* 48 8b 00 mov (%rax),%rax <-- trapping instruction 2d: 89 45 f4 mov %eax,-0xc(%rbp) 30: 48 8b 45 98 mov -0x68(%rbp),%rax 34: 8b 40 74 mov 0x74(%rax),%eax 37: 83 e8 01 sub $0x1,%eax 3a: 39 45 f4 cmp %eax,-0xc(%rbp) 3d: 75 1d jne 0x5c 3f: 48 rex.W Code starting with the faulting instruction =========================================== 0: 48 8b 00 mov (%rax),%rax 3: 89 45 f4 mov %eax,-0xc(%rbp) 6: 48 8b 45 98 mov -0x68(%rbp),%rax a: 8b 40 74 mov 0x74(%rax),%eax d: 83 e8 01 sub $0x1,%eax 10: 39 45 f4 cmp %eax,-0xc(%rbp) 13: 75 1d jne 0x32 15: 48 rex.W kern :info : [ 72.511780] [ T2521] sud_test[2521]: segfault at 0 ip 0000558da6f1242c sp 00007fffd6f2faf0 error 4 in sud_test[342c,558da6f11000+5000] likely on CPU 23 (core 8, socket 0) kern :info : [ 72.513080] [ T2521] Code: 48 89 e5 48 83 ec 70 48 89 7d 98 48 89 75 90 48 8b 45 98 8b 40 70 83 f8 ff 0f 84 36 02 00 00 48 8b 45 98 48 8b 80 80 00 00 00 <48> 8b 00 89 45 f4 48 8b 45 98 8b 40 74 83 e8 01 39 45 f4 75 1d 48 All code ======== 0: 48 89 e5 mov %rsp,%rbp 3: 48 83 ec 70 sub $0x70,%rsp 7: 48 89 7d 98 mov %rdi,-0x68(%rbp) b: 48 89 75 90 mov %rsi,-0x70(%rbp) f: 48 8b 45 98 mov -0x68(%rbp),%rax 13: 8b 40 70 mov 0x70(%rax),%eax 16: 83 f8 ff cmp $0xffffffff,%eax 19: 0f 84 36 02 00 00 je 0x255 1f: 48 8b 45 98 mov -0x68(%rbp),%rax 23: 48 8b 80 80 00 00 00 mov 0x80(%rax),%rax 2a:* 48 8b 00 mov (%rax),%rax <-- trapping instruction 2d: 89 45 f4 mov %eax,-0xc(%rbp) 30: 48 8b 45 98 mov -0x68(%rbp),%rax 34: 8b 40 74 mov 0x74(%rax),%eax 37: 83 e8 01 sub $0x1,%eax 3a: 39 45 f4 cmp %eax,-0xc(%rbp) 3d: 75 1d jne 0x5c 3f: 48 rex.W Code starting with the faulting instruction =========================================== 0: 48 8b 00 mov (%rax),%rax 3: 89 45 f4 mov %eax,-0xc(%rbp) 6: 48 8b 45 98 mov -0x68(%rbp),%rax a: 8b 40 74 mov 0x74(%rax),%eax d: 83 e8 01 sub $0x1,%eax 10: 39 45 f4 cmp %eax,-0xc(%rbp) 13: 75 1d jne 0x32 15: 48 rex.W user :notice: [ 72.516773] [ T622] update-alternatives: warning: skip creation of /usr/share/man/man1/traceroute6.1.gz because associated file /usr/share/man/man1/traceroute6.db.1.gz (of link group traceroute6) doesn't exist kern :info : [ 72.517057] [ T2523] sud_test[2523]: segfault at 0 ip 0000558da6f1242c sp 00007fffd6f2faf0 error 4 in sud_test[342c,558da6f11000+5000] likely on CPU 27 (core 16, socket 0) kern :info : [ 72.519874] [ T2523] Code: 48 89 e5 48 83 ec 70 48 89 7d 98 48 89 75 90 48 8b 45 98 8b 40 70 83 f8 ff 0f 84 36 02 00 00 48 8b 45 98 48 8b 80 80 00 00 00 <48> 8b 00 89 45 f4 48 8b 45 98 8b 40 74 83 e8 01 39 45 f4 75 1d 48 All code ======== 0: 48 89 e5 mov %rsp,%rbp 3: 48 83 ec 70 sub $0x70,%rsp 7: 48 89 7d 98 mov %rdi,-0x68(%rbp) b: 48 89 75 90 mov %rsi,-0x70(%rbp) f: 48 8b 45 98 mov -0x68(%rbp),%rax 13: 8b 40 70 mov 0x70(%rax),%eax 16: 83 f8 ff cmp $0xffffffff,%eax 19: 0f 84 36 02 00 00 je 0x255 1f: 48 8b 45 98 mov -0x68(%rbp),%rax 23: 48 8b 80 80 00 00 00 mov 0x80(%rax),%rax 2a:* 48 8b 00 mov (%rax),%rax <-- trapping instruction 2d: 89 45 f4 mov %eax,-0xc(%rbp) 30: 48 8b 45 98 mov -0x68(%rbp),%rax 34: 8b 40 74 mov 0x74(%rax),%eax 37: 83 e8 01 sub $0x1,%eax 3a: 39 45 f4 cmp %eax,-0xc(%rbp) 3d: 75 1d jne 0x5c 3f: 48 rex.W Code starting with the faulting instruction =========================================== 0: 48 8b 00 mov (%rax),%rax 3: 89 45 f4 mov %eax,-0xc(%rbp) 6: 48 8b 45 98 mov -0x68(%rbp),%rax a: 8b 40 74 mov 0x74(%rax),%eax d: 83 e8 01 sub $0x1,%eax 10: 39 45 f4 cmp %eax,-0xc(%rbp) 13: 75 1d jne 0x32 15: 48 rex.W user :notice: [ 72.521352] [ T622] update-alternatives: warning: skip creation of /usr/share/man/man1/lft.1.gz because associated file /usr/share/man/man1/lft.db.1.gz (of link group lft) doesn't exist kern :info : [ 72.522679] [ T2524] sud_test[2524]: segfault at 0 ip 0000558da6f1242c sp 00007fffd6f2faf0 error 4 in sud_test[342c,558da6f11000+5000] likely on CPU 23 (core 8, socket 0) kern :info : [ 72.524467] [ T2524] Code: 48 89 e5 48 83 ec 70 48 89 7d 98 48 89 75 90 48 8b 45 98 8b 40 70 83 f8 ff 0f 84 36 02 00 00 48 8b 45 98 48 8b 80 80 00 00 00 <48> 8b 00 89 45 f4 48 8b 45 98 8b 40 74 83 e8 01 39 45 f4 75 1d 48 All code ======== 0: 48 89 e5 mov %rsp,%rbp 3: 48 83 ec 70 sub $0x70,%rsp 7: 48 89 7d 98 mov %rdi,-0x68(%rbp) b: 48 89 75 90 mov %rsi,-0x70(%rbp) f: 48 8b 45 98 mov -0x68(%rbp),%rax 13: 8b 40 70 mov 0x70(%rax),%eax 16: 83 f8 ff cmp $0xffffffff,%eax 19: 0f 84 36 02 00 00 je 0x255 1f: 48 8b 45 98 mov -0x68(%rbp),%rax 23: 48 8b 80 80 00 00 00 mov 0x80(%rax),%rax 2a:* 48 8b 00 mov (%rax),%rax <-- trapping instruction 2d: 89 45 f4 mov %eax,-0xc(%rbp) 30: 48 8b 45 98 mov -0x68(%rbp),%rax 34: 8b 40 74 mov 0x74(%rax),%eax 37: 83 e8 01 sub $0x1,%eax 3a: 39 45 f4 cmp %eax,-0xc(%rbp) 3d: 75 1d jne 0x5c 3f: 48 rex.W Code starting with the faulting instruction =========================================== 0: 48 8b 00 mov (%rax),%rax 3: 89 45 f4 mov %eax,-0xc(%rbp) 6: 48 8b 45 98 mov -0x68(%rbp),%rax a: 8b 40 74 mov 0x74(%rax),%eax d: 83 e8 01 sub $0x1,%eax 10: 39 45 f4 cmp %eax,-0xc(%rbp) 13: 75 1d jne 0x32 15: 48 rex.W user :notice: [ 72.526246] [ T622] update-alternatives: warning: skip creation of /usr/share/man/man1/traceproto.1.gz because associated file /usr/share/man/man1/traceproto.db.1.gz (of link group traceproto) doesn't exist kern :info : [ 72.529475] [ T2525] sud_test[2525]: segfault at 0 ip 0000558da6f1242c sp 00007fffd6f2faf0 error 4 in sud_test[342c,558da6f11000+5000] likely on CPU 16 (core 26, socket 0) kern :info : [ 72.530789] [ T2525] Code: 48 89 e5 48 83 ec 70 48 89 7d 98 48 89 75 90 48 8b 45 98 8b 40 70 83 f8 ff 0f 84 36 02 00 00 48 8b 45 98 48 8b 80 80 00 00 00 <48> 8b 00 89 45 f4 48 8b 45 98 8b 40 74 83 e8 01 39 45 f4 75 1d 48 All code ======== 0: 48 89 e5 mov %rsp,%rbp 3: 48 83 ec 70 sub $0x70,%rsp 7: 48 89 7d 98 mov %rdi,-0x68(%rbp) b: 48 89 75 90 mov %rsi,-0x70(%rbp) f: 48 8b 45 98 mov -0x68(%rbp),%rax 13: 8b 40 70 mov 0x70(%rax),%eax 16: 83 f8 ff cmp $0xffffffff,%eax 19: 0f 84 36 02 00 00 je 0x255 1f: 48 8b 45 98 mov -0x68(%rbp),%rax 23: 48 8b 80 80 00 00 00 mov 0x80(%rax),%rax 2a:* 48 8b 00 mov (%rax),%rax <-- trapping instruction 2d: 89 45 f4 mov %eax,-0xc(%rbp) 30: 48 8b 45 98 mov -0x68(%rbp),%rax 34: 8b 40 74 mov 0x74(%rax),%eax 37: 83 e8 01 sub $0x1,%eax 3a: 39 45 f4 cmp %eax,-0xc(%rbp) 3d: 75 1d jne 0x5c 3f: 48 rex.W Code starting with the faulting instruction =========================================== 0: 48 8b 00 mov (%rax),%rax 3: 89 45 f4 mov %eax,-0xc(%rbp) 6: 48 8b 45 98 mov -0x68(%rbp),%rax a: 8b 40 74 mov 0x74(%rax),%eax d: 83 e8 01 sub $0x1,%eax 10: 39 45 f4 cmp %eax,-0xc(%rbp) 13: 75 1d jne 0x32 15: 48 rex.W The kernel config and materials to reproduce are available at: https://download.01.org/0day-ci/archive/20251106/202511061615.3c5824f3-lkp@intel.com -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] selftests: harness: Support KCOV. 2025-10-28 2:42 [PATCH v2] selftests: harness: Support KCOV Kuniyuki Iwashima 2025-11-06 8:50 ` kernel test robot @ 2025-11-06 21:42 ` Shuah Khan 2025-11-07 7:08 ` Kuniyuki Iwashima 1 sibling, 1 reply; 4+ messages in thread From: Shuah Khan @ 2025-11-06 21:42 UTC (permalink / raw) To: Kuniyuki Iwashima, Shuah Khan Cc: Kuniyuki Iwashima, linux-kselftest, Shuah Khan On 10/27/25 20:42, Kuniyuki Iwashima wrote: > While writing a selftest with kselftest_harness.h, I often want to > check which paths are actually exercised. > > Let's support generating KCOV coverage data. > > We can specify the output directory via the KCOV_OUTPUT environment > variable, and the number of instructions to collect via the KCOV_SLOTS > environment variable. > > # KCOV_OUTPUT=$PWD/kcov KCOV_SLOTS=$((4096 * 2)) \ > ./tools/testing/selftests/net/af_unix/scm_inq > > Both variables can also be specified as the make variable. > > # make -C tools/testing/selftests/ \ > KCOV_OUTPUT=$PWD/kcov KCOV_SLOTS=$((4096 * 4)) \ > kselftest_override_timeout=60 TARGETS=net/af_unix run_tests > > The coverage data can be simply decoded with addr2line: > > $ cat kcov/* | sort | uniq | addr2line -e vmlinux | grep unix > net/unix/af_unix.c:1056 > net/unix/af_unix.c:3138 > net/unix/af_unix.c:3834 > net/unix/af_unix.c:3838 > net/unix/af_unix.c:311 (discriminator 2) > ... > > or more nicely with a script embedded in vock [0]: > > $ cat kcov/* | sort | uniq > local.log > $ python3 ~/kernel/tools/vock/report.py \ > --kernel-src ./ --vmlinux ./vmlinux \ > --mode local --local-log local.log --filter unix > ... > ------------------------------- Coverage Report -------------------------------- > 📄 net/unix/af_unix.c (276 lines) > ... > 942 | static int unix_setsockopt(struct socket *sock, int level, int optname, > 943 | sockptr_t optval, unsigned int optlen) > 944 | { > ... > 961 | switch (optname) { > 962 | case SO_INQ: > 963 > if (sk->sk_type != SOCK_STREAM) > 964 | return -EINVAL; > 965 | > 966 > if (val > 1 || val < 0) > 967 | return -EINVAL; > 968 | > 969 > WRITE_ONCE(u->recvmsg_inq, val); > 970 | break; > > Link: https://github.com/kzall0c/vock/blob/f3d97de9954f9df758c0ab287ca7e24e654288c7/report.py #[0] > Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> > --- > v2: Support TEST() > v1: https://lore.kernel.org/linux-kselftest/20251017084022.3721950-1-kuniyu@google.com/ > --- > Documentation/dev-tools/kselftest.rst | 41 ++++++ > tools/testing/selftests/Makefile | 14 ++- > tools/testing/selftests/kselftest_harness.h | 133 +++++++++++++++++++- > 3 files changed, 178 insertions(+), 10 deletions(-) > I am okay with kcov support being added. You probably have to fix a few things. kernel test robot is still complaining on v2. thanks, -- Shuah ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] selftests: harness: Support KCOV. 2025-11-06 21:42 ` Shuah Khan @ 2025-11-07 7:08 ` Kuniyuki Iwashima 0 siblings, 0 replies; 4+ messages in thread From: Kuniyuki Iwashima @ 2025-11-07 7:08 UTC (permalink / raw) To: Shuah Khan; +Cc: Shuah Khan, Kuniyuki Iwashima, linux-kselftest On Thu, Nov 6, 2025 at 1:42 PM Shuah Khan <skhan@linuxfoundation.org> wrote: > > On 10/27/25 20:42, Kuniyuki Iwashima wrote: > > While writing a selftest with kselftest_harness.h, I often want to > > check which paths are actually exercised. > > > > Let's support generating KCOV coverage data. > > > > We can specify the output directory via the KCOV_OUTPUT environment > > variable, and the number of instructions to collect via the KCOV_SLOTS > > environment variable. > > > > # KCOV_OUTPUT=$PWD/kcov KCOV_SLOTS=$((4096 * 2)) \ > > ./tools/testing/selftests/net/af_unix/scm_inq > > > > Both variables can also be specified as the make variable. > > > > # make -C tools/testing/selftests/ \ > > KCOV_OUTPUT=$PWD/kcov KCOV_SLOTS=$((4096 * 4)) \ > > kselftest_override_timeout=60 TARGETS=net/af_unix run_tests > > > > The coverage data can be simply decoded with addr2line: > > > > $ cat kcov/* | sort | uniq | addr2line -e vmlinux | grep unix > > net/unix/af_unix.c:1056 > > net/unix/af_unix.c:3138 > > net/unix/af_unix.c:3834 > > net/unix/af_unix.c:3838 > > net/unix/af_unix.c:311 (discriminator 2) > > ... > > > > or more nicely with a script embedded in vock [0]: > > > > $ cat kcov/* | sort | uniq > local.log > > $ python3 ~/kernel/tools/vock/report.py \ > > --kernel-src ./ --vmlinux ./vmlinux \ > > --mode local --local-log local.log --filter unix > > ... > > ------------------------------- Coverage Report -------------------------------- > > 📄 net/unix/af_unix.c (276 lines) > > ... > > 942 | static int unix_setsockopt(struct socket *sock, int level, int optname, > > 943 | sockptr_t optval, unsigned int optlen) > > 944 | { > > ... > > 961 | switch (optname) { > > 962 | case SO_INQ: > > 963 > if (sk->sk_type != SOCK_STREAM) > > 964 | return -EINVAL; > > 965 | > > 966 > if (val > 1 || val < 0) > > 967 | return -EINVAL; > > 968 | > > 969 > WRITE_ONCE(u->recvmsg_inq, val); > > 970 | break; > > > > Link: https://github.com/kzall0c/vock/blob/f3d97de9954f9df758c0ab287ca7e24e654288c7/report.py #[0] > > Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> > > --- > > v2: Support TEST() > > v1: https://lore.kernel.org/linux-kselftest/20251017084022.3721950-1-kuniyu@google.com/ > > --- > > Documentation/dev-tools/kselftest.rst | 41 ++++++ > > tools/testing/selftests/Makefile | 14 ++- > > tools/testing/selftests/kselftest_harness.h | 133 +++++++++++++++++++- > > 3 files changed, 178 insertions(+), 10 deletions(-) > > > > I am okay with kcov support being added. You probably have to fix a few things. > kernel test robot is still complaining on v2. Thank you, Shuah! Will fix the issue in v3. ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-11-07 7:08 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-10-28 2:42 [PATCH v2] selftests: harness: Support KCOV Kuniyuki Iwashima 2025-11-06 8:50 ` kernel test robot 2025-11-06 21:42 ` Shuah Khan 2025-11-07 7:08 ` Kuniyuki Iwashima
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox