Include kvm_test_harness.h first which will include kselftest_harness.h
for _GNU_SOURCE to get defined first before inclusion of stdio.h. It
is required for declaration of asprintf(). It removes the following
build error caught by clang-17:
In file included from x86_64/fix_hypercall_test.c:12:
In file included from include/kvm_test_harness.h:11:
../kselftest_harness.h:1169:2: error: call to undeclared function
'asprintf'; ISO C99 and later do not support implicit function declarations
[-Wimplicit-function-declaration]
1169 | asprintf(&test_name, "%s%s%s.%s", f->name,
| ^
Signed-off-by: Muhammad Usama Anjum <usama.anjum(a)collabora.com>
---
tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c b/tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c
index f3c2239228b10..75306dcfaad6c 100644
--- a/tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c
+++ b/tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c
@@ -4,12 +4,12 @@
*
* Tests for KVM paravirtual feature disablement
*/
+#include "kvm_test_harness.h"
#include <asm/kvm_para.h>
#include <linux/kvm_para.h>
#include <linux/stringify.h>
#include <stdint.h>
-#include "kvm_test_harness.h"
#include "apic.h"
#include "test_util.h"
#include "kvm_util.h"
--
2.39.2
Some unit tests intentionally trigger warning backtraces by passing bad
parameters to kernel API functions. Such unit tests typically check the
return value from such calls, not the existence of the warning backtrace.
Such intentionally generated warning backtraces are neither desirable
nor useful for a number of reasons.
- They can result in overlooked real problems.
- A warning that suddenly starts to show up in unit tests needs to be
investigated and has to be marked to be ignored, for example by
adjusting filter scripts. Such filters are ad-hoc because there is
no real standard format for warnings. On top of that, such filter
scripts would require constant maintenance.
One option to address problem would be to add messages such as "expected
warning backtraces start / end here" to the kernel log. However, that
would again require filter scripts, it might result in missing real
problematic warning backtraces triggered while the test is running, and
the irrelevant backtrace(s) would still clog the kernel log.
Solve the problem by providing a means to identify and suppress specific
warning backtraces while executing test code. Support suppressing multiple
backtraces while at the same time limiting changes to generic code to the
absolute minimum. Architecture specific changes are kept at minimum by
retaining function names only if both CONFIG_DEBUG_BUGVERBOSE and
CONFIG_KUNIT are enabled.
The first patch of the series introduces the necessary infrastructure.
The second patch introduces support for counting suppressed backtraces.
This capability is used in patch three to implement unit tests.
Patch four documents the new API.
The next two patches add support for suppressing backtraces in drm_rect
and dev_addr_lists unit tests. These patches are intended to serve as
examples for the use of the functionality introduced with this series.
The remaining patches implement the necessary changes for all
architectures with GENERIC_BUG support.
With CONFIG_KUNIT enabled, image size increase with this series applied is
approximately 1%. The image size increase (and with it the functionality
introduced by this series) can be avoided by disabling
CONFIG_KUNIT_SUPPRESS_BACKTRACE.
This series is based on the RFC patch and subsequent discussion at
https://patchwork.kernel.org/project/linux-kselftest/patch/02546e59-1afe-4b…
and offers a more comprehensive solution of the problem discussed there.
Design note:
Function pointers are only added to the __bug_table section if both
CONFIG_KUNIT_SUPPRESS_BACKTRACE and CONFIG_DEBUG_BUGVERBOSE are enabled
to avoid image size increases if CONFIG_KUNIT is disabled. There would be
some benefits to adding those pointers all the time (reduced complexity,
ability to display function names in BUG/WARNING messages). That change,
if desired, can be made later.
Checkpatch note:
Remaining checkpatch errors and warnings were deliberately ignored.
Some are triggered by matching coding style or by comments interpreted
as code, others by assembler macros which are disliked by checkpatch.
Suggestions for improvements are welcome.
Changes since RFC:
- Introduced CONFIG_KUNIT_SUPPRESS_BACKTRACE
- Minor cleanups and bug fixes
- Added support for all affected architectures
- Added support for counting suppressed warnings
- Added unit tests using those counters
- Added patch to suppress warning backtraces in dev_addr_lists tests
Changes since v1:
- Rebased to v6.9-rc1
- Added Tested-by:, Acked-by:, and Reviewed-by: tags
[I retained those tags since there have been no functional changes]
- Introduced KUNIT_SUPPRESS_BACKTRACE configuration option, enabled by
default.
Changes since v2:
- Rebased to v6.9-rc2
- Added comments to drm warning suppression explaining why it is needed.
- Added patch to move conditional code in arch/sh/include/asm/bug.h
to avoid kerneldoc warning
- Added architecture maintainers to Cc: for architecture specific patches
- No functional changes
----------------------------------------------------------------
Guenter Roeck (15):
bug/kunit: Core support for suppressing warning backtraces
kunit: bug: Count suppressed warning backtraces
kunit: Add test cases for backtrace warning suppression
kunit: Add documentation for warning backtrace suppression API
drm: Suppress intentional warning backtraces in scaling unit tests
net: kunit: Suppress lock warning noise at end of dev_addr_lists tests
x86: Add support for suppressing warning backtraces
arm64: Add support for suppressing warning backtraces
loongarch: Add support for suppressing warning backtraces
parisc: Add support for suppressing warning backtraces
s390: Add support for suppressing warning backtraces
sh: Add support for suppressing warning backtraces
sh: Move defines needed for suppressing warning backtraces
riscv: Add support for suppressing warning backtraces
powerpc: Add support for suppressing warning backtraces
Documentation/dev-tools/kunit/usage.rst | 30 ++++++++-
arch/arm64/include/asm/asm-bug.h | 29 ++++++---
arch/arm64/include/asm/bug.h | 8 ++-
arch/loongarch/include/asm/bug.h | 38 ++++++++----
arch/parisc/include/asm/bug.h | 29 ++++++---
arch/powerpc/include/asm/bug.h | 37 +++++++++---
arch/riscv/include/asm/bug.h | 38 ++++++++----
arch/s390/include/asm/bug.h | 17 +++++-
arch/sh/include/asm/bug.h | 28 +++++++--
arch/x86/include/asm/bug.h | 21 +++++--
drivers/gpu/drm/tests/drm_rect_test.c | 16 +++++
include/asm-generic/bug.h | 16 ++++-
include/kunit/bug.h | 56 +++++++++++++++++
include/kunit/test.h | 1 +
include/linux/bug.h | 13 ++++
lib/bug.c | 51 ++++++++++++++--
lib/kunit/Kconfig | 9 +++
lib/kunit/Makefile | 7 ++-
lib/kunit/backtrace-suppression-test.c | 104 ++++++++++++++++++++++++++++++++
lib/kunit/bug.c | 42 +++++++++++++
net/core/dev_addr_lists_test.c | 6 ++
21 files changed, 524 insertions(+), 72 deletions(-)
create mode 100644 include/kunit/bug.h
create mode 100644 lib/kunit/backtrace-suppression-test.c
create mode 100644 lib/kunit/bug.c
I lied, there aren't three different definitions of the KVM clock. The
fourth is on i386, where it's still based on CLOCK_MONOTONIC (well,
boot time which might as well be the same sine we offset it anyway).
If we fix *that* to be based on CLOCK_MONOTONIC_RAW then we can rip out
a whole bunch of mechanisms which were added to cope with NTP frequency
skew.
This cleans up the mess and gets us back down to the two unavoidable
definitions of the KVM clock: when the host and guest TSCs are well
behaved and in sync, it's in "master clock" mode where it's defined as
a simple arithmetic function of the guest TSC, otherwise it's clamped
to the host's CLOCK_MONOTONIC_RAW.
It includes Jack's KVM_[GS]ET_CLOCK_GUEST patch to allow accurate
migration. Also my KVM_VCPU_TSC_SCALE which exposes the precise TSC
scaling factors. This is needed to get accurate migration of the guest
TSC, and can *also* be used by userspace to have vDSO-style access to
the KVM clock. Thus allowing hypercalls and other emulated clock devices
(e.g. PIT, HPET, ACPI timer) to be based on the KVM clock too, giving
*consistency* across a live migration.
I do still need to fix KVM_REQ_MASTERCLOCK_UPDATE so that it doesn't
clamp the clock back to CLOCK_MONOTONIC_RAW; we should *update* the
ka->kvmclock_offset when we've been running in use_master_clock mode.
Should probably do that in kvm_arch_hardware_disable() for timekeeping
across hibernation too, but I haven't finished working that one out.
I think there are still some places left where KVM reads the time twice
in close(ish) succession and then assumes they were at the *same* time,
which I'll audit and fix too.
I also need to flesh out the test cases and do some real testing from
VMMs, but I think it's ready for some heckling at least.
https://git.infradead.org/users/dwmw2/linux.git/shortlog/refs/heads/clocks
David Woodhouse (8):
KVM: x86/xen: Do not corrupt KVM clock in kvm_xen_shared_info_init()
KVM: x86: Improve accuracy of KVM clock when TSC scaling is in force
KVM: x86: Explicitly disable TSC scaling without CONSTANT_TSC
KVM: x86: Add KVM_VCPU_TSC_SCALE and fix the documentation on TSC migration
KVM: x86: Avoid NTP frequency skew for KVM clock on 32-bit host
KVM: x86: Remove periodic global clock updates
KVM: x86: Kill KVM_REQ_GLOBAL_CLOCK_UPDATE
KVM: x86: Fix KVM clock precision in __get_kvmclock()
Jack Allister (2):
KVM: x86: Add KVM_[GS]ET_CLOCK_GUEST for accurate KVM clock migration
KVM: selftests: Add KVM/PV clock selftest to prove timer correction
Documentation/virt/kvm/api.rst | 37 ++
Documentation/virt/kvm/devices/vcpu.rst | 115 ++++--
arch/x86/include/asm/kvm_host.h | 8 +-
arch/x86/include/uapi/asm/kvm.h | 6 +
arch/x86/kvm/svm/svm.c | 3 +-
arch/x86/kvm/vmx/vmx.c | 2 +-
arch/x86/kvm/x86.c | 438 +++++++++++++---------
arch/x86/kvm/xen.c | 4 +-
include/uapi/linux/kvm.h | 3 +
tools/testing/selftests/kvm/Makefile | 1 +
tools/testing/selftests/kvm/x86_64/pvclock_test.c | 192 ++++++++++
11 files changed, 600 insertions(+), 209 deletions(-)
Fix the warnings by initializing and marking the variable as unused.
I've caught the warnings by using clang.
split_huge_page_test.c:303:6: warning: variable 'dummy' set but not used [-Wunused-but-set-variable]
303 | int dummy;
| ^
split_huge_page_test.c:343:3: warning: variable 'dummy' is uninitialized when used here [-Wuninitialized]
343 | dummy += *(*addr + i);
| ^~~~~
split_huge_page_test.c:303:11: note: initialize the variable 'dummy' to silence this warning
303 | int dummy;
| ^
| = 0
2 warnings generated.
Fixes: fc4d182316bd ("mm: huge_memory: enable debugfs to split huge pages to any order")
Signed-off-by: Muhammad Usama Anjum <usama.anjum(a)collabora.com>
---
tools/testing/selftests/mm/split_huge_page_test.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/mm/split_huge_page_test.c b/tools/testing/selftests/mm/split_huge_page_test.c
index 6c988bd2f3356..d3c7f5fb3e7b7 100644
--- a/tools/testing/selftests/mm/split_huge_page_test.c
+++ b/tools/testing/selftests/mm/split_huge_page_test.c
@@ -300,7 +300,7 @@ int create_pagecache_thp_and_fd(const char *testfile, size_t fd_size, int *fd,
char **addr)
{
size_t i;
- int dummy;
+ int __attribute__((unused)) dummy = 0;
srand(time(NULL));
--
2.39.2
The sources for the powerpc selftests are arranged into sub-directories.
However when the tests are built and installed, the sub-directories are
squashed, losing the structure.
For example, with the current code the result of installing the selftests is:
$ tree tools/testing/selftests/kselftest_install
tools/testing/selftests/kselftest_install
├── kselftest
│ ├── ktap_helpers.sh
│ ├── module.sh
│ ├── prefix.pl
│ └── runner.sh
├── kselftest-list.txt
├── powerpc
│ ├── alignment_handler
│ ├── attr_test
│ ├── back_to_back_ebbs_test
│ ├── bad_accesses
│ ├── bhrb_filter_map_test
│ ├── bhrb_no_crash_wo_pmu_test
│ ├── blacklisted_events_test
│ ├── cache_shape
│ ├── close_clears_pmcc_test
│ ├── context_switch
│ ├── copy_first_unaligned
...
│ ├── settings
...
│ └── wild_bctr
└── run_kselftest.sh
All the powerpc tests are squashed into the single powerpc directory. In
particular, note that there is a single `settings` file, even though
there are multiple settings files in the powerpc selftest sources. One
of the settings files ends up installed, depending on install order,
even if they have different contents.
Similarly if there were two tests with the same name in different
sub-directories they would clobber each other.
Fix it by replicating the directory structure of the source tree into
the install directory. The result being for example:
$ tree tools/testing/selftests/kselftest_install
tools/testing/selftests/kselftest_install
├── kselftest
│ ├── ktap_helpers.sh
│ ├── module.sh
│ ├── prefix.pl
│ └── runner.sh
├── kselftest-list.txt
├── powerpc
│ ├── alignment
│ │ ├── alignment_handler
│ │ └── copy_first_unaligned
│ ├── benchmarks
│ │ ├── context_switch
│ │ ├── exec_target
│ │ ├── fork
│ │ ├── futex_bench
│ │ ├── gettimeofday
│ │ ├── mmap_bench
│ │ ├── null_syscall
│ │ └── settings
...
│ ├── eeh
│ │ ├── eeh-basic.sh
│ │ ├── eeh-functions.sh
│ │ └── settings
...
│ └── vphn
│ └── test-vphn
└── run_kselftest.sh
Note multiple settings files in different sub-directories.
This change also has the effect of changing the names of the tests from
the point of view of the kselftest runner. Before the tests are named
eg:
powerpc:copy_first_unaligned
powerpc:cache_shape
powerpc:reg_access_test
After, the test collection names include the sub-directory:
powerpc/alignment:copy_first_unaligned
powerpc/cache_shape:cache_shape
powerpc/pmu/ebb:reg_access_test
That means whereas previously all powerpc tests could be run with:
$ ./run_kselftest.sh -c powerpc
After the change it's necessary to pass a regex that matches all powerpc
entries, eg:
$ ./run_kselftest.sh -c "powerpc.*"
The latter form also works before and after the change.
Signed-off-by: Michael Ellerman <mpe(a)ellerman.id.au>
---
tools/testing/selftests/powerpc/Makefile | 4 ++--
tools/testing/selftests/powerpc/pmu/Makefile | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
index 2f299fd04d2d..b175e94e1901 100644
--- a/tools/testing/selftests/powerpc/Makefile
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -52,14 +52,14 @@ endef
override define INSTALL_RULE
+@for TARGET in $(SUB_DIRS); do \
BUILD_TARGET=$(OUTPUT)/$$TARGET; \
- $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET install;\
+ $(MAKE) OUTPUT=$$BUILD_TARGET INSTALL_PATH=$$INSTALL_PATH/$$TARGET -C $$TARGET install;\
done;
endef
emit_tests:
+@for TARGET in $(SUB_DIRS); do \
BUILD_TARGET=$(OUTPUT)/$$TARGET; \
- $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET $@;\
+ $(MAKE) OUTPUT=$$BUILD_TARGET COLLECTION=$(COLLECTION)/$$TARGET -s -C $$TARGET $@;\
done;
override define CLEAN
diff --git a/tools/testing/selftests/powerpc/pmu/Makefile b/tools/testing/selftests/powerpc/pmu/Makefile
index 773933e5180e..7e9dbf3d0d09 100644
--- a/tools/testing/selftests/powerpc/pmu/Makefile
+++ b/tools/testing/selftests/powerpc/pmu/Makefile
@@ -44,7 +44,7 @@ emit_tests:
done
+@for TARGET in $(SUB_DIRS); do \
BUILD_TARGET=$(OUTPUT)/$$TARGET; \
- $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET emit_tests; \
+ $(MAKE) OUTPUT=$$BUILD_TARGET COLLECTION=$(COLLECTION)/$$TARGET -s -C $$TARGET emit_tests; \
done;
DEFAULT_INSTALL_RULE := $(INSTALL_RULE)
@@ -52,7 +52,7 @@ override define INSTALL_RULE
$(DEFAULT_INSTALL_RULE)
+@for TARGET in $(SUB_DIRS); do \
BUILD_TARGET=$(OUTPUT)/$$TARGET; \
- $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET install; \
+ $(MAKE) OUTPUT=$$BUILD_TARGET INSTALL_PATH=$$INSTALL_PATH/$$TARGET -C $$TARGET install; \
done;
endef
--
2.44.0
From: Oleg Nesterov <oleg(a)redhat.com>
check_timer_distribution() runs ten threads in a busy loop and tries to
test that the kernel distributes a process posix CPU timer signal to every
thread over time.
There is not guarantee that this is true even after commit bcb7ee79029d
("posix-timers: Prefer delivery of signals to the current thread") because
that commit only avoids waking up the sleeping process leader thread, but
that has nothing to do with the actual signal delivery.
As the signal is process wide the first thread which observes sigpending
and wins the race to lock sighand will deliver the signal. Testing shows
that this hangs on a regular base because some threads never win the race.
The comment "This primarily tests that the kernel does not favour any one."
is wrong. The kernel does favour a thread which hits the timer interrupt
when CLOCK_PROCESS_CPUTIME_ID expires.
Rewrite the test so it only checks that the group leader sleeping in join()
never receives SIGALRM and the thread which burns CPU cycles receives all
signals.
In older kernels which do not have commit bcb7ee79029d ("posix-timers:
Prefer delivery of signals to the current thread") the test-case fails
immediately, the very 1st tick wakes the leader up. Otherwise it quickly
succeeds after 100 ticks.
CI testing wants to use newer selftest versions on stable kernels. In this
case the test is guaranteed to fail.
So check in the failure case whether the kernel version is less than v6.3
and skip the test result in that case.
[ tglx: Massaged change log, renamed the version check helper ]
[ edliaw: 071af0c9e582 ("selftests: timers: Convert posix_timers test to
generate KTAP output") wasn't merged to 6.6.y, so resolved merge
conflicts. ]
Fixes: e797203fb3ba ("selftests/timers/posix_timers: Test delivery of signals across threads")
Signed-off-by: Oleg Nesterov <oleg(a)redhat.com>
Signed-off-by: Thomas Gleixner <tglx(a)linutronix.de>
Cc: stable(a)vger.kernel.org
Link: https://lore.kernel.org/r/20240409133802.GD29396@redhat.com
(cherry picked from commit 6d029c25b71f2de2838a6f093ce0fa0e69336154)
Signed-off-by: Edward Liaw <edliaw(a)google.com>
---
tools/testing/selftests/kselftest.h | 13 +++
tools/testing/selftests/timers/posix_timers.c | 99 +++++++++----------
2 files changed, 59 insertions(+), 53 deletions(-)
diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
index 529d29a35900..68d5a93dff8d 100644
--- a/tools/testing/selftests/kselftest.h
+++ b/tools/testing/selftests/kselftest.h
@@ -49,6 +49,7 @@
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
+#include <sys/utsname.h>
#endif
#ifndef ARRAY_SIZE
@@ -327,4 +328,16 @@ static inline int ksft_exit_skip(const char *msg, ...)
exit(KSFT_SKIP);
}
+static inline int ksft_min_kernel_version(unsigned int min_major,
+ unsigned int min_minor)
+{
+ unsigned int major, minor;
+ struct utsname info;
+
+ if (uname(&info) || sscanf(info.release, "%u.%u.", &major, &minor) != 2)
+ ksft_exit_fail_msg("Can't parse kernel version\n");
+
+ return major > min_major || (major == min_major && minor >= min_minor);
+}
+
#endif /* __KSELFTEST_H */
diff --git a/tools/testing/selftests/timers/posix_timers.c b/tools/testing/selftests/timers/posix_timers.c
index 9a42403eaff7..aaec7f9845c5 100644
--- a/tools/testing/selftests/timers/posix_timers.c
+++ b/tools/testing/selftests/timers/posix_timers.c
@@ -188,78 +188,71 @@ static int check_timer_create(int which)
return 0;
}
-int remain;
-__thread int got_signal;
+static pthread_t ctd_thread;
+static volatile int ctd_count, ctd_failed;
-static void *distribution_thread(void *arg)
+static void ctd_sighandler(int sig)
{
- while (__atomic_load_n(&remain, __ATOMIC_RELAXED));
- return NULL;
+ if (pthread_self() != ctd_thread)
+ ctd_failed = 1;
+ ctd_count--;
}
-static void distribution_handler(int nr)
+static void *ctd_thread_func(void *arg)
{
- if (!__atomic_exchange_n(&got_signal, 1, __ATOMIC_RELAXED))
- __atomic_fetch_sub(&remain, 1, __ATOMIC_RELAXED);
-}
-
-/*
- * Test that all running threads _eventually_ receive CLOCK_PROCESS_CPUTIME_ID
- * timer signals. This primarily tests that the kernel does not favour any one.
- */
-static int check_timer_distribution(void)
-{
- int err, i;
- timer_t id;
- const int nthreads = 10;
- pthread_t threads[nthreads];
struct itimerspec val = {
.it_value.tv_sec = 0,
.it_value.tv_nsec = 1000 * 1000,
.it_interval.tv_sec = 0,
.it_interval.tv_nsec = 1000 * 1000,
};
+ timer_t id;
- printf("Check timer_create() per process signal distribution... ");
- fflush(stdout);
+ /* 1/10 seconds to ensure the leader sleeps */
+ usleep(10000);
- remain = nthreads + 1; /* worker threads + this thread */
- signal(SIGALRM, distribution_handler);
- err = timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id);
- if (err < 0) {
- perror("Can't create timer\n");
- return -1;
- }
- err = timer_settime(id, 0, &val, NULL);
- if (err < 0) {
- perror("Can't set timer\n");
- return -1;
- }
+ ctd_count = 100;
+ if (timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id))
+ return "Can't create timer\n";
+ if (timer_settime(id, 0, &val, NULL))
+ return "Can't set timer\n";
- for (i = 0; i < nthreads; i++) {
- if (pthread_create(&threads[i], NULL, distribution_thread, NULL)) {
- perror("Can't create thread\n");
- return -1;
- }
- }
+ while (ctd_count > 0 && !ctd_failed)
+ ;
- /* Wait for all threads to receive the signal. */
- while (__atomic_load_n(&remain, __ATOMIC_RELAXED));
+ if (timer_delete(id))
+ return "Can't delete timer\n";
- for (i = 0; i < nthreads; i++) {
- if (pthread_join(threads[i], NULL)) {
- perror("Can't join thread\n");
- return -1;
- }
- }
+ return NULL;
+}
- if (timer_delete(id)) {
- perror("Can't delete timer\n");
- return -1;
- }
+/*
+ * Test that only the running thread receives the timer signal.
+ */
+static int check_timer_distribution(void)
+{
+ const char *errmsg;
- printf("[OK]\n");
+ signal(SIGALRM, ctd_sighandler);
+
+ errmsg = "Can't create thread\n";
+ if (pthread_create(&ctd_thread, NULL, ctd_thread_func, NULL))
+ goto err;
+
+ errmsg = "Can't join thread\n";
+ if (pthread_join(ctd_thread, (void **)&errmsg) || errmsg)
+ goto err;
+
+ if (!ctd_failed)
+ ksft_test_result_pass("check signal distribution\n");
+ else if (ksft_min_kernel_version(6, 3))
+ ksft_test_result_fail("check signal distribution\n");
+ else
+ ksft_test_result_skip("check signal distribution (old kernel)\n");
return 0;
+err:
+ ksft_print_msg(errmsg);
+ return -1;
}
int main(int argc, char **argv)
--
2.44.0.769.g3c40516874-goog