[PATCH 0/2] timers test fix and duplicate defines cleanup
The first patch in this two patch fixes warn_unused_result compile time warning in posix_timers test. The second patch removes local NSEC_PER_SEC and USEC_PER_SEC defines. NSEC_PER_SEC and USEC_PER_SEC are defines in several timers tests. These defines are inconsistent with variations of ULL, LL, etc. without any explanation why it is necessary. These defines can be picked up from include/vdso/time64.h header file. In the interest of making it easier to maintain, remove the local defines. Include include/vdso/time64.h instead. This change will also make the defines consistent. Shuah Khan (2): selftests:timers: posix_timers: Fix warn_unused_result in __fatal_error() selftests: timers: Remove local NSEC_PER_SEC and USEC_PER_SEC defines tools/testing/selftests/timers/Makefile | 2 +- tools/testing/selftests/timers/adjtick.c | 4 +-- .../selftests/timers/alarmtimer-suspend.c | 2 +- .../selftests/timers/inconsistency-check.c| 2 +- tools/testing/selftests/timers/leap-a-day.c | 2 +- tools/testing/selftests/timers/mqueue-lat.c | 2 +- tools/testing/selftests/timers/nanosleep.c| 3 +-- tools/testing/selftests/timers/posix_timers.c | 27 ++- tools/testing/selftests/timers/raw_skew.c | 2 +- tools/testing/selftests/timers/set-2038.c | 3 +-- .../testing/selftests/timers/set-timer-lat.c | 3 +-- .../testing/selftests/timers/valid-adjtimex.c | 4 +-- 12 files changed, 26 insertions(+), 30 deletions(-) -- 2.40.1
Re: [PATCH v3 0/3] selftests: livepatch: test livepatching a kprobed function
On Mon 2024-09-23 10:16:29, Shuah Khan wrote: > On 9/23/24 08:45, Marcos Paulo de Souza wrote: > > On Fri, 2024-09-20 at 13:56 +0200, Michael Vetter wrote: > > > This patchset adds a test for livepatching a kprobed function. > > > > > > Michael Vetter (3): > > > selftests: livepatch: rename KLP_SYSFS_DIR to SYSFS_KLP_DIR > > > selftests: livepatch: save and restore kprobe state > > > selftests: livepatch: test livepatching a kprobed function > > > > > > > Assuming this is going through livepatch tree: Yup, I am going to take it via the livepatch tree. Though I am going to wait for more potential feedback a week or so. > Acked-by: Shuah Khan Thanks for the review. Best Regards, Petr
Re: [PATCH v3 0/3] selftests: livepatch: test livepatching a kprobed function
On Fri 2024-09-20 13:56:28, Michael Vetter wrote: > This patchset adds a test for livepatching a kprobed function. > > Michael Vetter (3): > selftests: livepatch: rename KLP_SYSFS_DIR to SYSFS_KLP_DIR > selftests: livepatch: save and restore kprobe state > selftests: livepatch: test livepatching a kprobed function Looks good. For the entire patchset: Reviewed-by: Petr Mladek Tested-by: Petr Mladek Best Regards, Petr
Re: [PATCH v8 5/8] platform: Add test managed platform_device/driver APIs
On Thu, Jul 18, 2024 at 02:05:04PM -0700, Stephen Boyd wrote: > Introduce KUnit resource wrappers around platform_driver_register(), > platform_device_alloc(), and platform_device_add() so that test authors > can register platform drivers/devices from their tests and have the > drivers/devices automatically be unregistered when the test is done. > > This makes test setup code simpler when a platform driver or platform > device is needed. Add a few test cases at the same time to make sure the > APIs work as intended. > > Cc: Brendan Higgins > Reviewed-by: David Gow > Cc: Rae Moar > Reviewed-by: Greg Kroah-Hartman > Cc: "Rafael J. Wysocki" > Signed-off-by: Stephen Boyd This patch adds another intentional warning traceback seen whenever CONFIG_KUNIT_TEST is enabled. sysfs: cannot create duplicate filename '/devices/platform/kunit-platform-add-2' CPU: 0 UID: 0 PID: 421 Comm: kunit_try_catch Tainted: G N 6.11.0-mac-09967-g2ece55614b92 #1 Tainted: [N]=TEST Stack from 015a9de0: 015a9de0 006168ac 006168ac 0158c000 026e8ea0 00c4a6b8 004bbe32 006168ac 00166cd4 005fa210 0158c000 026e8ea0 ffef 00c4a6b8 0067a18c 00166dc0 00c4a6b8 026e8ea0 01a6ac0e 006cb3c8 01a6ac0a 006cb3c8 0049b6de 01a6ac0a 01a6ac0a 006cb3c8 01a6ac0a 006cb3c8 01a6ac0a 015a9e78 0049b8b4 01a6ac0a 01a6ac00 01a6ac0a 0001bbfa 00321592 01a6ac0a 006cb3c8 01a6ac00 0067a18c 0002d21c Call Trace: [<004bbe32>] dump_stack+0xc/0x10 [<00166cd4>] sysfs_warn_dup+0x52/0x64 [<00166dc0>] sysfs_create_dir_ns+0x9a/0xac [<0049b6de>] kobject_add_internal+0xdc/0x238 [<0049b8b4>] kobject_add+0x7a/0x7e [<0001bbfa>] insert_resource+0x0/0x1a [<00321592>] device_add+0x104/0x588 [<0002d21c>] list_del_init+0x0/0x2a [<0001bbfa>] insert_resource+0x0/0x1a [<00326358>] platform_device_add+0x58/0x180 [<00326378>] platform_device_add+0x78/0x180 [<00273234>] IS_ERR_OR_NULL+0x0/0x1c [<00270c58>] kunit_platform_device_add+0x14/0x118 [<0002d21c>] list_del_init+0x0/0x2a [<00270c44>] kunit_platform_device_add+0x0/0x118 [<00273234>] IS_ERR_OR_NULL+0x0/0x1c [<002733de>] kunit_platform_device_add_twice_fails_test+0x118/0x170 [<00050e44>] ktime_get_ts64+0x0/0xd8 [<00050e44>] ktime_get_ts64+0x0/0xd8 [<004b04d0>] memset+0x0/0x8c [<0026cc3e>] kunit_try_run_case+0xa0/0x176 [<0002d21c>] list_del_init+0x0/0x2a [<0002cfaa>] kthread_exit+0x0/0x14 [<0026e3d0>] kunit_generic_run_threadfn_adapter+0x0/0x2a [<0026e3e6>] kunit_generic_run_threadfn_adapter+0x16/0x2a [<0002d2d6>] kthread+0x90/0x9a [<0002d246>] kthread+0x0/0x9a [<252c>] ret_from_kernel_thread+0xc/0x14 kobject: kobject_add_internal failed for kunit-platform-add-2 with -EEXIST, don't try to register things with the same name in the same directory. # kunit_platform_device_add_twice_fails_test: pass:1 fail:0 skip:0 total:1 ok 3 kunit_platform_device_add_twice_fails_test # kunit_platform_device_add_cleans_up: pass:1 fail:0 skip:0 total:1 ok 4 kunit_platform_device_add_cleans_up # kunit_platform_device: pass:4 fail:0 skip:0 total:4 I have said several times that my test system can and will not handle intentional warning backtraces. I strongly believe that it is wrong to expect that testbed maintainers have to keep track of intentional backtraces. That means that I now also disabled CONFIG_KUNIT_TEST in my testbed. Guenter
Re: [PATCH v3 0/3] selftests: livepatch: test livepatching a kprobed function
On 9/23/24 08:45, Marcos Paulo de Souza wrote: On Fri, 2024-09-20 at 13:56 +0200, Michael Vetter wrote: This patchset adds a test for livepatching a kprobed function. Thanks to Petr and Marcos for the reviews! V3: Save and restore kprobe state also when test fails, by integrating it into setup_config() and cleanup(). Rename SYSFS variables in a more logical way. Sort test modules in alphabetical order. Rename module description. V2: Save and restore kprobe state. Michael Vetter (3): selftests: livepatch: rename KLP_SYSFS_DIR to SYSFS_KLP_DIR selftests: livepatch: save and restore kprobe state selftests: livepatch: test livepatching a kprobed function Thanks for the new version! LGTM, so the series is Reviewed-by: Marcos Paulo de Souza tools/testing/selftests/livepatch/Makefile | 3 +- .../testing/selftests/livepatch/functions.sh | 13 +++- .../selftests/livepatch/test-kprobe.sh | 62 +++ .../selftests/livepatch/test_modules/Makefile | 3 +- .../livepatch/test_modules/test_klp_kprobe.c | 38 5 files changed, 114 insertions(+), 5 deletions(-) create mode 100755 tools/testing/selftests/livepatch/test-kprobe.sh create mode 100644 tools/testing/selftests/livepatch/test_modules/test_klp_kprobe.c Assuming this is going through livepatch tree: Acked-by: Shuah Khan thanks, -- Shuah
Re: [PATCH v3 0/3] selftests: livepatch: test livepatching a kprobed function
On Fri, 2024-09-20 at 13:56 +0200, Michael Vetter wrote: > This patchset adds a test for livepatching a kprobed function. > > Thanks to Petr and Marcos for the reviews! > > V3: > Save and restore kprobe state also when test fails, by integrating it > into setup_config() and cleanup(). > Rename SYSFS variables in a more logical way. > Sort test modules in alphabetical order. > Rename module description. > > V2: > Save and restore kprobe state. > > Michael Vetter (3): > selftests: livepatch: rename KLP_SYSFS_DIR to SYSFS_KLP_DIR > selftests: livepatch: save and restore kprobe state > selftests: livepatch: test livepatching a kprobed function > Thanks for the new version! LGTM, so the series is Reviewed-by: Marcos Paulo de Souza > tools/testing/selftests/livepatch/Makefile | 3 +- > .../testing/selftests/livepatch/functions.sh | 13 +++- > .../selftests/livepatch/test-kprobe.sh | 62 > +++ > .../selftests/livepatch/test_modules/Makefile | 3 +- > .../livepatch/test_modules/test_klp_kprobe.c | 38 > 5 files changed, 114 insertions(+), 5 deletions(-) > create mode 100755 tools/testing/selftests/livepatch/test-kprobe.sh > create mode 100644 > tools/testing/selftests/livepatch/test_modules/test_klp_kprobe.c >
[PATCH 4/4] selftests: KVM: Add new test for faulty mmio usage
Implement the test which covers "weird" mmio usage. The test has 4 test cases: 1) Guest sets IDT/GDT base to point to an MMIO region. Triple fault and shutdown are expected there. 2) Guest jumps to MMIO address. Fetches from MMIO are not permitted, so UD is expected there. 3) Guest sets an IDT entry to point to MMIO range. MMIO here happens after event delivery, so UD is expected. 4) Guest points the UD IDT entry to MMIO range and causes UD after that. We should not go into infinite loop here, as we are constantly putting exception info onto the stack and it will eventually overflow. These test cases depend on previous patches in this patch series. Signed-off-by: Ivan Orlov --- tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/x86_64/faulty_mmio.c| 199 ++ 2 files changed, 200 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/faulty_mmio.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 0c4b254ab56b..d9928c54e851 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -129,6 +129,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/amx_test TEST_GEN_PROGS_x86_64 += x86_64/max_vcpuid_cap_test TEST_GEN_PROGS_x86_64 += x86_64/triple_fault_event_test TEST_GEN_PROGS_x86_64 += x86_64/recalc_apic_map_test +TEST_GEN_PROGS_x86_64 += x86_64/faulty_mmio TEST_GEN_PROGS_x86_64 += access_tracking_perf_test TEST_GEN_PROGS_x86_64 += demand_paging_test TEST_GEN_PROGS_x86_64 += dirty_log_test diff --git a/tools/testing/selftests/kvm/x86_64/faulty_mmio.c b/tools/testing/selftests/kvm/x86_64/faulty_mmio.c new file mode 100644 index ..b83c1d646696 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/faulty_mmio.c @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This test covers error processing when doing weird things with MMIO addresses, + * i.e. jumping into MMIO range or specifying it as IDT / GDT descriptor base. + */ +#include +#include "kvm_util.h" +#include "processor.h" +#include + +#define MMIO_ADDR 0xDEADBEE000UL +/* This address is not canonical, so any reference will result in #GP */ +#define GP_ADDR 0xDEADBEEFDEADBEEFULL + +enum test_desc_type { + TEST_DESC_IDT, + TEST_DESC_GDT, +}; + +static const struct desc_ptr faulty_desc = { + .address = MMIO_ADDR, + .size = 0xFFF, +}; + +static void faulty_desc_guest_code(enum test_desc_type dtype) +{ + if (dtype == TEST_DESC_IDT) + __asm__ __volatile__("lidt %0"::"m"(faulty_desc)); + else + __asm__ __volatile__("lgdt %0"::"m"(faulty_desc)); + + /* Generate a #GP */ + *((uint8_t *)GP_ADDR) = 0x1; + + /* We should never reach this point */ + GUEST_ASSERT(0); +} + +/* + * This test tries to point the IDT / GDT descriptor to an MMIO range. + * This action should cause a triple fault in guest, as it happens when + * your descriptors are messed up on the actual hardware. + */ +static void test_faulty_desc(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + int i; + + enum test_desc_type dtype_tests[] = { TEST_DESC_IDT, TEST_DESC_GDT }; + + for (i = 0; i < ARRAY_SIZE(dtype_tests); i++) { + vm = vm_create_with_one_vcpu(&vcpu, faulty_desc_guest_code); + vcpu_args_set(vcpu, 1, dtype_tests[i]); + virt_map(vm, MMIO_ADDR, MMIO_ADDR, 1); + + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN); + kvm_vm_free(vm); + } +} + +static void jump_to_mmio_guest_code(bool write_first) +{ + void (*f)(void) = (void *)(MMIO_ADDR); + + if (write_first) { + /* +* We get different vmexit codes when accessing the MMIO address for the second +* time with VMX. For the first time it is an EPT violation, for the second - +* EPT misconfig. We need to check that we get #UD in both cases. +*/ + *((char *)MMIO_ADDR) = 0x1; + } + + f(); + + /* We should never reach this point */ + GUEST_ASSERT(0); +} + +static void guest_ud_handler(struct ex_regs *regs) +{ + GUEST_DONE(); +} + +/* + * This test tries to jump to an MMIO address. As fetching the instructions + * from MMIO is not supported by KVM and doesn't make any practical sense, + * KVM should handle it gracefully and inject #UD into guest. + */ +static void test_jump_to_mmio(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + struct kvm_run *run; + struct ucall uc; + int i; + + bool test_cases_write_first[] = { false, true }; + + for (i = 0; i < ARRAY_SIZE(test_cases_write_first); i++) { + vm = vm_create_with_one_vcpu(&vcpu, jump_to_mmio_guest_code); +
[PATCH] Revert "list: test: fix tests for list_cut_position()"
This reverts commit e620799c414a035dea1208bcb51c869744931dbb. The commit introduces unit test failures. Expected cur == &entries[i], but cur == 037fffadfd80 &entries[i] == 037fffadfd60 # list_test_list_cut_position: pass:0 fail:1 skip:0 total:1 not ok 21 list_test_list_cut_position # list_test_list_cut_before: EXPECTATION FAILED at lib/list-test.c:444 Expected cur == &entries[i], but cur == 037fffa9fd70 &entries[i] == 037fffa9fd60 # list_test_list_cut_before: EXPECTATION FAILED at lib/list-test.c:444 Expected cur == &entries[i], but cur == 037fffa9fd80 &entries[i] == 037fffa9fd70 Revert it. Fixes: e620799c414a ("list: test: fix tests for list_cut_position()") Cc: I Hsin Cheng Cc: David Gow Cc: Andrew Morton Signed-off-by: Guenter Roeck --- lib/list-test.c | 6 -- 1 file changed, 6 deletions(-) diff --git a/lib/list-test.c b/lib/list-test.c index 4f3dc75baec1..e207c4c98d70 100644 --- a/lib/list-test.c +++ b/lib/list-test.c @@ -408,13 +408,10 @@ static void list_test_list_cut_position(struct kunit *test) KUNIT_EXPECT_EQ(test, i, 2); - i = 0; list_for_each(cur, &list1) { KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); i++; } - - KUNIT_EXPECT_EQ(test, i, 1); } static void list_test_list_cut_before(struct kunit *test) @@ -439,13 +436,10 @@ static void list_test_list_cut_before(struct kunit *test) KUNIT_EXPECT_EQ(test, i, 1); - i = 0; list_for_each(cur, &list1) { KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); i++; } - - KUNIT_EXPECT_EQ(test, i, 2); } static void list_test_list_splice(struct kunit *test) -- 2.45.2
[PATCH] selftest: remoteproc: Add basic test for start/stop sequence
Add new basic remoteproc test that check start/stop sequence of all subsystems available. diff --git a/MAINTAINERS b/MAINTAINERS index e062b5328341..aff76edc4242 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -18225,6 +18225,7 @@ F: Documentation/staging/remoteproc.rst F: drivers/remoteproc/ F: include/linux/remoteproc.h F: include/linux/remoteproc/ +F: tools/testing/selftests/remoteproc/ REMOTE PROCESSOR MESSAGING (RPMSG) SUBSYSTEM M: Bjorn Andersson diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 697f13bbbc32..31db0311efdc 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -68,6 +68,7 @@ TARGETS += proc TARGETS += pstore TARGETS += ptrace TARGETS += openat2 +TARGETS += remoteproc TARGETS += resctrl TARGETS += riscv TARGETS += rlimits diff --git a/tools/testing/selftests/remoteproc/Makefile b/tools/testing/selftests/remoteproc/Makefile new file mode 100644 index ..a84b3934fd36 --- /dev/null +++ b/tools/testing/selftests/remoteproc/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +TEST_PROGS := remoteproc_test.sh + +include ../lib.mk diff --git a/tools/testing/selftests/remoteproc/config b/tools/testing/selftests/remoteproc/config new file mode 100644 index ..a5c237d2f3b4 --- /dev/null +++ b/tools/testing/selftests/remoteproc/config @@ -0,0 +1 @@ +CONFIG_REMOTEPROC=y diff --git a/tools/testing/selftests/remoteproc/remoteproc_test.sh b/tools/testing/selftests/remoteproc/remoteproc_test.sh new file mode 100644 index ..88c8f15d8406 --- /dev/null +++ b/tools/testing/selftests/remoteproc/remoteproc_test.sh @@ -0,0 +1,165 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. +# + +DIR="$(dirname $(readlink -f "$0"))" + +KTAP_HELPERS="${DIR}/../kselftest/ktap_helpers.sh" +if [ -e "$KTAP_HELPERS" ]; then +source "$KTAP_HELPERS" +else +echo -n "1..0 # SKIP $KTAP_HELPERS file not found" + exit 4 +fi + +RPROC_SYS=/sys/class/remoteproc +RPROC_SEQ_SLEEP=5 +rproc_ss_files= +num_tests=0 +test_err=0 + +check_error() { + if [ $? -ne 0 ]; then + test_err=$((test_err+1)) + ktap_print_msg "$@" + fi +} + +rproc_seq_test_ss_one() { + ss=$1 + rproc=${RPROC_SYS}/$ss + rproc_name=$(cat $rproc/name) + rproc_state=$(cat $rproc/state) + rproc_ssr=$(cat $rproc/recovery) + ktap_print_msg "Testing rproc sequence for $rproc_name" + + # Reset test_err value + test_err=0 + if [ "$rproc_ssr" != "enabled" ]; then + echo enabled > $rproc/recovery + check_error "$rproc_name SSR-enabled failed" + fi + + if [ "$rproc_state" != "running" ]; then + echo start > "$rproc/state" + check_error "$rproc_name state-start failed" + + sleep ${RPROC_SEQ_SLEEP} + + echo stop > "$rproc/state" + check_error "$rproc_name state-stop failed" + else + echo stop > "$rproc/state" + check_error "$rproc_name state-stop failed" + + sleep ${RPROC_SEQ_SLEEP} + + echo start > "$rproc/state" + check_error "$rproc_name state-start failed" + fi + + if [ $test_err -ne 0 ]; then + ktap_test_fail "$rproc_name" + else + ktap_test_pass "$rproc_name" + fi +} + +rproc_seq_test_all_ss() { + # Declare an array to save initial states of each ss + org_ss_to_state="" + + # Reset test_err value + test_err=0 + + for ss in ${rproc_ss_files}; do + rproc=${RPROC_SYS}/$ss + rproc_name=$(cat $rproc/name) + rproc_ssr=$(cat $rproc/recovery) + + # Enable SSR-recovery support + if [ "$rproc_ssr" != "enabled" ]; then + echo enabled > $rproc/recovery + check_error "$rproc_name SSR-enabled failed" + fi + done + + for ss in ${rproc_ss_files}; do + rproc=${RPROC_SYS}/$ss + rproc_name=$(cat $rproc/name) + rproc_state=$(cat $rproc/state) + + # Save initial states for each ss + org_ss_to_state="$org_ss_to_state $rproc_state" + + # Initiate start/stop sequence + if [ "$rproc_state" != "running" ]; then + echo start > "$rproc/state" + check_error "$rproc_name state-start failed" +
[RFC PATCH v2 3/3] bpf: Add sk_lookup test to use ORIGDSTADDR cmsg.
This patch reuses the framework already in place for sk_lookup, allowing it now to send a reply from the server fd directly, instead of having to create a socket bound to the original destination address and reply from there. It does this by passing the source address and port from where to reply from in a IP_ORIGDSTADDR ancillary message passed in sendmsg. Signed-off-by: Tiago Lam --- tools/testing/selftests/bpf/prog_tests/sk_lookup.c | 67 +++--- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c index ae87c00867ba..df780624c16c 100644 --- a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c +++ b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c @@ -75,6 +75,7 @@ struct test { struct inet_addr listen_at; enum server accept_on; bool reuseport_has_conns; /* Add a connected socket to reuseport group */ + bool dont_bind_reply; /* Don't bind, send direct from server fd. */ }; struct cb_opts { @@ -363,7 +364,7 @@ static void v4_to_v6(struct sockaddr_storage *ss) memset(&v6->sin6_addr.s6_addr[0], 0, 10); } -static int udp_recv_send(int server_fd) +static int udp_recv_send(int server_fd, bool dont_bind_reply) { char cmsg_buf[CMSG_SPACE(sizeof(struct sockaddr_storage))]; struct sockaddr_storage _src_addr = { 0 }; @@ -373,7 +374,7 @@ static int udp_recv_send(int server_fd) struct iovec iov = { 0 }; struct cmsghdr *cm; char buf[1]; - int ret, fd; + int fd; ssize_t n; iov.iov_base = buf; @@ -415,26 +416,37 @@ static int udp_recv_send(int server_fd) v4_to_v6(dst_addr); } - /* Reply from original destination address. */ - fd = start_server_addr(SOCK_DGRAM, dst_addr, sizeof(*dst_addr), NULL); - if (!ASSERT_OK_FD(fd, "start_server_addr")) { - log_err("failed to create tx socket"); - return -1; - } + if (dont_bind_reply) { + /* Reply directly from server fd, specifying the source address +* and/or port in struct msghdr. +*/ + n = sendmsg(server_fd, &msg, 0); + if (CHECK(n <= 0, "sendmsg", "failed\n")) { + log_err("failed to send echo reply"); + return -1; + } + } else { + /* Reply from original destination address. */ + fd = start_server_addr(SOCK_DGRAM, dst_addr, sizeof(*dst_addr), + NULL); + if (!ASSERT_OK_FD(fd, "start_server_addr")) { + log_err("failed to create tx socket"); + return -1; + } - msg.msg_control = NULL; - msg.msg_controllen = 0; - n = sendmsg(fd, &msg, 0); - if (CHECK(n <= 0, "sendmsg", "failed\n")) { - log_err("failed to send echo reply"); - ret = -1; - goto out; + msg.msg_control = NULL; + msg.msg_controllen = 0; + n = sendmsg(fd, &msg, 0); + if (CHECK(n <= 0, "sendmsg", "failed\n")) { + log_err("failed to send echo reply"); + close(fd); + return -1; + } + + close(fd); } - ret = 0; -out: - close(fd); - return ret; + return 0; } static int tcp_echo_test(int client_fd, int server_fd) @@ -454,14 +466,14 @@ static int tcp_echo_test(int client_fd, int server_fd) return 0; } -static int udp_echo_test(int client_fd, int server_fd) +static int udp_echo_test(int client_fd, int server_fd, bool dont_bind_reply) { int err; err = send_byte(client_fd); if (err) return -1; - err = udp_recv_send(server_fd); + err = udp_recv_send(server_fd, dont_bind_reply); if (err) return -1; err = recv_byte(client_fd); @@ -653,7 +665,8 @@ static void run_lookup_prog(const struct test *t) if (t->sotype == SOCK_STREAM) tcp_echo_test(client_fd, server_fds[t->accept_on]); else - udp_echo_test(client_fd, server_fds[t->accept_on]); + udp_echo_test(client_fd, server_fds[t->accept_on], + t->dont_bind_reply); close(client_fd); close: @@ -775,6 +788,16 @@ static void test_redirect_lookup(struct test_sk_lookup *skel) .listen_at = { INT_IP4, INT_PORT }, .accept_on = SERVER_B, }, + { + .desc = &
[PATCH v3 0/3] selftests: livepatch: test livepatching a kprobed function
This patchset adds a test for livepatching a kprobed function. Thanks to Petr and Marcos for the reviews! V3: Save and restore kprobe state also when test fails, by integrating it into setup_config() and cleanup(). Rename SYSFS variables in a more logical way. Sort test modules in alphabetical order. Rename module description. V2: Save and restore kprobe state. Michael Vetter (3): selftests: livepatch: rename KLP_SYSFS_DIR to SYSFS_KLP_DIR selftests: livepatch: save and restore kprobe state selftests: livepatch: test livepatching a kprobed function tools/testing/selftests/livepatch/Makefile| 3 +- .../testing/selftests/livepatch/functions.sh | 13 +++- .../selftests/livepatch/test-kprobe.sh| 62 +++ .../selftests/livepatch/test_modules/Makefile | 3 +- .../livepatch/test_modules/test_klp_kprobe.c | 38 5 files changed, 114 insertions(+), 5 deletions(-) create mode 100755 tools/testing/selftests/livepatch/test-kprobe.sh create mode 100644 tools/testing/selftests/livepatch/test_modules/test_klp_kprobe.c -- 2.46.0
[PATCH v3 3/3] selftests: livepatch: test livepatching a kprobed function
The test proves that a function that is being kprobed and uses a post_handler cannot be livepatched. Only one ftrace_ops with FTRACE_OPS_FL_IPMODIFY set may be registered to any given function at a time. Signed-off-by: Michael Vetter --- tools/testing/selftests/livepatch/Makefile| 3 +- .../selftests/livepatch/test-kprobe.sh| 62 +++ .../selftests/livepatch/test_modules/Makefile | 3 +- .../livepatch/test_modules/test_klp_kprobe.c | 38 4 files changed, 104 insertions(+), 2 deletions(-) create mode 100755 tools/testing/selftests/livepatch/test-kprobe.sh create mode 100644 tools/testing/selftests/livepatch/test_modules/test_klp_kprobe.c diff --git a/tools/testing/selftests/livepatch/Makefile b/tools/testing/selftests/livepatch/Makefile index 35418a4790be..a080eb54a215 100644 --- a/tools/testing/selftests/livepatch/Makefile +++ b/tools/testing/selftests/livepatch/Makefile @@ -10,7 +10,8 @@ TEST_PROGS := \ test-state.sh \ test-ftrace.sh \ test-sysfs.sh \ - test-syscall.sh + test-syscall.sh \ + test-kprobe.sh TEST_FILES := settings diff --git a/tools/testing/selftests/livepatch/test-kprobe.sh b/tools/testing/selftests/livepatch/test-kprobe.sh new file mode 100755 index ..0c62c6b81e18 --- /dev/null +++ b/tools/testing/selftests/livepatch/test-kprobe.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 SUSE +# Author: Michael Vetter + +. $(dirname $0)/functions.sh + +MOD_LIVEPATCH=test_klp_livepatch +MOD_KPROBE=test_klp_kprobe + +setup_config + +# Kprobe a function and verify that we can't livepatch that same function +# when it uses a post_handler since only one IPMODIFY maybe be registered +# to any given function at a time. + +start_test "livepatch interaction with kprobed function with post_handler" + +echo 1 > /sys/kernel/debug/kprobes/enabled + +load_mod $MOD_KPROBE has_post_handler=true +load_failing_mod $MOD_LIVEPATCH +unload_mod $MOD_KPROBE + +check_result "% insmod test_modules/test_klp_kprobe.ko has_post_handler=true +% insmod test_modules/$MOD_LIVEPATCH.ko +livepatch: enabling patch '$MOD_LIVEPATCH' +livepatch: '$MOD_LIVEPATCH': initializing patching transition +livepatch: failed to register ftrace handler for function 'cmdline_proc_show' (-16) +livepatch: failed to patch object 'vmlinux' +livepatch: failed to enable patch '$MOD_LIVEPATCH' +livepatch: '$MOD_LIVEPATCH': canceling patching transition, going to unpatch +livepatch: '$MOD_LIVEPATCH': completing unpatching transition +livepatch: '$MOD_LIVEPATCH': unpatching complete +insmod: ERROR: could not insert module test_modules/$MOD_LIVEPATCH.ko: Device or resource busy +% rmmod test_klp_kprobe" + +start_test "livepatch interaction with kprobed function without post_handler" + +load_mod $MOD_KPROBE has_post_handler=false +load_lp $MOD_LIVEPATCH + +unload_mod $MOD_KPROBE +disable_lp $MOD_LIVEPATCH +unload_lp $MOD_LIVEPATCH + +check_result "% insmod test_modules/test_klp_kprobe.ko has_post_handler=false +% insmod test_modules/$MOD_LIVEPATCH.ko +livepatch: enabling patch '$MOD_LIVEPATCH' +livepatch: '$MOD_LIVEPATCH': initializing patching transition +livepatch: '$MOD_LIVEPATCH': starting patching transition +livepatch: '$MOD_LIVEPATCH': completing patching transition +livepatch: '$MOD_LIVEPATCH': patching complete +% rmmod test_klp_kprobe +% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled +livepatch: '$MOD_LIVEPATCH': initializing unpatching transition +livepatch: '$MOD_LIVEPATCH': starting unpatching transition +livepatch: '$MOD_LIVEPATCH': completing unpatching transition +livepatch: '$MOD_LIVEPATCH': unpatching complete +% rmmod $MOD_LIVEPATCH" + +exit 0 diff --git a/tools/testing/selftests/livepatch/test_modules/Makefile b/tools/testing/selftests/livepatch/test_modules/Makefile index e6e638c4bcba..939230e571f5 100644 --- a/tools/testing/selftests/livepatch/test_modules/Makefile +++ b/tools/testing/selftests/livepatch/test_modules/Makefile @@ -6,11 +6,12 @@ obj-m += test_klp_atomic_replace.o \ test_klp_callbacks_demo.o \ test_klp_callbacks_demo2.o \ test_klp_callbacks_mod.o \ + test_klp_kprobe.o \ test_klp_livepatch.o \ + test_klp_shadow_vars.o \ test_klp_state.o \ test_klp_state2.o \ test_klp_state3.o \ - test_klp_shadow_vars.o \ test_klp_syscall.o # Ensure that KDIR exists, otherwise skip the compilation diff --git a/tools/testing/selftests/livepatch/test_modules/test_klp_kprobe.c b/tools/testing/selftests/livepatch/test_modules/test_klp_kprobe.c new file mode 100644 index ..67a8d29012f6 --- /dev/null +++ b/tools/testing/selftests/livepatch/test_modules/test_klp_
[PATCH v2 5/6] KVM: x86: selftests: Test core events
Test events on core counters by iterating through every combination of events in amd_pmu_zen_events with every core counter. For each combination, calculate the appropriate register addresses for the event selection/control register and the counter register. The base addresses and layout schemes change depending on whether we have the CoreExt feature. To do the testing, reuse GUEST_TEST_EVENT to run a standard known workload. Decouple it from guest_assert_event_count (now guest_assert_intel_event_count) to generalize to AMD. Then assert the most specific detail that can be reasonably known about the counter result. Exact count is defined and known for some events and for other events merely asserted to be nonzero. Note on exact counts: AMD counts one more branch than Intel for the same workload. Though I can't confirm a reason, the only thing it could be is the boundary of the loop instruction being counted differently. Presumably, when the counter reaches 0 and execution continues to the next instruction, AMD counts this as a branch and Intel doesn't. Signed-off-by: Colton Lewis --- .../selftests/kvm/x86_64/pmu_counters_test.c | 87 --- 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c b/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c index 79ca7d608e00..cf2941cc7c4c 100644 --- a/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c +++ b/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c @@ -29,6 +29,9 @@ /* Total number of instructions retired within the measured section. */ #define NUM_INSNS_RETIRED (NUM_LOOPS * NUM_INSNS_PER_LOOP + NUM_EXTRA_INSNS) +/* AMD counting one extra branch. Probably at loop boundary condition. */ +#define NUM_BRANCH_INSNS_RETIRED_AMD (NUM_LOOPS+1) +#define NUM_INSNS_RETIRED_AMD (NUM_INSNS_RETIRED+1) /* * Limit testing to MSRs that are actually defined by Intel (in the SDM). MSRs @@ -109,7 +112,7 @@ static uint8_t guest_get_pmu_version(void) * Sanity check that in all cases, the event doesn't count when it's disabled, * and that KVM correctly emulates the write of an arbitrary value. */ -static void guest_assert_event_count(uint8_t idx, +static void guest_assert_intel_event_count(uint8_t idx, struct kvm_x86_pmu_feature event, uint32_t pmc, uint32_t pmc_msr) { @@ -151,6 +154,33 @@ static void guest_assert_event_count(uint8_t idx, GUEST_ASSERT_EQ(_rdpmc(pmc), 0xdead); } +static void guest_assert_amd_event_count(uint8_t evt_idx, uint8_t cnt_idx, uint32_t pmc_msr) +{ + uint64_t count; + uint64_t count_pmc; + + count = rdmsr(pmc_msr); + count_pmc = _rdpmc(cnt_idx); + GUEST_ASSERT_EQ(count, count_pmc); + + switch (evt_idx) { + case AMD_ZEN_CORE_CYCLES_INDEX: + GUEST_ASSERT_NE(count, 0); + break; + case AMD_ZEN_INSTRUCTIONS_INDEX: + GUEST_ASSERT_EQ(count, NUM_INSNS_RETIRED_AMD); + break; + case AMD_ZEN_BRANCHES_INDEX: + GUEST_ASSERT_EQ(count, NUM_BRANCH_INSNS_RETIRED_AMD); + break; + case AMD_ZEN_BRANCH_MISSES_INDEX: + GUEST_ASSERT_NE(count, 0); + break; + default: + break; + } + +} /* * Enable and disable the PMC in a monolithic asm blob to ensure that the * compiler can't insert _any_ code into the measured sequence. Note, ECX @@ -183,28 +213,29 @@ do { \ ); \ } while (0) -#define GUEST_TEST_EVENT(_idx, _event, _pmc, _pmc_msr, _ctrl_msr, _value, FEP) \ +#define GUEST_TEST_EVENT(_pmc_msr, _ctrl_msr, _ctrl_value, FEP) \ do { \ wrmsr(_pmc_msr, 0); \ \ if (this_cpu_has(X86_FEATURE_CLFLUSHOPT)) \ - GUEST_MEASURE_EVENT(_ctrl_msr, _value, "clflushopt .", FEP); \ + GUEST_MEASURE_EVENT(_ctrl_msr, _ctrl_value, "clflushopt .", FEP); \ else if (this_cpu_has(X86_FEATURE_CLFLUSH)) \ - GUEST_MEASURE_EVENT(_ctrl_msr, _value, "clflush .", FEP); \ + GUEST_MEASURE_EVENT(_ctrl_msr, _ctrl_value, "clflush .", FEP); \ else \ - GUEST_MEASURE_EVENT(_ctrl_msr, _value, "nop", FEP); \ -
[PATCH v2 6/6] KVM: x86: selftests: Test PerfMonV2
Test PerfMonV2, which defines global registers to enable multiple performance counters with a single MSR write, in its own function. If the feature is available, ensure the global control register has the ability to start and stop the performance counters and the global status register correctly flags an overflow by the associated counter. Signed-off-by: Colton Lewis --- .../selftests/kvm/x86_64/pmu_counters_test.c | 53 +++ 1 file changed, 53 insertions(+) diff --git a/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c b/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c index cf2941cc7c4c..a90df8b67a19 100644 --- a/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c +++ b/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c @@ -763,10 +763,63 @@ static void guest_test_core_events(void) } } +static void guest_test_perfmon_v2(void) +{ + uint64_t i; + uint64_t eventsel = ARCH_PERFMON_EVENTSEL_OS | + ARCH_PERFMON_EVENTSEL_ENABLE | + AMD_ZEN_CORE_CYCLES; + bool core_ext = this_cpu_has(X86_FEATURE_PERF_CTR_EXT_CORE); + uint64_t sel_msr_base = core_ext ? MSR_F15H_PERF_CTL : MSR_K7_EVNTSEL0; + uint64_t cnt_msr_base = core_ext ? MSR_F15H_PERF_CTR : MSR_K7_PERFCTR0; + uint64_t msr_step = core_ext ? 2 : 1; + uint8_t nr_counters = guest_nr_core_counters(); + bool perfmon_v2 = this_cpu_has(X86_FEATURE_PERFMON_V2); + uint64_t sel_msr; + uint64_t cnt_msr; + + if (!perfmon_v2) + return; + + for (i = 0; i < nr_counters; i++) { + sel_msr = sel_msr_base + msr_step * i; + cnt_msr = cnt_msr_base + msr_step * i; + + /* Ensure count stays 0 when global register disables counter. */ + wrmsr(MSR_AMD64_PERF_CNTR_GLOBAL_CTL, 0); + wrmsr(sel_msr, eventsel); + wrmsr(cnt_msr, 0); + __asm__ __volatile__("loop ." : "+c"((int){NUM_LOOPS})); + GUEST_ASSERT(!_rdpmc(i)); + + /* Ensure counter is >0 when global register enables counter. */ + wrmsr(MSR_AMD64_PERF_CNTR_GLOBAL_CTL, BIT_ULL(i)); + __asm__ __volatile__("loop ." : "+c"((int){NUM_LOOPS})); + wrmsr(MSR_AMD64_PERF_CNTR_GLOBAL_CTL, 0); + GUEST_ASSERT(_rdpmc(i)); + + /* Ensure global status register flags a counter overflow. */ + wrmsr(cnt_msr, -1); + wrmsr(MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR, 0xff); + wrmsr(MSR_AMD64_PERF_CNTR_GLOBAL_CTL, BIT_ULL(i)); + __asm__ __volatile__("loop ." : "+c"((int){NUM_LOOPS})); + wrmsr(MSR_AMD64_PERF_CNTR_GLOBAL_CTL, 0); + GUEST_ASSERT(rdmsr(MSR_AMD64_PERF_CNTR_GLOBAL_STATUS) & +BIT_ULL(i)); + + /* Ensure global status register flag is cleared correctly. */ + wrmsr(MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR, BIT_ULL(i)); + GUEST_ASSERT(!(rdmsr(MSR_AMD64_PERF_CNTR_GLOBAL_STATUS) & +BIT_ULL(i))); + } +} + + static void guest_test_core_counters(void) { guest_test_rdwr_core_counters(); guest_test_core_events(); + guest_test_perfmon_v2(); GUEST_DONE(); } -- 2.46.0.662.g92d0881bb0-goog
[PATCH v2 4/6] KVM: x86: selftests: Test read/write core counters
Run a basic test to ensure we can write an arbitrary value to the core counters and read it back. Signed-off-by: Colton Lewis --- .../selftests/kvm/x86_64/pmu_counters_test.c | 54 +++ 1 file changed, 54 insertions(+) diff --git a/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c b/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c index 5b240585edc5..79ca7d608e00 100644 --- a/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c +++ b/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c @@ -641,11 +641,65 @@ static uint8_t nr_core_counters(void) return AMD_NR_CORE_EXT_COUNTERS; return AMD_NR_CORE_COUNTERS; +} + +static uint8_t guest_nr_core_counters(void) +{ + uint8_t nr_counters = this_cpu_property(X86_PROPERTY_NUM_PERF_CTR_CORE); + bool core_ext = this_cpu_has(X86_FEATURE_PERF_CTR_EXT_CORE); + + if (nr_counters != 0) + return nr_counters; + + if (core_ext) + return AMD_NR_CORE_EXT_COUNTERS; + + return AMD_NR_CORE_COUNTERS; + +} +static void guest_test_rdwr_core_counters(void) +{ + bool core_ext = this_cpu_has(X86_FEATURE_PERF_CTR_EXT_CORE); + uint8_t nr_counters = guest_nr_core_counters(); + uint8_t i; + uint32_t esel_msr_base = core_ext ? MSR_F15H_PERF_CTL : MSR_K7_EVNTSEL0; + uint32_t cnt_msr_base = core_ext ? MSR_F15H_PERF_CTR : MSR_K7_PERFCTR0; + uint32_t msr_step = core_ext ? 2 : 1; + + for (i = 0; i < AMD_NR_CORE_EXT_COUNTERS; i++) { + uint64_t test_val = 0x; + uint32_t esel_msr = esel_msr_base + msr_step * i; + uint32_t cnt_msr = cnt_msr_base + msr_step * i; + bool expect_gp = !(i < nr_counters); + uint8_t vector; + uint64_t val; + + /* Test event selection register. */ + vector = wrmsr_safe(esel_msr, test_val); + GUEST_ASSERT_PMC_MSR_ACCESS(WRMSR, esel_msr, expect_gp, vector); + + vector = rdmsr_safe(esel_msr, &val); + GUEST_ASSERT_PMC_MSR_ACCESS(RDMSR, esel_msr, expect_gp, vector); + + if (!expect_gp) + GUEST_ASSERT_PMC_VALUE(RDMSR, esel_msr, val, test_val); + + /* Test counter register. */ + vector = wrmsr_safe(cnt_msr, test_val); + GUEST_ASSERT_PMC_MSR_ACCESS(WRMSR, cnt_msr, expect_gp, vector); + + vector = rdmsr_safe(cnt_msr, &val); + GUEST_ASSERT_PMC_MSR_ACCESS(RDMSR, cnt_msr, expect_gp, vector); + + if (!expect_gp) + GUEST_ASSERT_PMC_VALUE(RDMSR, cnt_msr, val, test_val); + } } static void guest_test_core_counters(void) { + guest_test_rdwr_core_counters(); GUEST_DONE(); } -- 2.46.0.662.g92d0881bb0-goog
[PATCH bpf-next v2 2/2] bpf, selftests: Add test case for cgroup skb to get net_cls classid helpers
From: Feng Zhou This patch adds a test for cgroup skb to get classid. Signed-off-by: Feng Zhou --- .../bpf/prog_tests/cg_skb_get_classid.c | 87 +++ .../selftests/bpf/progs/cg_skb_get_classid.c | 19 2 files changed, 106 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/cg_skb_get_classid.c create mode 100644 tools/testing/selftests/bpf/progs/cg_skb_get_classid.c diff --git a/tools/testing/selftests/bpf/prog_tests/cg_skb_get_classid.c b/tools/testing/selftests/bpf/prog_tests/cg_skb_get_classid.c new file mode 100644 index ..13a5943c387d --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/cg_skb_get_classid.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/* + * Copyright 2024 Bytedance. + */ + +#include + +#include "cg_skb_get_classid.skel.h" + +#include "cgroup_helpers.h" +#include "network_helpers.h" + +static int run_test(int cgroup_fd, int server_fd) +{ + struct cg_skb_get_classid *skel; + int fd, err = 0; + + skel = cg_skb_get_classid__open_and_load(); + if (!ASSERT_OK_PTR(skel, "skel_open")) + return -1; + + skel->links.cg_skb_classid = + bpf_program__attach_cgroup(skel->progs.cg_skb_classid, + cgroup_fd); + if (!ASSERT_OK_PTR(skel->links.cg_skb_classid, "prog_attach")) { + err = -1; + goto out; + } + + if (!ASSERT_OK(join_classid(), "join_classid")) { + err = -1; + goto out; + } + + errno = 0; + fd = connect_to_fd_opts(server_fd, NULL); + if (fd >= 0) { + if (skel->bss->classid != getpid()) { + log_err("Get unexpected classid"); + err = -1; + } + + close(fd); + } else { + log_err("Unexpected errno from connect to server"); + err = -1; + } +out: + cg_skb_get_classid__destroy(skel); + return err; +} + +void test_cg_skb_get_classid(void) +{ + struct network_helper_opts opts = {}; + int server_fd, client_fd, cgroup_fd; + static const int port = 60120; + + /* Step 1: Check base connectivity works without any BPF. */ + server_fd = start_server(AF_INET, SOCK_STREAM, NULL, port, 0); + if (!ASSERT_GE(server_fd, 0, "server_fd")) + return; + client_fd = connect_to_fd_opts(server_fd, &opts); + if (!ASSERT_GE(client_fd, 0, "client_fd")) { + close(server_fd); + return; + } + close(client_fd); + close(server_fd); + + /* Step 2: Check BPF prog attached to cgroups. */ + cgroup_fd = test__join_cgroup("/cg_skb_get_classid"); + if (!ASSERT_GE(cgroup_fd, 0, "cgroup_fd")) + return; + server_fd = start_server(AF_INET, SOCK_STREAM, NULL, port, 0); + if (!ASSERT_GE(server_fd, 0, "server_fd")) { + close(cgroup_fd); + return; + } + setup_classid_environment(); + set_classid(); + ASSERT_OK(run_test(cgroup_fd, server_fd), "cg_skb_get_classid"); + cleanup_classid_environment(); + close(server_fd); + close(cgroup_fd); +} diff --git a/tools/testing/selftests/bpf/progs/cg_skb_get_classid.c b/tools/testing/selftests/bpf/progs/cg_skb_get_classid.c new file mode 100644 index ..aef0265d24eb --- /dev/null +++ b/tools/testing/selftests/bpf/progs/cg_skb_get_classid.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/* + * Copyright 2024 Bytedance. + */ + +#include +#include +#include + +__u32 classid = 0; + +SEC("cgroup_skb/egress") +int cg_skb_classid(struct __sk_buff *ctx) +{ + classid = bpf_skb_cgroup_classid(ctx); + + return 1; +} -- 2.30.2
Re: [RESEND PATCH v2] list: test: Mending tests for list_cut_position()
On Tue, 10 Sept 2024 at 12:35, I Hsin Cheng wrote: > > Mending test for list_cut_position*() for the missing check of integer > "i" after the second loop. The variable should be checked for second > time to make sure both lists after the cut operation are formed as > expected. > > Signed-off-by: I Hsin Cheng > --- Alas, this breaks the list test, as we're comparing the entries we get from list_for_each() with entries[i], so changing the value of 'i' will compare against the wrong elements. You could either update the KUNIT_EXPECT_EQ at the bottom to verify the _total_ number of elements (which should be fine, as we already verify the value of i after the first loop), or compare each entry against, e.g., &entries[2 + i]. This is causing a test failure on -next: https://lore.kernel.org/all/202409161554.6c3e8d5d-oliver.s...@intel.com/ Could we remove this from mm-nonmm pending a fix? Cheers, -- David > lib/list-test.c | 6 ++ > 1 file changed, 6 insertions(+) > > diff --git a/lib/list-test.c b/lib/list-test.c > index 37cbc33e9fdb..8d1d47a9fe9e 100644 > --- a/lib/list-test.c > +++ b/lib/list-test.c > @@ -404,10 +404,13 @@ static void list_test_list_cut_position(struct kunit > *test) > > KUNIT_EXPECT_EQ(test, i, 2); > > + i = 0; > list_for_each(cur, &list1) { > KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); Either change this to &entries[2 + i], or... > i++; > } > + > + KUNIT_EXPECT_EQ(test, i, 1); This to expect i == 3 > } > > static void list_test_list_cut_before(struct kunit *test) > @@ -432,10 +435,13 @@ static void list_test_list_cut_before(struct kunit > *test) > > KUNIT_EXPECT_EQ(test, i, 1); > > + i = 0; > list_for_each(cur, &list1) { > KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); Either change this to &entries[1 + i], or... > i++; > } > + > + KUNIT_EXPECT_EQ(test, i, 2); This to expect i == 3. > } > > static void list_test_list_splice(struct kunit *test) > -- > 2.43.0 > smime.p7s Description: S/MIME Cryptographic Signature
Re: [PATCH] selftests: riscv: Allow mmap test to compile on 32-bit
Hello: This patch was applied to riscv/linux.git (for-next) by Palmer Dabbelt : On Thu, 08 Aug 2024 11:41:40 -0700 you wrote: > Macros needed for 32-bit compilations were hidden behind 64-bit riscv > ifdefs. Fix the 32-bit compilations by moving macros to allow the > memory_layout test to run on 32-bit. > > Signed-off-by: Charlie Jenkins > Fixes: 73d05262a2ca ("selftests: riscv: Generalize mm selftests") > > [...] Here is the summary with links: - selftests: riscv: Allow mmap test to compile on 32-bit https://git.kernel.org/riscv/c/11c2dbd7f241 You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html
Re: [RFC PATCH 3/3] bpf: Add sk_lookup test to use ORIGDSTADDR cmsg.
On Fri, Sep 13, 2024 at 08:10:24PM +0800, Philo Lu wrote: > Hi Tiago, > > On 2024/9/13 17:39, Tiago Lam wrote: > > This patch reuses the framework already in place for sk_lookup, allowing > > it now to send a reply from the server fd directly, instead of having to > > create a socket bound to the original destination address and reply from > > there. It does this by passing the source address and port from where to > > reply from in a IP_ORIGDSTADDR ancilliary message passed in sendmsg. > > > > Signed-off-by: Tiago Lam > > --- > > tools/testing/selftests/bpf/prog_tests/sk_lookup.c | 70 > > +++--- > > 1 file changed, 48 insertions(+), 22 deletions(-) > > > > diff --git a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c > > b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c > > index ae87c00867ba..b99aff2e3976 100644 > > --- a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c > > +++ b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c > > @@ -75,6 +75,7 @@ struct test { > > struct inet_addr listen_at; > > enum server accept_on; > > bool reuseport_has_conns; /* Add a connected socket to reuseport group > > */ > > + bool dont_bind_reply; /* Don't bind, send direct from server fd. */ > > }; > > struct cb_opts { > > @@ -363,7 +364,7 @@ static void v4_to_v6(struct sockaddr_storage *ss) > > memset(&v6->sin6_addr.s6_addr[0], 0, 10); > > } > > -static int udp_recv_send(int server_fd) > > +static int udp_recv_send(int server_fd, bool dont_bind_reply) > > { > > char cmsg_buf[CMSG_SPACE(sizeof(struct sockaddr_storage))]; > > struct sockaddr_storage _src_addr = { 0 }; > > @@ -415,26 +416,41 @@ static int udp_recv_send(int server_fd) > > v4_to_v6(dst_addr); > > } > > - /* Reply from original destination address. */ > > - fd = start_server_addr(SOCK_DGRAM, dst_addr, sizeof(*dst_addr), NULL); > > - if (!ASSERT_OK_FD(fd, "start_server_addr")) { > > - log_err("failed to create tx socket"); > > - return -1; > > - } > > + if (dont_bind_reply) { > > + /* Reply directly from server fd, specifying the source address > > and/or > > +* port in struct msghdr. > > +*/ > > + n = sendmsg(server_fd, &msg, 0); > > + if (CHECK(n <= 0, "sendmsg", "failed\n")) { > > + log_err("failed to send echo reply"); > > + return -1; > > + } > > + } else { > > + /* Reply from original destination address. */ > > + fd = socket(dst_addr->ss_family, SOCK_DGRAM, 0); > > + if (CHECK(fd < 0, "socket", "failed\n")) { > > + log_err("failed to create tx socket"); > > + return -1; > > + } > Just curious, why not use start_server_addr() here like before? > Thanks, you're right. Initially I rebased this on commit e3d332aaf898ed755b29c8cdf59be2cfba1cac4b (v6.6.31), which didn't have start_server_addr(), and used bind() instead. I must have messed up the rebased. I've fixed this and included your other suggestion in the patch below and will fold it into the next revision. diff --git a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c index b99aff2e3976..0628a67681c5 100644 --- a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c +++ b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c @@ -374,7 +374,7 @@ static int udp_recv_send(int server_fd, bool dont_bind_reply) struct iovec iov = { 0 }; struct cmsghdr *cm; char buf[1]; - int ret, fd; + int fd; ssize_t n; iov.iov_base = buf; @@ -427,19 +427,12 @@ static int udp_recv_send(int server_fd, bool dont_bind_reply) } } else { /* Reply from original destination address. */ - fd = socket(dst_addr->ss_family, SOCK_DGRAM, 0); - if (CHECK(fd < 0, "socket", "failed\n")) { + fd = start_server_addr(SOCK_DGRAM, dst_addr, sizeof(*dst_addr), NULL); + if (!ASSERT_OK_FD(fd, "start_server_addr")) { log_err("failed to create tx socket"); return -1; } - ret = bind(fd, (struct sockaddr *)dst_addr, sizeof(*dst_addr)); - if (CHECK(ret, "bind", "failed\n")) { - log_err("failed to bind tx socket"); - close(fd); - return ret; - } - msg.msg_control = NULL; msg.msg_controllen = 0; n = sendmsg(fd, &msg, 0); @@ -451,6 +444,8 @@ static int udp_recv_send(int server_fd, bool dont_bind_reply) close(fd); } + + return 0; } static int tcp_echo_test(int client_fd, int server_fd)
[RFC PATCH 4/4] WIP: hazptr: Add hazptr test sample
Sample code for hazptr. This should go away or get more polished when hazptr support is added into rcutorture. Signed-off-by: Boqun Feng --- samples/Kconfig | 6 +++ samples/Makefile | 1 + samples/hazptr/hazptr_test.c | 87 3 files changed, 94 insertions(+) create mode 100644 samples/hazptr/hazptr_test.c diff --git a/samples/Kconfig b/samples/Kconfig index b288d9991d27..9b42cde35dca 100644 --- a/samples/Kconfig +++ b/samples/Kconfig @@ -293,6 +293,12 @@ config SAMPLE_CGROUP source "samples/rust/Kconfig" +config SAMPLE_HAZPTR + bool "Build hazptr sample code" + help + Build samples that shows hazard pointer usage. Currently only + builtin usage is supported. + endif # SAMPLES config HAVE_SAMPLE_FTRACE_DIRECT diff --git a/samples/Makefile b/samples/Makefile index b85fa64390c5..0be21edc8a30 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -39,3 +39,4 @@ obj-$(CONFIG_SAMPLE_KMEMLEAK) += kmemleak/ obj-$(CONFIG_SAMPLE_CORESIGHT_SYSCFG) += coresight/ obj-$(CONFIG_SAMPLE_FPROBE)+= fprobe/ obj-$(CONFIG_SAMPLES_RUST) += rust/ +obj-$(CONFIG_SAMPLE_HAZPTR)+= hazptr/ diff --git a/samples/hazptr/hazptr_test.c b/samples/hazptr/hazptr_test.c new file mode 100644 index ..3cf0cdc8a83a --- /dev/null +++ b/samples/hazptr/hazptr_test.c @@ -0,0 +1,87 @@ +#include +#include +#include + +struct foo { + int i; + struct callback_head head; +}; + +static void simple_func(struct callback_head *head) +{ + struct foo *ptr = container_of(head, struct foo, head); + + printk("callback called %px, i is %d\n", ptr, ptr->i); + kfree(ptr); +} + +static void simple(void) +{ + struct hazptr_context ctx; + struct foo *dummy, *tmp, *other; + hazptr_t *hptr; + hazptr_t *hptr2; + + dummy = kzalloc(sizeof(*dummy), GFP_KERNEL); + dummy->i = 42; + + other = kzalloc(sizeof(*dummy), GFP_KERNEL); + other->i = 43; + + if (!dummy || !other) { + printk("allocation failed, skip test\n"); + return; + } + + init_hazptr_context(&ctx); + hptr = hazptr_alloc(&ctx); + BUG_ON(!hptr); + + // Get a second hptr. + hptr2 = hazptr_alloc(&ctx); + BUG_ON(!hptr2); + + // No one is modifying 'dummy', protection must succeed. + BUG_ON(!hazptr_tryprotect(hptr, dummy, head)); + + // Simulate changing a global pointer. + tmp = dummy; + WRITE_ONCE(dummy, other); + + // Callback will run after no active readers. + printk("callback added, %px\n", tmp); + + call_hazptr(&tmp->head, simple_func); + + // No one is modifying 'dummy', protection must succeed. + tmp = hazptr_protect(hptr2, dummy, head); + + printk("reader2 got %px, i is %d\n", tmp, tmp->i); + + // The above callback should run after this. + hazptr_clear(hptr); + printk("first reader is out\n"); + + for (int i = 0; i < 10; i++) + schedule(); // yield a few times. + + // Simulate freeing a global pointer. + tmp = dummy; + WRITE_ONCE(dummy, NULL); + printk("callback added, %px\n", tmp); + call_hazptr(&tmp->head, simple_func); + + cleanup_hazptr_context(&ctx); + printk("no reader here\n"); + + for (int i = 0; i < 10; i++) + schedule(); // yield a few times. +} + +static int hazptr_test(void) +{ + simple(); + printk("test ends\n"); + return 0; +} +module_init(hazptr_test); -- 2.45.2
[PATCH net-next] selftests: net: add pmtu_bad.sh regression test
From: Mitchell Augustin Introduce a regression test that reproduces a bug in pmtu_ipv6_ipv6_exception which causes veth_A-R1's reference counter to remain > 0 after cleanup should have already completed. On affected kernels/platforms, running this test will result in the following being displayed repeatedly in dmesg: unregister_netdevice: waiting for veth_A-R1 to become free. Usage count = 5 and future attempts to modprobe/rmmod ip6_vti will hang forever. Link: https://lore.kernel.org/all/CAHTA-uZDaJ-71o+bo8a96TV4ck-8niimztQFaa=qoendum-...@mail.gmail.com/ Requested-by: Jakub Kicinski Signed-off-by: Mitchell Augustin --- tools/testing/selftests/net/pmtu_bad.sh | 901 1 file changed, 901 insertions(+) create mode 100755 tools/testing/selftests/net/pmtu_bad.sh diff --git a/tools/testing/selftests/net/pmtu_bad.sh b/tools/testing/selftests/net/pmtu_bad.sh new file mode 100755 index ..4bbc9815b661 --- /dev/null +++ b/tools/testing/selftests/net/pmtu_bad.sh @@ -0,0 +1,901 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Pinned version of pmtu.sh pmtu_ipv6_ipv6_exception and all dependencies +# configured to reproduce a kernel bug where the veth_A-R1 device's +# resource counter remains > 0 after cleanup should have already been +# completed. +# +# On affected kernels/platforms, running this test will result in the following +# being displayed repeatedly in dmesg: +# unregister_netdevice: waiting for veth_A-R1 to become free. Usage count = 5 +# +# and future attempts to modprobe/rmmod ip6_vti will hang forever. +# +# Link: https://lore.kernel.org/all/CAHTA-uZDaJ-71o+bo8a96TV4ck-8niimztQFaa=qoendum-...@mail.gmail.com/ +# +# BugLink: https://bugs.launchpad.net/ubuntu-kernel-tests/+bug/2072501 +# +# pmtu.sh: +# Check that route PMTU values match expectations, and that initial device MTU +# values are assigned correctly +# +# Tests currently implemented: +# +# - pmtu_bad +# Sets the CPU governor to "performance" for all CPUs, then +# runs a pinned, affected version of the pmtu_ipv6_ipv6_exception test with +# nexthop objects 100 times. If this causes the following to be output +# to dmesg, the test is considered to have failed and returns an error: +# +# unregister_netdevice: waiting for veth_A-R1 to become free +# +# Otherwise, the test passes. After execution of the test, the CPU governor +# is restored to its original settings. +# - pmtu_ipv6_ipv6_exception +# Same as pmtu_ipv4_vxlan4, but using a IPv4/IPv6 tunnel over IPv4/IPv6, +# instead of VXLAN + +# Pinned version of lib.sh +## +# Defines + +WAIT_TIMEOUT=${WAIT_TIMEOUT:=20} +BUSYWAIT_TIMEOUT=$((WAIT_TIMEOUT * 1000)) # ms + +# Kselftest framework requirement - SKIP code is 4. +ksft_skip=4 +# namespace list created by setup_ns +NS_LIST=() + +## +# Helpers + +__ksft_status_merge() +{ + local a=$1; shift + local b=$1; shift + local -A weights + local weight=0 + + local i + for i in "$@"; do + weights[$i]=$((weight++)) + done + + if [[ ${weights[$a]} > ${weights[$b]} ]]; then + echo "$a" + return 0 + else + echo "$b" + return 1 + fi +} + +ksft_status_merge() +{ + local a=$1; shift + local b=$1; shift + + __ksft_status_merge "$a" "$b" \ + $ksft_pass $ksft_xfail $ksft_skip $ksft_fail +} + +ksft_exit_status_merge() +{ + local a=$1; shift + local b=$1; shift + + __ksft_status_merge "$a" "$b" \ + $ksft_xfail $ksft_pass $ksft_skip $ksft_fail +} + +loopy_wait() +{ + local sleep_cmd=$1; shift + local timeout_ms=$1; shift + + local start_time="$(date -u +%s%3N)" + while true + do + local out + if out=$("$@"); then + echo -n "$out" + return 0 + fi + + local current_time="$(date -u +%s%3N)" + if ((current_time - start_time > timeout_ms)); then + echo -n "$out" + return 1 + fi + + $sleep_cmd + done +} + +busywait() +{ + local timeout_ms=$1; shift + + loopy_wait : "$timeout_ms" "$@" +} + +# timeout in seconds +slowwait() +{ + local timeout_sec=$1; shift + + loopy_wait "sleep 0.1" "$((timeout_sec * 1000))" "$@" +} + +until_counter_is() +{ + local expr=$1; shift + local current=$("$@") + + echo $((current)) + ((current $expr)) +} + +busywait_for_counter()
Re: [PATCH 2/2] kselftests: mm: Fail the test if userfaultfd syscall isn't found
On 9/12/24 10:28 PM, Shuah Khan wrote: > On 9/12/24 10:10, Shuah Khan wrote: >> On 9/12/24 04:31, Muhammad Usama Anjum wrote: >>> The userfaultfd is enabled in the config fragment of mm selftest suite. >>> It must always be present. If it isn't present, we should throw error >>> and not just skip. This would have helped us catch the test breakage. >> >> Please elaborate on this to help understand the what breakage was >> missed. >> >> Also this commit log doesn't look right to me. syscall() could >> fail for any reason. Do you mean to see skip is incorrect in this >> error leg? Please see comments below. >> >>> Adding this now to catch the future breakages. >>> >>> Signed-off-by: Muhammad Usama Anjum >>> --- >>> tools/testing/selftests/mm/pagemap_ioctl.c | 2 +- >>> 1 file changed, 1 insertion(+), 1 deletion(-) >>> >>> diff --git a/tools/testing/selftests/mm/pagemap_ioctl.c >>> b/tools/testing/selftests/mm/pagemap_ioctl.c >>> index bcc73b4e805c6..d83dda8edf62c 100644 >>> --- a/tools/testing/selftests/mm/pagemap_ioctl.c >>> +++ b/tools/testing/selftests/mm/pagemap_ioctl.c >>> @@ -95,7 +95,7 @@ int init_uffd(void) >>> uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK | >>> UFFD_USER_MODE_ONLY); >>> if (uffd == -1) >>> - return uffd; >>> + ksft_exit_fail_perror("Userfaultfd syscall failed"); >> >> This looks wrong to me - Is missing config the only reason this syscall >> would fail? > > It should still skip if __NR_userfaultfd isn't supported on a release > or an architecture. > > The real problem seems to be in main(): > > if (init_uffd()) > ksft_exit_pass(); > > > Why is this ksft_exit_pass()? Looks like further investigation is > necessary to understand the problem and fix. Let's skip this patch as it'll create more noise on unsupported architectures than catching failures on supported architectures. > > thanks, > -- Shuah -- BR, Muhammad Usama Anjum
[RFC 4/6] percpu-refcount-torture: Extend test with runtime mode switches
Extend the test to exercise runtime switching from managed mode to other reinitable active modes. Signed-off-by: Neeraj Upadhyay --- lib/percpu-refcount-torture.c | 41 +-- lib/percpu-refcount.c | 12 +- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/lib/percpu-refcount-torture.c b/lib/percpu-refcount-torture.c index 686f5a228b40..cb2700b16517 100644 --- a/lib/percpu-refcount-torture.c +++ b/lib/percpu-refcount-torture.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -59,6 +60,7 @@ static struct task_struct **busted_late_release_tasks; static struct percpu_ref *refs; static long *num_per_ref_users; +static struct mutex *ref_switch_mutexes; static atomic_t running; static atomic_t *ref_running; @@ -97,19 +99,36 @@ static int percpu_ref_manager_thread(void *data) static int percpu_ref_test_thread(void *data) { struct percpu_ref *ref = (struct percpu_ref *)data; + DEFINE_TORTURE_RANDOM(rand); + int ref_idx = ref - refs; + int do_switch; int i = 0; percpu_ref_get(ref); do { percpu_ref_get(ref); + /* Perform checks once per 256 iterations */ + do_switch = (torture_random(&rand) & 0xff); udelay(delay_us); + if (do_switch) { + mutex_lock(&ref_switch_mutexes[ref_idx]); + percpu_ref_switch_to_unmanaged(ref); + udelay(delay_us); + percpu_ref_switch_to_atomic_sync(ref); + if (do_switch & 1) + percpu_ref_switch_to_percpu(ref); + udelay(delay_us); + percpu_ref_switch_to_managed(ref); + mutex_unlock(&ref_switch_mutexes[ref_idx]); + udelay(delay_us); + } percpu_ref_put(ref); stutter_wait("percpu_ref_test_thread"); i++; } while (i < niterations); - atomic_dec(&ref_running[ref - refs]); + atomic_dec(&ref_running[ref_idx]); /* Order ref release with ref_running[ref_idx] == 0 */ smp_mb(); percpu_ref_put(ref); @@ -213,6 +232,13 @@ static void percpu_ref_test_cleanup(void) kfree(num_per_ref_users); num_per_ref_users = NULL; + if (ref_switch_mutexes) { + for (i = 0; i < nrefs; i++) + mutex_destroy(&ref_switch_mutexes[i]); + kfree(ref_switch_mutexes); + ref_switch_mutexes = NULL; + } + if (refs) { for (i = 0; i < nrefs; i++) percpu_ref_exit(&refs[i]); @@ -251,7 +277,8 @@ static int __init percpu_ref_torture_init(void) goto init_err; } for (i = 0; i < nrefs; i++) { - flags = torture_random(trsp) & 1 ? PERCPU_REF_INIT_ATOMIC : PERCPU_REF_REL_MANAGED; + flags = (torture_random(trsp) & 1) ? PERCPU_REF_INIT_ATOMIC : + PERCPU_REF_REL_MANAGED; err = percpu_ref_init(&refs[i], percpu_ref_test_release, flags, GFP_KERNEL); if (err) @@ -269,6 +296,16 @@ static int __init percpu_ref_torture_init(void) for (i = 0; i < nrefs; i++) num_per_ref_users[i] = 0; + ref_switch_mutexes = kcalloc(nrefs, sizeof(ref_switch_mutexes[0]), GFP_KERNEL); + if (!ref_switch_mutexes) { + TOROUT_ERRSTRING("out of memory"); + err = -ENOMEM; + goto init_err; + } + + for (i = 0; i < nrefs; i++) + mutex_init(&ref_switch_mutexes[i]); + ref_user_tasks = kcalloc(nusers, sizeof(ref_user_tasks[0]), GFP_KERNEL); if (!ref_user_tasks) { TOROUT_ERRSTRING("out of memory"); diff --git a/lib/percpu-refcount.c b/lib/percpu-refcount.c index b79e36905aa4..4e0a453bd51f 100644 --- a/lib/percpu-refcount.c +++ b/lib/percpu-refcount.c @@ -723,6 +723,7 @@ EXPORT_SYMBOL_GPL(percpu_ref_test_is_percpu); void percpu_ref_test_flush_release_work(void) { int max_flush = READ_ONCE(max_scan_count); + struct list_head *next; int max_count = 1000; /* Complete any executing release work */ @@ -738,8 +739,17 @@ void percpu_ref_test_flush_release_work(void) /* max scan count update visible to work */ smp_mb(); flush_delayed_work(&percpu_ref_release_work); - while (READ_ONCE(last_percpu_ref_node) != NULL && max_count--) + + while (true) { + if (!max_count--) + break; + spin_lock(&percpu_ref_manage_lock); + next
[RFC 2/6] percpu-refcount: Add torture test for percpu refcount
Add torture test to verify percpu managed mode operations, verifying that a percpu ref does not have non-zero count when all users have dropped their reference and that there is no early release of the ref while users hold references to it. Signed-off-by: Neeraj Upadhyay --- .../admin-guide/kernel-parameters.txt | 57 +++ lib/Kconfig.debug | 9 + lib/Makefile | 1 + lib/percpu-refcount-torture.c | 367 ++ lib/percpu-refcount.c | 49 ++- lib/percpu-refcount.h | 6 + 6 files changed, 483 insertions(+), 6 deletions(-) create mode 100644 lib/percpu-refcount-torture.c create mode 100644 lib/percpu-refcount.h diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 0f02a1b04fe9..225f2dac294d 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -4677,6 +4677,63 @@ Default: 5000 ms + percpu_refcount_torture.busted_early_ref_release= [KNL] + Enable testing buggy release of percpu ref while + there are active users. Used for testing failure + scenarios in the test. + + Default: 0 (disabled) + + percpu_refcount_torture.busted_late_ref_release= [KNL] + Enable testing buggy non-zero reference count after + all ref users have dropped their reference. Used for + testing failure scenarios in the test. + + Default: 0 (disabled) + + percpu_refcount_torture.delay_us= [KNL] + Delay (in us) between reference increment and decrement + operations of ref users. + + Default: 10 + + percpu_refcount_torture.niterations= [KNL] + Number of iterations of ref increment and decrement by + ref users. + + Default: 100 + + percpu_refcount_torture.nrefs= [KNL] + Number of percpu ref instances. + + Default: 2 + + percpu_refcount_torture.nusers= [KNL] + Number of percpu ref user threads which increment and + decrement a percpu ref. + + Default: 2 + + percpu_refcount_torture.onoff_holdoff= [KNL] + Set time (s) after boot for CPU-hotplug testing. + + Default: 0 + + percpu_refcount_torture.onoff_interval= [KNL] + Set time (jiffies) between CPU-hotplug operations, + or zero to disable CPU-hotplug testing. + + percpu_refcount_torture.stutter= [KNL] + Set wait time (jiffies) between two iterations of + percpu ref operations. + + Default: 0 + + percpu_refcount_torture.verbose= [KNL] + Enable additional printk() statements. + + Default: 0 (Disabled) + pirq= [SMP,APIC] Manual mp-table setup See Documentation/arch/x86/i386/IO-APIC.rst. diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index a30c03a66172..7e0117e01f05 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1611,6 +1611,15 @@ config SCF_TORTURE_TEST module may be built after the fact on the running kernel to be tested, if desired. +config PERCPU_REFCOUNT_TORTURE_TEST + tristate "torture tests for percpu refcount" + select TORTURE_TEST + help + This options provides a kernel module that runs percpu + refcount torture tests for managed percpu refs. The kernel + module may be built after the fact on the running kernel + to be tested, if desired. + config CSD_LOCK_WAIT_DEBUG bool "Debugging for csd_lock_wait(), called from smp_call_function*()" depends on DEBUG_KERNEL diff --git a/lib/Makefile b/lib/Makefile index 322bb127b4dc..d0286f7dfb37 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -50,6 +50,7 @@ obj-y += bcd.o sort.o parser.o debug_locks.o random32.o \ once.o refcount.o rcuref.o usercopy.o errseq.o bucket_locks.o \ generic-radix-tree.o bitmap-str.o obj-$(CONFIG_STRING_KUNIT_TEST) += string_kunit.o +obj-$(CONFIG_PERCPU_REFCOUNT_TORTURE_TEST) += percpu-refcount-torture.o obj-y += string_helpers.o obj-$(CONFIG_STRING_HELPERS_KUNIT_TEST) += string_helpers_kunit.o obj-y += hexdump.o diff --git a/lib/percpu-refcount-torture.c b/lib/percpu-refcount-torture.c new file mode 100644 index ..686f5a228b40 --- /dev/null +++ b/lib/percpu-refcount-torture.c @@ -0,0 +1,367 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include
[PATCH bpf-next v3 2/2] selftests/bpf: Setget_sockopt add a test for tcp over ipv4 via ipv6
From: Feng Zhou This patch adds a test for TCP over IPv4 via INET6 API. Signed-off-by: Feng Zhou --- .../selftests/bpf/prog_tests/setget_sockopt.c | 33 +++ .../selftests/bpf/progs/setget_sockopt.c | 13 ++-- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/setget_sockopt.c b/tools/testing/selftests/bpf/prog_tests/setget_sockopt.c index 7d4a9b3d3722..3cad92128e60 100644 --- a/tools/testing/selftests/bpf/prog_tests/setget_sockopt.c +++ b/tools/testing/selftests/bpf/prog_tests/setget_sockopt.c @@ -15,8 +15,11 @@ #define CG_NAME "/setget-sockopt-test" +#define INT_PORT 8008 + static const char addr4_str[] = "127.0.0.1"; static const char addr6_str[] = "::1"; +static const char addr6_any_str[] = "::"; static struct setget_sockopt *skel; static int cg_fd; @@ -67,6 +70,35 @@ static void test_tcp(int family) ASSERT_EQ(bss->nr_binddev, 2, "nr_bind"); } +static void test_tcp_over_ipv4_via_ipv6(void) +{ + struct setget_sockopt__bss *bss = skel->bss; + int sfd, cfd; + + memset(bss, 0, sizeof(*bss)); + skel->bss->test_tcp_over_ipv4_via_ipv6 = 1; + + sfd = start_server(AF_INET6, SOCK_STREAM, + addr6_any_str, INT_PORT, 0); + if (!ASSERT_GE(sfd, 0, "start_server")) + return; + + cfd = connect_to_addr_str(AF_INET, SOCK_STREAM, addr4_str, INT_PORT, NULL); + if (!ASSERT_GE(cfd, 0, "connect_to_addr_str")) { + close(sfd); + return; + } + close(sfd); + close(cfd); + + ASSERT_EQ(bss->nr_listen, 1, "nr_listen"); + ASSERT_EQ(bss->nr_connect, 1, "nr_connect"); + ASSERT_EQ(bss->nr_active, 1, "nr_active"); + ASSERT_EQ(bss->nr_passive, 1, "nr_passive"); + ASSERT_EQ(bss->nr_socket_post_create, 2, "nr_socket_post_create"); + ASSERT_EQ(bss->nr_binddev, 2, "nr_bind"); +} + static void test_udp(int family) { struct setget_sockopt__bss *bss = skel->bss; @@ -191,6 +223,7 @@ void test_setget_sockopt(void) test_udp(AF_INET); test_ktls(AF_INET6); test_ktls(AF_INET); + test_tcp_over_ipv4_via_ipv6(); done: setget_sockopt__destroy(skel); diff --git a/tools/testing/selftests/bpf/progs/setget_sockopt.c b/tools/testing/selftests/bpf/progs/setget_sockopt.c index 60518aed1ffc..ff834d94dd23 100644 --- a/tools/testing/selftests/bpf/progs/setget_sockopt.c +++ b/tools/testing/selftests/bpf/progs/setget_sockopt.c @@ -20,6 +20,7 @@ int nr_connect; int nr_binddev; int nr_socket_post_create; int nr_fin_wait1; +int test_tcp_over_ipv4_via_ipv6; struct sockopt_test { int opt; @@ -262,9 +263,15 @@ static int bpf_test_sockopt(void *ctx, struct sock *sk) if (n != ARRAY_SIZE(sol_ip_tests)) return -1; } else { - n = bpf_loop(ARRAY_SIZE(sol_ipv6_tests), bpf_test_ipv6_sockopt, &lc, 0); - if (n != ARRAY_SIZE(sol_ipv6_tests)) - return -1; + if (test_tcp_over_ipv4_via_ipv6) { + n = bpf_loop(ARRAY_SIZE(sol_ip_tests), bpf_test_ip_sockopt, &lc, 0); + if (n != ARRAY_SIZE(sol_ip_tests)) + return -1; + } else { + n = bpf_loop(ARRAY_SIZE(sol_ipv6_tests), bpf_test_ipv6_sockopt, &lc, 0); + if (n != ARRAY_SIZE(sol_ipv6_tests)) + return -1; + } } return 0; -- 2.30.2
Re: [RFC PATCH 3/3] bpf: Add sk_lookup test to use ORIGDSTADDR cmsg.
Hi Tiago, On 2024/9/13 17:39, Tiago Lam wrote: This patch reuses the framework already in place for sk_lookup, allowing it now to send a reply from the server fd directly, instead of having to create a socket bound to the original destination address and reply from there. It does this by passing the source address and port from where to reply from in a IP_ORIGDSTADDR ancilliary message passed in sendmsg. Signed-off-by: Tiago Lam --- tools/testing/selftests/bpf/prog_tests/sk_lookup.c | 70 +++--- 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c index ae87c00867ba..b99aff2e3976 100644 --- a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c +++ b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c @@ -75,6 +75,7 @@ struct test { struct inet_addr listen_at; enum server accept_on; bool reuseport_has_conns; /* Add a connected socket to reuseport group */ + bool dont_bind_reply; /* Don't bind, send direct from server fd. */ }; struct cb_opts { @@ -363,7 +364,7 @@ static void v4_to_v6(struct sockaddr_storage *ss) memset(&v6->sin6_addr.s6_addr[0], 0, 10); } -static int udp_recv_send(int server_fd) +static int udp_recv_send(int server_fd, bool dont_bind_reply) { char cmsg_buf[CMSG_SPACE(sizeof(struct sockaddr_storage))]; struct sockaddr_storage _src_addr = { 0 }; @@ -415,26 +416,41 @@ static int udp_recv_send(int server_fd) v4_to_v6(dst_addr); } - /* Reply from original destination address. */ - fd = start_server_addr(SOCK_DGRAM, dst_addr, sizeof(*dst_addr), NULL); - if (!ASSERT_OK_FD(fd, "start_server_addr")) { - log_err("failed to create tx socket"); - return -1; - } + if (dont_bind_reply) { + /* Reply directly from server fd, specifying the source address and/or +* port in struct msghdr. +*/ + n = sendmsg(server_fd, &msg, 0); + if (CHECK(n <= 0, "sendmsg", "failed\n")) { + log_err("failed to send echo reply"); + return -1; + } + } else { + /* Reply from original destination address. */ + fd = socket(dst_addr->ss_family, SOCK_DGRAM, 0); + if (CHECK(fd < 0, "socket", "failed\n")) { + log_err("failed to create tx socket"); + return -1; + } Just curious, why not use start_server_addr() here like before? - msg.msg_control = NULL; - msg.msg_controllen = 0; - n = sendmsg(fd, &msg, 0); - if (CHECK(n <= 0, "sendmsg", "failed\n")) { - log_err("failed to send echo reply"); - ret = -1; - goto out; - } + ret = bind(fd, (struct sockaddr *)dst_addr, sizeof(*dst_addr)); + if (CHECK(ret, "bind", "failed\n")) { + log_err("failed to bind tx socket"); + close(fd); + return ret; + } - ret = 0; -out: - close(fd); - return ret; + msg.msg_control = NULL; + msg.msg_controllen = 0; + n = sendmsg(fd, &msg, 0); + if (CHECK(n <= 0, "sendmsg", "failed\n")) { + log_err("failed to send echo reply"); + close(fd); + return -1; + } + + close(fd); + } nit: "return 0" missed. } -- Philo
[RFC PATCH 3/3] bpf: Add sk_lookup test to use ORIGDSTADDR cmsg.
This patch reuses the framework already in place for sk_lookup, allowing it now to send a reply from the server fd directly, instead of having to create a socket bound to the original destination address and reply from there. It does this by passing the source address and port from where to reply from in a IP_ORIGDSTADDR ancilliary message passed in sendmsg. Signed-off-by: Tiago Lam --- tools/testing/selftests/bpf/prog_tests/sk_lookup.c | 70 +++--- 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c index ae87c00867ba..b99aff2e3976 100644 --- a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c +++ b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c @@ -75,6 +75,7 @@ struct test { struct inet_addr listen_at; enum server accept_on; bool reuseport_has_conns; /* Add a connected socket to reuseport group */ + bool dont_bind_reply; /* Don't bind, send direct from server fd. */ }; struct cb_opts { @@ -363,7 +364,7 @@ static void v4_to_v6(struct sockaddr_storage *ss) memset(&v6->sin6_addr.s6_addr[0], 0, 10); } -static int udp_recv_send(int server_fd) +static int udp_recv_send(int server_fd, bool dont_bind_reply) { char cmsg_buf[CMSG_SPACE(sizeof(struct sockaddr_storage))]; struct sockaddr_storage _src_addr = { 0 }; @@ -415,26 +416,41 @@ static int udp_recv_send(int server_fd) v4_to_v6(dst_addr); } - /* Reply from original destination address. */ - fd = start_server_addr(SOCK_DGRAM, dst_addr, sizeof(*dst_addr), NULL); - if (!ASSERT_OK_FD(fd, "start_server_addr")) { - log_err("failed to create tx socket"); - return -1; - } + if (dont_bind_reply) { + /* Reply directly from server fd, specifying the source address and/or +* port in struct msghdr. +*/ + n = sendmsg(server_fd, &msg, 0); + if (CHECK(n <= 0, "sendmsg", "failed\n")) { + log_err("failed to send echo reply"); + return -1; + } + } else { + /* Reply from original destination address. */ + fd = socket(dst_addr->ss_family, SOCK_DGRAM, 0); + if (CHECK(fd < 0, "socket", "failed\n")) { + log_err("failed to create tx socket"); + return -1; + } - msg.msg_control = NULL; - msg.msg_controllen = 0; - n = sendmsg(fd, &msg, 0); - if (CHECK(n <= 0, "sendmsg", "failed\n")) { - log_err("failed to send echo reply"); - ret = -1; - goto out; - } + ret = bind(fd, (struct sockaddr *)dst_addr, sizeof(*dst_addr)); + if (CHECK(ret, "bind", "failed\n")) { + log_err("failed to bind tx socket"); + close(fd); + return ret; + } - ret = 0; -out: - close(fd); - return ret; + msg.msg_control = NULL; + msg.msg_controllen = 0; + n = sendmsg(fd, &msg, 0); + if (CHECK(n <= 0, "sendmsg", "failed\n")) { + log_err("failed to send echo reply"); + close(fd); + return -1; + } + + close(fd); + } } static int tcp_echo_test(int client_fd, int server_fd) @@ -454,14 +470,14 @@ static int tcp_echo_test(int client_fd, int server_fd) return 0; } -static int udp_echo_test(int client_fd, int server_fd) +static int udp_echo_test(int client_fd, int server_fd, bool dont_bind_reply) { int err; err = send_byte(client_fd); if (err) return -1; - err = udp_recv_send(server_fd); + err = udp_recv_send(server_fd, dont_bind_reply); if (err) return -1; err = recv_byte(client_fd); @@ -653,7 +669,7 @@ static void run_lookup_prog(const struct test *t) if (t->sotype == SOCK_STREAM) tcp_echo_test(client_fd, server_fds[t->accept_on]); else - udp_echo_test(client_fd, server_fds[t->accept_on]); + udp_echo_test(client_fd, server_fds[t->accept_on], t->dont_bind_reply); close(client_fd); close: @@ -775,6 +791,16 @@ static void test_redirect_lookup(struct test_sk_lookup *skel) .listen_at = { INT_IP4, INT_PORT }, .accept_on = SERVER_B, }, + { + .desc
[PATCH V2 13/13] selftests/resctrl: Keep results from first test run
The resctrl selftests drop the results from every first test run to avoid (per comment) "inaccurate due to monitoring setup transition phase" data. Previously inaccurate data resulted from workloads needing some time to "settle" and also the measurements themselves to account for earlier measurements to measure across needed timeframe. commit da50de0a92f3 ("selftests/resctrl: Calculate resctrl FS derived mem bw over sleep(1) only") ensured that measurements accurately measure just the time frame of interest. The default "fill_buf" benchmark since separated the buffer prepare phase from the benchmark run phase reducing the need for the tests themselves to accommodate the benchmark's "settle" time. With these enhancements there are no remaining portions needing to "settle" and the first test run can contribute to measurements. Signed-off-by: Reinette Chatre --- Changes since V1: - Remove comment about needing results from first run removed. - Fix existing incorrect spacing while changing line. --- tools/testing/selftests/resctrl/cmt_test.c | 5 ++--- tools/testing/selftests/resctrl/mba_test.c | 10 +++--- tools/testing/selftests/resctrl/mbm_test.c | 10 +++--- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/tools/testing/selftests/resctrl/cmt_test.c b/tools/testing/selftests/resctrl/cmt_test.c index a7effe76b419..d4b85d144985 100644 --- a/tools/testing/selftests/resctrl/cmt_test.c +++ b/tools/testing/selftests/resctrl/cmt_test.c @@ -99,14 +99,13 @@ static int check_results(struct resctrl_val_param *param, size_t span, int no_of } /* Field 3 is llc occ resc value */ - if (runs > 0) - sum_llc_occu_resc += strtoul(token_array[3], NULL, 0); + sum_llc_occu_resc += strtoul(token_array[3], NULL, 0); runs++; } fclose(fp); return show_results_info(sum_llc_occu_resc, no_of_bits, span, -MAX_DIFF, MAX_DIFF_PERCENT, runs - 1, true); +MAX_DIFF, MAX_DIFF_PERCENT, runs, true); } static void cmt_test_cleanup(void) diff --git a/tools/testing/selftests/resctrl/mba_test.c b/tools/testing/selftests/resctrl/mba_test.c index 5c6063d0a77c..89c2446b9f80 100644 --- a/tools/testing/selftests/resctrl/mba_test.c +++ b/tools/testing/selftests/resctrl/mba_test.c @@ -86,18 +86,14 @@ static bool show_mba_info(unsigned long *bw_imc, unsigned long *bw_resc) int avg_diff_per; float avg_diff; - /* -* The first run is discarded due to inaccurate value from -* phase transition. -*/ - for (runs = NUM_OF_RUNS * allocation + 1; + for (runs = NUM_OF_RUNS * allocation; runs < NUM_OF_RUNS * allocation + NUM_OF_RUNS ; runs++) { sum_bw_imc += bw_imc[runs]; sum_bw_resc += bw_resc[runs]; } - avg_bw_imc = sum_bw_imc / (NUM_OF_RUNS - 1); - avg_bw_resc = sum_bw_resc / (NUM_OF_RUNS - 1); + avg_bw_imc = sum_bw_imc / NUM_OF_RUNS; + avg_bw_resc = sum_bw_resc / NUM_OF_RUNS; if (avg_bw_imc < THROTTLE_THRESHOLD || avg_bw_resc < THROTTLE_THRESHOLD) { ksft_print_msg("Bandwidth below threshold (%d MiB). Dropping results from MBA schemata %u.\n", THROTTLE_THRESHOLD, diff --git a/tools/testing/selftests/resctrl/mbm_test.c b/tools/testing/selftests/resctrl/mbm_test.c index 7635ee6b9339..8c818e292dce 100644 --- a/tools/testing/selftests/resctrl/mbm_test.c +++ b/tools/testing/selftests/resctrl/mbm_test.c @@ -22,17 +22,13 @@ show_bw_info(unsigned long *bw_imc, unsigned long *bw_resc, size_t span) int runs, ret, avg_diff_per; float avg_diff = 0; - /* -* Discard the first value which is inaccurate due to monitoring setup -* transition phase. -*/ - for (runs = 1; runs < NUM_OF_RUNS ; runs++) { + for (runs = 0; runs < NUM_OF_RUNS; runs++) { sum_bw_imc += bw_imc[runs]; sum_bw_resc += bw_resc[runs]; } - avg_bw_imc = sum_bw_imc / 4; - avg_bw_resc = sum_bw_resc / 4; + avg_bw_imc = sum_bw_imc / NUM_OF_RUNS; + avg_bw_resc = sum_bw_resc / NUM_OF_RUNS; avg_diff = (float)labs(avg_bw_resc - avg_bw_imc) / avg_bw_imc; avg_diff_per = (int)(avg_diff * 100); -- 2.46.0
Re: [PATCH 2/2] kselftests: mm: Fail the test if userfaultfd syscall isn't found
On 9/12/24 10:10, Shuah Khan wrote: On 9/12/24 04:31, Muhammad Usama Anjum wrote: The userfaultfd is enabled in the config fragment of mm selftest suite. It must always be present. If it isn't present, we should throw error and not just skip. This would have helped us catch the test breakage. Please elaborate on this to help understand the what breakage was missed. Also this commit log doesn't look right to me. syscall() could fail for any reason. Do you mean to see skip is incorrect in this error leg? Please see comments below. Adding this now to catch the future breakages. Signed-off-by: Muhammad Usama Anjum --- tools/testing/selftests/mm/pagemap_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/mm/pagemap_ioctl.c b/tools/testing/selftests/mm/pagemap_ioctl.c index bcc73b4e805c6..d83dda8edf62c 100644 --- a/tools/testing/selftests/mm/pagemap_ioctl.c +++ b/tools/testing/selftests/mm/pagemap_ioctl.c @@ -95,7 +95,7 @@ int init_uffd(void) uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY); if (uffd == -1) - return uffd; + ksft_exit_fail_perror("Userfaultfd syscall failed"); This looks wrong to me - Is missing config the only reason this syscall would fail? It should still skip if __NR_userfaultfd isn't supported on a release or an architecture. The real problem seems to be in main(): if (init_uffd()) ksft_exit_pass(); Why is this ksft_exit_pass()? Looks like further investigation is necessary to understand the problem and fix. thanks, -- Shuah
Re: [PATCH 2/2] kselftests: mm: Fail the test if userfaultfd syscall isn't found
On 9/12/24 04:31, Muhammad Usama Anjum wrote: The userfaultfd is enabled in the config fragment of mm selftest suite. It must always be present. If it isn't present, we should throw error and not just skip. This would have helped us catch the test breakage. Please elaborate on this to help understand the what breakage was missed. Also this commit log doesn't look right to me. syscall() could fail for any reason. Do you mean to see skip is incorrect in this error leg? Please see comments below. Adding this now to catch the future breakages. Signed-off-by: Muhammad Usama Anjum --- tools/testing/selftests/mm/pagemap_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/mm/pagemap_ioctl.c b/tools/testing/selftests/mm/pagemap_ioctl.c index bcc73b4e805c6..d83dda8edf62c 100644 --- a/tools/testing/selftests/mm/pagemap_ioctl.c +++ b/tools/testing/selftests/mm/pagemap_ioctl.c @@ -95,7 +95,7 @@ int init_uffd(void) uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY); if (uffd == -1) - return uffd; + ksft_exit_fail_perror("Userfaultfd syscall failed"); This looks wrong to me - Is missing config the only reason this syscall would fail? uffdio_api.api = UFFD_API; uffdio_api.features = UFFD_FEATURE_WP_UNPOPULATED | UFFD_FEATURE_WP_ASYNC | thanks, -- Shuah
Re: [PATCH 13/13] media: i2c: imx214: Add test pattern control
On Mon, Sep 2, 2024 at 11:53 PM André Apitzsch via B4 Relay wrote: > > From: André Apitzsch > > This adds V4L2_CID_TEST_PATTERN control support. > > Signed-off-by: André Apitzsch Acked-by: Ricardo Ribalda > --- > drivers/media/i2c/imx214.c | 77 > -- > 1 file changed, 75 insertions(+), 2 deletions(-) > > diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c > index 6493a9b9ea88..6d67c7b307bd 100644 > --- a/drivers/media/i2c/imx214.c > +++ b/drivers/media/i2c/imx214.c > @@ -181,6 +181,23 @@ > > #define IMX214_REG_ATR_FAST_MOVE CCI_REG8(0x9300) > > +/* Test Pattern Control */ > +#define IMX214_REG_TEST_PATTERNCCI_REG16(0x0600) > +#define IMX214_TEST_PATTERN_DISABLE0 > +#define IMX214_TEST_PATTERN_SOLID_COLOR1 > +#define IMX214_TEST_PATTERN_COLOR_BARS 2 > +#define IMX214_TEST_PATTERN_GREY_COLOR 3 > +#define IMX214_TEST_PATTERN_PN94 > + > +/* Test pattern colour components */ > +#define IMX214_REG_TESTP_RED CCI_REG16(0x0602) > +#define IMX214_REG_TESTP_GREENRCCI_REG16(0x0604) > +#define IMX214_REG_TESTP_BLUE CCI_REG16(0x0606) > +#define IMX214_REG_TESTP_GREENBCCI_REG16(0x0608) > +#define IMX214_TESTP_COLOUR_MIN0 > +#define IMX214_TESTP_COLOUR_MAX0x03ff > +#define IMX214_TESTP_COLOUR_STEP 1 > + > /* IMX214 native and active pixel array size */ > #define IMX214_NATIVE_WIDTH4224U > #define IMX214_NATIVE_HEIGHT 3136U > @@ -213,6 +230,22 @@ static const u32 imx214_mbus_formats[] = { > MEDIA_BUS_FMT_SBGGR10_1X10, > }; > > +static const char * const imx214_test_pattern_menu[] = { > + "Disabled", > + "Color Bars", > + "Solid Color", > + "Grey Color Bars", > + "PN9" > +}; > + > +static const int imx214_test_pattern_val[] = { > + IMX214_TEST_PATTERN_DISABLE, > + IMX214_TEST_PATTERN_COLOR_BARS, > + IMX214_TEST_PATTERN_SOLID_COLOR, > + IMX214_TEST_PATTERN_GREY_COLOR, > + IMX214_TEST_PATTERN_PN9, > +}; > + > struct imx214 { > struct device *dev; > struct clk *xclk; > @@ -819,6 +852,26 @@ static int imx214_set_ctrl(struct v4l2_ctrl *ctrl) > cci_write(imx214->regmap, IMX214_REG_FRM_LENGTH_LINES, > format->height + ctrl->val, &ret); > break; > + case V4L2_CID_TEST_PATTERN: > + cci_write(imx214->regmap, IMX214_REG_TEST_PATTERN, > + imx214_test_pattern_val[ctrl->val], &ret); > + break; > + case V4L2_CID_TEST_PATTERN_RED: > + cci_write(imx214->regmap, IMX214_REG_TESTP_RED, > + ctrl->val, &ret); > + break; > + case V4L2_CID_TEST_PATTERN_GREENR: > + cci_write(imx214->regmap, IMX214_REG_TESTP_GREENR, > + ctrl->val, &ret); > + break; > + case V4L2_CID_TEST_PATTERN_BLUE: > + cci_write(imx214->regmap, IMX214_REG_TESTP_BLUE, > + ctrl->val, &ret); > + break; > + case V4L2_CID_TEST_PATTERN_GREENB: > + cci_write(imx214->regmap, IMX214_REG_TESTP_GREENB, > + ctrl->val, &ret); > + break; > default: > ret = -EINVAL; > } > @@ -846,14 +899,14 @@ static int imx214_ctrls_init(struct imx214 *imx214) > struct v4l2_ctrl_handler *ctrl_hdlr; > int exposure_max, exposure_def; > int hblank; > - int ret; > + int i, ret; > > ret = v4l2_fwnode_device_parse(imx214->dev, &props); > if (ret < 0) > return ret; > > ctrl_hdlr = &imx214->ctrls; > - ret = v4l2_ctrl_handler_init(&imx214->ctrls, 12); > + ret = v4l2_ctrl_handler_init(&imx214->ctrls, 13); > if (ret) > return ret; > > @@ -908,6 +961,26 @@ static int imx214_ctrls_init(struct imx214 *imx214) > if (imx214->vflip) > imx214->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; > > + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx214_ctrl_ops, > +V4L2_CID_TEST_PATTERN, > +ARRAY_SIZE(imx214_test_pattern_menu) - 1, > +0, 0, imx214_test_pattern_menu); > +
[PATCH 2/2] kselftests: mm: Fail the test if userfaultfd syscall isn't found
The userfaultfd is enabled in the config fragment of mm selftest suite. It must always be present. If it isn't present, we should throw error and not just skip. This would have helped us catch the test breakage. Adding this now to catch the future breakages. Signed-off-by: Muhammad Usama Anjum --- tools/testing/selftests/mm/pagemap_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/mm/pagemap_ioctl.c b/tools/testing/selftests/mm/pagemap_ioctl.c index bcc73b4e805c6..d83dda8edf62c 100644 --- a/tools/testing/selftests/mm/pagemap_ioctl.c +++ b/tools/testing/selftests/mm/pagemap_ioctl.c @@ -95,7 +95,7 @@ int init_uffd(void) uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY); if (uffd == -1) - return uffd; + ksft_exit_fail_perror("Userfaultfd syscall failed"); uffdio_api.api = UFFD_API; uffdio_api.features = UFFD_FEATURE_WP_UNPOPULATED | UFFD_FEATURE_WP_ASYNC | -- 2.39.2
Re: [PATCH net-next] page_pool: add a test module for page_pool
On 2024/9/10 19:27, Jesper Dangaard Brouer wrote: ... >> >> The main issue I remembered was that it only support x86:( >> > > Yes, because I've added ASM code for reading TSC counter in a very > precise manor. Given we run many iterations, then I don't think we > need this precise reading. I guess it can simply be replaced with > get_cycles() or get_cycles64(). Then it should work on all archs. Agreed. > > The code already supports wall-clock time via ktime_get() (specifically > ktime_get_real_ts64()). > > >>> >>> My preference here (for the performance part) is to upstream the >>> out-of-tree tests that Jesper (and probably others) are using, rather >>> than adding a new performance test that is not as battle-hardened. >> >> I looked through the out-of-tree tests again, it seems we can take the >> best of them. >> For Jesper' ko: >> It seems we can do prefill as something that pp_fill_ptr_ring() does >> in bench_page_pool_simple.c to avoid the noise from the page allocator. >> >> >> For the ko in this patch: >> It uses NAPI instead of tasklet mimicking the NAPI context, support >> PP_FLAG_DMA_MAP flag testing, and return '-EAGAIN' in module_init() >> to use perf stat for collecting and calculating performance data. >> > My bench don't return minus-number on module load, because I used perf > record, and to see symbols decoded with perf report, I needed the module > to be loaded. > > I started on reading the PMU counters[1] around the bench loop, it works > if enabling PMU counters yourself/manually, but I never finished that work. > > [1] > https://github.com/netoptimizer/prototype-kernel/blob/master/kernel/include/linux/time_bench.h#L195-L209 > > >> Is there other testcase or better practicing that we can learn from >> Jesper' out of tree ko? >> > > I created a time_bench.c [2] module that other modules [3] can use to > easier reuse the benchmarking code in other modules. > > [2] > https://github.com/netoptimizer/prototype-kernel/blob/master/kernel/lib/time_bench.c > > [3] > https://github.com/netoptimizer/prototype-kernel/blob/master/kernel/lib/bench_page_pool_simple.c Will take a look at it, thanks. > > --Jesper
[RFC PATCH 35/39] KVM: selftests: Test that pinned pages block KVM from setting memory attributes to PRIVATE
CONFIG_GUP_TEST provides userspace with an ioctl to invoke pin_user_pages(), and this test uses the ioctl to pin pages, to check that memory attributes cannot be set to private if shared pages are pinned. Signed-off-by: Ackerley Tng --- tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/guest_memfd_pin_test.c | 104 ++ 2 files changed, 105 insertions(+) create mode 100644 tools/testing/selftests/kvm/guest_memfd_pin_test.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 3c1f35456bfc..c5a1c8c7125a 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -136,6 +136,7 @@ TEST_GEN_PROGS_x86_64 += dirty_log_perf_test TEST_GEN_PROGS_x86_64 += guest_memfd_test TEST_GEN_PROGS_x86_64 += guest_memfd_hugetlb_reporting_test TEST_GEN_PROGS_x86_64 += guest_memfd_sharing_test +TEST_GEN_PROGS_x86_64 += guest_memfd_pin_test TEST_GEN_PROGS_x86_64 += guest_print_test TEST_GEN_PROGS_x86_64 += hardware_disable_test TEST_GEN_PROGS_x86_64 += kvm_create_max_vcpus diff --git a/tools/testing/selftests/kvm/guest_memfd_pin_test.c b/tools/testing/selftests/kvm/guest_memfd_pin_test.c new file mode 100644 index ..b45fb8024970 --- /dev/null +++ b/tools/testing/selftests/kvm/guest_memfd_pin_test.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Test that pinned pages block KVM from setting memory attributes to PRIVATE. + * + * Copyright (c) 2024, Google LLC. + */ +#include +#include +#include + +#include "test_util.h" +#include "kvm_util.h" +#include "../../../../mm/gup_test.h" + +#define GUEST_MEMFD_PIN_TEST_SLOT 10 +#define GUEST_MEMFD_PIN_TEST_GPA 0x5000ULL +#define GUEST_MEMFD_PIN_TEST_OFFSET 0 + +static int gup_test_fd; + +void pin_pages(void *vaddr, uint64_t size) +{ + const struct pin_longterm_test args = { + .addr = (uint64_t)vaddr, + .size = size, + .flags = PIN_LONGTERM_TEST_FLAG_USE_WRITE, + }; + + TEST_ASSERT_EQ(ioctl(gup_test_fd, PIN_LONGTERM_TEST_START, &args), 0); +} + +void unpin_pages(void) +{ + TEST_ASSERT_EQ(ioctl(gup_test_fd, PIN_LONGTERM_TEST_STOP), 0); +} + +void run_test(void) +{ + struct kvm_vm *vm; + size_t page_size; + void *mem; + int fd; + + vm = vm_create_barebones_type(KVM_X86_SW_PROTECTED_VM); + + page_size = getpagesize(); + fd = vm_create_guest_memfd(vm, page_size, 0); + + mem = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, + GUEST_MEMFD_PIN_TEST_OFFSET); + TEST_ASSERT(mem != MAP_FAILED, "mmap should return valid address"); + + /* +* Setting up this memslot with a KVM_X86_SW_PROTECTED_VM marks all +* offsets in the file as shared. +*/ + vm_set_user_memory_region2(vm, GUEST_MEMFD_PIN_TEST_SLOT, + KVM_MEM_GUEST_MEMFD, + GUEST_MEMFD_PIN_TEST_GPA, page_size, mem, fd, + GUEST_MEMFD_PIN_TEST_OFFSET); + + /* Before pinning pages, toggling memory attributes should be fine. */ + vm_mem_set_private(vm, GUEST_MEMFD_PIN_TEST_GPA, page_size); + vm_mem_set_shared(vm, GUEST_MEMFD_PIN_TEST_GPA, page_size); + + pin_pages(mem, page_size); + + /* +* Pinning also faults pages in, so remove these pages from userspace +* page tables to properly test that pinning blocks setting memory +* attributes to private. +*/ + TEST_ASSERT_EQ(madvise(mem, page_size, MADV_DONTNEED), 0); + + /* Should fail since the page is still faulted in. */ + TEST_ASSERT_EQ(__vm_set_memory_attributes(vm, GUEST_MEMFD_PIN_TEST_GPA, + page_size, + KVM_MEMORY_ATTRIBUTE_PRIVATE), + -1); + TEST_ASSERT_EQ(errno, EINVAL); + + unpin_pages(); + + /* With the pages unpinned, kvm can set this page to private. */ + vm_mem_set_private(vm, GUEST_MEMFD_PIN_TEST_GPA, page_size); + + kvm_vm_free(vm); + close(fd); +} + +int main(int argc, char *argv[]) +{ + gup_test_fd = open("/sys/kernel/debug/gup_test", O_RDWR); + /* +* This test depends on CONFIG_GUP_TEST to provide a kernel module that +* exposes pin_user_pages() to userspace. +*/ + TEST_REQUIRE(gup_test_fd != -1); + TEST_REQUIRE(kvm_check_cap(KVM_CAP_VM_TYPES) & BIT(KVM_X86_SW_PROTECTED_VM)); + + run_test(); + + return 0; +} -- 2.46.0.598.g6f2099f65c-goog
[RFC PATCH 33/39] KVM: selftests: Test guest_memfd memory sharing between guest and host
Minimal test for guest_memfd to test that when memory is marked shared in a VM, the host can read and write to it via an mmap()ed address, and the guest can also read and write to it. Signed-off-by: Ackerley Tng --- tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/guest_memfd_sharing_test.c | 160 ++ 2 files changed, 161 insertions(+) create mode 100644 tools/testing/selftests/kvm/guest_memfd_sharing_test.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index b3b7e83f39fc..3c1f35456bfc 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -135,6 +135,7 @@ TEST_GEN_PROGS_x86_64 += dirty_log_test TEST_GEN_PROGS_x86_64 += dirty_log_perf_test TEST_GEN_PROGS_x86_64 += guest_memfd_test TEST_GEN_PROGS_x86_64 += guest_memfd_hugetlb_reporting_test +TEST_GEN_PROGS_x86_64 += guest_memfd_sharing_test TEST_GEN_PROGS_x86_64 += guest_print_test TEST_GEN_PROGS_x86_64 += hardware_disable_test TEST_GEN_PROGS_x86_64 += kvm_create_max_vcpus diff --git a/tools/testing/selftests/kvm/guest_memfd_sharing_test.c b/tools/testing/selftests/kvm/guest_memfd_sharing_test.c new file mode 100644 index ..fef5a73e5053 --- /dev/null +++ b/tools/testing/selftests/kvm/guest_memfd_sharing_test.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Minimal test for guest_memfd to test that when memory is marked shared in a + * VM, the host can read and write to it via an mmap()ed address, and the guest + * can also read and write to it. + * + * Copyright (c) 2024, Google LLC. + */ +#include +#include +#include + +#include "test_util.h" +#include "kvm_util.h" +#include "ucall_common.h" + +#define GUEST_MEMFD_SHARING_TEST_SLOT 10 +#define GUEST_MEMFD_SHARING_TEST_GPA 0x5000ULL +#define GUEST_MEMFD_SHARING_TEST_GVA 0x9000ULL +#define GUEST_MEMFD_SHARING_TEST_OFFSET 0 +#define GUEST_MEMFD_SHARING_TEST_GUEST_TO_HOST_VALUE 0x11 +#define GUEST_MEMFD_SHARING_TEST_HOST_TO_GUEST_VALUE 0x22 + +static void guest_code(int page_size) +{ + char *mem; + int i; + + mem = (char *)GUEST_MEMFD_SHARING_TEST_GVA; + + for (i = 0; i < page_size; ++i) { + GUEST_ASSERT_EQ(mem[i], GUEST_MEMFD_SHARING_TEST_HOST_TO_GUEST_VALUE); + } + + memset(mem, GUEST_MEMFD_SHARING_TEST_GUEST_TO_HOST_VALUE, page_size); + + GUEST_DONE(); +} + +int run_test(struct kvm_vcpu *vcpu, void *hva, int page_size) +{ + struct ucall uc; + uint64_t uc_cmd; + + memset(hva, GUEST_MEMFD_SHARING_TEST_HOST_TO_GUEST_VALUE, page_size); + vcpu_args_set(vcpu, 1, page_size); + + /* Reset vCPU to guest_code every time run_test is called. */ + vcpu_arch_set_entry_point(vcpu, guest_code); + + vcpu_run(vcpu); + uc_cmd = get_ucall(vcpu, &uc); + + if (uc_cmd == UCALL_ABORT) { + REPORT_GUEST_ASSERT(uc); + return 1; + } else if (uc_cmd == UCALL_DONE) { + char *mem; + int i; + + mem = hva; + for (i = 0; i < page_size; ++i) + TEST_ASSERT_EQ(mem[i], GUEST_MEMFD_SHARING_TEST_GUEST_TO_HOST_VALUE); + + return 0; + } else { + TEST_FAIL("Unknown ucall 0x%lx.", uc.cmd); + return 1; + } +} + +void *add_memslot(struct kvm_vm *vm, int guest_memfd, size_t page_size, + bool back_shared_memory_with_guest_memfd) +{ + void *mem; + + if (back_shared_memory_with_guest_memfd) { + mem = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, + guest_memfd, GUEST_MEMFD_SHARING_TEST_OFFSET); + } else { + mem = mmap(NULL, page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + } + TEST_ASSERT(mem != MAP_FAILED, "mmap should return valid address"); + + /* +* Setting up this memslot with a KVM_X86_SW_PROTECTED_VM marks all +* offsets in the file as shared. +*/ + vm_set_user_memory_region2(vm, GUEST_MEMFD_SHARING_TEST_SLOT, + KVM_MEM_GUEST_MEMFD, + GUEST_MEMFD_SHARING_TEST_GPA, page_size, mem, + guest_memfd, GUEST_MEMFD_SHARING_TEST_OFFSET); + + return mem; +} + +void test_sharing(bool back_shared_memory_with_guest_memfd) +{ + const struct vm_shape shape = { + .mode = VM_MODE_DEFAULT, + .type = KVM_X86_SW_PROTECTED_VM, + }; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + size_t page_size; + int guest_memfd; + void *mem; + + TEST_REQUIRE(kvm_check_cap(KVM_CAP_VM_TYPES) & BIT(KVM_X86_SW_PROTECTED_VM)); + + vm = vm_create_shape_with_one_vcpu(shape, &vcpu, &
[RFC PATCH 32/39] KVM: selftests: Test using guest_memfd memory from userspace
Test using guest_memfd from userspace, since guest_memfd now has mmap() support. Tests: 1. mmap() should now always return a valid address 2. Test that madvise() doesn't give any issues when pages are not faulted in. 3. Test that pages should not be faultable before association with a memslot, and that faults result in SIGBUS. 4. Test that pages can be faulted if marked faultable, and the flow of setting a memory range as private, which is: a. madvise(MADV_DONTNEED) to request kernel to unmap pages b. Set memory attributes of VM to private Also test that if pages are still mapped, setting memory attributes will fail. 5. Test that madvise(MADV_REMOVE) can be used to remove pages from guest_memfd, forcing zeroing of those pages before the next time the pages are faulted in. Signed-off-by: Ackerley Tng --- .../testing/selftests/kvm/guest_memfd_test.c | 195 +- 1 file changed, 189 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/kvm/guest_memfd_test.c b/tools/testing/selftests/kvm/guest_memfd_test.c index 3618ce06663e..b6f3c3e6d0dd 100644 --- a/tools/testing/selftests/kvm/guest_memfd_test.c +++ b/tools/testing/selftests/kvm/guest_memfd_test.c @@ -6,6 +6,7 @@ */ #include #include +#include #include #include #include @@ -35,12 +36,192 @@ static void test_file_read_write(int fd) "pwrite on a guest_mem fd should fail"); } -static void test_mmap(int fd, size_t page_size) +static void test_mmap_should_map_pages_into_userspace(int fd, size_t page_size) { char *mem; mem = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - TEST_ASSERT_EQ(mem, MAP_FAILED); + TEST_ASSERT(mem != MAP_FAILED, "mmap should return valid address"); + + TEST_ASSERT_EQ(munmap(mem, page_size), 0); +} + +static void test_madvise_no_error_when_pages_not_faulted(int fd, size_t page_size) +{ + char *mem; + + mem = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + TEST_ASSERT(mem != MAP_FAILED, "mmap should return valid address"); + + TEST_ASSERT_EQ(madvise(mem, page_size, MADV_DONTNEED), 0); + + TEST_ASSERT_EQ(munmap(mem, page_size), 0); +} + +static void assert_not_faultable(char *address) +{ + pid_t child_pid; + + child_pid = fork(); + TEST_ASSERT(child_pid != -1, "fork failed"); + + if (child_pid == 0) { + *address = 'A'; + } else { + int status; + waitpid(child_pid, &status, 0); + + TEST_ASSERT(WIFSIGNALED(status), + "Child should have exited with a signal"); + TEST_ASSERT_EQ(WTERMSIG(status), SIGBUS); + } +} + +/* + * Pages should not be faultable before association with memslot because pages + * (in a KVM_X86_SW_PROTECTED_VM) only default to faultable at memslot + * association time. + */ +static void test_pages_not_faultable_if_not_associated_with_memslot(int fd, + size_t page_size) +{ + char *mem = mmap(NULL, page_size, PROT_READ | PROT_WRITE, +MAP_SHARED, fd, 0); + TEST_ASSERT(mem != MAP_FAILED, "mmap should return valid address"); + + assert_not_faultable(mem); + + TEST_ASSERT_EQ(munmap(mem, page_size), 0); +} + +static void test_pages_faultable_if_marked_faultable(struct kvm_vm *vm, int fd, +size_t page_size) +{ + char *mem; + uint64_t gpa = 0; + uint64_t guest_memfd_offset = 0; + + /* +* This test uses KVM_X86_SW_PROTECTED_VM is required to set +* arch.has_private_mem, to add a memslot with guest_memfd to a VM. +*/ + if (!(kvm_check_cap(KVM_CAP_VM_TYPES) & BIT(KVM_X86_SW_PROTECTED_VM))) { + printf("Faultability test skipped since KVM_X86_SW_PROTECTED_VM is not supported."); + return; + } + + mem = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, + guest_memfd_offset); + TEST_ASSERT(mem != MAP_FAILED, "mmap should return valid address"); + + /* +* Setting up this memslot with a KVM_X86_SW_PROTECTED_VM marks all +* offsets in the file as shared, allowing pages to be faulted in. +*/ + vm_set_user_memory_region2(vm, 0, KVM_MEM_GUEST_MEMFD, gpa, page_size, + mem, fd, guest_memfd_offset); + + *mem = 'A'; + TEST_ASSERT_EQ(*mem, 'A'); + + /* Should fail since the page is still faulted in. */ + TEST_ASSERT_EQ(__vm_set_memory_attributes(vm, gpa, page_size, + KVM_MEMORY_ATTRIBUTE_PRIVATE), + -1); + TEST_ASSERT_EQ(errno, EINVAL); + +
[RFC PATCH 21/39] KVM: selftests: Test that guest_memfd usage is reported via hugetlb
Using HugeTLB as the huge page allocator for guest_memfd allows reuse of HugeTLB's reporting mechanism. Signed-off-by: Ackerley Tng --- tools/testing/selftests/kvm/Makefile | 1 + .../kvm/guest_memfd_hugetlb_reporting_test.c | 222 ++ 2 files changed, 223 insertions(+) create mode 100644 tools/testing/selftests/kvm/guest_memfd_hugetlb_reporting_test.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 48d32c5aa3eb..b3b7e83f39fc 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -134,6 +134,7 @@ TEST_GEN_PROGS_x86_64 += demand_paging_test TEST_GEN_PROGS_x86_64 += dirty_log_test TEST_GEN_PROGS_x86_64 += dirty_log_perf_test TEST_GEN_PROGS_x86_64 += guest_memfd_test +TEST_GEN_PROGS_x86_64 += guest_memfd_hugetlb_reporting_test TEST_GEN_PROGS_x86_64 += guest_print_test TEST_GEN_PROGS_x86_64 += hardware_disable_test TEST_GEN_PROGS_x86_64 += kvm_create_max_vcpus diff --git a/tools/testing/selftests/kvm/guest_memfd_hugetlb_reporting_test.c b/tools/testing/selftests/kvm/guest_memfd_hugetlb_reporting_test.c new file mode 100644 index ..cb9fdf0d4ec8 --- /dev/null +++ b/tools/testing/selftests/kvm/guest_memfd_hugetlb_reporting_test.c @@ -0,0 +1,222 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "kvm_util.h" +#include "test_util.h" +#include "processor.h" + +static int read_int(const char *file_name) +{ + FILE *fp; + int num; + + fp = fopen(file_name, "r"); + TEST_ASSERT(fp != NULL, "Error opening file %s!\n", file_name); + + TEST_ASSERT_EQ(fscanf(fp, "%d", &num), 1); + + fclose(fp); + + return num; +} + +enum hugetlb_statistic { + FREE_HUGEPAGES, + NR_HUGEPAGES, + NR_OVERCOMMIT_HUGEPAGES, + RESV_HUGEPAGES, + SURPLUS_HUGEPAGES, + NR_TESTED_HUGETLB_STATISTICS, +}; + +static const char *hugetlb_statistics[NR_TESTED_HUGETLB_STATISTICS] = { + [FREE_HUGEPAGES] = "free_hugepages", + [NR_HUGEPAGES] = "nr_hugepages", + [NR_OVERCOMMIT_HUGEPAGES] = "nr_overcommit_hugepages", + [RESV_HUGEPAGES] = "resv_hugepages", + [SURPLUS_HUGEPAGES] = "surplus_hugepages", +}; + +enum test_page_size { + TEST_SZ_2M, + TEST_SZ_1G, + NR_TEST_SIZES, +}; + +struct test_param { + size_t page_size; + int memfd_create_flags; + int guest_memfd_flags; + char *path_suffix; +}; + +const struct test_param *test_params(enum test_page_size size) +{ + static const struct test_param params[] = { + [TEST_SZ_2M] = { + .page_size = PG_SIZE_2M, + .memfd_create_flags = MFD_HUGETLB | MFD_HUGE_2MB, + .guest_memfd_flags = KVM_GUEST_MEMFD_HUGETLB | KVM_GUEST_MEMFD_HUGE_2MB, + .path_suffix = "2048kB", + }, + [TEST_SZ_1G] = { + .page_size = PG_SIZE_1G, + .memfd_create_flags = MFD_HUGETLB | MFD_HUGE_1GB, + .guest_memfd_flags = KVM_GUEST_MEMFD_HUGETLB | KVM_GUEST_MEMFD_HUGE_1GB, + .path_suffix = "1048576kB", + }, + }; + + return ¶ms[size]; +} + +static int read_statistic(enum test_page_size size, enum hugetlb_statistic statistic) +{ + char path[PATH_MAX] = "/sys/kernel/mm/hugepages/hugepages-"; + + strcat(path, test_params(size)->path_suffix); + strcat(path, "/"); + strcat(path, hugetlb_statistics[statistic]); + + return read_int(path); +} + +static int baseline[NR_TEST_SIZES][NR_TESTED_HUGETLB_STATISTICS]; + +static void establish_baseline(void) +{ + int i, j; + + for (i = 0; i < NR_TEST_SIZES; ++i) + for (j = 0; j < NR_TESTED_HUGETLB_STATISTICS; ++j) + baseline[i][j] = read_statistic(i, j); +} + +static void assert_stats_at_baseline(void) +{ + TEST_ASSERT_EQ(read_statistic(TEST_SZ_2M, FREE_HUGEPAGES), + baseline[TEST_SZ_2M][FREE_HUGEPAGES]); + TEST_ASSERT_EQ(read_statistic(TEST_SZ_2M, NR_HUGEPAGES), + baseline[TEST_SZ_2M][NR_HUGEPAGES]); + TEST_ASSERT_EQ(read_statistic(TEST_SZ_2M, NR_OVERCOMMIT_HUGEPAGES), + baseline[TEST_SZ_2M][NR_OVERCOMMIT_HUGEPAGES]); + TEST_ASSERT_EQ(read_statistic(TEST_SZ_2M, RESV_HUGEPAGES), + baseline[TEST_SZ_2M][RESV_HUGEPAGES]); + TEST_ASSERT_EQ(read_statistic(TEST_SZ_2M, SURPLUS_HUGEPAGES), + baseline[TEST_SZ_2M][SURPLUS_HUGEPAGES]); + + TEST_ASSERT_EQ(read_statistic(TEST_SZ_1G, FREE_HUGEPAGES), + baseline[TEST_SZ_1G][FREE_HUGEPAGES]); + TEST_ASSERT_EQ(read_statistic(TEST_SZ_1G, NR_HUGEPAGES), + baseline[TEST_SZ_1G][NR_HUGEPAGES]); + TEST_ASSERT_EQ(read_statistic(TEST_SZ_1G, NR_OVERCOMMIT_HUGEPAGES
[RFC PATCH 19/39] KVM: selftests: Update test for various private memory backing source types
Update private_mem_conversions_test for various private memory backing source types. Signed-off-by: Ackerley Tng --- .../kvm/x86_64/private_mem_conversions_test.c | 28 ++- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/tools/testing/selftests/kvm/x86_64/private_mem_conversions_test.c b/tools/testing/selftests/kvm/x86_64/private_mem_conversions_test.c index 82a8d88b5338..71f480c19f92 100644 --- a/tools/testing/selftests/kvm/x86_64/private_mem_conversions_test.c +++ b/tools/testing/selftests/kvm/x86_64/private_mem_conversions_test.c @@ -366,14 +366,20 @@ static void *__test_mem_conversions(void *__vcpu) } } -static void test_mem_conversions(enum vm_mem_backing_src_type src_type, uint32_t nr_vcpus, -uint32_t nr_memslots) +static void +test_mem_conversions(enum vm_mem_backing_src_type src_type, +enum vm_private_mem_backing_src_type private_mem_src_type, +uint32_t nr_vcpus, +uint32_t nr_memslots) { /* * Allocate enough memory so that each vCPU's chunk of memory can be * naturally aligned with respect to the size of the backing store. */ - const size_t alignment = max_t(size_t, SZ_2M, get_backing_src_pagesz(src_type)); + const size_t alignment = max_t(size_t, SZ_2M, + max_t(size_t, + get_private_mem_backing_src_pagesz(private_mem_src_type), +get_backing_src_pagesz(src_type))); const size_t per_cpu_size = align_up(PER_CPU_DATA_SIZE, alignment); const size_t memfd_size = per_cpu_size * nr_vcpus; const size_t slot_size = memfd_size / nr_memslots; @@ -394,7 +400,9 @@ static void test_mem_conversions(enum vm_mem_backing_src_type src_type, uint32_t vm_enable_cap(vm, KVM_CAP_EXIT_HYPERCALL, (1 << KVM_HC_MAP_GPA_RANGE)); - memfd = vm_create_guest_memfd(vm, memfd_size, 0); + memfd = vm_create_guest_memfd( + vm, memfd_size, + vm_private_mem_backing_src_alias(private_mem_src_type)->flag); for (i = 0; i < nr_memslots; i++) vm_mem_add(vm, src_type, BASE_DATA_GPA + slot_size * i, @@ -440,10 +448,12 @@ static void test_mem_conversions(enum vm_mem_backing_src_type src_type, uint32_t static void usage(const char *cmd) { puts(""); - printf("usage: %s [-h] [-m nr_memslots] [-s mem_type] [-n nr_vcpus]\n", cmd); + printf("usage: %s [-h] [-m nr_memslots] [-s mem_type] [-p private_mem_type] [-n nr_vcpus]\n", cmd); puts(""); backing_src_help("-s"); puts(""); + private_mem_backing_src_help("-p"); + puts(""); puts(" -n: specify the number of vcpus (default: 1)"); puts(""); puts(" -m: specify the number of memslots (default: 1)"); @@ -453,17 +463,21 @@ static void usage(const char *cmd) int main(int argc, char *argv[]) { enum vm_mem_backing_src_type src_type = DEFAULT_VM_MEM_SRC; + enum vm_private_mem_backing_src_type private_mem_src_type = DEFAULT_VM_PRIVATE_MEM_SRC; uint32_t nr_memslots = 1; uint32_t nr_vcpus = 1; int opt; TEST_REQUIRE(kvm_check_cap(KVM_CAP_VM_TYPES) & BIT(KVM_X86_SW_PROTECTED_VM)); - while ((opt = getopt(argc, argv, "hm:s:n:")) != -1) { + while ((opt = getopt(argc, argv, "hm:s:p:n:")) != -1) { switch (opt) { case 's': src_type = parse_backing_src_type(optarg); break; + case 'p': + private_mem_src_type = parse_private_mem_backing_src_type(optarg); + break; case 'n': nr_vcpus = atoi_positive("nr_vcpus", optarg); break; @@ -477,7 +491,7 @@ int main(int argc, char *argv[]) } } - test_mem_conversions(src_type, nr_vcpus, nr_memslots); + test_mem_conversions(src_type, private_mem_src_type, nr_vcpus, nr_memslots); return 0; } -- 2.46.0.598.g6f2099f65c-goog
[PATCH HID v2 11/11] selftests/hid: add test to disable hid-input
Add a test for the newly enabled feature to control the connect_mask of hid-generic. Signed-off-by: Benjamin Tissoires --- changes in v2: - amended for the new API --- tools/testing/selftests/hid/hid_bpf.c | 60 +- tools/testing/selftests/hid/progs/hid.c| 1 + .../testing/selftests/hid/progs/hid_bpf_helpers.h | 1 + 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/hid/hid_bpf.c b/tools/testing/selftests/hid/hid_bpf.c index edc061b38528..41cacc30ef8b 100644 --- a/tools/testing/selftests/hid/hid_bpf.c +++ b/tools/testing/selftests/hid/hid_bpf.c @@ -4,6 +4,38 @@ #include "hid_common.h" #include +static const __u8 mouse_rdesc[] = { + 0x05, 0x01, /* .Usage Page (Generic Desktop)0 */ + 0x09, 0x02, /* .Usage (Mouse) 2 */ + 0xa1, 0x01, /* .Collection (Application)4 */ + 0x09, 0x02, /* ..Usage (Mouse) 6 */ + 0xa1, 0x02, /* ..Collection (Logical) 8 */ + 0x09, 0x01, /* ...Usage (Pointer) 10 */ + 0xa1, 0x00, /* ...Collection (Physical) 12 */ + 0x05, 0x09, /* Usage Page (Button) 14 */ + 0x19, 0x01, /* Usage Minimum (1)16 */ + 0x29, 0x03, /* Usage Maximum (3)18 */ + 0x15, 0x00, /* Logical Minimum (0) 20 */ + 0x25, 0x01, /* Logical Maximum (1) 22 */ + 0x75, 0x01, /* Report Size (1) 24 */ + 0x95, 0x03, /* Report Count (3) 26 */ + 0x81, 0x02, /* Input (Data,Var,Abs) 28 */ + 0x75, 0x05, /* Report Size (5) 30 */ + 0x95, 0x01, /* Report Count (1) 32 */ + 0x81, 0x03, /* Input (Cnst,Var,Abs) 34 */ + 0x05, 0x01, /* Usage Page (Generic Desktop) 36 */ + 0x09, 0x30, /* Usage (X)38 */ + 0x09, 0x31, /* Usage (Y)40 */ + 0x15, 0x81, /* Logical Minimum (-127) 42 */ + 0x25, 0x7f, /* Logical Maximum (127)44 */ + 0x75, 0x08, /* Report Size (8) 46 */ + 0x95, 0x02, /* Report Count (2) 48 */ + 0x81, 0x06, /* Input (Data,Var,Rel) 50 */ + 0xc0,/* ...End Collection52 */ + 0xc0,/* ..End Collection 53 */ + 0xc0,/* .End Collection 54 */ +}; + struct hid_hw_request_syscall_args { __u8 data[10]; unsigned int hid; @@ -59,6 +91,8 @@ struct specific_device { __u16 bus; __u32 vid; __u32 pid; + const __u8 *rdesc; + const size_t rdesc_size; }; FIXTURE_SETUP(hid_bpf) @@ -72,11 +106,15 @@ FIXTURE_SETUP(hid_bpf) .bus = BUS_BLUETOOTH, .vid = 0x05ac, /* USB_VENDOR_ID_APPLE */ .pid = 0x022c, /* USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI */ + .rdesc = mouse_rdesc, + .rdesc_size = sizeof(mouse_rdesc), }, { .test_name = "*", .bus = BUS_USB, .vid = 0x0001, .pid = 0x0a36, + .rdesc = rdesc, + .rdesc_size = sizeof(rdesc), }}; for (int i = 0; i < ARRAY_SIZE(devices); i++) { @@ -88,7 +126,7 @@ FIXTURE_SETUP(hid_bpf) ASSERT_OK_PTR(match); err = setup_uhid(_metadata, &self->hid, match->bus, match->vid, match->pid, -rdesc, sizeof(rdesc)); +match->rdesc, match->rdesc_size); ASSERT_OK(err); } @@ -914,6 +952,24 @@ static bool is_using_driver(struct __test_metadata *_metadata, struct uhid_devic return found; } +static bool has_hid_input(struct uhid_device *hid) +{ + char input[1024]; + DIR *d; + + sprintf(input, "/sys/bus/hid/devices/%04X:%04X:%04X.%04X/input", + hid->bus, hid->vid, hid->pid, hid->hid_id); + + d = opendir(input); + if (d) { + closedir(d); + + return true; + } + + return false; +} + /* * Attach hid_driver_probe to the given uhid device, * check that the device is now using hid-generic. @@ -927,10 +983,12 @@ TEST_F(hid_bpf, test_hid_driver_probe) }; ASSERT_TRUE(is_using_driver(_metadata, &self->hid, "apple")); + ASSERT_TRUE(has_hid_input(&self->hid)) TH_LOG("input node not found"); LOAD_PROGRAMS(progs); ASSERT_TRUE(is_using_driver(_metadata, &self->hid, "hid-generic")); + ASSERT_FALSE(has_hid_input(&self->hid)) TH_LOG("input node u
[PATCH HID v2 09/11] selftests/hid: add test for assigning a given device to hid-generic
We use a well known VID/PID on a driver that doesn't need to talk to the device, ensures we created the device against the target driver, then load our program and ensure we have unbound to this driver and use hid-generic instead. Signed-off-by: Benjamin Tissoires --- changes in v2: - amended for the new API --- tools/testing/selftests/hid/hid_bpf.c | 80 +- tools/testing/selftests/hid/progs/hid.c| 12 .../testing/selftests/hid/progs/hid_bpf_helpers.h | 6 +- 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/hid/hid_bpf.c b/tools/testing/selftests/hid/hid_bpf.c index 7eb15da62bdc..edc061b38528 100644 --- a/tools/testing/selftests/hid/hid_bpf.c +++ b/tools/testing/selftests/hid/hid_bpf.c @@ -54,11 +54,41 @@ FIXTURE_TEARDOWN(hid_bpf) { hid_bpf_teardown(_metadata, self, variant); \ } while (0) +struct specific_device { + const char test_name[64]; + __u16 bus; + __u32 vid; + __u32 pid; +}; + FIXTURE_SETUP(hid_bpf) { + const struct specific_device *match = NULL; int err; - err = setup_uhid(_metadata, &self->hid, BUS_USB, 0x0001, 0x0a36, rdesc, sizeof(rdesc)); + const struct specific_device devices[] = { + { + .test_name = "test_hid_driver_probe", + .bus = BUS_BLUETOOTH, + .vid = 0x05ac, /* USB_VENDOR_ID_APPLE */ + .pid = 0x022c, /* USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI */ + }, { + .test_name = "*", + .bus = BUS_USB, + .vid = 0x0001, + .pid = 0x0a36, + }}; + + for (int i = 0; i < ARRAY_SIZE(devices); i++) { + match = &devices[i]; + if (!strncmp(_metadata->name, devices[i].test_name, sizeof(devices[i].test_name))) + break; + } + + ASSERT_OK_PTR(match); + + err = setup_uhid(_metadata, &self->hid, match->bus, match->vid, match->pid, +rdesc, sizeof(rdesc)); ASSERT_OK(err); } @@ -855,6 +885,54 @@ TEST_F(hid_bpf, test_hid_attach_flags) ASSERT_EQ(buf[3], 3); } +static bool is_using_driver(struct __test_metadata *_metadata, struct uhid_device *hid, + const char *driver) +{ + char driver_line[512]; + char uevent[1024]; + char temp[512]; + int fd, nread; + bool found = false; + + sprintf(uevent, "/sys/bus/hid/devices/%04X:%04X:%04X.%04X/uevent", + hid->bus, hid->vid, hid->pid, hid->hid_id); + + fd = open(uevent, O_RDONLY | O_NONBLOCK); + if (fd < 0) { + TH_LOG("couldn't open '%s': %d, %d", uevent, fd, errno); + return false; + } + + sprintf(driver_line, "DRIVER=%s", driver); + + nread = read(fd, temp, ARRAY_SIZE(temp)); + if (nread > 0 && (strstr(temp, driver_line)) != NULL) + found = true; + + close(fd); + + return found; +} + +/* + * Attach hid_driver_probe to the given uhid device, + * check that the device is now using hid-generic. + */ +TEST_F(hid_bpf, test_hid_driver_probe) +{ + const struct test_program progs[] = { + { + .name = "hid_test_driver_probe", + }, + }; + + ASSERT_TRUE(is_using_driver(_metadata, &self->hid, "apple")); + + LOAD_PROGRAMS(progs); + + ASSERT_TRUE(is_using_driver(_metadata, &self->hid, "hid-generic")); +} + /* * Attach hid_rdesc_fixup to the given uhid device, * retrieve and open the matching hidraw node, diff --git a/tools/testing/selftests/hid/progs/hid.c b/tools/testing/selftests/hid/progs/hid.c index 5ecc845ef792..9b22e9a0e658 100644 --- a/tools/testing/selftests/hid/progs/hid.c +++ b/tools/testing/selftests/hid/progs/hid.c @@ -598,3 +598,15 @@ SEC(".struct_ops.link") struct hid_bpf_ops test_infinite_loop_input_report = { .hid_device_event = (void *)hid_test_infinite_loop_input_report, }; + +SEC("?struct_ops.s/hid_rdesc_fixup") +int BPF_PROG(hid_test_driver_probe, struct hid_bpf_ctx *hid_ctx) +{ + hid_ctx->hid->quirks |= HID_QUIRK_IGNORE_SPECIAL_DRIVER; + return 0; +} + +SEC(".struct_ops.link") +struct hid_bpf_ops test_driver_probe = { + .hid_rdesc_fixup = (void *)hid_test_driver_probe, +}; diff --git a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h index e5db897586bb..1a645684a117 100644 --- a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h +++ b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h @@ -84,10 +84,14 @@ struct hid_bpf_ops { struct hid_device *hdev; }; +#define BIT(n) (1U << n) + #ifndef BPF_F_BEFORE -#define BPF_F_BEFORE (1U << 3) +#define BPF_F_BEFORE BIT(3) #endif +#define HID_QUIRK_IGNORE_SPECIAL_DRIVERBIT(22) + /* following are kfuncs exported by HID for HID-BPF */ extern __u8 *hid_bpf_get_da
[PATCH HID v2 07/11] selftests/hid: allow to parametrize bus/vid/pid/rdesc on the test device
This will be useful to introduce variants in tests to test the interactions between HID-BPF and some kernel modules. Signed-off-by: Benjamin Tissoires --- no changes in v2 --- tools/testing/selftests/hid/hid_bpf.c| 2 +- tools/testing/selftests/hid/hid_common.h | 46 tools/testing/selftests/hid/hidraw.c | 2 +- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/tools/testing/selftests/hid/hid_bpf.c b/tools/testing/selftests/hid/hid_bpf.c index 17ccbf5ff4b5..7eb15da62bdc 100644 --- a/tools/testing/selftests/hid/hid_bpf.c +++ b/tools/testing/selftests/hid/hid_bpf.c @@ -58,7 +58,7 @@ FIXTURE_SETUP(hid_bpf) { int err; - err = setup_uhid(_metadata, &self->hid); + err = setup_uhid(_metadata, &self->hid, BUS_USB, 0x0001, 0x0a36, rdesc, sizeof(rdesc)); ASSERT_OK(err); } diff --git a/tools/testing/selftests/hid/hid_common.h b/tools/testing/selftests/hid/hid_common.h index a7d836a35bb1..f77f69c6657d 100644 --- a/tools/testing/selftests/hid/hid_common.h +++ b/tools/testing/selftests/hid/hid_common.h @@ -23,6 +23,9 @@ struct uhid_device { int dev_id; /* uniq (random) number to identify the device */ int uhid_fd; int hid_id; /* HID device id in the system */ + __u16 bus; + __u32 vid; + __u32 pid; pthread_t tid; /* thread for reading uhid events */ }; @@ -129,7 +132,9 @@ static int uhid_write(struct __test_metadata *_metadata, int fd, const struct uh } } -static int uhid_create(struct __test_metadata *_metadata, int fd, int rand_nb) +static int uhid_create(struct __test_metadata *_metadata, int fd, int rand_nb, + __u16 bus, __u32 vid, __u32 pid, __u8 *rdesc, + size_t rdesc_size) { struct uhid_event ev; char buf[25]; @@ -140,10 +145,10 @@ static int uhid_create(struct __test_metadata *_metadata, int fd, int rand_nb) ev.type = UHID_CREATE; strcpy((char *)ev.u.create.name, buf); ev.u.create.rd_data = rdesc; - ev.u.create.rd_size = sizeof(rdesc); - ev.u.create.bus = BUS_USB; - ev.u.create.vendor = 0x0001; - ev.u.create.product = 0x0a37; + ev.u.create.rd_size = rdesc_size; + ev.u.create.bus = bus; + ev.u.create.vendor = vid; + ev.u.create.product = pid; ev.u.create.version = 0; ev.u.create.country = 0; @@ -305,15 +310,17 @@ static int uhid_send_event(struct __test_metadata *_metadata, struct uhid_device return uhid_write(_metadata, hid->uhid_fd, &ev); } -static bool match_sysfs_device(int dev_id, const char *workdir, struct dirent *dir) +static bool match_sysfs_device(struct uhid_device *hid, const char *workdir, struct dirent *dir) { - const char *target = "0003:0001:0A37.*"; + char target[20] = ""; char phys[512]; char uevent[1024]; char temp[512]; int fd, nread; bool found = false; + snprintf(target, sizeof(target), "%04X:%04X:%04X.*", hid->bus, hid->vid, hid->pid); + if (fnmatch(target, dir->d_name, 0)) return false; @@ -324,7 +331,7 @@ static bool match_sysfs_device(int dev_id, const char *workdir, struct dirent *d if (fd < 0) return false; - sprintf(phys, "PHYS=%d", dev_id); + sprintf(phys, "PHYS=%d", hid->dev_id); nread = read(fd, temp, ARRAY_SIZE(temp)); if (nread > 0 && (strstr(temp, phys)) != NULL) @@ -335,7 +342,7 @@ static bool match_sysfs_device(int dev_id, const char *workdir, struct dirent *d return found; } -static int get_hid_id(int dev_id) +static int get_hid_id(struct uhid_device *hid) { const char *workdir = "/sys/devices/virtual/misc/uhid"; const char *str_id; @@ -350,10 +357,10 @@ static int get_hid_id(int dev_id) d = opendir(workdir); if (d) { while ((dir = readdir(d)) != NULL) { - if (!match_sysfs_device(dev_id, workdir, dir)) + if (!match_sysfs_device(hid, workdir, dir)) continue; - str_id = dir->d_name + sizeof("0003:0001:0A37."); + str_id = dir->d_name + sizeof("::."); found = (int)strtol(str_id, NULL, 16); break; @@ -367,7 +374,7 @@ static int get_hid_id(int dev_id) return found; } -static int get_hidraw(int dev_id) +static int get_hidraw(struct uhid_device *hid) { const char *workdir = "/sys/devices/virtual/misc/uhid"; char sysfs[1024]; @@ -384,7 +391,7 @@ static int get_hidraw(int dev_id)
Re: [PATCH net-next] page_pool: add a test module for page_pool
On 10/09/2024 12.46, Yunsheng Lin wrote: On 2024/9/10 1:28, Mina Almasry wrote: On Mon, Sep 9, 2024 at 2:25 AM Yunsheng Lin wrote: The testing is done by ensuring that the page allocated from the page_pool instance is pushed into a ptr_ring instance in a kthread/napi binded to a specified cpu, and a kthread/napi binded to a specified cpu will pop the page from the ptr_ring and free it back to the page_pool. Signed-off-by: Yunsheng Lin It seems this test is has a correctness part and a performance part. For the performance test, Jesper has out of tree tests for the page_pool: https://github.com/netoptimizer/prototype-kernel/blob/master/kernel/lib/bench_page_pool_simple.c I have these rebased on top of net-next and use them to verify devmem & memory-provider performance: https://github.com/mina/linux/commit/07fd1c04591395d15d83c07298b4d37f6b56157f Yes, I used that testing ko too when adding frag API support for page_pool. The main issue I remembered was that it only support x86:( Yes, because I've added ASM code for reading TSC counter in a very precise manor. Given we run many iterations, then I don't think we need this precise reading. I guess it can simply be replaced with get_cycles() or get_cycles64(). Then it should work on all archs. The code already supports wall-clock time via ktime_get() (specifically ktime_get_real_ts64()). My preference here (for the performance part) is to upstream the out-of-tree tests that Jesper (and probably others) are using, rather than adding a new performance test that is not as battle-hardened. I looked through the out-of-tree tests again, it seems we can take the best of them. For Jesper' ko: It seems we can do prefill as something that pp_fill_ptr_ring() does in bench_page_pool_simple.c to avoid the noise from the page allocator. For the ko in this patch: It uses NAPI instead of tasklet mimicking the NAPI context, support PP_FLAG_DMA_MAP flag testing, and return '-EAGAIN' in module_init() to use perf stat for collecting and calculating performance data. My bench don't return minus-number on module load, because I used perf record, and to see symbols decoded with perf report, I needed the module to be loaded. I started on reading the PMU counters[1] around the bench loop, it works if enabling PMU counters yourself/manually, but I never finished that work. [1] https://github.com/netoptimizer/prototype-kernel/blob/master/kernel/include/linux/time_bench.h#L195-L209 Is there other testcase or better practicing that we can learn from Jesper' out of tree ko? I created a time_bench.c [2] module that other modules [3] can use to easier reuse the benchmarking code in other modules. [2] https://github.com/netoptimizer/prototype-kernel/blob/master/kernel/lib/time_bench.c [3] https://github.com/netoptimizer/prototype-kernel/blob/master/kernel/lib/bench_page_pool_simple.c --Jesper
Re: [PATCH net-next] page_pool: add a test module for page_pool
On 2024/9/10 1:28, Mina Almasry wrote: > On Mon, Sep 9, 2024 at 2:25 AM Yunsheng Lin wrote: >> >> The testing is done by ensuring that the page allocated from >> the page_pool instance is pushed into a ptr_ring instance in >> a kthread/napi binded to a specified cpu, and a kthread/napi >> binded to a specified cpu will pop the page from the ptr_ring >> and free it back to the page_pool. >> >> Signed-off-by: Yunsheng Lin > > It seems this test is has a correctness part and a performance part. > For the performance test, Jesper has out of tree tests for the > page_pool: > https://github.com/netoptimizer/prototype-kernel/blob/master/kernel/lib/bench_page_pool_simple.c > > I have these rebased on top of net-next and use them to verify devmem > & memory-provider performance: > https://github.com/mina/linux/commit/07fd1c04591395d15d83c07298b4d37f6b56157f Yes, I used that testing ko too when adding frag API support for page_pool. The main issue I remembered was that it only support x86:( > > My preference here (for the performance part) is to upstream the > out-of-tree tests that Jesper (and probably others) are using, rather > than adding a new performance test that is not as battle-hardened. I looked through the out-of-tree tests again, it seems we can take the best of them. For Jesper' ko: It seems we can do prefill as something that pp_fill_ptr_ring() does in bench_page_pool_simple.c to avoid the noise from the page allocator. For the ko in this patch: It uses NAPI instead of tasklet mimicking the NAPI context, support PP_FLAG_DMA_MAP flag testing, and return '-EAGAIN' in module_init() to use perf stat for collecting and calculating performance data. Is there other testcase or better practicing that we can learn from Jesper' out of tree ko? > > -- > Thanks, > Mina >
[RESEND PATCH v2] list: test: Mending tests for list_cut_position()
Mending test for list_cut_position*() for the missing check of integer "i" after the second loop. The variable should be checked for second time to make sure both lists after the cut operation are formed as expected. Signed-off-by: I Hsin Cheng --- lib/list-test.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/lib/list-test.c b/lib/list-test.c index 37cbc33e9fdb..8d1d47a9fe9e 100644 --- a/lib/list-test.c +++ b/lib/list-test.c @@ -404,10 +404,13 @@ static void list_test_list_cut_position(struct kunit *test) KUNIT_EXPECT_EQ(test, i, 2); + i = 0; list_for_each(cur, &list1) { KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); i++; } + + KUNIT_EXPECT_EQ(test, i, 1); } static void list_test_list_cut_before(struct kunit *test) @@ -432,10 +435,13 @@ static void list_test_list_cut_before(struct kunit *test) KUNIT_EXPECT_EQ(test, i, 1); + i = 0; list_for_each(cur, &list1) { KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); i++; } + + KUNIT_EXPECT_EQ(test, i, 2); } static void list_test_list_splice(struct kunit *test) -- 2.43.0
[PATCH] list: test: Mending tests for list_cut_position()
Mending test for list_cut_position*() for the missing check of integer "i" after the second loop. The variable should be checked for second time to make sure both lists after the cut operation are formed as expected. Signed-off-by: I Hsin Cheng --- lib/list-test.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/lib/list-test.c b/lib/list-test.c index 37cbc33e9fdb..f59188fc2aca 100644 --- a/lib/list-test.c +++ b/lib/list-test.c @@ -404,10 +404,13 @@ static void list_test_list_cut_position(struct kunit *test) KUNIT_EXPECT_EQ(test, i, 2); + i = 0; list_for_each(cur, &list1) { KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); i++; } + + KUNIT_EXPECT_EQ(test, i, 1); } static void list_test_list_cut_before(struct kunit *test) @@ -432,10 +435,13 @@ static void list_test_list_cut_before(struct kunit *test) KUNIT_EXPECT_EQ(test, i, 1); + i = 0; list_for_each(cur, &list1) { KUNIT_EXPECT_PTR_EQ(test, cur, &entries[i]); i++; } + + KUNIT_EXPECT_EQ(i, 2); } static void list_test_list_splice(struct kunit *test) -- 2.43.0
[PATCH] list: test: Increasing coverage of list_test_list_replace*()
Increase the test coverage of list_test_list_replace*() by adding the checks to compare the pointer of "a_new.next" and "a_new.prev" to make sure a perfect circular doubly linked list is formed after the replacement. Signed-off-by: I Hsin Cheng --- lib/list-test.c | 4 1 file changed, 4 insertions(+) diff --git a/lib/list-test.c b/lib/list-test.c index 37cbc33e9fdb..e207c4c98d70 100644 --- a/lib/list-test.c +++ b/lib/list-test.c @@ -102,6 +102,8 @@ static void list_test_list_replace(struct kunit *test) /* now: [list] -> a_new -> b */ KUNIT_EXPECT_PTR_EQ(test, list.next, &a_new); KUNIT_EXPECT_PTR_EQ(test, b.prev, &a_new); + KUNIT_EXPECT_PTR_EQ(test, a_new.next, &b); + KUNIT_EXPECT_PTR_EQ(test, a_new.prev, &list); } static void list_test_list_replace_init(struct kunit *test) @@ -118,6 +120,8 @@ static void list_test_list_replace_init(struct kunit *test) /* now: [list] -> a_new -> b */ KUNIT_EXPECT_PTR_EQ(test, list.next, &a_new); KUNIT_EXPECT_PTR_EQ(test, b.prev, &a_new); + KUNIT_EXPECT_PTR_EQ(test, a_new.next, &b); + KUNIT_EXPECT_PTR_EQ(test, a_new.prev, &list); /* check a_old is empty (initialized) */ KUNIT_EXPECT_TRUE(test, list_empty_careful(&a_old)); -- 2.43.0
[PATCH RFC 3/3] selftest: gpio: Add a new set-get config test
Add a new kselftest that sets a configuration to a GPIO line and then gets it back to verify that it was correctly carried out by the driver. Setting a configuration is done through the GPIO uAPI, but retrieving it is done through the debugfs interface since that is the only place where it can be retrieved from userspace. The test reads the test plan from a YAML file, which includes the chips and pin settings to set and validate. Signed-off-by: Nícolas F. R. A. Prado --- tools/testing/selftests/gpio/Makefile | 2 +- .../gpio-set-get-config-example-test-plan.yaml | 15 ++ .../testing/selftests/gpio/gpio-set-get-config.py | 183 + 3 files changed, 199 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/gpio/Makefile b/tools/testing/selftests/gpio/Makefile index e0884390447d..bdfeb0c9aadd 100644 --- a/tools/testing/selftests/gpio/Makefile +++ b/tools/testing/selftests/gpio/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -TEST_PROGS := gpio-mockup.sh gpio-sim.sh +TEST_PROGS := gpio-mockup.sh gpio-sim.sh gpio-set-get-config.py TEST_FILES := gpio-mockup-sysfs.sh TEST_GEN_PROGS_EXTENDED := gpio-mockup-cdev gpio-chip-info gpio-line-name CFLAGS += -O2 -g -Wall $(KHDR_INCLUDES) diff --git a/tools/testing/selftests/gpio/gpio-set-get-config-example-test-plan.yaml b/tools/testing/selftests/gpio/gpio-set-get-config-example-test-plan.yaml new file mode 100644 index ..3b749be3c8dc --- /dev/null +++ b/tools/testing/selftests/gpio/gpio-set-get-config-example-test-plan.yaml @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +# Top-level contains a list of the GPIO chips that will be tested. Each one is +# chosen based on the GPIO chip's info label. +- label: "gpiochip_device_label" + # For each GPIO chip, multiple pin configurations can be tested, which are + # listed under 'tests' + tests: + # pin indicates the pin number to test + - pin: 34 +# bias can be 'pull-up', 'pull-down', 'disabled' +bias: "pull-up" + - pin: 34 +bias: "pull-down" + - pin: 34 +bias: "disabled" diff --git a/tools/testing/selftests/gpio/gpio-set-get-config.py b/tools/testing/selftests/gpio/gpio-set-get-config.py new file mode 100755 index ..6f1444c8d46b --- /dev/null +++ b/tools/testing/selftests/gpio/gpio-set-get-config.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2024 Collabora Ltd + +# +# This test validates GPIO pin configuration. It takes a test plan in YAML (see +# gpio-set-get-config-example-test-plan.yaml) and sets and gets back each pin +# configuration described in the plan and checks that they match in order to +# validate that they are being applied correctly. +# +# When the file name for the test plan is not provided through --test-plan, it +# will be guessed based on the platform ID (DT compatible or DMI). +# + +import time +import os +import sys +import argparse +import re +import subprocess +import glob +import signal + +import yaml + +# Allow ksft module to be imported from different directory +this_dir = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(this_dir, "../kselftest/")) + +import ksft + + +def config_pin(chip_dev, pin_config): +flags = [] +if pin_config.get("bias"): +flags += f"-b {pin_config['bias']}".split() +flags += ["-w", chip_dev, str(pin_config["pin"])] +gpio_mockup_cdev_path = os.path.join(this_dir, "gpio-mockup-cdev") +return subprocess.Popen([gpio_mockup_cdev_path] + flags) + + +def get_bias_debugfs(chip_debugfs_path, pin): +with open(os.path.join(chip_debugfs_path, "pinconf-pins")) as f: +for l in f: +m = re.match(rf"pin {pin}.*bias (?P(pull )?\w+)", l) +if m: +return m.group("bias") + + +def check_config_pin(chip, chip_debugfs_dir, pin_config): +test_passed = True + +if pin_config.get("bias"): +bias = get_bias_debugfs(chip_debugfs_dir, pin_config["pin"]) +# Convert "pull up" / "pull down" to "pull-up" / "pull-down" +bias = bias.replace(" ", "-") +if bias != pin_config["bias"]: +ksft.print_msg( +f"Bias doesn't match: Expected {pin_config['bias']}, read {bias}." +) +test_passed = False + +ksft.test_result( +test_passed, +f"{chip['label']}.{pin_config['pin']}.{pin_config['bias']}", +) + + +def get_devfs_chip_file(chip_dict): +gpio_chip_info_path = os.path.join(this_dir, 'gpio-chip-info') +for f in glob.glob("/dev/gpiochip*"): +proc = s
[PATCH RFC 0/3] Verify bias functionality for pinctrl_paris driver through new gpio test
This series was motivated by the regression fixed by 166bf8af9122 ("pinctrl: mediatek: common-v2: Fix broken bias-disable for PULL_PU_PD_RSEL_TYPE"). A bug was introduced in the pinctrl_paris driver which prevented certain pins from having their bias configured. Running this test on the mt8195-tomato platform with the test plan included below[1] shows the test passing with the fix applied, but failing without the fix: With fix: $ ./gpio-setget-config.py TAP version 13 # Using test plan file: ./google,tomato.yaml 1..3 ok 1 pinctrl_paris.34.pull-up ok 2 pinctrl_paris.34.pull-down ok 3 pinctrl_paris.34.disabled # Totals: pass:3 fail:0 xfail:0 xpass:0 skip:0 error:0 Without fix: $ ./gpio-setget-config.py TAP version 13 # Using test plan file: ./google,tomato.yaml 1..3 # Bias doesn't match: Expected pull-up, read pull-down. not ok 1 pinctrl_paris.34.pull-up ok 2 pinctrl_paris.34.pull-down # Bias doesn't match: Expected disabled, read pull-down. not ok 3 pinctrl_paris.34.disabled # Totals: pass:1 fail:2 xfail:0 xpass:0 skip:0 error:0 In order to achieve this, the first patch exposes bias configuration through the GPIO API in the pinctrl_paris driver, patch 2 extends the gpio-mockup-cdev utility for use by patch 3, and patch 3 introduces a new GPIO kselftest that takes a test plan in YAML, which can be tailored per-platform to specify the configurations to test, and sets and gets back each pin configuration to verify that they match and thus that the driver is behaving as expected. Since the GPIO uAPI only allows setting the pin configuration, getting it back is done through pinconf-pins in the pinctrl debugfs folder. The test currently only verifies bias but it would be easy to extend to verify other pin configurations. The test plan YAML file can be customized for each use-case and is platform-dependant. For that reason, only an example is included in patch 3 and the user is supposed to provide their test plan. That said, the aim is to collect test plans for ease of use at [2]. [1] This is the test plan used for mt8195-tomato: - label: "pinctrl_paris" tests: # Pin 34 has type MTK_PULL_PU_PD_RSEL_TYPE and is unused. # Setting bias to MTK_PULL_PU_PD_RSEL_TYPE pins was fixed by # 166bf8af9122 ("pinctrl: mediatek: common-v2: Fix broken bias-disable for PULL_PU_PD_RSEL_TYPE") - pin: 34 bias: "pull-up" - pin: 34 bias: "pull-down" - pin: 34 bias: "disabled" [2] https://github.com/kernelci/platform-test-parameters Signed-off-by: Nícolas F. R. A. Prado --- Nícolas F. R. A. Prado (3): pinctrl: mediatek: paris: Expose more configurations to GPIO set_config selftest: gpio: Add wait flag to gpio-mockup-cdev selftest: gpio: Add a new set-get config test drivers/pinctrl/mediatek/pinctrl-paris.c | 20 +-- tools/testing/selftests/gpio/Makefile | 2 +- tools/testing/selftests/gpio/gpio-mockup-cdev.c| 14 +- .../gpio-set-get-config-example-test-plan.yaml | 15 ++ .../testing/selftests/gpio/gpio-set-get-config.py | 183 + 5 files changed, 220 insertions(+), 14 deletions(-) --- base-commit: 6a7917c89f219f09b1d88d09f376000914a52763 change-id: 20240906-kselftest-gpio-set-get-config-6e5bb670c1a5 Best regards, -- Nícolas F. R. A. Prado
Re: [PATCH net-next] page_pool: add a test module for page_pool
On Mon, Sep 9, 2024 at 2:25 AM Yunsheng Lin wrote: > > The testing is done by ensuring that the page allocated from > the page_pool instance is pushed into a ptr_ring instance in > a kthread/napi binded to a specified cpu, and a kthread/napi > binded to a specified cpu will pop the page from the ptr_ring > and free it back to the page_pool. > > Signed-off-by: Yunsheng Lin It seems this test is has a correctness part and a performance part. For the performance test, Jesper has out of tree tests for the page_pool: https://github.com/netoptimizer/prototype-kernel/blob/master/kernel/lib/bench_page_pool_simple.c I have these rebased on top of net-next and use them to verify devmem & memory-provider performance: https://github.com/mina/linux/commit/07fd1c04591395d15d83c07298b4d37f6b56157f My preference here (for the performance part) is to upstream the out-of-tree tests that Jesper (and probably others) are using, rather than adding a new performance test that is not as battle-hardened. -- Thanks, Mina
[PATCH net-next] page_pool: add a test module for page_pool
The testing is done by ensuring that the page allocated from the page_pool instance is pushed into a ptr_ring instance in a kthread/napi binded to a specified cpu, and a kthread/napi binded to a specified cpu will pop the page from the ptr_ring and free it back to the page_pool. Signed-off-by: Yunsheng Lin --- tools/testing/selftests/net/Makefile | 3 + .../testing/selftests/net/page_pool/Makefile | 18 + .../selftests/net/page_pool/page_pool_test.c | 433 ++ tools/testing/selftests/net/test_page_pool.sh | 175 +++ 4 files changed, 629 insertions(+) create mode 100644 tools/testing/selftests/net/page_pool/Makefile create mode 100644 tools/testing/selftests/net/page_pool/page_pool_test.c create mode 100755 tools/testing/selftests/net/test_page_pool.sh diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index 27362e40eb37..4d4ddd853ef8 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -6,6 +6,8 @@ CFLAGS += -I../../../../usr/include/ $(KHDR_INCLUDES) # Additional include paths needed by kselftest.h CFLAGS += -I../ +TEST_GEN_MODS_DIR := page_pool + TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh \ rtnetlink.sh xfrm_policy.sh test_blackhole_dev.sh TEST_PROGS += fib_tests.sh fib-onlink-tests.sh pmtu.sh udpgso.sh ip_defrag.sh @@ -96,6 +98,7 @@ TEST_PROGS += fdb_flush.sh TEST_PROGS += fq_band_pktlimit.sh TEST_PROGS += vlan_hw_filter.sh TEST_PROGS += bpf_offload.py +TEST_PROGS += test_page_pool.sh TEST_FILES := settings TEST_FILES += in_netns.sh lib.sh net_helper.sh setup_loopback.sh setup_veth.sh diff --git a/tools/testing/selftests/net/page_pool/Makefile b/tools/testing/selftests/net/page_pool/Makefile new file mode 100644 index ..4380a70d6391 --- /dev/null +++ b/tools/testing/selftests/net/page_pool/Makefile @@ -0,0 +1,18 @@ +PAGE_POOL_TEST_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST) +KDIR ?= $(abspath $(PAGE_POOL_TEST_DIR)/../../../../..) + +ifeq ($(V),1) +Q = +else +Q = @ +endif + +MODULES = page_pool_test.ko + +obj-m += page_pool_test.o + +all: + +$(Q)make -C $(KDIR) M=$(PAGE_POOL_TEST_DIR) modules + +clean: + +$(Q)make -C $(KDIR) M=$(PAGE_POOL_TEST_DIR) clean diff --git a/tools/testing/selftests/net/page_pool/page_pool_test.c b/tools/testing/selftests/net/page_pool/page_pool_test.c new file mode 100644 index ..475b64f21b78 --- /dev/null +++ b/tools/testing/selftests/net/page_pool/page_pool_test.c @@ -0,0 +1,433 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Test module for page_pool + * + * Copyright (C) 2024 Yunsheng Lin + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct ptr_ring ptr_ring; +static int nr_objs = 512; +static atomic_t nthreads; +static struct completion wait; +static struct page_pool *test_pool; +static struct device *dev; +static u64 dma_mask = DMA_BIT_MASK(64); + +static int nr_test = 200; +module_param(nr_test, int, 0); +MODULE_PARM_DESC(nr_test, "number of iterations to test"); + +static bool test_frag; +module_param(test_frag, bool, 0); +MODULE_PARM_DESC(test_frag, "use frag API for testing"); + +static bool test_dma; +module_param(test_dma, bool, 0); +MODULE_PARM_DESC(test_dma, "enable dma mapping for testing"); + +static bool test_napi; +module_param(test_napi, bool, 0); +MODULE_PARM_DESC(test_napi, "use NAPI softirq for testing"); + +static bool test_direct; +module_param(test_direct, bool, 0); +MODULE_PARM_DESC(test_direct, "enable direct recycle for testing"); + +static int test_alloc_len = 2048; +module_param(test_alloc_len, int, 0); +MODULE_PARM_DESC(test_alloc_len, "alloc len for testing"); + +static int test_push_cpu; +module_param(test_push_cpu, int, 0); +MODULE_PARM_DESC(test_push_cpu, "test cpu for pushing page"); + +static int test_pop_cpu; +module_param(test_pop_cpu, int, 0); +MODULE_PARM_DESC(test_pop_cpu, "test cpu for popping page"); + +static void page_pool_test_dev_release(struct device *dev) +{ + kfree(dev); +} + +static struct page_pool *page_pool_test_create(void) +{ + struct page_pool_params page_pool_params = { + .pool_size = nr_objs, + .flags = 0, + .nid = cpu_to_mem(test_push_cpu), + }; + int ret; + + if (test_dma) { + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return ERR_PTR(-ENOMEM); + + dev->release = page_pool_test_dev_release; + dev->dma_mask = &dma_mask; + device_initialize(dev); + + ret = dev_set_name(dev, "page_pool_dev"); + if (ret) { + pr_err("page_pool_test dev_set_name() failed: %d\n", +
Re: [PATCH v2] selftests/futex: Create test for robust list
Hi André, kernel test robot noticed the following build warnings: [auto build test WARNING on tip/locking/core] [also build test WARNING on linus/master v6.11-rc6 next-20240906] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Andr-Almeida/selftests-futex-Create-test-for-robust-list/20240903-214428 base: tip/locking/core patch link: https://lore.kernel.org/r/20240903134033.816500-1-andrealmeid%40igalia.com patch subject: [PATCH v2] selftests/futex: Create test for robust list :: branch date: 4 days ago :: commit date: 4 days ago compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240907/202409071354.clw9rcwr-...@intel.com/reproduce) 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 | Closes: https://lore.kernel.org/r/202409071354.clw9rcwr-...@intel.com/ All warnings (new ones prefixed by >>): >> robust_list.c:117:44: warning: passing 'int *' to parameter of type >> 'unsigned int *' converts between pointers to integer types with different >> sign [-Wpointer-sign] 117 | if (atomic_compare_exchange_strong(futex, &zero, tid)) { | ^ /opt/cross/clang-617a15a9ea/lib/clang/18/include/stdatomic.h:144:112: note: expanded from macro 'atomic_compare_exchange_strong' 144 | #define atomic_compare_exchange_strong(object, expected, desired) __c11_atomic_compare_exchange_strong(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) | ^~~~ 1 warning generated. vim +117 tools/testing/selftests/futex/functional/robust_list.c 32807b4449f353 André Almeida 2024-09-03 101 32807b4449f353 André Almeida 2024-09-03 102 /* 32807b4449f353 André Almeida 2024-09-03 103 * A basic (and incomplete) mutex lock function with robustness 32807b4449f353 André Almeida 2024-09-03 104 */ 32807b4449f353 André Almeida 2024-09-03 105 static int mutex_lock(struct lock_struct *lock, struct robust_list_head *head, bool error_inject) 32807b4449f353 André Almeida 2024-09-03 106 { 32807b4449f353 André Almeida 2024-09-03 107_Atomic(unsigned int) *futex = &lock->futex; 32807b4449f353 André Almeida 2024-09-03 108int zero = 0, ret = -1; 32807b4449f353 André Almeida 2024-09-03 109pid_t tid = gettid(); 32807b4449f353 André Almeida 2024-09-03 110 32807b4449f353 André Almeida 2024-09-03 111/* 32807b4449f353 André Almeida 2024-09-03 112 * Set list_op_pending before starting the lock, so the kernel can catch 32807b4449f353 André Almeida 2024-09-03 113 * the case where the thread died during the lock operation 32807b4449f353 André Almeida 2024-09-03 114 */ 32807b4449f353 André Almeida 2024-09-03 115head->list_op_pending = &lock->list; 32807b4449f353 André Almeida 2024-09-03 116 32807b4449f353 André Almeida 2024-09-03 @117if (atomic_compare_exchange_strong(futex, &zero, tid)) { 32807b4449f353 André Almeida 2024-09-03 118/* 32807b4449f353 André Almeida 2024-09-03 119 * We took the lock, insert it in the robust list 32807b4449f353 André Almeida 2024-09-03 120 */ 32807b4449f353 André Almeida 2024-09-03 121struct robust_list *list = &head->list; 32807b4449f353 André Almeida 2024-09-03 122 32807b4449f353 André Almeida 2024-09-03 123/* Error injection to test list_op_pending */ 32807b4449f353 André Almeida 2024-09-03 124if (error_inject) 32807b4449f353 André Almeida 2024-09-03 125return 0; 32807b4449f353 André Almeida 2024-09-03 126 32807b4449f353 André Almeida 2024-09-03 127while (list->next != &head->list) 32807b4449f353 André Almeida 2024-09-03 128list = list->next; 32807b4449f353 André Almeida 2024-09-03 129 32807b4449f353 André Almeida 2024-09-03 130list->next = &lock->list; 32807b4449f353 André Almeida 2024-09-03 131lock->list.next = &head->list; 32807b4449f353 André Almeida 2024-09-03 132 32807b4449f353 André Almeida 2024-09-03 133ret = 0; 32807b4449f353 André Almeida 2024-09-03 134} else { 32807b4449f353 André Almeida 2024-09-03 135/* 32807b4449f353 André Almeida 2024-09-03 136 * We didn't take the lock, wait until the owner wakes (or dies)
Re: [PATCH 2/3] list: test: Add a test for hlist_cut_number()
On Wed, 4 Sept 2024 at 21:43, 'Zhen Lei' via KUnit Development wrote: > > Test cases cover all possible situations: > 1. The cut number is invalid: zero or negative > 2. Partially cut. > 3. Cut all. > 4. The cut number is greater than the number of nodes in the old list. > 5. The old list is empty. > > Signed-off-by: Zhen Lei > --- Thanks very much for the detailed test. It's great to see these kept up-to-date! Reviewed-by: David Gow Cheers, -- David > lib/list-test.c | 51 + > 1 file changed, 51 insertions(+) > > diff --git a/lib/list-test.c b/lib/list-test.c > index 37cbc33e9fdb380..3c60a6458545452 100644 > --- a/lib/list-test.c > +++ b/lib/list-test.c > @@ -1172,6 +1172,56 @@ static void hlist_test_for_each_entry_safe(struct > kunit *test) > KUNIT_EXPECT_TRUE(test, hlist_empty(&list)); > } > > +static void hlist_test_cut_number(struct kunit *test) > +{ > + struct hlist_node a[4], *last; > + HLIST_HEAD(old); > + HLIST_HEAD(new); > + int cnt; > + > + hlist_add_head(&a[3], &old); > + hlist_add_head(&a[2], &old); > + hlist_add_head(&a[1], &old); > + hlist_add_head(&a[0], &old); > + > + /* The cut number is less than 0 or zero */ > + cnt = hlist_cut_number(&new, &old, -1, &last); > + KUNIT_EXPECT_EQ(test, cnt, 0); > + KUNIT_EXPECT_EQ(test, hlist_count_nodes(&old), 4); > + cnt = hlist_cut_number(&new, &old, 0, &last); > + KUNIT_EXPECT_EQ(test, cnt, 0); > + KUNIT_EXPECT_EQ(test, hlist_count_nodes(&old), 4); > + > + /* The cut number is less than the number of nodes in the old list. */ > + cnt = hlist_cut_number(&new, &old, 2, &last); > + KUNIT_EXPECT_EQ(test, cnt, 2); > + KUNIT_EXPECT_EQ(test, hlist_count_nodes(&old), 2); > + KUNIT_EXPECT_EQ(test, hlist_count_nodes(&new), 2); > + KUNIT_EXPECT_PTR_EQ(test, last, &a[1]); > + hlist_splice_init(&new, last, &old); > + > + /* The cut number is equal to the number of nodes in the old list. */ > + cnt = hlist_cut_number(&new, &old, 4, &last); > + KUNIT_EXPECT_EQ(test, cnt, 4); > + KUNIT_EXPECT_TRUE(test, hlist_empty(&old)); > + KUNIT_EXPECT_EQ(test, hlist_count_nodes(&new), 4); > + KUNIT_EXPECT_PTR_EQ(test, last, &a[3]); > + hlist_splice_init(&new, last, &old); > + > + /* The cut number is greater than the number of nodes in the old > list. */ > + cnt = hlist_cut_number(&new, &old, 5, &last); > + KUNIT_EXPECT_EQ(test, cnt, 4); > + KUNIT_EXPECT_TRUE(test, hlist_empty(&old)); > + KUNIT_EXPECT_EQ(test, hlist_count_nodes(&new), 4); > + KUNIT_EXPECT_PTR_EQ(test, last, &a[3]); > + > + /* The old list is empty. */ > + cnt = hlist_cut_number(&new, &old, 1, &last); > + KUNIT_EXPECT_EQ(test, cnt, 0); > + KUNIT_EXPECT_TRUE(test, hlist_empty(&old)); > + KUNIT_EXPECT_TRUE(test, hlist_empty(&new)); > +} > + > > static struct kunit_case hlist_test_cases[] = { > KUNIT_CASE(hlist_test_init), > @@ -1192,6 +1242,7 @@ static struct kunit_case hlist_test_cases[] = { > KUNIT_CASE(hlist_test_for_each_entry_continue), > KUNIT_CASE(hlist_test_for_each_entry_from), > KUNIT_CASE(hlist_test_for_each_entry_safe), > + KUNIT_CASE(hlist_test_cut_number), > {}, > }; > > -- > 2.34.1 > > -- > You received this message because you are subscribed to the Google Groups > "KUnit Development" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to kunit-dev+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/kunit-dev/20240904134152.2141-3-thunder.leizhen%40huawei.com. smime.p7s Description: S/MIME Cryptographic Signature
[PATCH net-next v2 3/5] selftests: mptcp: reset the last TS before the first test
Just to slightly improve the precision of the duration of the first test. In mptcp_join.sh, the last append_prev_results is now done as soon as the last test is over: this will add the last result in the list, and get a more precise time for this last test. Reviewed-by: Mat Martineau Signed-off-by: Matthieu Baerts (NGI0) --- tools/testing/selftests/net/mptcp/mptcp_connect.sh | 2 ++ tools/testing/selftests/net/mptcp/mptcp_join.sh| 3 ++- tools/testing/selftests/net/mptcp/mptcp_sockopt.sh | 1 + tools/testing/selftests/net/mptcp/pm_netlink.sh| 2 ++ tools/testing/selftests/net/mptcp/simult_flows.sh | 1 + tools/testing/selftests/net/mptcp/userspace_pm.sh | 1 + 6 files changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh index f61e2f5870ea..49d90c4dbc01 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh @@ -847,6 +847,8 @@ stop_if_error() make_file "$cin" "client" make_file "$sin" "server" +mptcp_lib_subtests_last_ts_reset + check_mptcp_disabled stop_if_error "The kernel configuration is not valid for MPTCP" diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh index 43f8a9bd84c4..3564cd06643c 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_join.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh @@ -3959,9 +3959,11 @@ if [ ${#tests[@]} -eq 0 ]; then tests=("${all_tests_names[@]}") fi +mptcp_lib_subtests_last_ts_reset for subtests in "${tests[@]}"; do "${subtests}" done +append_prev_results if [ ${ret} -ne 0 ]; then echo @@ -3972,7 +3974,6 @@ if [ ${ret} -ne 0 ]; then echo fi -append_prev_results mptcp_lib_result_print_all_tap exit $ret diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh index 68899a303a1a..5e8d5b83e2d0 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh @@ -349,6 +349,7 @@ init make_file "$cin" "client" 1 make_file "$sin" "server" 1 trap cleanup EXIT +mptcp_lib_subtests_last_ts_reset run_tests $ns1 $ns2 10.0.1.1 run_tests $ns1 $ns2 dead:beef:1::1 diff --git a/tools/testing/selftests/net/mptcp/pm_netlink.sh b/tools/testing/selftests/net/mptcp/pm_netlink.sh index 2757378b1b13..2e6648a2b2c0 100755 --- a/tools/testing/selftests/net/mptcp/pm_netlink.sh +++ b/tools/testing/selftests/net/mptcp/pm_netlink.sh @@ -137,6 +137,8 @@ check() fi } +mptcp_lib_subtests_last_ts_reset + check "show_endpoints" "" "defaults addr list" default_limits="$(get_limits)" diff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh index f74e1c3c126d..8fa77c8e9b65 100755 --- a/tools/testing/selftests/net/mptcp/simult_flows.sh +++ b/tools/testing/selftests/net/mptcp/simult_flows.sh @@ -286,6 +286,7 @@ while getopts "bcdhi" option;do done setup +mptcp_lib_subtests_last_ts_reset run_test 10 10 0 0 "balanced bwidth" run_test 10 10 1 25 "balanced bwidth with unbalanced delay" diff --git a/tools/testing/selftests/net/mptcp/userspace_pm.sh b/tools/testing/selftests/net/mptcp/userspace_pm.sh index 9cb05978269d..3651f73451cf 100755 --- a/tools/testing/selftests/net/mptcp/userspace_pm.sh +++ b/tools/testing/selftests/net/mptcp/userspace_pm.sh @@ -150,6 +150,7 @@ mptcp_lib_events "${ns2}" "${client_evts}" client_evts_pid server_evts=$(mktemp) mptcp_lib_events "${ns1}" "${server_evts}" server_evts_pid sleep 0.5 +mptcp_lib_subtests_last_ts_reset print_title "Init" print_test "Created network namespaces ns1, ns2" -- 2.45.2
[PATCH 3/3] KVM: selftests: Add guest Intel PT test
Add a test that starts Intel PT traces on host and guest. The test requires support for Intel PT and having Host/Guest mode enabled i.e. kvm_intel module parameter pt_mode=1. Signed-off-by: Adrian Hunter --- tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/include/x86_64/processor.h | 1 + tools/testing/selftests/kvm/x86_64/intel_pt.c | 381 ++ 3 files changed, 383 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/intel_pt.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 48d32c5aa3eb..0722c5c384cc 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -79,6 +79,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/hyperv_features TEST_GEN_PROGS_x86_64 += x86_64/hyperv_ipi TEST_GEN_PROGS_x86_64 += x86_64/hyperv_svm_test TEST_GEN_PROGS_x86_64 += x86_64/hyperv_tlb_flush +TEST_GEN_PROGS_x86_64 += x86_64/intel_pt TEST_GEN_PROGS_x86_64 += x86_64/kvm_clock_test TEST_GEN_PROGS_x86_64 += x86_64/kvm_pv_test TEST_GEN_PROGS_x86_64 += x86_64/monitor_mwait_test diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h index a0c1440017bb..87f98d342e79 100644 --- a/tools/testing/selftests/kvm/include/x86_64/processor.h +++ b/tools/testing/selftests/kvm/include/x86_64/processor.h @@ -157,6 +157,7 @@ struct kvm_x86_cpu_feature { #defineX86_FEATURE_PCOMMIT KVM_X86_CPU_FEATURE(0x7, 0, EBX, 22) #defineX86_FEATURE_CLFLUSHOPT KVM_X86_CPU_FEATURE(0x7, 0, EBX, 23) #defineX86_FEATURE_CLWBKVM_X86_CPU_FEATURE(0x7, 0, EBX, 24) +#defineX86_FEATURE_INTEL_PTKVM_X86_CPU_FEATURE(0x7, 0, EBX, 25) #defineX86_FEATURE_UMIPKVM_X86_CPU_FEATURE(0x7, 0, ECX, 2) #defineX86_FEATURE_PKU KVM_X86_CPU_FEATURE(0x7, 0, ECX, 3) #defineX86_FEATURE_OSPKE KVM_X86_CPU_FEATURE(0x7, 0, ECX, 4) diff --git a/tools/testing/selftests/kvm/x86_64/intel_pt.c b/tools/testing/selftests/kvm/x86_64/intel_pt.c new file mode 100644 index ..94753b12936e --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/intel_pt.c @@ -0,0 +1,381 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * KVM guest Intel PT test + * + * Copyright (C) 2024, Intel Corporation. + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "kvm_util.h" +#include "test_util.h" +#include "processor.h" +#include "ucall_common.h" + +#define MEM_GPASZ_256M +/* Set PT_NR_PAGES to 1 to avoid single range errata on some processors */ +#define PT_NR_PAGES1 + +#define PT_CPUID_LEAVES2 +#define PT_CPUID_REGS_NUM 4 /* number of registers (eax, ebx, ecx, edx) */ + +/* Capability-related code is from the Kernel Intel PT driver */ +enum pt_capabilities { + PT_CAP_max_subleaf = 0, + PT_CAP_cr3_filtering, + PT_CAP_psb_cyc, + PT_CAP_ip_filtering, + PT_CAP_mtc, + PT_CAP_ptwrite, + PT_CAP_power_event_trace, + PT_CAP_event_trace, + PT_CAP_tnt_disable, + PT_CAP_topa_output, + PT_CAP_topa_multiple_entries, + PT_CAP_single_range_output, + PT_CAP_output_subsys, + PT_CAP_payloads_lip, + PT_CAP_num_address_ranges, + PT_CAP_mtc_periods, + PT_CAP_cycle_thresholds, + PT_CAP_psb_periods, +}; + +#define PT_CAP(_n, _l, _r, _m) \ + [PT_CAP_ ## _n] = { .name = __stringify(_n), .leaf = _l,\ + .reg = KVM_ ## _r, .mask = _m } + +static struct pt_cap_desc { + const char *name; + u32 leaf; + u8 reg; + u32 mask; +} pt_caps[] = { + PT_CAP(max_subleaf, 0, CPUID_EAX, 0x), + PT_CAP(cr3_filtering, 0, CPUID_EBX, BIT(0)), + PT_CAP(psb_cyc, 0, CPUID_EBX, BIT(1)), + PT_CAP(ip_filtering,0, CPUID_EBX, BIT(2)), + PT_CAP(mtc, 0, CPUID_EBX, BIT(3)), + PT_CAP(ptwrite, 0, CPUID_EBX, BIT(4)), + PT_CAP(power_event_trace, 0, CPUID_EBX, BIT(5)), + PT_CAP(event_trace, 0, CPUID_EBX, BIT(7)), + PT_CAP(tnt_disable, 0, CPUID_EBX, BIT(8)), + PT_CAP(topa_output, 0, CPUID_ECX, BIT(0)), + PT_CAP(topa_multiple_entries, 0, CPUID_ECX, BIT(1)), + PT_CAP(single_range_output, 0, CPUID_ECX, BIT(2)), + PT_CAP(output_subsys, 0, CPUID_ECX, BIT(3)), + PT_CAP(payloads_lip,0, CPUID_ECX, BIT(31)), + PT_CAP(num_address_ranges, 1, CPUID_EAX, 0x7), + PT_CAP(mtc_periods, 1, CPUID_EAX, 0x), + PT_CAP(cycle
[PATCH net-next v18 01/14] mm: page_frag: add a test module for page_frag
The testing is done by ensuring that the fragment allocated from a frag_frag_cache instance is pushed into a ptr_ring instance in a kthread binded to a specified cpu, and a kthread binded to a specified cpu will pop the fragment from the ptr_ring and free the fragment. CC: Alexander Duyck Signed-off-by: Yunsheng Lin Reviewed-by: Alexander Duyck --- tools/testing/selftests/mm/Makefile | 3 + tools/testing/selftests/mm/page_frag/Makefile | 18 ++ .../selftests/mm/page_frag/page_frag_test.c | 170 + tools/testing/selftests/mm/run_vmtests.sh | 8 + tools/testing/selftests/mm/test_page_frag.sh | 171 ++ 5 files changed, 370 insertions(+) create mode 100644 tools/testing/selftests/mm/page_frag/Makefile create mode 100644 tools/testing/selftests/mm/page_frag/page_frag_test.c create mode 100755 tools/testing/selftests/mm/test_page_frag.sh diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile index cfad627e8d94..e98ec779b2aa 100644 --- a/tools/testing/selftests/mm/Makefile +++ b/tools/testing/selftests/mm/Makefile @@ -36,6 +36,8 @@ MAKEFLAGS += --no-builtin-rules CFLAGS = -Wall -I $(top_srcdir) $(EXTRA_CFLAGS) $(KHDR_INCLUDES) $(TOOLS_INCLUDES) LDLIBS = -lrt -lpthread -lm +TEST_GEN_MODS_DIR := page_frag + TEST_GEN_FILES = cow TEST_GEN_FILES += compaction_test TEST_GEN_FILES += gup_longterm @@ -125,6 +127,7 @@ TEST_FILES += test_hmm.sh TEST_FILES += va_high_addr_switch.sh TEST_FILES += charge_reserved_hugetlb.sh TEST_FILES += hugetlb_reparenting_test.sh +TEST_FILES += test_page_frag.sh # required by charge_reserved_hugetlb.sh TEST_FILES += write_hugetlb_memory.sh diff --git a/tools/testing/selftests/mm/page_frag/Makefile b/tools/testing/selftests/mm/page_frag/Makefile new file mode 100644 index ..58dda74d50a3 --- /dev/null +++ b/tools/testing/selftests/mm/page_frag/Makefile @@ -0,0 +1,18 @@ +PAGE_FRAG_TEST_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST) +KDIR ?= $(abspath $(PAGE_FRAG_TEST_DIR)/../../../../..) + +ifeq ($(V),1) +Q = +else +Q = @ +endif + +MODULES = page_frag_test.ko + +obj-m += page_frag_test.o + +all: + +$(Q)make -C $(KDIR) M=$(PAGE_FRAG_TEST_DIR) modules + +clean: + +$(Q)make -C $(KDIR) M=$(PAGE_FRAG_TEST_DIR) clean diff --git a/tools/testing/selftests/mm/page_frag/page_frag_test.c b/tools/testing/selftests/mm/page_frag/page_frag_test.c new file mode 100644 index ..6d6f31936b10 --- /dev/null +++ b/tools/testing/selftests/mm/page_frag/page_frag_test.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Test module for page_frag cache + * + * Copyright (C) 2024 Yunsheng Lin + */ + +#include +#include +#include +#include +#include +#include + +static struct ptr_ring ptr_ring; +static int nr_objs = 512; +static atomic_t nthreads; +static struct completion wait; +static struct page_frag_cache test_nc; + +static int nr_test = 200; +module_param(nr_test, int, 0); +MODULE_PARM_DESC(nr_test, "number of iterations to test"); + +static bool test_align; +module_param(test_align, bool, 0); +MODULE_PARM_DESC(test_align, "use align API for testing"); + +static int test_alloc_len = 2048; +module_param(test_alloc_len, int, 0); +MODULE_PARM_DESC(test_alloc_len, "alloc len for testing"); + +static int test_push_cpu; +module_param(test_push_cpu, int, 0); +MODULE_PARM_DESC(test_push_cpu, "test cpu for pushing fragment"); + +static int test_pop_cpu; +module_param(test_pop_cpu, int, 0); +MODULE_PARM_DESC(test_pop_cpu, "test cpu for popping fragment"); + +static int page_frag_pop_thread(void *arg) +{ + struct ptr_ring *ring = arg; + int nr = nr_test; + + pr_info("page_frag pop test thread begins on cpu %d\n", + smp_processor_id()); + + while (nr > 0) { + void *obj = __ptr_ring_consume(ring); + + if (obj) { + nr--; + page_frag_free(obj); + } else { + cond_resched(); + } + } + + if (atomic_dec_and_test(&nthreads)) + complete(&wait); + + pr_info("page_frag pop test thread exits on cpu %d\n", + smp_processor_id()); + + return 0; +} + +static int page_frag_push_thread(void *arg) +{ + struct ptr_ring *ring = arg; + int nr = nr_test; + + pr_info("page_frag push test thread begins on cpu %d\n", + smp_processor_id()); + + while (nr > 0) { + void *va; + int ret; + + if (test_align) { + va = page_frag_alloc_align(&test_nc, test_alloc_len, + GFP_KERNEL, SMP_CACHE_BYTES); + + WARN_ONCE((unsigned long)va & (SMP_CACHE_BYTES - 1), + &quo
[PATCH v3 8/9] KVM: selftests: Add a CoCo-specific test for KVM_PRE_FAULT_MEMORY
From: Michael Roth SEV, SEV-ES, and SNP have a few corner cases where there is potential for KVM_PRE_FAULT_MEMORY to behave differently depending on when it is issued during initial guest setup. Exercising these various paths requires a bit more fine-grained control over when the KVM_PRE_FAULT_MEMORY requests are issued while setting up the guests. Since these CoCo-specific events are likely to be architecture-specific KST helpers, take the existing generic test in pre_fault_memory_test.c as a starting template, and then introduce an x86-specific version of it with expanded coverage for SEV, SEV-ES, and SNP. Since there's a reasonable chance that TDX could extend this for similar testing of TDX, give it a "coco-" prefix rather than an SEV-specific one. Signed-off-by: Michael Roth Co-developed-by: Pratik R. Sampat Signed-off-by: Pratik R. Sampat Tested-by: Peter Gonda Tested-by: Srikanth Aithal --- tools/testing/selftests/kvm/Makefile | 1 + .../kvm/x86_64/coco_pre_fault_memory_test.c | 314 ++ 2 files changed, 315 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/coco_pre_fault_memory_test.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 45cb70c048bb..7b97750a7d71 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -129,6 +129,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/amx_test TEST_GEN_PROGS_x86_64 += x86_64/max_vcpuid_cap_test TEST_GEN_PROGS_x86_64 += x86_64/triple_fault_event_test TEST_GEN_PROGS_x86_64 += x86_64/recalc_apic_map_test +TEST_GEN_PROGS_x86_64 += x86_64/coco_pre_fault_memory_test TEST_GEN_PROGS_x86_64 += access_tracking_perf_test TEST_GEN_PROGS_x86_64 += coalesced_io_test TEST_GEN_PROGS_x86_64 += demand_paging_test diff --git a/tools/testing/selftests/kvm/x86_64/coco_pre_fault_memory_test.c b/tools/testing/selftests/kvm/x86_64/coco_pre_fault_memory_test.c new file mode 100644 index ..c31a5f9e18f4 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/coco_pre_fault_memory_test.c @@ -0,0 +1,314 @@ +// SPDX-License-Identifier: GPL-2.0 +#include + +#include +#include +#include +#include "sev.h" + +/* Arbitrarily chosen values */ +#define TEST_SIZE (SZ_2M + PAGE_SIZE) +#define TEST_NPAGES(TEST_SIZE / PAGE_SIZE) +#define TEST_SLOT 10 +#define TEST_GPA 0x1ul +#define TEST_GVA 0x1ul + +enum prefault_snp_test_type { + /* Skip pre-faulting tests. */ + NO_PREFAULT_TYPE, + /* +* Issue KVM_PRE_FAULT_MEMORY for GFNs mapping non-private memory +* before finalizing the initial guest contents (e.g. via +* KVM_SEV_SNP_LAUNCH_FINISH for SNP guests). +* +* This should result in failure since KVM explicitly disallows +* KVM_PRE_FAULT_MEMORY from being issued prior to finalizing the +* initial guest contents. +*/ + PREFAULT_SHARED_BEFORE_FINALIZING, + /* +* Issue KVM_PRE_FAULT_MEMORY for GFNs mapping private memory +* before finalizing the initial guest contents (e.g. via +* KVM_SEV_SNP_LAUNCH_FINISH for SNP guests). +* +* This should result in failure since KVM explicitly disallows +* KVM_PRE_FAULT_MEMORY from being issued prior to finalizing the +* initial guest contents. +*/ + PREFAULT_PRIVATE_BEFORE_FINALIZING, + /* +* Issue KVM_PRE_FAULT_MEMORY for GFNs mapping shared/private +* memory after finalizing the initial guest contents +* (e.g. via * KVM_SEV_SNP_LAUNCH_FINISH for SNP guests). +* +* This should succeed since pre-faulting is supported for both +* non-private/private memory once the guest contents are finalized. +*/ + PREFAULT_PRIVATE_SHARED_AFTER_FINALIZING +}; + +static void guest_code_sev(void) +{ + int i; + + GUEST_ASSERT(rdmsr(MSR_AMD64_SEV) & MSR_AMD64_SEV_ENABLED); + + for (i = 0; i < TEST_NPAGES; i++) { + uint64_t *src = (uint64_t *)(TEST_GVA + i * PAGE_SIZE); + uint64_t val = *src; + + /* Validate the data stored in the pages */ + if ((i < TEST_NPAGES / 2 && val != i + 1) || + (i >= TEST_NPAGES / 2 && val != 0)) { + GUEST_FAIL("Inconsistent view of memory values in guest"); + } + } + + if (rdmsr(MSR_AMD64_SEV) & MSR_AMD64_SEV_ES_ENABLED) { + wrmsr(MSR_AMD64_SEV_ES_GHCB, GHCB_MSR_TERM_REQ); + __asm__ __volatile__("rep; vmmcall"); + GUEST_FAIL("This should be unreachable."); + } + + GUEST_DONE(); +} + +static void __pre_fault_memory(struct kvm_vcpu *vcpu, u64 gpa, u64 size, + u64 left, bool
[PATCH v3 6/9] KVM: selftests: SEV-SNP test for KVM_SEV_INIT2
Add SEV-SNP VM type to exercise the KVM_SEV_INIT2 call. Also ensure that SNP case is skipped for scenarios where CPUID supports it but KVM does not so that a failure is not reported for such cases. Signed-off-by: Pratik R. Sampat Tested-by: Peter Gonda Tested-by: Srikanth Aithal --- .../testing/selftests/kvm/x86_64/sev_init2_tests.c | 13 + 1 file changed, 13 insertions(+) diff --git a/tools/testing/selftests/kvm/x86_64/sev_init2_tests.c b/tools/testing/selftests/kvm/x86_64/sev_init2_tests.c index 3fb967f40c6a..3f8fb2cc3431 100644 --- a/tools/testing/selftests/kvm/x86_64/sev_init2_tests.c +++ b/tools/testing/selftests/kvm/x86_64/sev_init2_tests.c @@ -28,6 +28,7 @@ int kvm_fd; u64 supported_vmsa_features; bool have_sev_es; +bool have_snp; static int __sev_ioctl(int vm_fd, int cmd_id, void *data) { @@ -83,6 +84,9 @@ void test_vm_types(void) if (have_sev_es) test_init2(KVM_X86_SEV_ES_VM, &(struct kvm_sev_init){}); + if (have_snp) + test_init2(KVM_X86_SNP_VM, &(struct kvm_sev_init){}); + test_init2_invalid(0, &(struct kvm_sev_init){}, "VM type is KVM_X86_DEFAULT_VM"); if (kvm_check_cap(KVM_CAP_VM_TYPES) & BIT(KVM_X86_SW_PROTECTED_VM)) @@ -138,15 +142,24 @@ int main(int argc, char *argv[]) "sev-es: KVM_CAP_VM_TYPES (%x) does not match cpuid (checking %x)", kvm_check_cap(KVM_CAP_VM_TYPES), 1 << KVM_X86_SEV_ES_VM); + have_snp = kvm_check_cap(KVM_CAP_VM_TYPES) & BIT(KVM_X86_SNP_VM); + TEST_ASSERT(!have_snp || kvm_cpu_has(X86_FEATURE_SNP), + "sev-snp: KVM_CAP_VM_TYPES (%x) indicates SNP support (bit %d), but CPUID does not", + kvm_check_cap(KVM_CAP_VM_TYPES), KVM_X86_SNP_VM); + test_vm_types(); test_flags(KVM_X86_SEV_VM); if (have_sev_es) test_flags(KVM_X86_SEV_ES_VM); + if (have_snp) + test_flags(KVM_X86_SNP_VM); test_features(KVM_X86_SEV_VM, 0); if (have_sev_es) test_features(KVM_X86_SEV_ES_VM, supported_vmsa_features); + if (have_snp) + test_features(KVM_X86_SNP_VM, supported_vmsa_features); return 0; } -- 2.34.1
[PATCH v3 5/9] KVM: selftests: SNP IOCTL test
Introduce testing of SNP ioctl calls. Tests attributes such as flags, page types, and policies in various combinations along the SNP launch path. Signed-off-by: Pratik R. Sampat Tested-by: Peter Gonda Tested-by: Srikanth Aithal --- .../testing/selftests/kvm/include/kvm_util.h | 11 ++ .../selftests/kvm/x86_64/sev_smoke_test.c | 140 +- 2 files changed, 150 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h index bc7c242480d6..ab213708b551 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -912,6 +912,17 @@ static inline struct kvm_vm *vm_create(uint32_t nr_runnable_vcpus) return __vm_create(VM_SHAPE_DEFAULT, nr_runnable_vcpus, 0); } +static inline struct kvm_vm *vm_create_type(unsigned long type, + uint32_t nr_runnable_vcpus) +{ + const struct vm_shape shape = { + .mode = VM_MODE_DEFAULT, + .type = type, + }; + + return __vm_create(shape, nr_runnable_vcpus, 0); +} + struct kvm_vm *__vm_create_with_vcpus(struct vm_shape shape, uint32_t nr_vcpus, uint64_t extra_mem_pages, void *guest_code, struct kvm_vcpu *vcpus[]); diff --git a/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c b/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c index 5fa4ee27609b..9a7efbe214ce 100644 --- a/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c +++ b/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c @@ -224,13 +224,151 @@ static void test_sev_launch(void *guest_code, uint32_t type, uint64_t policy) kvm_vm_free(vm); } +static int __test_snp_launch_start(uint32_t type, uint64_t policy, + uint8_t flags, bool assert) +{ + struct kvm_vm *vm; + int ret = 0; + + vm = vm_create_type(type, 1); + ret = __snp_vm_launch_start(vm, policy, flags); + if (assert) + TEST_ASSERT_VM_VCPU_IOCTL(!ret, KVM_SEV_SNP_LAUNCH_START, ret, vm); + kvm_vm_free(vm); + + return ret; +} + +static void test_snp_launch_start(uint32_t type, uint64_t policy) +{ + uint8_t i; + int ret; + + /* Flags must be zero for success */ + __test_snp_launch_start(type, policy, 0, true); + + for (i = 1; i < 8; i++) { + ret = __test_snp_launch_start(type, policy, BIT(i), false); + TEST_ASSERT(ret && errno == EINVAL, + "KVM_SEV_SNP_LAUNCH_START should fail, invalid flag\n" + "(type: %d policy: 0x%lx, flag: 0x%lx)", + type, policy, BIT(i)); + } + + ret = __test_snp_launch_start(type, SNP_POLICY_SMT, 0, false); + TEST_ASSERT(ret && errno == EINVAL, + "KVM_SEV_SNP_LAUNCH_START should fail, SNP_POLICY_RSVD_MBO policy bit not set\n" + "(type: %d policy: 0x%llx, flags: 0x0)", + type, SNP_POLICY_SMT); + + ret = __test_snp_launch_start(type, SNP_POLICY_RSVD_MBO, 0, false); + if (unlikely(!is_smt_active())) { + TEST_ASSERT(!ret, + "KVM_SEV_SNP_LAUNCH_START should succeed, SNP_POLICY_SMT not required on non-SMT systems\n" + "(type: %d policy: 0x%llx, flags: 0x0)", + type, SNP_POLICY_RSVD_MBO); + } else { + TEST_ASSERT(ret && errno == EINVAL, + "KVM_SEV_SNP_LAUNCH_START should fail, SNP_POLICY_SMT is not set on a SMT system\n" + "(type: %d policy: 0x%llx, flags: 0x0)", + type, SNP_POLICY_RSVD_MBO); + } + + ret = __test_snp_launch_start(type, SNP_POLICY | + SNP_FW_VER_MAJOR(UINT8_MAX) | + SNP_FW_VER_MINOR(UINT8_MAX), 0, false); + TEST_ASSERT(ret && errno == EIO, + "KVM_SEV_SNP_LAUNCH_START should fail, invalid version\n" + "expected: %d.%d got: %d.%d (type: %d policy: 0x%llx, flags: 0x0)", + SNP_FW_REQ_VER_MAJOR, SNP_FW_REQ_VER_MINOR, + UINT8_MAX, UINT8_MAX, type, + SNP_POLICY | SNP_FW_VER_MAJOR(UINT8_MAX) | SNP_FW_VER_MINOR(UINT8_MAX)); +} + +static void test_snp_launch_update(uint32_t type, uint64_t policy) +{ + struct kvm_vm *vm; + int ret; + + for (int pgtype = 0; pgtype <= KVM_SEV_SNP_PAGE_TYPE_CPUID + 1; pgtype++) { + vm = vm_create_type(type, 1); + snp_vm_launch_start(vm, policy); + ret = __snp_vm_launch_update(vm, pgtype); + + switch (pgtype) { + case KVM_SEV_SNP_PAGE_TYPE_NORMAL: + case KVM_SEV_SNP_PAGE_TYPE_ZERO: + case KVM_
[PATCH v3 4/9] KVM: selftests: SEV IOCTL test
Introduce tests for sev and sev-es ioctl that exercises the boot path of launch, update and finish on an invalid policy. Signed-off-by: Pratik R. Sampat Tested-by: Peter Gonda Tested-by: Srikanth Aithal --- .../selftests/kvm/x86_64/sev_smoke_test.c | 84 +++ 1 file changed, 84 insertions(+) diff --git a/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c b/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c index 8e798f5a2a53..5fa4ee27609b 100644 --- a/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c +++ b/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c @@ -142,12 +142,96 @@ static void test_sync_vmsa(uint32_t type, uint64_t policy) kvm_vm_free(vm); } +static void sev_guest_neg_status_assert(struct kvm_vm *vm, uint32_t type) +{ + struct kvm_sev_guest_status status; + int ret; + + ret = __vm_sev_ioctl(vm, KVM_SEV_GUEST_STATUS, &status); + TEST_ASSERT(ret, "KVM_SEV_GUEST_STATUS should fail, invalid VM Type."); +} + +static void vm_sev_es_launch_neg(struct kvm_vm *vm, uint32_t type, uint64_t policy) +{ + int ret; + + /* Launch start with policy SEV_POLICY_NO_DBG (0x0) */ + ret = __sev_vm_launch_start(vm, 0); + TEST_ASSERT(ret, + "KVM_SEV_LAUNCH_START should fail due to type (%d) - policy(0x0) mismatch", + type); + + ret = __sev_vm_launch_update(vm, policy); + TEST_ASSERT(ret, + "KVM_SEV_LAUNCH_UPDATE should fail due to LAUNCH_START. type: %d policy: 0x%lx", + type, policy); + sev_guest_neg_status_assert(vm, type); + + ret = __sev_vm_launch_measure(vm, alloca(256)); + TEST_ASSERT(ret, + "KVM_SEV_LAUNCH_UPDATE should fail due to LAUNCH_START. type: %d policy: 0x%lx", + type, policy); + sev_guest_neg_status_assert(vm, type); + + ret = __sev_vm_launch_finish(vm); + TEST_ASSERT(ret, + "KVM_SEV_LAUNCH_UPDATE should fail due to LAUNCH_START. type: %d policy: 0x%lx", + type, policy); + sev_guest_neg_status_assert(vm, type); +} + +/* + * Test for SEV ioctl launch path + * VMs of the type SEV and SEV-ES are created, however they are launched with + * an empty policy to observe the effect on the control flow of launching a VM. + * + * SEV - Expected to pass through the path of launch start, update, measure, + * and finish. vcpu_run expected to fail with error KVM_EXIT_IO. + * + * SEV-ES - Expected to fail the launch start as vm created with type + * KVM_X86_DEFAULT_VM but policy passed to launch start is KVM_X86_SEV_ES_VM. + * Post this, calls that pass the correct policy to update, measure, and finish + * are also expected to fail cascading. + */ +static void test_sev_launch(void *guest_code, uint32_t type, uint64_t policy) +{ + struct kvm_vcpu *vcpu; + int exp_exit_reason; + struct kvm_vm *vm; + struct ucall uc; + + vm = vm_sev_create_with_one_vcpu(type, guest_code, &vcpu); + + if (type == KVM_X86_SEV_VM) { + sev_vm_launch(vm, 0); + sev_vm_launch_measure(vm, alloca(256)); + sev_vm_launch_finish(vm); + } else { + vm_sev_es_launch_neg(vm, type, policy); + } + + vcpu_run(vcpu); + get_ucall(vcpu, &uc); + if (type == KVM_X86_SEV_VM) + exp_exit_reason = KVM_EXIT_IO; + else + exp_exit_reason = KVM_EXIT_FAIL_ENTRY; + + TEST_ASSERT(vcpu->run->exit_reason == exp_exit_reason, + "vcpu_run failed exit expected: %d, got: %d", + exp_exit_reason, vcpu->run->exit_reason); + + kvm_vm_free(vm); +} + static void test_sev(void *guest_code, uint32_t type, uint64_t policy) { struct kvm_vcpu *vcpu; struct kvm_vm *vm; struct ucall uc; + test_sev_launch(guest_code, type, policy); + vm = vm_sev_create_with_one_vcpu(type, guest_code, &vcpu); /* TODO: Validate the measurement is as expected. */ -- 2.34.1
[PATCH v3 2/9] KVM: selftests: Add a basic SNP smoke test
Extend sev_smoke_test to also run a minimal SEV-SNP smoke test that initializes and sets up private memory regions required to run a simple SEV-SNP guest. Similar to its SEV-ES smoke test counterpart, this also does not support GHCB and ucall yet and uses the GHCB MSR protocol to trigger an exit of the type KVM_EXIT_SYSTEM_EVENT. Also, decouple policy and type and require functions to provide both such that there is no assumption regarding the type using policy. Signed-off-by: Pratik R. Sampat Tested-by: Peter Gonda Tested-by: Srikanth Aithal --- .../selftests/kvm/include/x86_64/processor.h | 1 + .../selftests/kvm/include/x86_64/sev.h| 54 +++- tools/testing/selftests/kvm/lib/kvm_util.c| 8 +- .../selftests/kvm/lib/x86_64/processor.c | 6 +- tools/testing/selftests/kvm/lib/x86_64/sev.c | 116 +- .../selftests/kvm/x86_64/sev_smoke_test.c | 67 -- 6 files changed, 230 insertions(+), 22 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h index e247f99e0473..1dfa2c03b40f 100644 --- a/tools/testing/selftests/kvm/include/x86_64/processor.h +++ b/tools/testing/selftests/kvm/include/x86_64/processor.h @@ -199,6 +199,7 @@ struct kvm_x86_cpu_feature { #defineX86_FEATURE_VGIFKVM_X86_CPU_FEATURE(0x800A, 0, EDX, 16) #define X86_FEATURE_SEVKVM_X86_CPU_FEATURE(0x801F, 0, EAX, 1) #define X86_FEATURE_SEV_ES KVM_X86_CPU_FEATURE(0x801F, 0, EAX, 3) +#define X86_FEATURE_SNPKVM_X86_CPU_FEATURE(0x801F, 0, EAX, 4) /* * KVM defined paravirt features. diff --git a/tools/testing/selftests/kvm/include/x86_64/sev.h b/tools/testing/selftests/kvm/include/x86_64/sev.h index 3998152cc081..658c3cca208d 100644 --- a/tools/testing/selftests/kvm/include/x86_64/sev.h +++ b/tools/testing/selftests/kvm/include/x86_64/sev.h @@ -22,8 +22,21 @@ enum sev_guest_state { SEV_GUEST_STATE_RUNNING, }; +/* Minimum firmware version required for the SEV-SNP support */ +#define SNP_FW_REQ_VER_MAJOR 1 +#define SNP_FW_REQ_VER_MINOR 51 +#define SNP_POLICY_MINOR_BIT 0 +#define SNP_POLICY_MAJOR_BIT 8 + #define SEV_POLICY_NO_DBG (1UL << 0) #define SEV_POLICY_ES (1UL << 2) +#define SNP_POLICY_SMT (1ULL << 16) +#define SNP_POLICY_RSVD_MBO(1ULL << 17) +#define SNP_POLICY_DBG (1ULL << 19) +#define SNP_POLICY (SNP_POLICY_SMT | SNP_POLICY_RSVD_MBO) + +#define SNP_FW_VER_MAJOR(maj) ((uint8_t)(maj) << SNP_POLICY_MAJOR_BIT) +#define SNP_FW_VER_MINOR(min) ((uint8_t)(min) << SNP_POLICY_MINOR_BIT) #define GHCB_MSR_TERM_REQ 0x100 @@ -32,14 +45,22 @@ int __sev_vm_launch_start(struct kvm_vm *vm, uint32_t policy); int __sev_vm_launch_update(struct kvm_vm *vm, uint32_t policy); int __sev_vm_launch_measure(struct kvm_vm *vm, uint8_t *measurement); int __sev_vm_launch_finish(struct kvm_vm *vm); +int __snp_vm_launch_start(struct kvm_vm *vm, uint64_t policy, uint8_t flags); +int __snp_vm_launch_update(struct kvm_vm *vm, uint8_t page_type); +int __snp_vm_launch_finish(struct kvm_vm *vm, uint16_t flags); void sev_vm_launch(struct kvm_vm *vm, uint32_t policy); void sev_vm_launch_measure(struct kvm_vm *vm, uint8_t *measurement); void sev_vm_launch_finish(struct kvm_vm *vm); +void snp_vm_launch_start(struct kvm_vm *vm, uint64_t policy); +void snp_vm_launch_update(struct kvm_vm *vm); +void snp_vm_launch_finish(struct kvm_vm *vm); + +bool is_kvm_snp_supported(void); struct kvm_vm *vm_sev_create_with_one_vcpu(uint32_t type, void *guest_code, struct kvm_vcpu **cpu); -void vm_sev_launch(struct kvm_vm *vm, uint32_t policy, uint8_t *measurement); +void vm_sev_launch(struct kvm_vm *vm, uint64_t policy, uint8_t *measurement); kvm_static_assert(SEV_RET_SUCCESS == 0); @@ -74,8 +95,18 @@ kvm_static_assert(SEV_RET_SUCCESS == 0); __TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, vm); \ }) +/* Ensure policy is within bounds for SEV, SEV-ES */ +#define ASSERT_SEV_POLICY(type, policy)\ +({ \ + if (type == KVM_X86_SEV_VM || type == KVM_X86_SEV_ES_VM) { \ + TEST_ASSERT(policy < ((uint32_t)~0U), \ + "Policy beyond bounds for SEV");\ + } \ +}) \ + void sev_vm_init(struct kvm_vm *vm); void sev_es_vm_init(struct kvm_vm *vm); +void snp_vm_init(struct kvm_vm *vm); static inline void sev_register_encrypted_memory(struct kvm_vm *vm, struct userspace_mem_region *region) @@ -99,6 +130,
[PATCH 10/18] kunit: string-stream-test: Include instead of
Usage of pseudo-random functions requires inclusion of header instead of . Signed-off-by: Uros Bizjak Cc: Brendan Higgins Cc: David Gow Cc: Rae Moar Cc: linux-kselft...@vger.kernel.org Cc: kunit-...@googlegroups.com --- lib/kunit/string-stream-test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/kunit/string-stream-test.c b/lib/kunit/string-stream-test.c index 7511442ea98f..7734e33156f9 100644 --- a/lib/kunit/string-stream-test.c +++ b/lib/kunit/string-stream-test.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include -- 2.46.0
Re: [PATCH v2] selftests/futex: Create test for robust list
On 9/3/24 07:40, André Almeida wrote: Create a test for the robust list mechanism. What does this test - can you elaborate on the testing details? It will help reviewers catch if any tests are missed or not - be able to review the patch. Include output from the test in the chane log. Signed-off-by: André Almeida --- Changes from v1: - Change futex type from int to _Atomic(unsigned int) - Use old futex(FUTEX_WAIT) instead of the new sys_futex_wait() --- .../selftests/futex/functional/.gitignore | 1 + .../selftests/futex/functional/Makefile | 3 +- .../selftests/futex/functional/robust_list.c | 448 ++ 3 files changed, 451 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/futex/functional/robust_list.c diff --git a/tools/testing/selftests/futex/functional/.gitignore b/tools/testing/selftests/futex/functional/.gitignore index fbcbdb6963b3..4726e1be7497 100644 --- a/tools/testing/selftests/futex/functional/.gitignore +++ b/tools/testing/selftests/futex/functional/.gitignore @@ -9,3 +9,4 @@ futex_wait_wouldblock futex_wait futex_requeue futex_waitv +robust_list diff --git a/tools/testing/selftests/futex/functional/Makefile b/tools/testing/selftests/futex/functional/Makefile index f79f9bac7918..b8635a1ac7f6 100644 --- a/tools/testing/selftests/futex/functional/Makefile +++ b/tools/testing/selftests/futex/functional/Makefile @@ -17,7 +17,8 @@ TEST_GEN_PROGS := \ futex_wait_private_mapped_file \ futex_wait \ futex_requeue \ - futex_waitv + futex_waitv \ + robust_list TEST_PROGS := run.sh diff --git a/tools/testing/selftests/futex/functional/robust_list.c b/tools/testing/selftests/futex/functional/robust_list.c new file mode 100644 index ..9308eb189d48 --- /dev/null +++ b/tools/testing/selftests/futex/functional/robust_list.c @@ -0,0 +1,448 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2024 Igalia S.L. + * + * Robust list test by André Almeida + * + * The robust list uAPI allows userspace to create "robust" locks, in the sense + * that if the lock holder thread dies, the remaining threads that are waiting + * for the lock won't block forever, waiting for a lock that will never be + * released. + * + * This is achieve by userspace setting a list where a thread can enter all the + * locks (futexes) that it is holding. The robust list is a linked list, and + * userspace register the start of the list with the syscall set_robust_list(). + * If such thread eventually dies, the kernel will walk this list, waking up one + * thread waiting for each futex and marking the futex word with the flag + * FUTEX_OWNER_DIED. + * + * See also + * man set_robust_list + * Documententation/locking/robust-futex-ABI.rst + * Documententation/locking/robust-futexes.rst + */ + +#define _GNU_SOURCE + +#include "../../kselftest_harness.h" futex test suite doesn't kselftest_harness at the moment. Let's not mix and match the framework in the same test suite. Keep it consistent. thanks, -- Shuah
Re: [PATCH net-next v17 01/14] mm: page_frag: add a test module for page_frag
On Mon, Sep 2, 2024 at 5:09 AM Yunsheng Lin wrote: > > The testing is done by ensuring that the fragment allocated > from a frag_frag_cache instance is pushed into a ptr_ring > instance in a kthread binded to a specified cpu, and a kthread > binded to a specified cpu will pop the fragment from the > ptr_ring and free the fragment. > > CC: Alexander Duyck > Signed-off-by: Yunsheng Lin > --- > tools/testing/selftests/mm/Makefile | 3 + > tools/testing/selftests/mm/page_frag/Makefile | 18 ++ > .../selftests/mm/page_frag/page_frag_test.c | 170 + > tools/testing/selftests/mm/run_vmtests.sh | 8 + > tools/testing/selftests/mm/test_page_frag.sh | 171 ++ > 5 files changed, 370 insertions(+) > create mode 100644 tools/testing/selftests/mm/page_frag/Makefile > create mode 100644 tools/testing/selftests/mm/page_frag/page_frag_test.c > create mode 100755 tools/testing/selftests/mm/test_page_frag.sh > ... > diff --git a/tools/testing/selftests/mm/test_page_frag.sh > b/tools/testing/selftests/mm/test_page_frag.sh > new file mode 100755 > index ..d2b0734a90b5 > --- /dev/null > +++ b/tools/testing/selftests/mm/test_page_frag.sh > @@ -0,0 +1,171 @@ ... > +check_test_requirements() > +{ > + uid=$(id -u) > + if [ $uid -ne 0 ]; then > + echo "$0: Must be run as root" > + exit $ksft_skip > + fi > + > + if ! which insmod > /dev/null 2>&1; then > + echo "$0: You need insmod installed" > + exit $ksft_skip > + fi > + > + if [ ! -f $DRIVER ]; then > + echo "$0: You need to compile page_frag_test module" > + exit $ksft_skip > + fi > +} > + > +run_nonaligned_check() > +{ > + echo "Run performance tests to evaluate how fast nonaligned alloc API > is." > + > + insmod $DRIVER $NONALIGNED_PARAM > /dev/null 2>&1 > + echo "Done." > + echo "Ccheck the kernel ring buffer to see the summary." Typo, should be "Check". > +} > + > +run_aligned_check() > +{ > + echo "Run performance tests to evaluate how fast aligned alloc API > is." > + > + insmod $DRIVER $ALIGNED_PARAM > /dev/null 2>&1 > + echo "Done." > + echo "Check the kernel ring buffer to see the summary." > +} > + Other than the one typo it looks fine to me. Reviewed-by: Alexander Duyck
[PATCH 2/3] list: test: Add a test for hlist_cut_number()
Test cases cover all possible situations: 1. The cut number is invalid: zero or negative 2. Partially cut. 3. Cut all. 4. The cut number is greater than the number of nodes in the old list. 5. The old list is empty. Signed-off-by: Zhen Lei --- lib/list-test.c | 51 + 1 file changed, 51 insertions(+) diff --git a/lib/list-test.c b/lib/list-test.c index 37cbc33e9fdb380..3c60a6458545452 100644 --- a/lib/list-test.c +++ b/lib/list-test.c @@ -1172,6 +1172,56 @@ static void hlist_test_for_each_entry_safe(struct kunit *test) KUNIT_EXPECT_TRUE(test, hlist_empty(&list)); } +static void hlist_test_cut_number(struct kunit *test) +{ + struct hlist_node a[4], *last; + HLIST_HEAD(old); + HLIST_HEAD(new); + int cnt; + + hlist_add_head(&a[3], &old); + hlist_add_head(&a[2], &old); + hlist_add_head(&a[1], &old); + hlist_add_head(&a[0], &old); + + /* The cut number is less than 0 or zero */ + cnt = hlist_cut_number(&new, &old, -1, &last); + KUNIT_EXPECT_EQ(test, cnt, 0); + KUNIT_EXPECT_EQ(test, hlist_count_nodes(&old), 4); + cnt = hlist_cut_number(&new, &old, 0, &last); + KUNIT_EXPECT_EQ(test, cnt, 0); + KUNIT_EXPECT_EQ(test, hlist_count_nodes(&old), 4); + + /* The cut number is less than the number of nodes in the old list. */ + cnt = hlist_cut_number(&new, &old, 2, &last); + KUNIT_EXPECT_EQ(test, cnt, 2); + KUNIT_EXPECT_EQ(test, hlist_count_nodes(&old), 2); + KUNIT_EXPECT_EQ(test, hlist_count_nodes(&new), 2); + KUNIT_EXPECT_PTR_EQ(test, last, &a[1]); + hlist_splice_init(&new, last, &old); + + /* The cut number is equal to the number of nodes in the old list. */ + cnt = hlist_cut_number(&new, &old, 4, &last); + KUNIT_EXPECT_EQ(test, cnt, 4); + KUNIT_EXPECT_TRUE(test, hlist_empty(&old)); + KUNIT_EXPECT_EQ(test, hlist_count_nodes(&new), 4); + KUNIT_EXPECT_PTR_EQ(test, last, &a[3]); + hlist_splice_init(&new, last, &old); + + /* The cut number is greater than the number of nodes in the old list. */ + cnt = hlist_cut_number(&new, &old, 5, &last); + KUNIT_EXPECT_EQ(test, cnt, 4); + KUNIT_EXPECT_TRUE(test, hlist_empty(&old)); + KUNIT_EXPECT_EQ(test, hlist_count_nodes(&new), 4); + KUNIT_EXPECT_PTR_EQ(test, last, &a[3]); + + /* The old list is empty. */ + cnt = hlist_cut_number(&new, &old, 1, &last); + KUNIT_EXPECT_EQ(test, cnt, 0); + KUNIT_EXPECT_TRUE(test, hlist_empty(&old)); + KUNIT_EXPECT_TRUE(test, hlist_empty(&new)); +} + static struct kunit_case hlist_test_cases[] = { KUNIT_CASE(hlist_test_init), @@ -1192,6 +1242,7 @@ static struct kunit_case hlist_test_cases[] = { KUNIT_CASE(hlist_test_for_each_entry_continue), KUNIT_CASE(hlist_test_for_each_entry_from), KUNIT_CASE(hlist_test_for_each_entry_safe), + KUNIT_CASE(hlist_test_cut_number), {}, }; -- 2.34.1
[PATCH v2] selftests/futex: Create test for robust list
Create a test for the robust list mechanism. Signed-off-by: André Almeida --- Changes from v1: - Change futex type from int to _Atomic(unsigned int) - Use old futex(FUTEX_WAIT) instead of the new sys_futex_wait() --- .../selftests/futex/functional/.gitignore | 1 + .../selftests/futex/functional/Makefile | 3 +- .../selftests/futex/functional/robust_list.c | 448 ++ 3 files changed, 451 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/futex/functional/robust_list.c diff --git a/tools/testing/selftests/futex/functional/.gitignore b/tools/testing/selftests/futex/functional/.gitignore index fbcbdb6963b3..4726e1be7497 100644 --- a/tools/testing/selftests/futex/functional/.gitignore +++ b/tools/testing/selftests/futex/functional/.gitignore @@ -9,3 +9,4 @@ futex_wait_wouldblock futex_wait futex_requeue futex_waitv +robust_list diff --git a/tools/testing/selftests/futex/functional/Makefile b/tools/testing/selftests/futex/functional/Makefile index f79f9bac7918..b8635a1ac7f6 100644 --- a/tools/testing/selftests/futex/functional/Makefile +++ b/tools/testing/selftests/futex/functional/Makefile @@ -17,7 +17,8 @@ TEST_GEN_PROGS := \ futex_wait_private_mapped_file \ futex_wait \ futex_requeue \ - futex_waitv + futex_waitv \ + robust_list TEST_PROGS := run.sh diff --git a/tools/testing/selftests/futex/functional/robust_list.c b/tools/testing/selftests/futex/functional/robust_list.c new file mode 100644 index ..9308eb189d48 --- /dev/null +++ b/tools/testing/selftests/futex/functional/robust_list.c @@ -0,0 +1,448 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2024 Igalia S.L. + * + * Robust list test by André Almeida + * + * The robust list uAPI allows userspace to create "robust" locks, in the sense + * that if the lock holder thread dies, the remaining threads that are waiting + * for the lock won't block forever, waiting for a lock that will never be + * released. + * + * This is achieve by userspace setting a list where a thread can enter all the + * locks (futexes) that it is holding. The robust list is a linked list, and + * userspace register the start of the list with the syscall set_robust_list(). + * If such thread eventually dies, the kernel will walk this list, waking up one + * thread waiting for each futex and marking the futex word with the flag + * FUTEX_OWNER_DIED. + * + * See also + * man set_robust_list + * Documententation/locking/robust-futex-ABI.rst + * Documententation/locking/robust-futexes.rst + */ + +#define _GNU_SOURCE + +#include "../../kselftest_harness.h" + +#include "futextest.h" + +#include +#include +#include + +#define STACK_SIZE (1024 * 1024) + +#define FUTEX_TIMEOUT 3 + +static pthread_barrier_t barrier, barrier2; + +int set_robust_list(struct robust_list_head *head, size_t len) +{ + return syscall(SYS_set_robust_list, head, len); +} + +int get_robust_list(int pid, struct robust_list_head **head, size_t *len_ptr) +{ + return syscall(SYS_get_robust_list, pid, head, len_ptr); +} + +/* + * Basic lock struct, contains just the futex word and the robust list element + * Real implementations have also a *prev to easily walk in the list + */ +struct lock_struct { + _Atomic(unsigned int) futex; + struct robust_list list; +}; + +/* + * Helper function to spawn a child thread. Returns -1 on error, pid on success + */ +static int create_child(int (*fn)(void *arg), void *arg) +{ + char *stack; + pid_t pid; + + stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, +MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); + if (stack == MAP_FAILED) + return -1; + + stack += STACK_SIZE; + + pid = clone(fn, stack, CLONE_VM | SIGCHLD, arg); + + if (pid == -1) + return -1; + + return pid; +} + +/* + * Helper function to prepare and register a robust list + */ +static int set_list(struct robust_list_head *head) +{ + int ret; + + ret = set_robust_list(head, sizeof(struct robust_list_head)); + if (ret) + return ret; + + head->futex_offset = (size_t) offsetof(struct lock_struct, futex) - +(size_t) offsetof(struct lock_struct, list); + head->list.next = &head->list; + head->list_op_pending = NULL; + + return 0; +} + +/* + * A basic (and incomplete) mutex lock function with robustness + */ +static int mutex_lock(struct lock_struct *lock, struct robust_list_head *head, bool error_inject) +{ + _Atomic(unsigned int) *futex = &lock->futex; + int zero = 0, ret = -1; + pid_t tid = gettid(); + + /* +* Set list_op_pending before starting the lock, so the kernel can catch +* the case where the thread died during the lock operation +*/
[PATCH] utimer-test: remove unused variables
The variable i is never referenced in the code, just remove it. Signed-off-by: bajing --- tools/testing/selftests/alsa/utimer-test.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/testing/selftests/alsa/utimer-test.c b/tools/testing/selftests/alsa/utimer-test.c index 32ee3ce57721..9d2683c83ef3 100644 --- a/tools/testing/selftests/alsa/utimer-test.c +++ b/tools/testing/selftests/alsa/utimer-test.c @@ -140,7 +140,6 @@ TEST_F(timer_f, utimer) { TEST(wrong_timers_test) { int timer_dev_fd; int utimer_fd; - size_t i; struct snd_timer_uinfo wrong_timer = { .resolution = 0, .id = UTIMER_DEFAULT_ID, -- 2.33.0
[PATCH 13/13] media: i2c: imx214: Add test pattern control
From: André Apitzsch This adds V4L2_CID_TEST_PATTERN control support. Signed-off-by: André Apitzsch --- drivers/media/i2c/imx214.c | 77 -- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c index 6493a9b9ea88..6d67c7b307bd 100644 --- a/drivers/media/i2c/imx214.c +++ b/drivers/media/i2c/imx214.c @@ -181,6 +181,23 @@ #define IMX214_REG_ATR_FAST_MOVE CCI_REG8(0x9300) +/* Test Pattern Control */ +#define IMX214_REG_TEST_PATTERNCCI_REG16(0x0600) +#define IMX214_TEST_PATTERN_DISABLE0 +#define IMX214_TEST_PATTERN_SOLID_COLOR1 +#define IMX214_TEST_PATTERN_COLOR_BARS 2 +#define IMX214_TEST_PATTERN_GREY_COLOR 3 +#define IMX214_TEST_PATTERN_PN94 + +/* Test pattern colour components */ +#define IMX214_REG_TESTP_RED CCI_REG16(0x0602) +#define IMX214_REG_TESTP_GREENRCCI_REG16(0x0604) +#define IMX214_REG_TESTP_BLUE CCI_REG16(0x0606) +#define IMX214_REG_TESTP_GREENBCCI_REG16(0x0608) +#define IMX214_TESTP_COLOUR_MIN0 +#define IMX214_TESTP_COLOUR_MAX0x03ff +#define IMX214_TESTP_COLOUR_STEP 1 + /* IMX214 native and active pixel array size */ #define IMX214_NATIVE_WIDTH4224U #define IMX214_NATIVE_HEIGHT 3136U @@ -213,6 +230,22 @@ static const u32 imx214_mbus_formats[] = { MEDIA_BUS_FMT_SBGGR10_1X10, }; +static const char * const imx214_test_pattern_menu[] = { + "Disabled", + "Color Bars", + "Solid Color", + "Grey Color Bars", + "PN9" +}; + +static const int imx214_test_pattern_val[] = { + IMX214_TEST_PATTERN_DISABLE, + IMX214_TEST_PATTERN_COLOR_BARS, + IMX214_TEST_PATTERN_SOLID_COLOR, + IMX214_TEST_PATTERN_GREY_COLOR, + IMX214_TEST_PATTERN_PN9, +}; + struct imx214 { struct device *dev; struct clk *xclk; @@ -819,6 +852,26 @@ static int imx214_set_ctrl(struct v4l2_ctrl *ctrl) cci_write(imx214->regmap, IMX214_REG_FRM_LENGTH_LINES, format->height + ctrl->val, &ret); break; + case V4L2_CID_TEST_PATTERN: + cci_write(imx214->regmap, IMX214_REG_TEST_PATTERN, + imx214_test_pattern_val[ctrl->val], &ret); + break; + case V4L2_CID_TEST_PATTERN_RED: + cci_write(imx214->regmap, IMX214_REG_TESTP_RED, + ctrl->val, &ret); + break; + case V4L2_CID_TEST_PATTERN_GREENR: + cci_write(imx214->regmap, IMX214_REG_TESTP_GREENR, + ctrl->val, &ret); + break; + case V4L2_CID_TEST_PATTERN_BLUE: + cci_write(imx214->regmap, IMX214_REG_TESTP_BLUE, + ctrl->val, &ret); + break; + case V4L2_CID_TEST_PATTERN_GREENB: + cci_write(imx214->regmap, IMX214_REG_TESTP_GREENB, + ctrl->val, &ret); + break; default: ret = -EINVAL; } @@ -846,14 +899,14 @@ static int imx214_ctrls_init(struct imx214 *imx214) struct v4l2_ctrl_handler *ctrl_hdlr; int exposure_max, exposure_def; int hblank; - int ret; + int i, ret; ret = v4l2_fwnode_device_parse(imx214->dev, &props); if (ret < 0) return ret; ctrl_hdlr = &imx214->ctrls; - ret = v4l2_ctrl_handler_init(&imx214->ctrls, 12); + ret = v4l2_ctrl_handler_init(&imx214->ctrls, 13); if (ret) return ret; @@ -908,6 +961,26 @@ static int imx214_ctrls_init(struct imx214 *imx214) if (imx214->vflip) imx214->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx214_ctrl_ops, +V4L2_CID_TEST_PATTERN, +ARRAY_SIZE(imx214_test_pattern_menu) - 1, +0, 0, imx214_test_pattern_menu); + for (i = 0; i < 4; i++) { + /* +* The assumption is that +* V4L2_CID_TEST_PATTERN_GREENR == V4L2_CID_TEST_PATTERN_RED + 1 +* V4L2_CID_TEST_PATTERN_BLUE == V4L2_CID_TEST_PATTERN_RED + 2 +* V4L2_CID_TEST_PATTERN_GREENB == V4L2_CID_TEST_PATTERN_RED + 3 +*/ + v4l2_ctrl_new_std(ctrl_hdlr, &imx214_ctrl_ops, + V4L2_CID_TEST_PATTERN_RED + i, + IMX214_TESTP_COLOUR_MIN, + IMX214_TESTP_COLOUR_MAX, + IMX214_TESTP_COLOUR_STEP, +
Re: [PATCH bpf-next 2/2] selftests/bpf: Add uprobe pid filter test for multiple processes
On Thu, Aug 29, 2024 at 12:45 PM Jiri Olsa wrote: > > The idea is to create and monitor 3 uprobes, each trigered in separate typo: triggered > process and make sure the bpf program gets executed just for the proper > PID specified via pid filter. > > Signed-off-by: Jiri Olsa > --- > .../bpf/prog_tests/uprobe_multi_test.c| 103 ++ > .../bpf/progs/uprobe_multi_pid_filter.c | 61 +++ > 2 files changed, 164 insertions(+) > create mode 100644 > tools/testing/selftests/bpf/progs/uprobe_multi_pid_filter.c > It's good to have a test, thanks for adding it! But we should couple it with the fix in multi-uprobe and land together, right? I'm not exactly sure why we can't just use task->signal-based check, but let's try to converge on something and fix it. pw-bot: cr [...] > +#define TASKS 3 > + > +static void run_pid_filter(struct uprobe_multi_pid_filter *skel, > + create_link_t create_link, bool retprobe) > +{ > + struct bpf_link *link[TASKS] = {}; > + struct child child[TASKS] = {}; > + int i; > + > + printf("%s retprobe %d\n", create_link == create_link_uprobe ? > "uprobe" : "uprobe_multi", > + retprobe); leftovers > + > + memset(skel->bss->test, 0, sizeof(skel->bss->test)); > + > + for (i = 0; i < TASKS; i++) { > + if (!ASSERT_OK(spawn_child(&child[i]), "spawn_child")) > + goto cleanup; > + skel->bss->pids[i] = child[i].pid; > + } [...]
Re: [PATCH bpf-next 0/2] selftests/bpf: Add uprobe pid filter test
On 08/29, Jiri Olsa wrote: > hi, > in response to [1] patch, I'm adding bpf selftest that confirms the > change fixes problem for bpf programs trigered by return uprobe created > over perf event. > > Oleg pointed out other issues with uprobe_multi pid filter, > I plan to send another patchset for that. Not sure whether Oleg or Andrii plan to take a look, but LGTM: Acked-by: Stanislav Fomichev
[PATCH bpf-next 2/2] selftests/bpf: Add uprobe pid filter test for multiple processes
The idea is to create and monitor 3 uprobes, each trigered in separate process and make sure the bpf program gets executed just for the proper PID specified via pid filter. Signed-off-by: Jiri Olsa --- .../bpf/prog_tests/uprobe_multi_test.c| 103 ++ .../bpf/progs/uprobe_multi_pid_filter.c | 61 +++ 2 files changed, 164 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/uprobe_multi_pid_filter.c diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c index 250eb47c68f9..59c460675af9 100644 --- a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c @@ -7,6 +7,7 @@ #include "uprobe_multi_bench.skel.h" #include "uprobe_multi_usdt.skel.h" #include "uprobe_multi_consumers.skel.h" +#include "uprobe_multi_pid_filter.skel.h" #include "bpf/libbpf_internal.h" #include "testing_helpers.h" #include "../sdt.h" @@ -935,6 +936,106 @@ static void test_consumers(void) uprobe_multi_consumers__destroy(skel); } +typedef struct bpf_link *(create_link_t)(struct uprobe_multi_pid_filter *, int, int, bool); + +static struct bpf_program *uprobe_program(struct uprobe_multi_pid_filter *skel, int idx) +{ + switch (idx) { + case 0: return skel->progs.uprobe_0; + case 1: return skel->progs.uprobe_1; + case 2: return skel->progs.uprobe_2; + } + return NULL; +} + +static struct bpf_link *create_link_uprobe(struct uprobe_multi_pid_filter *skel, + int idx, int pid, bool retprobe) +{ + LIBBPF_OPTS(bpf_uprobe_opts, opts, + .retprobe = retprobe, + .func_name = "uprobe_multi_func_1", + ); + + return bpf_program__attach_uprobe_opts(uprobe_program(skel, idx), pid, + "/proc/self/exe", 0, &opts); +} + +static struct bpf_program *uprobe_multi_program(struct uprobe_multi_pid_filter *skel, int idx) +{ + switch (idx) { + case 0: return skel->progs.uprobe_multi_0; + case 1: return skel->progs.uprobe_multi_1; + case 2: return skel->progs.uprobe_multi_2; + } + return NULL; +} + +static struct bpf_link *create_link_uprobe_multi(struct uprobe_multi_pid_filter *skel, +int idx, int pid, bool retprobe) +{ + LIBBPF_OPTS(bpf_uprobe_multi_opts, opts, .retprobe = retprobe); + + return bpf_program__attach_uprobe_multi(uprobe_multi_program(skel, idx), pid, + "/proc/self/exe", "uprobe_multi_func_1", &opts); +} + +#define TASKS 3 + +static void run_pid_filter(struct uprobe_multi_pid_filter *skel, + create_link_t create_link, bool retprobe) +{ + struct bpf_link *link[TASKS] = {}; + struct child child[TASKS] = {}; + int i; + + printf("%s retprobe %d\n", create_link == create_link_uprobe ? "uprobe" : "uprobe_multi", + retprobe); + + memset(skel->bss->test, 0, sizeof(skel->bss->test)); + + for (i = 0; i < TASKS; i++) { + if (!ASSERT_OK(spawn_child(&child[i]), "spawn_child")) + goto cleanup; + skel->bss->pids[i] = child[i].pid; + } + + for (i = 0; i < TASKS; i++) { + link[i] = create_link(skel, i, child[i].pid, retprobe); + if (!ASSERT_OK_PTR(link[i], "create_link")) + goto cleanup; + } + + for (i = 0; i < TASKS; i++) + kick_child(&child[i]); + + for (i = 0; i < TASKS; i++) { + ASSERT_EQ(skel->bss->test[i][0], 1, "pid"); + ASSERT_EQ(skel->bss->test[i][1], 0, "unknown"); + } + +cleanup: + for (i = 0; i < TASKS; i++) + bpf_link__destroy(link[i]); + for (i = 0; i < TASKS; i++) + release_child(&child[i]); +} + +static void test_pid_filter_process(void) +{ + struct uprobe_multi_pid_filter *skel; + + skel = uprobe_multi_pid_filter__open_and_load(); + if (!ASSERT_OK_PTR(skel, "uprobe_multi_pid_filter__open_and_load")) + return; + + run_pid_filter(skel, create_link_uprobe, false); + run_pid_filter(skel, create_link_uprobe, true); + run_pid_filter(skel, create_link_uprobe_multi, false); + run_pid_filter(skel, create_link_uprobe_multi, true); + + uprobe_multi_pid_filter__destroy(skel); +} + static void test_bench_attach_uprobe(void) { long attach_start_ns = 0, attach_end_ns = 0; @@ -1027,4 +1128,6 @@ void test_uprob
[PATCH bpf-next 0/2] selftests/bpf: Add uprobe pid filter test
hi, in response to [1] patch, I'm adding bpf selftest that confirms the change fixes problem for bpf programs trigered by return uprobe created over perf event. Oleg pointed out other issues with uprobe_multi pid filter, I plan to send another patchset for that. thanks, jirka [1] https://lore.kernel.org/linux-trace-kernel/me0p300mb0416034322b9915ecd3888649d...@me0p300mb0416.ausp300.prod.outlook.com/ --- Jiri Olsa (2): selftests/bpf: Add child argument to spawn_child function selftests/bpf: Add uprobe pid filter test for multiple processes tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c | 188 --- tools/testing/selftests/bpf/progs/uprobe_multi_pid_filter.c | 61 ++ 2 files changed, 203 insertions(+), 46 deletions(-) create mode 100644 tools/testing/selftests/bpf/progs/uprobe_multi_pid_filter.c
[PATCH v3 7/6 DONT_MERGE] selftests: livepatch: Test failing IBT checks crashing the module
This patch is only an example of how to generate #GP by IBT. It serves only as an example for those wondering how the Linux behaves in this case. Don't merge this patch, because it causes a refcount underflow of the test module, so it's not possible to unload it. Signed-off-by: Lukas Hruska --- tools/testing/selftests/livepatch/Makefile| 4 ++ tools/testing/selftests/livepatch/test-ibt.sh | 57 +++ .../selftests/livepatch/test_modules/Makefile | 2 + .../test_modules/test_klp_extern_hello.c | 20 +++ .../livepatch/test_modules/test_klp_ibt.c | 51 + 5 files changed, 134 insertions(+) create mode 100644 tools/testing/selftests/livepatch/test-ibt.sh create mode 100644 tools/testing/selftests/livepatch/test_modules/test_klp_ibt.c diff --git a/tools/testing/selftests/livepatch/Makefile b/tools/testing/selftests/livepatch/Makefile index 611ee16bef56..3ef2040e4c50 100644 --- a/tools/testing/selftests/livepatch/Makefile +++ b/tools/testing/selftests/livepatch/Makefile @@ -13,6 +13,10 @@ TEST_PROGS := \ test-syscall.sh \ test-extern.sh +ifdef CONFIG_X86_KERNEL_IBT + TEST_PROGS += test-ibt.sh +endif + TEST_FILES := settings include ../lib.mk diff --git a/tools/testing/selftests/livepatch/test-ibt.sh b/tools/testing/selftests/livepatch/test-ibt.sh new file mode 100644 index ..c5f49fb7af4d --- /dev/null +++ b/tools/testing/selftests/livepatch/test-ibt.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 Lukas Hruska + +. $(dirname $0)/functions.sh + +MOD_LIVEPATCH=test_klp_ibt +MOD_HELLO=test_klp_extern_hello +PARAM_HELLO=hello + +setup_config + +# - load a module to be livepatched +# - load a livepatch that calls the unused function which does not have endbr64 +# as its first instruction +# - unload the livepatch and make sure the patch was removed +# - unload the module that was livepatched + +start_test "livepatch with external symbol" + +load_mod $MOD_HELLO + +read_module_param $MOD_HELLO $PARAM_HELLO + +load_lp $MOD_LIVEPATCH + +read_module_param $MOD_HELLO $PARAM_HELLO + +disable_lp $MOD_LIVEPATCH +unload_lp $MOD_LIVEPATCH + +read_module_param $MOD_HELLO $PARAM_HELLO + +unload_mod $MOD_HELLO + +check_result "% insmod test_modules/$MOD_HELLO.ko +% echo \"$MOD_HELLO/parameters/$PARAM_HELLO: \$(cat /sys/module/$MOD_HELLO/parameters/$PARAM_HELLO)\" +$MOD_HELLO/parameters/$PARAM_HELLO: Hello from kernel module. +% insmod test_modules/$MOD_LIVEPATCH.ko +livepatch: enabling patch '$MOD_LIVEPATCH' +livepatch: '$MOD_LIVEPATCH': initializing patching transition +livepatch: '$MOD_LIVEPATCH': starting patching transition +livepatch: '$MOD_LIVEPATCH': completing patching transition +livepatch: '$MOD_LIVEPATCH': patching complete +% echo \"$MOD_HELLO/parameters/$PARAM_HELLO: \$(cat /sys/module/$MOD_HELLO/parameters/$PARAM_HELLO)\" +$MOD_HELLO/parameters/$PARAM_HELLO: Hello from livepatched module. +% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled +livepatch: '$MOD_LIVEPATCH': initializing unpatching transition +livepatch: '$MOD_LIVEPATCH': starting unpatching transition +livepatch: '$MOD_LIVEPATCH': completing unpatching transition +livepatch: '$MOD_LIVEPATCH': unpatching complete +% rmmod $MOD_LIVEPATCH +% echo \"$MOD_HELLO/parameters/$PARAM_HELLO: \$(cat /sys/module/$MOD_HELLO/parameters/$PARAM_HELLO)\" +$MOD_HELLO/parameters/$PARAM_HELLO: Hello from kernel module. +% rmmod $MOD_HELLO" + +exit 0 diff --git a/tools/testing/selftests/livepatch/test_modules/Makefile b/tools/testing/selftests/livepatch/test_modules/Makefile index 0d6df14787da..49a22ea90f3a 100644 --- a/tools/testing/selftests/livepatch/test_modules/Makefile +++ b/tools/testing/selftests/livepatch/test_modules/Makefile @@ -15,6 +15,8 @@ obj-m += test_klp_atomic_replace.o \ test_klp_shadow_vars.o \ test_klp_syscall.o +obj-$(CONFIG_X86_KERNEL_IBT) += test_klp_ibt.o + # Ensure that KDIR exists, otherwise skip the compilation modules: ifneq ("$(wildcard $(KDIR))", "") diff --git a/tools/testing/selftests/livepatch/test_modules/test_klp_extern_hello.c b/tools/testing/selftests/livepatch/test_modules/test_klp_extern_hello.c index 431c55b5849a..37e1cd2cecdb 100644 --- a/tools/testing/selftests/livepatch/test_modules/test_klp_extern_hello.c +++ b/tools/testing/selftests/livepatch/test_modules/test_klp_extern_hello.c @@ -13,6 +13,26 @@ static int hello_get(char *buffer, const struct kernel_param *kp) return sysfs_emit(buffer, "%s kernel module.\n", hello_msg); } +#ifdef CONFIG_X86_KERNEL_IBT +static __attribute__((nocf_check)) int hello_get_alt(char *buffer, const struct kernel_param *kp) +{ + return sysfs_emit(buffer, "%s unused function.\n", hello_msg); +} + +static int fail_
[PATCH v3 6/6] selftests: livepatch: Test livepatching function using an external symbol
The test proves that klp-convert works as intended and it is possible to livepatch a function that use an external symbol. Signed-off-by: Lukas Hruska Reviewed-by: Petr Mladek Tested-by: Petr Mladek --- tools/testing/selftests/livepatch/Makefile| 3 +- .../testing/selftests/livepatch/functions.sh | 14 + .../selftests/livepatch/test-extern.sh| 57 +++ .../selftests/livepatch/test_modules/Makefile | 2 + .../livepatch/test_modules/test_klp_extern.c | 51 + .../test_modules/test_klp_extern_hello.c | 36 6 files changed, 162 insertions(+), 1 deletion(-) create mode 100755 tools/testing/selftests/livepatch/test-extern.sh create mode 100644 tools/testing/selftests/livepatch/test_modules/test_klp_extern.c create mode 100644 tools/testing/selftests/livepatch/test_modules/test_klp_extern_hello.c diff --git a/tools/testing/selftests/livepatch/Makefile b/tools/testing/selftests/livepatch/Makefile index 35418a4790be..611ee16bef56 100644 --- a/tools/testing/selftests/livepatch/Makefile +++ b/tools/testing/selftests/livepatch/Makefile @@ -10,7 +10,8 @@ TEST_PROGS := \ test-state.sh \ test-ftrace.sh \ test-sysfs.sh \ - test-syscall.sh + test-syscall.sh \ + test-extern.sh TEST_FILES := settings diff --git a/tools/testing/selftests/livepatch/functions.sh b/tools/testing/selftests/livepatch/functions.sh index fc4c6a016d38..9b6a19eee3a2 100644 --- a/tools/testing/selftests/livepatch/functions.sh +++ b/tools/testing/selftests/livepatch/functions.sh @@ -7,6 +7,7 @@ MAX_RETRIES=600 RETRY_INTERVAL=".1"# seconds KLP_SYSFS_DIR="/sys/kernel/livepatch" +MODULE_SYSFS_DIR="/sys/module" # Kselftest framework requirement - SKIP code is 4 ksft_skip=4 @@ -344,3 +345,16 @@ function check_sysfs_value() { die "Unexpected value in $path: $expected_value vs. $value" fi } + +# read_module_param_value(modname, param) - read module parameter value +# modname - livepatch module creating the sysfs interface +# param - parameter name +function read_module_param() { + local mod="$1"; shift + local param="$1"; shift + + local path="$MODULE_SYSFS_DIR/$mod/parameters/$param" + + log "% echo \"$mod/parameters/$param: \$(cat $path)\"" + log "$mod/parameters/$param: $(cat $path)" +} diff --git a/tools/testing/selftests/livepatch/test-extern.sh b/tools/testing/selftests/livepatch/test-extern.sh new file mode 100755 index ..3dde6cabb07c --- /dev/null +++ b/tools/testing/selftests/livepatch/test-extern.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2024 Lukas Hruska + +. $(dirname $0)/functions.sh + +MOD_LIVEPATCH=test_klp_extern +MOD_HELLO=test_klp_extern_hello +PARAM_HELLO=hello + +setup_config + +# - load a module to be livepatched +# - load a livepatch that modifies the output from 'hello' parameter +# of the previously loaded module and verify correct behaviour +# - unload the livepatch and make sure the patch was removed +# - unload the module that was livepatched + +start_test "livepatch with external symbol" + +load_mod $MOD_HELLO + +read_module_param $MOD_HELLO $PARAM_HELLO + +load_lp $MOD_LIVEPATCH + +read_module_param $MOD_HELLO $PARAM_HELLO + +disable_lp $MOD_LIVEPATCH +unload_lp $MOD_LIVEPATCH + +read_module_param $MOD_HELLO $PARAM_HELLO + +unload_mod $MOD_HELLO + +check_result "% insmod test_modules/$MOD_HELLO.ko +% echo \"$MOD_HELLO/parameters/$PARAM_HELLO: \$(cat /sys/module/$MOD_HELLO/parameters/$PARAM_HELLO)\" +$MOD_HELLO/parameters/$PARAM_HELLO: Hello from kernel module. +% insmod test_modules/$MOD_LIVEPATCH.ko +livepatch: enabling patch '$MOD_LIVEPATCH' +livepatch: '$MOD_LIVEPATCH': initializing patching transition +livepatch: '$MOD_LIVEPATCH': starting patching transition +livepatch: '$MOD_LIVEPATCH': completing patching transition +livepatch: '$MOD_LIVEPATCH': patching complete +% echo \"$MOD_HELLO/parameters/$PARAM_HELLO: \$(cat /sys/module/$MOD_HELLO/parameters/$PARAM_HELLO)\" +$MOD_HELLO/parameters/$PARAM_HELLO: Hello from livepatched module. +% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled +livepatch: '$MOD_LIVEPATCH': initializing unpatching transition +livepatch: '$MOD_LIVEPATCH': starting unpatching transition +livepatch: '$MOD_LIVEPATCH': completing unpatching transition +livepatch: '$MOD_LIVEPATCH': unpatching complete +% rmmod $MOD_LIVEPATCH +% echo \"$MOD_HELLO/parameters/$PARAM_HELLO: \$(cat /sys/module/$MOD_HELLO/parameters/$PARAM_HELLO)\" +$MOD_HELLO/parameters/$PARAM_HELLO: Hello from kernel module. +% rmmod $MOD_HELLO" + +exit 0 diff --git a/tools/testing/selftests/livepatch/test_modules/Makefile b/tools/testing/sel
[PATCH v13 18/20] selftests/ftrace: Add a test case for repeating register/unregister fprobe
From: Masami Hiramatsu (Google) This test case repeats define and undefine the fprobe dynamic event to ensure that the fprobe does not cause any issue with such operations. Signed-off-by: Masami Hiramatsu (Google) --- .../test.d/dynevent/add_remove_fprobe_repeat.tc| 19 +++ 1 file changed, 19 insertions(+) create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/add_remove_fprobe_repeat.tc diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_fprobe_repeat.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_fprobe_repeat.tc new file mode 100644 index ..b4ad09237e2a --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_fprobe_repeat.tc @@ -0,0 +1,19 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Generic dynamic event - Repeating add/remove fprobe events +# requires: dynamic_events "f[:[/][]] [%return] []":README + +echo 0 > events/enable +echo > dynamic_events + +PLACE=$FUNCTION_FORK +REPEAT_TIMES=64 + +for i in `seq 1 $REPEAT_TIMES`; do + echo "f:myevent $PLACE" >> dynamic_events + grep -q myevent dynamic_events + test -d events/fprobes/myevent + echo > dynamic_events +done + +clear_trace
[PATCH v3 5/5] sefltests/tracing: Add a test for tracepoint events on modules
From: Masami Hiramatsu (Google) Add a test case for tracepoint events on modules. This checks if it can add and remove the events correctly. Signed-off-by: Masami Hiramatsu (Google) --- Changes in v3: - Add not-loaded module test. --- tools/testing/selftests/ftrace/config |1 .../test.d/dynevent/add_remove_tprobe_module.tc| 61 2 files changed, 62 insertions(+) create mode 100644 tools/testing/selftests/ftrace/test.d/dynevent/add_remove_tprobe_module.tc diff --git a/tools/testing/selftests/ftrace/config b/tools/testing/selftests/ftrace/config index 048a312abf40..544de0db5f58 100644 --- a/tools/testing/selftests/ftrace/config +++ b/tools/testing/selftests/ftrace/config @@ -20,6 +20,7 @@ CONFIG_PREEMPT_TRACER=y CONFIG_PROBE_EVENTS_BTF_ARGS=y CONFIG_SAMPLES=y CONFIG_SAMPLE_FTRACE_DIRECT=m +CONFIG_SAMPLE_TRACE_EVENTS=m CONFIG_SAMPLE_TRACE_PRINTK=m CONFIG_SCHED_TRACER=y CONFIG_STACK_TRACER=y diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_tprobe_module.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_tprobe_module.tc new file mode 100644 index ..d319d5ed4226 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_tprobe_module.tc @@ -0,0 +1,61 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Generic dynamic event - add/remove tracepoint probe events on module +# requires: dynamic_events "t[:[/][]] []":README + +rmmod trace-events-sample ||: +if ! modprobe trace-events-sample ; then + echo "No trace-events sample module - please make CONFIG_SAMPLE_TRACE_EVENTS=m" + exit_unresolved; +fi +trap "rmmod trace-events-sample" EXIT + +echo 0 > events/enable +echo > dynamic_events + +TRACEPOINT1=foo_bar +TRACEPOINT2=foo_bar_with_cond + +echo "t:myevent1 $TRACEPOINT1" >> dynamic_events +echo "t:myevent2 $TRACEPOINT2" >> dynamic_events + +grep -q myevent1 dynamic_events +grep -q myevent2 dynamic_events +test -d events/tracepoints/myevent1 +test -d events/tracepoints/myevent2 + +echo "-:myevent2" >> dynamic_events + +grep -q myevent1 dynamic_events +! grep -q myevent2 dynamic_events + +echo > dynamic_events + +clear_trace + +:;: "Try to put a probe on a tracepoint in non-loaded module" ;: +rmmod trace-events-sample + +echo "t:myevent1 $TRACEPOINT1" >> dynamic_events +echo "t:myevent2 $TRACEPOINT2" >> dynamic_events + +grep -q myevent1 dynamic_events +grep -q myevent2 dynamic_events +test -d events/tracepoints/myevent1 +test -d events/tracepoints/myevent2 + +echo 1 > events/tracepoints/enable + +modprobe trace-events-sample + +sleep 2 + +grep -q "myevent1" trace +grep -q "myevent2" trace + +rmmod trace-events-sample +trap "" EXIT + +echo 0 > events/tracepoints/enable +echo > dynamic_events +clear_trace
Re: [PATCH v4 0/4] Add SBAF test to IFS
Hi, On 8/1/24 7:18 AM, Kuppuswamy Sathyanarayanan wrote: > This patch series adds support for Structural Based Functional Test at > Field (SBAF) in the IFS driver. SBAF is a new type of testing that > provides comprehensive core test coverage, complementing existing IFS > tests like Scan at Field (SAF) and ArrayBist. Granite Rapids (GNR) is > the first platform that supports SBAF. > > SBAF mimics the manufacturing screening environment and leverages the > same test suite. It makes use of Design For Test (DFT) observation > sites and features to maximize coverage in minimum time. > > Similar to the SAF test, SBAF isolates the core under test from the > rest of the system during execution. Upon completion, the core > seamlessly resets to its pre-test state and resumes normal operation. > Any machine checks or hangs encountered during the test are confined to > the isolated core, preventing disruption to the overall system. Like > SAF test, the SBAF test is also divided into multiple batches, and each > batch test can take hundreds of milliseconds (100-200 ms) to complete. > If such a lengthy interruption is undesirable, it is recommended to > relocate the time-sensitive applications to other cores for the > duration of the test. Thank you for your patch-series, I've applied the series to my review-hans branch: https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans Note it will show up in my review-hans branch once I've pushed my local branch there, which might take a while. Once I've run some tests on this branch the patches there will be added to the platform-drivers-x86/for-next branch and eventually will be included in the pdx86 pull-request to Linus for the next merge-window. Regards, Hans > > Patch Details: > > Patch 1/4: Refactors MSR usage in IFS image loading code to share the >code between SBAF and SAF tests. > Patch 2/4: Leverages SAF image loading logic and adds SBAF image loading > support. > Patch 3/4: Adds support for user to trigger SBAF test. > Patch 4/4: Adds trace support for SBAF tests. > > This series is originally authored by Jithu Joseph. I have made cleanups > related to code reuse between the SBAF and SAF tests and resubmitting it for > review. > > Changes since v3: > * Rebased on top of v6.11-rc1 > * Added missing error return value in validate_ifs_metadata(). > > Changes since v2: > * Added Reviewed-by tags from Ilpo and Steven. > * Fixed minor issues raised by Ilpo. > > Changes since v1: > * Addressed trace struct hole issue (Steven) > * Fixed initialization issue in ifs_sbaf_test_core() (Ilpo) > > Jithu Joseph (3): > platform/x86/intel/ifs: Add SBAF test image loading support > platform/x86/intel/ifs: Add SBAF test support > trace: platform/x86/intel/ifs: Add SBAF trace support > > Kuppuswamy Sathyanarayanan (1): > platform/x86/intel/ifs: Refactor MSR usage in IFS test code > > arch/x86/include/asm/msr-index.h | 2 + > drivers/platform/x86/intel/ifs/ifs.h | 92 - > include/trace/events/intel_ifs.h | 27 +++ > drivers/platform/x86/intel/ifs/core.c| 33 > drivers/platform/x86/intel/ifs/load.c| 40 ++-- > drivers/platform/x86/intel/ifs/runtest.c | 233 +++ > 6 files changed, 412 insertions(+), 15 deletions(-) >
[PATCH v2] LoongArch: Revert qspinlock to test-and-set simple lock on VM
Similar with x86, when VM is detected, revert to a simple test-and-set lock to avoid the horrors of queue preemption. Tested on 3C5000 Dual-way machine with 32 cores and 2 numa nodes, test case is kcbench on kernel mainline 6.10, the detailed command is "kcbench --src /root/src/linux" Performance on host machine kernel compile time performance impact Original 150.29 seconds With patch 150.19 secondsalmost no impact Performance on virtual machine: 1. 1 VM with 32 vCPUs and 2 numa node, numa node pinned kernel compile time performance impact Original 170.87 seconds With patch 171.73 secondsalmost no impact 2. 2 VMs, each VM with 32 vCPUs and 2 numa node, numa node pinned kernel compile time performance impact Original 2362.04 seconds With patch 354.73 seconds+565% Signed-off-by: Bibo Mao --- v1 ... v2: 1. Define static key virt_spin_lock_key as false by default 2. Add prefix __init with function smp_prepare_boot_cpu(), since there is prefix __init with called function pv_spinlock_init(). --- arch/loongarch/include/asm/Kbuild | 1 - arch/loongarch/include/asm/paravirt.h | 3 ++ arch/loongarch/include/asm/qspinlock.h | 40 ++ arch/loongarch/kernel/paravirt.c | 9 ++ arch/loongarch/kernel/setup.c | 5 arch/loongarch/kernel/smp.c| 4 ++- 6 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 arch/loongarch/include/asm/qspinlock.h diff --git a/arch/loongarch/include/asm/Kbuild b/arch/loongarch/include/asm/Kbuild index 2bb3676429c0..4635b755b2b4 100644 --- a/arch/loongarch/include/asm/Kbuild +++ b/arch/loongarch/include/asm/Kbuild @@ -6,7 +6,6 @@ generic-y += mcs_spinlock.h generic-y += parport.h generic-y += early_ioremap.h generic-y += qrwlock.h -generic-y += qspinlock.h generic-y += user.h generic-y += ioctl.h generic-y += statfs.h diff --git a/arch/loongarch/include/asm/paravirt.h b/arch/loongarch/include/asm/paravirt.h index dddec49671ae..dcc2b46d31fe 100644 --- a/arch/loongarch/include/asm/paravirt.h +++ b/arch/loongarch/include/asm/paravirt.h @@ -19,6 +19,7 @@ static inline u64 paravirt_steal_clock(int cpu) int __init pv_ipi_init(void); int __init pv_time_init(void); +void __init pv_spinlock_init(void); #else @@ -31,5 +32,7 @@ static inline int pv_time_init(void) { return 0; } + +static inline void pv_spinlock_init(void) { } #endif // CONFIG_PARAVIRT #endif diff --git a/arch/loongarch/include/asm/qspinlock.h b/arch/loongarch/include/asm/qspinlock.h new file mode 100644 index ..7dd6d961dc79 --- /dev/null +++ b/arch/loongarch/include/asm/qspinlock.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LOONGARCH_QSPINLOCK_H +#define _ASM_LOONGARCH_QSPINLOCK_H + +#include + +#ifdef CONFIG_PARAVIRT + +DECLARE_STATIC_KEY_FALSE(virt_spin_lock_key); + +#define virt_spin_lock virt_spin_lock +static inline bool virt_spin_lock(struct qspinlock *lock) +{ + int val; + + if (!static_branch_unlikely(&virt_spin_lock_key)) + return false; + + /* +* On hypervisors without PARAVIRT_SPINLOCKS support we fall + * back to a Test-and-Set spinlock, because fair locks have +* horrible lock 'holder' preemption issues. +*/ + +__retry: + val = atomic_read(&lock->val); + + if (val || !atomic_try_cmpxchg(&lock->val, &val, _Q_LOCKED_VAL)) { + cpu_relax(); + goto __retry; + } + + return true; +} + +#endif /* CONFIG_PARAVIRT */ + +#include + +#endif // _ASM_LOONGARCH_QSPINLOCK_H diff --git a/arch/loongarch/kernel/paravirt.c b/arch/loongarch/kernel/paravirt.c index 9c9b75b76f62..78b551f375ef 100644 --- a/arch/loongarch/kernel/paravirt.c +++ b/arch/loongarch/kernel/paravirt.c @@ -9,6 +9,7 @@ #include #include +DEFINE_STATIC_KEY_FALSE(virt_spin_lock_key); static int has_steal_clock; struct static_key paravirt_steal_enabled; struct static_key paravirt_steal_rq_enabled; @@ -300,3 +301,11 @@ int __init pv_time_init(void) return 0; } + +void __init pv_spinlock_init(void) +{ + if (!cpu_has_hypervisor) + return; + + static_branch_enable(&virt_spin_lock_key); +} diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c index 0f0740f0be27..70a670efe3cf 100644 --- a/arch/loongarch/kernel/setup.c +++ b/arch/loongarch/kernel/setup.c @@ -599,6 +599,11 @@ void __init setup_arch(char **cmdline_p) parse_early_param(); reserve_initrd_mem(); + /* +* Initialise the static keys early as they may be enabled by the +* cpufeature code and early parameters. +*/ + jump_label_init(); platform_init(); arch_mem_init(cmdline_p); d
Re: [syzbot] [trace?] linux-next test error: WARNING in rcu_core
On Fri, 2 Aug 2024 at 09:58, syzbot wrote: > > Hello, > > syzbot found the following issue on: > > HEAD commit:f524a5e4dfb7 Add linux-next specific files for 20240802 > git tree: linux-next > console output: https://syzkaller.appspot.com/x/log.txt?x=174c896d98 > kernel config: https://syzkaller.appspot.com/x/.config?x=a66a5509e9947c4c > dashboard link: https://syzkaller.appspot.com/bug?extid=263726e59eab6b442723 > compiler: Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) > 2.40 > > Downloadable assets: > disk image: > https://storage.googleapis.com/syzbot-assets/8c0255b9a6ad/disk-f524a5e4.raw.xz > vmlinux: > https://storage.googleapis.com/syzbot-assets/71d89466ea60/vmlinux-f524a5e4.xz > kernel image: > https://storage.googleapis.com/syzbot-assets/ba8fcf059463/bzImage-f524a5e4.xz > > IMPORTANT: if you fix the issue, please add the following tag to the commit: > Reported-by: syzbot+263726e59eab6b442...@syzkaller.appspotmail.com > > [ cut here ] > WARNING: CPU: 0 PID: 1 at mm/slub.c:4550 > slab_free_after_rcu_debug+0x18b/0x270 mm/slub.c:4550 See https://lore.kernel.org/all/zqyths-o85nqu...@elver.google.com/T/#u
[syzbot] [trace?] linux-next test error: WARNING in rcu_core
Hello, syzbot found the following issue on: HEAD commit:f524a5e4dfb7 Add linux-next specific files for 20240802 git tree: linux-next console output: https://syzkaller.appspot.com/x/log.txt?x=174c896d98 kernel config: https://syzkaller.appspot.com/x/.config?x=a66a5509e9947c4c dashboard link: https://syzkaller.appspot.com/bug?extid=263726e59eab6b442723 compiler: Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40 Downloadable assets: disk image: https://storage.googleapis.com/syzbot-assets/8c0255b9a6ad/disk-f524a5e4.raw.xz vmlinux: https://storage.googleapis.com/syzbot-assets/71d89466ea60/vmlinux-f524a5e4.xz kernel image: https://storage.googleapis.com/syzbot-assets/ba8fcf059463/bzImage-f524a5e4.xz IMPORTANT: if you fix the issue, please add the following tag to the commit: Reported-by: syzbot+263726e59eab6b442...@syzkaller.appspotmail.com [ cut here ] WARNING: CPU: 0 PID: 1 at mm/slub.c:4550 slab_free_after_rcu_debug+0x18b/0x270 mm/slub.c:4550 Modules linked in: CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.11.0-rc1-next-20240802-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 06/27/2024 RIP: 0010:slab_free_after_rcu_debug+0x18b/0x270 mm/slub.c:4550 Code: 48 89 04 19 48 8d 4a 08 49 8b 34 24 65 48 0f c7 0e 75 c8 4c 89 f7 48 83 c4 08 5b 41 5c 41 5d 41 5e 41 5f 5d e9 36 55 ff ff 90 <0f> 0b 90 eb 92 90 0f 0b 90 eb 8c 90 0f 0b 90 eb 86 41 8b 54 24 1c RSP: :c9007bc0 EFLAGS: 00010286 RAX: 88823bc0 RBX: 88802bcee5c0 RCX: 000a0fe0 RDX: ea00 RSI: RDI: RBP: c9007e30 R08: 8142b2ec R09: 126e8ce3 R10: dc00 R11: 81f0bb80 R12: dc00 R13: 817bd996 R14: 88823bca0fe0 R15: eaaf3a00 FS: () GS:8880b920() knlGS: CS: 0010 DS: ES: CR0: 80050033 CR2: 88823000 CR3: 0e734000 CR4: 003506f0 DR0: DR1: DR2: DR3: DR6: fffe0ff0 DR7: 0400 Call Trace: rcu_do_batch kernel/rcu/tree.c:2569 [inline] rcu_core+0xafd/0x1830 kernel/rcu/tree.c:2843 handle_softirqs+0x2c4/0x970 kernel/softirq.c:554 __do_softirq kernel/softirq.c:588 [inline] invoke_softirq kernel/softirq.c:428 [inline] __irq_exit_rcu+0xf4/0x1c0 kernel/softirq.c:637 irq_exit_rcu+0x9/0x30 kernel/softirq.c:649 instr_sysvec_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1043 [inline] sysvec_apic_timer_interrupt+0xa6/0xc0 arch/x86/kernel/apic/apic.c:1043 asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:702 RIP: 0010:lock_acquire+0x264/0x550 kernel/locking/lockdep.c:5826 Code: 2b 00 74 08 4c 89 f7 e8 8a 32 8c 00 f6 44 24 61 02 0f 85 85 01 00 00 41 f7 c7 00 02 00 00 74 01 fb 48 c7 44 24 40 0e 36 e0 45 <4b> c7 44 25 00 00 00 00 00 43 c7 44 25 09 00 00 00 00 43 c7 44 25 RSP: :c90675a0 EFLAGS: 0206 RAX: 0001 RBX: 1920cec0 RCX: 455ccde0f6bffc00 RDX: dc00 RSI: 8c0ae6a0 RDI: 8c609240 RBP: c9067700 R08: 93746717 R09: 126e8ce2 R10: dc00 R11: fbfff26e8ce3 R12: 1920cebc R13: dc00 R14: c9067600 R15: 0246 __fs_reclaim_acquire mm/page_alloc.c:3856 [inline] fs_reclaim_acquire+0x88/0x140 mm/page_alloc.c:3870 might_alloc include/linux/sched/mm.h:334 [inline] slab_pre_alloc_hook mm/slub.c:3979 [inline] slab_alloc_node mm/slub.c:4057 [inline] __do_kmalloc_node mm/slub.c:4197 [inline] __kmalloc_noprof+0xa9/0x400 mm/slub.c:4210 kmalloc_noprof include/linux/slab.h:685 [inline] kzalloc_noprof include/linux/slab.h:807 [inline] kobject_get_path+0xb8/0x230 lib/kobject.c:161 kobject_uevent_env+0x2a5/0x8e0 lib/kobject_uevent.c:545 kernel_add_sysfs_param+0x10a/0x130 kernel/params.c:821 param_sysfs_builtin+0x16e/0x1f0 kernel/params.c:856 param_sysfs_builtin_init+0x31/0x40 kernel/params.c:990 do_one_initcall+0x248/0x880 init/main.c:1267 do_initcall_level+0x157/0x210 init/main.c:1329 do_initcalls+0x3f/0x80 init/main.c:1345 kernel_init_freeable+0x435/0x5d0 init/main.c:1578 kernel_init+0x1d/0x2b0 init/main.c:1467 ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:144 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 Code disassembly (best guess): 0: 2b 00 sub(%rax),%eax 2: 74 08 je 0xc 4: 4c 89 f7mov%r14,%rdi 7: e8 8a 32 8c 00 call 0x8c3296 c: f6 44 24 61 02 testb $0x2,0x61(%rsp) 11: 0f 85 85 01 00 00 jne0x19c 17: 41 f7 c7 00 02 00 00test $0x200,%r15d 1e: 74 01 je 0x21 20: fb sti 21: 48 c7 44 24 40 0e 36movq $0x45e0360e,0x40(%rsp) 28: e0 4
[PATCH v4 3/4] platform/x86/intel/ifs: Add SBAF test support
From: Jithu Joseph In a core, the SBAF test engine is shared between sibling CPUs. An SBAF test image contains multiple bundles. Each bundle is further composed of subunits called programs. When a SBAF test (for a particular core) is triggered by the user, each SBAF bundle from the loaded test image is executed sequentially on all the threads on the core using the stop_core_cpuslocked mechanism. Each bundle execution is initiated by writing to MSR_ACTIVATE_SBAF. SBAF test bundle execution may be aborted when an interrupt occurs or if the CPU does not have enough power budget for the test. In these cases the kernel restarts the test from the aborted bundle. SBAF execution is not retried if the test fails or if the test makes no forward progress after 5 retries. Reviewed-by: Ashok Raj Reviewed-by: Tony Luck Reviewed-by: Ilpo Järvinen Signed-off-by: Jithu Joseph Signed-off-by: Kuppuswamy Sathyanarayanan --- Changes since v3: * None Changes since v2: * Removed unnecessary parenthesis for 2 * HZ. * Changed "Non valid" to Non-valid. * Use simplified confition for sbaf_bundle_completed(). drivers/platform/x86/intel/ifs/ifs.h | 30 +++ drivers/platform/x86/intel/ifs/runtest.c | 232 +++ 2 files changed, 262 insertions(+) diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h index 600bb8a1b285..b261be46bce8 100644 --- a/drivers/platform/x86/intel/ifs/ifs.h +++ b/drivers/platform/x86/intel/ifs/ifs.h @@ -157,6 +157,8 @@ #define MSR_SBAF_HASHES_STATUS 0x02b9 #define MSR_AUTHENTICATE_AND_COPY_SBAF_CHUNK 0x02ba #define MSR_SBAF_CHUNKS_AUTHENTICATION_STATUS 0x02bb +#define MSR_ACTIVATE_SBAF 0x02bc +#define MSR_SBAF_STATUS0x02bd #define MSR_COPY_SCAN_HASHES 0x02c2 #define MSR_SCAN_HASHES_STATUS 0x02c3 @@ -283,6 +285,34 @@ union ifs_array { }; }; +/* MSR_ACTIVATE_SBAF bit fields */ +union ifs_sbaf { + u64 data; + struct { + u32 bundle_idx :9; + u32 rsvd1 :5; + u32 pgm_idx :2; + u32 rsvd2 :16; + u32 delay :31; + u32 sigmce :1; + }; +}; + +/* MSR_SBAF_STATUS bit fields */ +union ifs_sbaf_status { + u64 data; + struct { + u32 bundle_idx :9; + u32 rsvd1 :5; + u32 pgm_idx :2; + u32 rsvd2 :16; + u32 error_code :8; + u32 rsvd3 :21; + u32 test_fail :1; + u32 sbaf_status :2; + }; +}; + /* * Driver populated error-codes * 0xFD: Test timed out before completing all the chunks. diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c index 282e4bfe30da..2a37f009d0b3 100644 --- a/drivers/platform/x86/intel/ifs/runtest.c +++ b/drivers/platform/x86/intel/ifs/runtest.c @@ -29,6 +29,13 @@ struct run_params { union ifs_status status; }; +struct sbaf_run_params { + struct ifs_data *ifsd; + int *retry_cnt; + union ifs_sbaf *activate; + union ifs_sbaf_status status; +}; + /* * Number of TSC cycles that a logical CPU will wait for the other * logical CPU on the core in the WRMSR(ACTIVATE_SCAN). @@ -146,6 +153,7 @@ static bool can_restart(union ifs_status status) #define SPINUNIT 100 /* 100 nsec */ static atomic_t array_cpus_in; static atomic_t scan_cpus_in; +static atomic_t sbaf_cpus_in; /* * Simplified cpu sibling rendezvous loop based on microcode loader __wait_for_cpus() @@ -387,6 +395,224 @@ static void ifs_array_test_gen1(int cpu, struct device *dev) ifsd->status = SCAN_TEST_PASS; } +#define SBAF_STATUS_PASS 0 +#define SBAF_STATUS_SIGN_FAIL 1 +#define SBAF_STATUS_INTR 2 +#define SBAF_STATUS_TEST_FAIL 3 + +enum sbaf_status_err_code { + IFS_SBAF_NO_ERROR = 0, + IFS_SBAF_OTHER_THREAD_COULD_NOT_JOIN= 1, + IFS_SBAF_INTERRUPTED_BEFORE_RENDEZVOUS = 2, + IFS_SBAF_UNASSIGNED_ERROR_CODE3 = 3, + IFS_SBAF_INVALID_BUNDLE_INDEX = 4, + IFS_SBAF_MISMATCH_ARGS_BETWEEN_THREADS = 5, + IFS_SBAF_CORE_NOT_CAPABLE_CURRENTLY = 6, + IFS_SBAF_UNASSIGNED_ERROR_CODE7 = 7, + IFS_SBAF_EXCEED_NUMBER_OF_THREADS_CONCURRENT= 8, + IFS_SBAF_INTERRUPTED_DURING_EXECUTION = 9, + IFS_SBAF_INVALID_PROGRAM_INDEX = 0xA, + IFS_SBAF_CORRUPTED_CHUNK= 0xB, + IFS_SBAF_DID_NOT_START
[PATCH v4 2/4] platform/x86/intel/ifs: Add SBAF test image loading support
From: Jithu Joseph Structural Based Functional Test at Field (SBAF) is a new type of testing that provides comprehensive core test coverage complementing existing IFS tests like Scan at Field (SAF) or ArrayBist. SBAF device will appear as a new device instance (intel_ifs_2) under /sys/devices/virtual/misc. The user interaction necessary to load the test image and test a particular core is the same as the existing scan test (intel_ifs_0). During the loading stage, the driver will look for a file named ff-mm-ss-.sbft in the /lib/firmware/intel/ifs_2 directory. The hardware interaction needed for loading the image is similar to SAF, with the only difference being the MSR addresses used. Reuse the SAF image loading code, passing the SBAF-specific MSR addresses via struct ifs_test_msrs in the driver device data. Unlike SAF, the SBAF test image chunks are further divided into smaller logical entities called bundles. Since the SBAF test is initiated per bundle, cache the maximum number of bundles in the current image, which is used for iterating through bundles during SBAF test execution. Reviewed-by: Ashok Raj Reviewed-by: Tony Luck Reviewed-by: Ilpo Järvinen Signed-off-by: Jithu Joseph Co-developed-by: Kuppuswamy Sathyanarayanan Signed-off-by: Kuppuswamy Sathyanarayanan --- Changes since v3: * Added missing error return in validate_ifs_metadata(). arch/x86/include/asm/msr-index.h | 2 ++ drivers/platform/x86/intel/ifs/ifs.h | 37 ++- drivers/platform/x86/intel/ifs/core.c | 24 + drivers/platform/x86/intel/ifs/load.c | 16 +--- 4 files changed, 74 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 82c6a4d350e0..a7c06a46fb76 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -247,6 +247,8 @@ #define MSR_INTEGRITY_CAPS_ARRAY_BIST BIT(MSR_INTEGRITY_CAPS_ARRAY_BIST_BIT) #define MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT 4 #define MSR_INTEGRITY_CAPS_PERIODIC_BIST BIT(MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT) +#define MSR_INTEGRITY_CAPS_SBAF_BIT8 +#define MSR_INTEGRITY_CAPS_SBAF BIT(MSR_INTEGRITY_CAPS_SBAF_BIT) #define MSR_INTEGRITY_CAPS_SAF_GEN_MASKGENMASK_ULL(10, 9) #define MSR_LBR_NHM_FROM 0x0680 diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h index 738cbc7a5d00..600bb8a1b285 100644 --- a/drivers/platform/x86/intel/ifs/ifs.h +++ b/drivers/platform/x86/intel/ifs/ifs.h @@ -126,11 +126,38 @@ * The driver does not make use of this, it only tests one core at a time. * * .. [#f1] https://github.com/intel/TBD + * + * + * Structural Based Functional Test at Field (SBAF): + * + * + * SBAF is a new type of testing that provides comprehensive core test + * coverage complementing Scan at Field (SAF) testing. SBAF mimics the + * manufacturing screening environment and leverages the same test suite. + * It makes use of Design For Test (DFT) observation sites and features + * to maximize coverage in minimum time. + * + * Similar to the SAF test, SBAF isolates the core under test from the + * rest of the system during execution. Upon completion, the core + * seamlessly resets to its pre-test state and resumes normal operation. + * Any machine checks or hangs encountered during the test are confined to + * the isolated core, preventing disruption to the overall system. + * + * Like the SAF test, the SBAF test is also divided into multiple batches, + * and each batch test can take hundreds of milliseconds (100-200 ms) to + * complete. If such a lengthy interruption is undesirable, it is + * recommended to relocate the time-sensitive applications to other cores. */ #include #include #define MSR_ARRAY_BIST 0x0105 + +#define MSR_COPY_SBAF_HASHES 0x02b8 +#define MSR_SBAF_HASHES_STATUS 0x02b9 +#define MSR_AUTHENTICATE_AND_COPY_SBAF_CHUNK 0x02ba +#define MSR_SBAF_CHUNKS_AUTHENTICATION_STATUS 0x02bb + #define MSR_COPY_SCAN_HASHES 0x02c2 #define MSR_SCAN_HASHES_STATUS 0x02c3 #define MSR_AUTHENTICATE_AND_COPY_CHUNK0x02c4 @@ -140,6 +167,7 @@ #define MSR_ARRAY_TRIGGER 0x02d6 #define MSR_ARRAY_STATUS 0x02d7 #define MSR_SAF_CTRL 0x04f0 +#define MSR_SBAF_CTRL 0x04f8 #define SCAN_NOT_TESTED0 #define SCAN_TEST_PASS 1 @@ -147,6 +175,7 @@ #define IFS_TYPE_SAF 0 #define IFS_TYPE_ARRAY_BIST1 +#define IFS_TYPE_SBAF 2 #define ARRAY_GEN0 0 #define ARRAY_GEN1 1 @@ -196,7 +225,8 @@ union
[PATCH v4 1/4] platform/x86/intel/ifs: Refactor MSR usage in IFS test code
IFS tests such as Scan at Field (SAF) or Structural Based Functional Test at Field (SBAF), require the user to load a test image. The image loading process is similar across these tests, with the only difference being MSR addresses used. To reuse the code between these tests, remove the hard coding of MSR addresses and allow the driver to pass the MSR addresses per IFS test (via driver device data). Add a new structure named "struct ifs_test_msrs" to specify the test-specific MSR addresses. Each IFS test will provide this structure, enabling them to reuse the common code. This is a preliminary patch in preparation for the addition of SBAF support. Reviewed-by: Ashok Raj Reviewed-by: Tony Luck Reviewed-by: Ilpo Järvinen Signed-off-by: Kuppuswamy Sathyanarayanan --- drivers/platform/x86/intel/ifs/ifs.h | 25 + drivers/platform/x86/intel/ifs/core.c | 9 + drivers/platform/x86/intel/ifs/load.c | 24 ++-- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h index 56b9f3e3cf76..738cbc7a5d00 100644 --- a/drivers/platform/x86/intel/ifs/ifs.h +++ b/drivers/platform/x86/intel/ifs/ifs.h @@ -266,6 +266,22 @@ struct ifs_test_caps { int test_num; }; +/** + * struct ifs_test_msrs - MSRs used in IFS tests + * @copy_hashes: Copy test hash data + * @copy_hashes_status: Status of copied test hash data + * @copy_chunks: Copy chunks of the test data + * @copy_chunks_status: Status of the copied test data chunks + * @test_ctrl: Control the test attributes + */ +struct ifs_test_msrs { + u32 copy_hashes; + u32 copy_hashes_status; + u32 copy_chunks; + u32 copy_chunks_status; + u32 test_ctrl; +}; + /** * struct ifs_data - attributes related to intel IFS driver * @loaded_version: stores the currently loaded ifs image version. @@ -299,6 +315,7 @@ struct ifs_work { struct ifs_device { const struct ifs_test_caps *test_caps; + const struct ifs_test_msrs *test_msrs; struct ifs_data rw_data; struct miscdevice misc; }; @@ -319,6 +336,14 @@ static inline const struct ifs_test_caps *ifs_get_test_caps(struct device *dev) return d->test_caps; } +static inline const struct ifs_test_msrs *ifs_get_test_msrs(struct device *dev) +{ + struct miscdevice *m = dev_get_drvdata(dev); + struct ifs_device *d = container_of(m, struct ifs_device, misc); + + return d->test_msrs; +} + extern bool *ifs_pkg_auth; int ifs_load_firmware(struct device *dev); int do_core_test(int cpu, struct device *dev); diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c index 33412a584836..f204ebbbf769 100644 --- a/drivers/platform/x86/intel/ifs/core.c +++ b/drivers/platform/x86/intel/ifs/core.c @@ -39,9 +39,18 @@ static const struct ifs_test_caps array_test = { .test_num = IFS_TYPE_ARRAY_BIST, }; +static const struct ifs_test_msrs scan_msrs = { + .copy_hashes = MSR_COPY_SCAN_HASHES, + .copy_hashes_status = MSR_SCAN_HASHES_STATUS, + .copy_chunks = MSR_AUTHENTICATE_AND_COPY_CHUNK, + .copy_chunks_status = MSR_CHUNKS_AUTHENTICATION_STATUS, + .test_ctrl = MSR_SAF_CTRL, +}; + static struct ifs_device ifs_devices[] = { [IFS_TYPE_SAF] = { .test_caps = &scan_test, + .test_msrs = &scan_msrs, .misc = { .name = "intel_ifs_0", .minor = MISC_DYNAMIC_MINOR, diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c index 39f19cb51749..ad0c107f0922 100644 --- a/drivers/platform/x86/intel/ifs/load.c +++ b/drivers/platform/x86/intel/ifs/load.c @@ -118,15 +118,17 @@ static void copy_hashes_authenticate_chunks(struct work_struct *work) union ifs_scan_hashes_status hashes_status; union ifs_chunks_auth_status chunk_status; struct device *dev = local_work->dev; + const struct ifs_test_msrs *msrs; int i, num_chunks, chunk_size; struct ifs_data *ifsd; u64 linear_addr, base; u32 err_code; ifsd = ifs_get_data(dev); + msrs = ifs_get_test_msrs(dev); /* run scan hash copy */ - wrmsrl(MSR_COPY_SCAN_HASHES, ifs_hash_ptr); - rdmsrl(MSR_SCAN_HASHES_STATUS, hashes_status.data); + wrmsrl(msrs->copy_hashes, ifs_hash_ptr); + rdmsrl(msrs->copy_hashes_status, hashes_status.data); /* enumerate the scan image information */ num_chunks = hashes_status.num_chunks; @@ -147,8 +149,8 @@ static void copy_hashes_authenticate_chunks(struct work_struct *work) linear_addr = base + i * chunk_size; linear_addr |= i; - wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, linear_addr); - rdmsrl(MSR_CHUN
[PATCH v4 0/4] Add SBAF test to IFS
This patch series adds support for Structural Based Functional Test at Field (SBAF) in the IFS driver. SBAF is a new type of testing that provides comprehensive core test coverage, complementing existing IFS tests like Scan at Field (SAF) and ArrayBist. Granite Rapids (GNR) is the first platform that supports SBAF. SBAF mimics the manufacturing screening environment and leverages the same test suite. It makes use of Design For Test (DFT) observation sites and features to maximize coverage in minimum time. Similar to the SAF test, SBAF isolates the core under test from the rest of the system during execution. Upon completion, the core seamlessly resets to its pre-test state and resumes normal operation. Any machine checks or hangs encountered during the test are confined to the isolated core, preventing disruption to the overall system. Like SAF test, the SBAF test is also divided into multiple batches, and each batch test can take hundreds of milliseconds (100-200 ms) to complete. If such a lengthy interruption is undesirable, it is recommended to relocate the time-sensitive applications to other cores for the duration of the test. Patch Details: Patch 1/4: Refactors MSR usage in IFS image loading code to share the code between SBAF and SAF tests. Patch 2/4: Leverages SAF image loading logic and adds SBAF image loading support. Patch 3/4: Adds support for user to trigger SBAF test. Patch 4/4: Adds trace support for SBAF tests. This series is originally authored by Jithu Joseph. I have made cleanups related to code reuse between the SBAF and SAF tests and resubmitting it for review. Changes since v3: * Rebased on top of v6.11-rc1 * Added missing error return value in validate_ifs_metadata(). Changes since v2: * Added Reviewed-by tags from Ilpo and Steven. * Fixed minor issues raised by Ilpo. Changes since v1: * Addressed trace struct hole issue (Steven) * Fixed initialization issue in ifs_sbaf_test_core() (Ilpo) Jithu Joseph (3): platform/x86/intel/ifs: Add SBAF test image loading support platform/x86/intel/ifs: Add SBAF test support trace: platform/x86/intel/ifs: Add SBAF trace support Kuppuswamy Sathyanarayanan (1): platform/x86/intel/ifs: Refactor MSR usage in IFS test code arch/x86/include/asm/msr-index.h | 2 + drivers/platform/x86/intel/ifs/ifs.h | 92 - include/trace/events/intel_ifs.h | 27 +++ drivers/platform/x86/intel/ifs/core.c| 33 drivers/platform/x86/intel/ifs/load.c| 40 ++-- drivers/platform/x86/intel/ifs/runtest.c | 233 +++ 6 files changed, 412 insertions(+), 15 deletions(-) -- 2.25.1
[PATCH] LoongArch: Revert qspinlock to test-and-set on VMs
Similar with x86, when VM is detected, revert to a simple test-and-set lock to avoid the horrors of queue preemption. Tested on 3C5000 Dual-way machine with 32 cores and 2 numa nodes, test case is kcbench on kernel mainline 6.10, the detailed command is "kcbench --src /root/src/linux" Performance on host machine kernel compile time performance impact Original 150.29 seconds With patch 150.19 secondsalmost no impact Performance on virtual machine: 1. 1 VM with 32 vCPUs and 2 numa node, numa node pinned kernel compile time performance impact Original 170.87 seconds With patch 171.73 secondsalmost no impact 2. 2 VMs, each VM with 32 vCPUs and 2 numa node, numa node pinned kernel compile time performance impact Original 2362.04 seconds With patch 354.73 seconds+565% Signed-off-by: Bibo Mao --- arch/loongarch/include/asm/Kbuild | 1 - arch/loongarch/include/asm/paravirt.h | 3 ++ arch/loongarch/include/asm/qspinlock.h | 41 ++ arch/loongarch/kernel/paravirt.c | 9 ++ arch/loongarch/kernel/setup.c | 5 arch/loongarch/kernel/smp.c| 2 ++ 6 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 arch/loongarch/include/asm/qspinlock.h diff --git a/arch/loongarch/include/asm/Kbuild b/arch/loongarch/include/asm/Kbuild index 2bb3676429c0..4635b755b2b4 100644 --- a/arch/loongarch/include/asm/Kbuild +++ b/arch/loongarch/include/asm/Kbuild @@ -6,7 +6,6 @@ generic-y += mcs_spinlock.h generic-y += parport.h generic-y += early_ioremap.h generic-y += qrwlock.h -generic-y += qspinlock.h generic-y += user.h generic-y += ioctl.h generic-y += statfs.h diff --git a/arch/loongarch/include/asm/paravirt.h b/arch/loongarch/include/asm/paravirt.h index dddec49671ae..dcc2b46d31fe 100644 --- a/arch/loongarch/include/asm/paravirt.h +++ b/arch/loongarch/include/asm/paravirt.h @@ -19,6 +19,7 @@ static inline u64 paravirt_steal_clock(int cpu) int __init pv_ipi_init(void); int __init pv_time_init(void); +void __init pv_spinlock_init(void); #else @@ -31,5 +32,7 @@ static inline int pv_time_init(void) { return 0; } + +static inline void pv_spinlock_init(void) { } #endif // CONFIG_PARAVIRT #endif diff --git a/arch/loongarch/include/asm/qspinlock.h b/arch/loongarch/include/asm/qspinlock.h new file mode 100644 index ..b2d53b8c6679 --- /dev/null +++ b/arch/loongarch/include/asm/qspinlock.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LOONGARCH_QSPINLOCK_H +#define _ASM_LOONGARCH_QSPINLOCK_H + +#include +#include + +#ifdef CONFIG_PARAVIRT + +DECLARE_STATIC_KEY_TRUE(virt_spin_lock_key); + +#define virt_spin_lock virt_spin_lock +static inline bool virt_spin_lock(struct qspinlock *lock) +{ + int val; + + if (static_branch_likely(&virt_spin_lock_key)) + return false; + + /* +* On hypervisors without PARAVIRT_SPINLOCKS support we fall + * back to a Test-and-Set spinlock, because fair locks have +* horrible lock 'holder' preemption issues. +*/ + +__retry: + val = atomic_read(&lock->val); + + if (val || !atomic_try_cmpxchg(&lock->val, &val, _Q_LOCKED_VAL)) { + cpu_relax(); + goto __retry; + } + + return true; +} + +#endif /* CONFIG_PARAVIRT */ + +#include + +#endif // _ASM_LOONGARCH_QSPINLOCK_H diff --git a/arch/loongarch/kernel/paravirt.c b/arch/loongarch/kernel/paravirt.c index 9c9b75b76f62..49ebc54bdbcb 100644 --- a/arch/loongarch/kernel/paravirt.c +++ b/arch/loongarch/kernel/paravirt.c @@ -9,6 +9,7 @@ #include #include +DEFINE_STATIC_KEY_TRUE(virt_spin_lock_key); static int has_steal_clock; struct static_key paravirt_steal_enabled; struct static_key paravirt_steal_rq_enabled; @@ -300,3 +301,11 @@ int __init pv_time_init(void) return 0; } + +void __init pv_spinlock_init(void) +{ + if (!cpu_has_hypervisor) + return; + + static_branch_disable(&virt_spin_lock_key); +} diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c index 0f0740f0be27..70a670efe3cf 100644 --- a/arch/loongarch/kernel/setup.c +++ b/arch/loongarch/kernel/setup.c @@ -599,6 +599,11 @@ void __init setup_arch(char **cmdline_p) parse_early_param(); reserve_initrd_mem(); + /* +* Initialise the static keys early as they may be enabled by the +* cpufeature code and early parameters. +*/ + jump_label_init(); platform_init(); arch_mem_init(cmdline_p); diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c index ca405ab86aae..f499bff1050b 100644 --- a/arch/loongarch/kernel/smp.c +++ b/arch/loongarch/kernel/smp.c @@ -
Re: [PATCH net-next v4 3/3] test/vsock: add ioctl unsent bytes test
On Tue, Jul 30, 2024 at 09:43:08PM GMT, Luigi Leonardi via B4 Relay wrote: From: Luigi Leonardi Introduce two tests, one for SOCK_STREAM and one for SOCK_SEQPACKET, which use SIOCOUTQ ioctl to check that the number of unsent bytes is zero after delivering a packet. vsock_connect and vsock_accept are no longer static: this is to create more generic tests, allowing code to be reused for SEQPACKET and STREAM. Yeah, good idea. We should use them for other tests as well. (for the future) Signed-off-by: Luigi Leonardi --- tools/testing/vsock/util.c | 6 +-- tools/testing/vsock/util.h | 3 ++ tools/testing/vsock/vsock_test.c | 85 3 files changed, 91 insertions(+), 3 deletions(-) LGTM and I ran them. All good :-) Reviewed-by: Stefano Garzarella diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c index 554b290fefdc..a3d448a075e3 100644 --- a/tools/testing/vsock/util.c +++ b/tools/testing/vsock/util.c @@ -139,7 +139,7 @@ int vsock_bind_connect(unsigned int cid, unsigned int port, unsigned int bind_po } /* Connect to and return the file descriptor. */ -static int vsock_connect(unsigned int cid, unsigned int port, int type) +int vsock_connect(unsigned int cid, unsigned int port, int type) { union { struct sockaddr sa; @@ -226,8 +226,8 @@ static int vsock_listen(unsigned int cid, unsigned int port, int type) /* Listen on and return the first incoming connection. The remote * address is stored to clientaddrp. clientaddrp may be NULL. */ -static int vsock_accept(unsigned int cid, unsigned int port, - struct sockaddr_vm *clientaddrp, int type) +int vsock_accept(unsigned int cid, unsigned int port, +struct sockaddr_vm *clientaddrp, int type) { union { struct sockaddr sa; diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h index e95e62485959..fff22d4a14c0 100644 --- a/tools/testing/vsock/util.h +++ b/tools/testing/vsock/util.h @@ -39,6 +39,9 @@ struct test_case { void init_signals(void); unsigned int parse_cid(const char *str); unsigned int parse_port(const char *str); +int vsock_connect(unsigned int cid, unsigned int port, int type); +int vsock_accept(unsigned int cid, unsigned int port, +struct sockaddr_vm *clientaddrp, int type); int vsock_stream_connect(unsigned int cid, unsigned int port); int vsock_bind_connect(unsigned int cid, unsigned int port, unsigned int bind_port, int type); diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c index f851f8961247..8d38dbf8f41f 100644 --- a/tools/testing/vsock/vsock_test.c +++ b/tools/testing/vsock/vsock_test.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include "vsock_test_zerocopy.h" #include "timeout.h" @@ -1238,6 +1240,79 @@ static void test_double_bind_connect_client(const struct test_opts *opts) } } +#define MSG_BUF_IOCTL_LEN 64 +static void test_unsent_bytes_server(const struct test_opts *opts, int type) +{ + unsigned char buf[MSG_BUF_IOCTL_LEN]; + int client_fd; + + client_fd = vsock_accept(VMADDR_CID_ANY, opts->peer_port, NULL, type); + if (client_fd < 0) { + perror("accept"); + exit(EXIT_FAILURE); + } + + recv_buf(client_fd, buf, sizeof(buf), 0, sizeof(buf)); + control_writeln("RECEIVED"); + + close(client_fd); +} + +static void test_unsent_bytes_client(const struct test_opts *opts, int type) +{ + unsigned char buf[MSG_BUF_IOCTL_LEN]; + int ret, fd, sock_bytes_unsent; + + fd = vsock_connect(opts->peer_cid, opts->peer_port, type); + if (fd < 0) { + perror("connect"); + exit(EXIT_FAILURE); + } + + for (int i = 0; i < sizeof(buf); i++) + buf[i] = rand() & 0xFF; + + send_buf(fd, buf, sizeof(buf), 0, sizeof(buf)); + control_expectln("RECEIVED"); + + ret = ioctl(fd, SIOCOUTQ, &sock_bytes_unsent); + if (ret < 0) { + if (errno == EOPNOTSUPP) { + fprintf(stderr, "Test skipped, SIOCOUTQ not supported.\n"); + } else { + perror("ioctl"); + exit(EXIT_FAILURE); + } + } else if (ret == 0 && sock_bytes_unsent != 0) { + fprintf(stderr, + "Unexpected 'SIOCOUTQ' value, expected 0, got %i\n", + sock_bytes_unsent); + exit(EXIT_FAILURE); + } + + close(fd); +} + +static void test_stream_unsent_bytes_client(const struct test_opts *opts) +{ + test_unsent_bytes_client(opts, SOCK_STREAM); +} + +static void test_stream_unsent_bytes_server(const struct test_opts *opts)
[PATCH net-next v4 3/3] test/vsock: add ioctl unsent bytes test
From: Luigi Leonardi Introduce two tests, one for SOCK_STREAM and one for SOCK_SEQPACKET, which use SIOCOUTQ ioctl to check that the number of unsent bytes is zero after delivering a packet. vsock_connect and vsock_accept are no longer static: this is to create more generic tests, allowing code to be reused for SEQPACKET and STREAM. Signed-off-by: Luigi Leonardi --- tools/testing/vsock/util.c | 6 +-- tools/testing/vsock/util.h | 3 ++ tools/testing/vsock/vsock_test.c | 85 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c index 554b290fefdc..a3d448a075e3 100644 --- a/tools/testing/vsock/util.c +++ b/tools/testing/vsock/util.c @@ -139,7 +139,7 @@ int vsock_bind_connect(unsigned int cid, unsigned int port, unsigned int bind_po } /* Connect to and return the file descriptor. */ -static int vsock_connect(unsigned int cid, unsigned int port, int type) +int vsock_connect(unsigned int cid, unsigned int port, int type) { union { struct sockaddr sa; @@ -226,8 +226,8 @@ static int vsock_listen(unsigned int cid, unsigned int port, int type) /* Listen on and return the first incoming connection. The remote * address is stored to clientaddrp. clientaddrp may be NULL. */ -static int vsock_accept(unsigned int cid, unsigned int port, - struct sockaddr_vm *clientaddrp, int type) +int vsock_accept(unsigned int cid, unsigned int port, +struct sockaddr_vm *clientaddrp, int type) { union { struct sockaddr sa; diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h index e95e62485959..fff22d4a14c0 100644 --- a/tools/testing/vsock/util.h +++ b/tools/testing/vsock/util.h @@ -39,6 +39,9 @@ struct test_case { void init_signals(void); unsigned int parse_cid(const char *str); unsigned int parse_port(const char *str); +int vsock_connect(unsigned int cid, unsigned int port, int type); +int vsock_accept(unsigned int cid, unsigned int port, +struct sockaddr_vm *clientaddrp, int type); int vsock_stream_connect(unsigned int cid, unsigned int port); int vsock_bind_connect(unsigned int cid, unsigned int port, unsigned int bind_port, int type); diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c index f851f8961247..8d38dbf8f41f 100644 --- a/tools/testing/vsock/vsock_test.c +++ b/tools/testing/vsock/vsock_test.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include "vsock_test_zerocopy.h" #include "timeout.h" @@ -1238,6 +1240,79 @@ static void test_double_bind_connect_client(const struct test_opts *opts) } } +#define MSG_BUF_IOCTL_LEN 64 +static void test_unsent_bytes_server(const struct test_opts *opts, int type) +{ + unsigned char buf[MSG_BUF_IOCTL_LEN]; + int client_fd; + + client_fd = vsock_accept(VMADDR_CID_ANY, opts->peer_port, NULL, type); + if (client_fd < 0) { + perror("accept"); + exit(EXIT_FAILURE); + } + + recv_buf(client_fd, buf, sizeof(buf), 0, sizeof(buf)); + control_writeln("RECEIVED"); + + close(client_fd); +} + +static void test_unsent_bytes_client(const struct test_opts *opts, int type) +{ + unsigned char buf[MSG_BUF_IOCTL_LEN]; + int ret, fd, sock_bytes_unsent; + + fd = vsock_connect(opts->peer_cid, opts->peer_port, type); + if (fd < 0) { + perror("connect"); + exit(EXIT_FAILURE); + } + + for (int i = 0; i < sizeof(buf); i++) + buf[i] = rand() & 0xFF; + + send_buf(fd, buf, sizeof(buf), 0, sizeof(buf)); + control_expectln("RECEIVED"); + + ret = ioctl(fd, SIOCOUTQ, &sock_bytes_unsent); + if (ret < 0) { + if (errno == EOPNOTSUPP) { + fprintf(stderr, "Test skipped, SIOCOUTQ not supported.\n"); + } else { + perror("ioctl"); + exit(EXIT_FAILURE); + } + } else if (ret == 0 && sock_bytes_unsent != 0) { + fprintf(stderr, + "Unexpected 'SIOCOUTQ' value, expected 0, got %i\n", + sock_bytes_unsent); + exit(EXIT_FAILURE); + } + + close(fd); +} + +static void test_stream_unsent_bytes_client(const struct test_opts *opts) +{ + test_unsent_bytes_client(opts, SOCK_STREAM); +} + +static void test_stream_unsent_bytes_server(const struct test_opts *opts) +{ + test_unsent_bytes_server(opts, SOCK_STREAM); +} + +static void test_seqpacket_unsent_bytes_client(const struct test_opts *opts) +{ + test_unsent_bytes_client(opts, SOCK_SEQPACKET); +} + +static void
[PATCH bpf-next 2/2] selftests/bpf: Augment send_signal test with remote signaling
Add testcases to test bpf_send_signal_pid/tgid(). In these new test cases, the main process triggers the BPF program and the forked process receives the signals. Signed-off-by: Puranjay Mohan --- .../selftests/bpf/prog_tests/send_signal.c| 110 +- .../bpf/progs/test_send_signal_kern.c | 17 ++- 2 files changed, 95 insertions(+), 32 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/send_signal.c b/tools/testing/selftests/bpf/prog_tests/send_signal.c index 6cc69900b310..a8392dfc69e2 100644 --- a/tools/testing/selftests/bpf/prog_tests/send_signal.c +++ b/tools/testing/selftests/bpf/prog_tests/send_signal.c @@ -12,13 +12,15 @@ static void sigusr1_handler(int signum) } static void test_send_signal_common(struct perf_event_attr *attr, - bool signal_thread) + bool signal_thread, bool remote) { struct test_send_signal_kern *skel; int pipe_c2p[2], pipe_p2c[2]; int err = -1, pmu_fd = -1; + volatile int j = 0; char buf[256]; pid_t pid; + int old_prio; if (!ASSERT_OK(pipe(pipe_c2p), "pipe_c2p")) return; @@ -39,9 +41,6 @@ static void test_send_signal_common(struct perf_event_attr *attr, } if (pid == 0) { - int old_prio; - volatile int j = 0; - /* install signal handler and notify parent */ ASSERT_NEQ(signal(SIGUSR1, sigusr1_handler), SIG_ERR, "signal"); @@ -52,10 +51,12 @@ static void test_send_signal_common(struct perf_event_attr *attr, * that if an interrupt happens, the underlying task * is this process. */ - errno = 0; - old_prio = getpriority(PRIO_PROCESS, 0); - ASSERT_OK(errno, "getpriority"); - ASSERT_OK(setpriority(PRIO_PROCESS, 0, -20), "setpriority"); + if (!remote) { + errno = 0; + old_prio = getpriority(PRIO_PROCESS, 0); + ASSERT_OK(errno, "getpriority"); + ASSERT_OK(setpriority(PRIO_PROCESS, 0, -20), "setpriority"); + } /* notify parent signal handler is installed */ ASSERT_EQ(write(pipe_c2p[1], buf, 1), 1, "pipe_write"); @@ -66,9 +67,12 @@ static void test_send_signal_common(struct perf_event_attr *attr, /* wait a little for signal handler */ for (int i = 0; i < 10 && !sigusr1_received; i++) { j /= i + j + 1; - if (!attr) - /* trigger the nanosleep tracepoint program. */ - usleep(1); + if (remote) + sleep(1); + else + if (!attr) + /* trigger the nanosleep tracepoint program. */ + usleep(1); } buf[0] = sigusr1_received ? '2' : '0'; @@ -79,7 +83,8 @@ static void test_send_signal_common(struct perf_event_attr *attr, ASSERT_EQ(read(pipe_p2c[0], buf, 1), 1, "pipe_read"); /* restore the old priority */ - ASSERT_OK(setpriority(PRIO_PROCESS, 0, old_prio), "setpriority"); + if (!remote) + ASSERT_OK(setpriority(PRIO_PROCESS, 0, old_prio), "setpriority"); close(pipe_c2p[1]); close(pipe_p2c[0]); @@ -93,6 +98,17 @@ static void test_send_signal_common(struct perf_event_attr *attr, if (!ASSERT_OK_PTR(skel, "skel_open_and_load")) goto skel_open_load_failure; + /* boost with a high priority so we got a higher chance +* that if an interrupt happens, the underlying task +* is this process. +*/ + if (remote) { + errno = 0; + old_prio = getpriority(PRIO_PROCESS, 0); + ASSERT_OK(errno, "getpriority"); + ASSERT_OK(setpriority(PRIO_PROCESS, 0, -20), "setpriority"); + } + if (!attr) { err = test_send_signal_kern__attach(skel); if (!ASSERT_OK(err, "skel_attach")) { @@ -100,8 +116,12 @@ static void test_send_signal_common(struct perf_event_attr *attr, goto destroy_skel; } } else { - pmu_fd = syscall(__NR_perf_event_open, attr, pid, -1 /* cpu */, --1 /* group id */, 0 /* flags */); + if (!remote) + pmu_fd = syscall(__NR_perf_event_open, attr, pid, -1 /* cpu */, +
Re: [PATCH net-next v3 3/3] test/vsock: add ioctl unsent bytes test
On Wed, Jun 26, 2024 at 02:08:37PM GMT, Luigi Leonardi via B4 Relay wrote: From: Luigi Leonardi Introduce two tests, one for SOCK_STREAM and one for SOCK_SEQPACKET, which checks after a packet is delivered, that the number of unsent bytes is zero, using ioctl SIOCOUTQ. Signed-off-by: Luigi Leonardi --- tools/testing/vsock/util.c | 6 +-- tools/testing/vsock/util.h | 3 ++ tools/testing/vsock/vsock_test.c | 85 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c index 554b290fefdc..a3d448a075e3 100644 --- a/tools/testing/vsock/util.c +++ b/tools/testing/vsock/util.c @@ -139,7 +139,7 @@ int vsock_bind_connect(unsigned int cid, unsigned int port, unsigned int bind_po } /* Connect to and return the file descriptor. */ -static int vsock_connect(unsigned int cid, unsigned int port, int type) +int vsock_connect(unsigned int cid, unsigned int port, int type) { union { struct sockaddr sa; @@ -226,8 +226,8 @@ static int vsock_listen(unsigned int cid, unsigned int port, int type) /* Listen on and return the first incoming connection. The remote * address is stored to clientaddrp. clientaddrp may be NULL. */ -static int vsock_accept(unsigned int cid, unsigned int port, - struct sockaddr_vm *clientaddrp, int type) +int vsock_accept(unsigned int cid, unsigned int port, +struct sockaddr_vm *clientaddrp, int type) { union { struct sockaddr sa; diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h index e95e62485959..fff22d4a14c0 100644 --- a/tools/testing/vsock/util.h +++ b/tools/testing/vsock/util.h @@ -39,6 +39,9 @@ struct test_case { void init_signals(void); unsigned int parse_cid(const char *str); unsigned int parse_port(const char *str); +int vsock_connect(unsigned int cid, unsigned int port, int type); +int vsock_accept(unsigned int cid, unsigned int port, +struct sockaddr_vm *clientaddrp, int type); I'd mention in the commit description that you need these functions to be more generic. Maybe in the future we can re-use them where we share the same test for both SEQPACKET and STREAM. The rest LGTM. Thanks, Stefano int vsock_stream_connect(unsigned int cid, unsigned int port); int vsock_bind_connect(unsigned int cid, unsigned int port, unsigned int bind_port, int type); diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c index f851f8961247..76bd17b4b291 100644 --- a/tools/testing/vsock/vsock_test.c +++ b/tools/testing/vsock/vsock_test.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include "vsock_test_zerocopy.h" #include "timeout.h" @@ -1238,6 +1240,79 @@ static void test_double_bind_connect_client(const struct test_opts *opts) } } +#define MSG_BUF_IOCTL_LEN 64 +static void test_unsent_bytes_server(const struct test_opts *opts, int type) +{ + unsigned char buf[MSG_BUF_IOCTL_LEN]; + int client_fd; + + client_fd = vsock_accept(VMADDR_CID_ANY, 1234, NULL, type); + if (client_fd < 0) { + perror("accept"); + exit(EXIT_FAILURE); + } + + recv_buf(client_fd, buf, sizeof(buf), 0, sizeof(buf)); + control_writeln("RECEIVED"); + + close(client_fd); +} + +static void test_unsent_bytes_client(const struct test_opts *opts, int type) +{ + unsigned char buf[MSG_BUF_IOCTL_LEN]; + int ret, fd, sock_bytes_unsent; + + fd = vsock_connect(opts->peer_cid, 1234, type); + if (fd < 0) { + perror("connect"); + exit(EXIT_FAILURE); + } + + for (int i = 0; i < sizeof(buf); i++) + buf[i] = rand() & 0xFF; + + send_buf(fd, buf, sizeof(buf), 0, sizeof(buf)); + control_expectln("RECEIVED"); + + ret = ioctl(fd, SIOCOUTQ, &sock_bytes_unsent); + if (ret < 0) { + if (errno == EOPNOTSUPP) { + fprintf(stderr, "Test skipped\n"); + } else { + perror("ioctl"); + exit(EXIT_FAILURE); + } + } else if (ret == 0 && sock_bytes_unsent != 0) { + fprintf(stderr, + "Unexpected 'SIOCOUTQ' value, expected 0, got %i\n", + sock_bytes_unsent); + exit(EXIT_FAILURE); + } + + close(fd); +} + +static void test_stream_unsent_bytes_client(const struct test_opts *opts) +{ + test_unsent_bytes_client(opts, SOCK_STREAM); +} + +static void test_stream_unsent_bytes_server(const struct test_opts *opts) +{ + test_unsent_bytes_server(opts, SOCK_STREAM); +} + +static void test_seqpacket_unsent_bytes_client(const struct test_
Re: [PATCH 2/2] selftests/bpf: Change uretprobe syscall number in uprobe_syscall test
On Mon, Jul 15, 2024 at 02:46:51PM +0900, Masami Hiramatsu wrote: > On Fri, 12 Jul 2024 11:27:30 -0700 > Andrii Nakryiko wrote: > > > On Fri, Jul 12, 2024 at 6:53 AM Jiri Olsa wrote: > > > > > > Fixing the syscall number value. > > > > > > Fixes: 9e7f74e64ae5 ("selftests/bpf: Add uretprobe syscall call from user > > > space test") > > > Signed-off-by: Jiri Olsa > > > --- > > > tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c | 2 +- > > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > > > > is this selftest in probes/for-next already? If yes, I'd combine these > > two patches to avoid any bisection problems yes it's all there.. I don't mind squashing it, I just did not want to combine kernel and user space parts.. up to Masami I guess > > > > but either way > > > > Acked-by: Andrii Nakryiko > > Thanks, let me pick it to for-next branch. thanks, jirka > > Thank you, > > > > > > > > diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c > > > b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c > > > index c8517c8f5313..bd8c75b620c2 100644 > > > --- a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c > > > +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c > > > @@ -216,7 +216,7 @@ static void test_uretprobe_regs_change(void) > > > } > > > > > > #ifndef __NR_uretprobe > > > -#define __NR_uretprobe 463 > > > +#define __NR_uretprobe 467 > > > #endif > > > > > > __naked unsigned long uretprobe_syscall_call_1(void) > > > -- > > > 2.45.2 > > > > > > -- > Masami Hiramatsu (Google)
Re: [PATCH 2/2] selftests/bpf: Change uretprobe syscall number in uprobe_syscall test
On Fri, 12 Jul 2024 11:27:30 -0700 Andrii Nakryiko wrote: > On Fri, Jul 12, 2024 at 6:53 AM Jiri Olsa wrote: > > > > Fixing the syscall number value. > > > > Fixes: 9e7f74e64ae5 ("selftests/bpf: Add uretprobe syscall call from user > > space test") > > Signed-off-by: Jiri Olsa > > --- > > tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > is this selftest in probes/for-next already? If yes, I'd combine these > two patches to avoid any bisection problems > > but either way > > Acked-by: Andrii Nakryiko Thanks, let me pick it to for-next branch. Thank you, > > > > diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c > > b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c > > index c8517c8f5313..bd8c75b620c2 100644 > > --- a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c > > +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c > > @@ -216,7 +216,7 @@ static void test_uretprobe_regs_change(void) > > } > > > > #ifndef __NR_uretprobe > > -#define __NR_uretprobe 463 > > +#define __NR_uretprobe 467 > > #endif > > > > __naked unsigned long uretprobe_syscall_call_1(void) > > -- > > 2.45.2 > > -- Masami Hiramatsu (Google)
Re: [PATCH V2] test/vsock: add install target
Hello: This patch was applied to netdev/net-next.git (main) by Jakub Kicinski : On Wed, 10 Jul 2024 20:27:28 +0800 you wrote: > From: Peng Fan > > Add install target for vsock to make Yocto easy to install the images. > > Signed-off-by: Peng Fan > --- > > [...] Here is the summary with links: - [V2] test/vsock: add install target https://git.kernel.org/netdev/net-next/c/42ffe242860c You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html
[PATCH v3 3/4] platform/x86/intel/ifs: Add SBAF test support
From: Jithu Joseph In a core, the SBAF test engine is shared between sibling CPUs. An SBAF test image contains multiple bundles. Each bundle is further composed of subunits called programs. When a SBAF test (for a particular core) is triggered by the user, each SBAF bundle from the loaded test image is executed sequentially on all the threads on the core using the stop_core_cpuslocked mechanism. Each bundle execution is initiated by writing to MSR_ACTIVATE_SBAF. SBAF test bundle execution may be aborted when an interrupt occurs or if the CPU does not have enough power budget for the test. In these cases the kernel restarts the test from the aborted bundle. SBAF execution is not retried if the test fails or if the test makes no forward progress after 5 retries. Reviewed-by: Ashok Raj Reviewed-by: Tony Luck Reviewed-by: Ilpo Järvinen Signed-off-by: Jithu Joseph Signed-off-by: Kuppuswamy Sathyanarayanan --- Changes since v2: * Removed unnecessary parenthesis for 2 * HZ. * Changed "Non valid" to Non-valid. * Use simplified confition for sbaf_bundle_completed(). drivers/platform/x86/intel/ifs/ifs.h | 30 +++ drivers/platform/x86/intel/ifs/runtest.c | 232 +++ 2 files changed, 262 insertions(+) diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h index 600bb8a1b285..b261be46bce8 100644 --- a/drivers/platform/x86/intel/ifs/ifs.h +++ b/drivers/platform/x86/intel/ifs/ifs.h @@ -157,6 +157,8 @@ #define MSR_SBAF_HASHES_STATUS 0x02b9 #define MSR_AUTHENTICATE_AND_COPY_SBAF_CHUNK 0x02ba #define MSR_SBAF_CHUNKS_AUTHENTICATION_STATUS 0x02bb +#define MSR_ACTIVATE_SBAF 0x02bc +#define MSR_SBAF_STATUS0x02bd #define MSR_COPY_SCAN_HASHES 0x02c2 #define MSR_SCAN_HASHES_STATUS 0x02c3 @@ -283,6 +285,34 @@ union ifs_array { }; }; +/* MSR_ACTIVATE_SBAF bit fields */ +union ifs_sbaf { + u64 data; + struct { + u32 bundle_idx :9; + u32 rsvd1 :5; + u32 pgm_idx :2; + u32 rsvd2 :16; + u32 delay :31; + u32 sigmce :1; + }; +}; + +/* MSR_SBAF_STATUS bit fields */ +union ifs_sbaf_status { + u64 data; + struct { + u32 bundle_idx :9; + u32 rsvd1 :5; + u32 pgm_idx :2; + u32 rsvd2 :16; + u32 error_code :8; + u32 rsvd3 :21; + u32 test_fail :1; + u32 sbaf_status :2; + }; +}; + /* * Driver populated error-codes * 0xFD: Test timed out before completing all the chunks. diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c index 282e4bfe30da..2a37f009d0b3 100644 --- a/drivers/platform/x86/intel/ifs/runtest.c +++ b/drivers/platform/x86/intel/ifs/runtest.c @@ -29,6 +29,13 @@ struct run_params { union ifs_status status; }; +struct sbaf_run_params { + struct ifs_data *ifsd; + int *retry_cnt; + union ifs_sbaf *activate; + union ifs_sbaf_status status; +}; + /* * Number of TSC cycles that a logical CPU will wait for the other * logical CPU on the core in the WRMSR(ACTIVATE_SCAN). @@ -146,6 +153,7 @@ static bool can_restart(union ifs_status status) #define SPINUNIT 100 /* 100 nsec */ static atomic_t array_cpus_in; static atomic_t scan_cpus_in; +static atomic_t sbaf_cpus_in; /* * Simplified cpu sibling rendezvous loop based on microcode loader __wait_for_cpus() @@ -387,6 +395,224 @@ static void ifs_array_test_gen1(int cpu, struct device *dev) ifsd->status = SCAN_TEST_PASS; } +#define SBAF_STATUS_PASS 0 +#define SBAF_STATUS_SIGN_FAIL 1 +#define SBAF_STATUS_INTR 2 +#define SBAF_STATUS_TEST_FAIL 3 + +enum sbaf_status_err_code { + IFS_SBAF_NO_ERROR = 0, + IFS_SBAF_OTHER_THREAD_COULD_NOT_JOIN= 1, + IFS_SBAF_INTERRUPTED_BEFORE_RENDEZVOUS = 2, + IFS_SBAF_UNASSIGNED_ERROR_CODE3 = 3, + IFS_SBAF_INVALID_BUNDLE_INDEX = 4, + IFS_SBAF_MISMATCH_ARGS_BETWEEN_THREADS = 5, + IFS_SBAF_CORE_NOT_CAPABLE_CURRENTLY = 6, + IFS_SBAF_UNASSIGNED_ERROR_CODE7 = 7, + IFS_SBAF_EXCEED_NUMBER_OF_THREADS_CONCURRENT= 8, + IFS_SBAF_INTERRUPTED_DURING_EXECUTION = 9, + IFS_SBAF_INVALID_PROGRAM_INDEX = 0xA, + IFS_SBAF_CORRUPTED_CHUNK= 0xB, + IFS_SBAF_DID_NOT_START = 0xC, +}; + +static const
[PATCH v3 2/4] platform/x86/intel/ifs: Add SBAF test image loading support
From: Jithu Joseph Structural Based Functional Test at Field (SBAF) is a new type of testing that provides comprehensive core test coverage complementing existing IFS tests like Scan at Field (SAF) or ArrayBist. SBAF device will appear as a new device instance (intel_ifs_2) under /sys/devices/virtual/misc. The user interaction necessary to load the test image and test a particular core is the same as the existing scan test (intel_ifs_0). During the loading stage, the driver will look for a file named ff-mm-ss-.sbft in the /lib/firmware/intel/ifs_2 directory. The hardware interaction needed for loading the image is similar to SAF, with the only difference being the MSR addresses used. Reuse the SAF image loading code, passing the SBAF-specific MSR addresses via struct ifs_test_msrs in the driver device data. Unlike SAF, the SBAF test image chunks are further divided into smaller logical entities called bundles. Since the SBAF test is initiated per bundle, cache the maximum number of bundles in the current image, which is used for iterating through bundles during SBAF test execution. Reviewed-by: Ashok Raj Reviewed-by: Tony Luck Reviewed-by: Ilpo Järvinen Signed-off-by: Jithu Joseph Co-developed-by: Kuppuswamy Sathyanarayanan Signed-off-by: Kuppuswamy Sathyanarayanan --- arch/x86/include/asm/msr-index.h | 2 ++ drivers/platform/x86/intel/ifs/ifs.h | 37 ++- drivers/platform/x86/intel/ifs/core.c | 24 + drivers/platform/x86/intel/ifs/load.c | 15 --- 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index e022e6eb766c..503d7acdda3f 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -247,6 +247,8 @@ #define MSR_INTEGRITY_CAPS_ARRAY_BIST BIT(MSR_INTEGRITY_CAPS_ARRAY_BIST_BIT) #define MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT 4 #define MSR_INTEGRITY_CAPS_PERIODIC_BIST BIT(MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT) +#define MSR_INTEGRITY_CAPS_SBAF_BIT8 +#define MSR_INTEGRITY_CAPS_SBAF BIT(MSR_INTEGRITY_CAPS_SBAF_BIT) #define MSR_INTEGRITY_CAPS_SAF_GEN_MASKGENMASK_ULL(10, 9) #define MSR_LBR_NHM_FROM 0x0680 diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h index 738cbc7a5d00..600bb8a1b285 100644 --- a/drivers/platform/x86/intel/ifs/ifs.h +++ b/drivers/platform/x86/intel/ifs/ifs.h @@ -126,11 +126,38 @@ * The driver does not make use of this, it only tests one core at a time. * * .. [#f1] https://github.com/intel/TBD + * + * + * Structural Based Functional Test at Field (SBAF): + * + * + * SBAF is a new type of testing that provides comprehensive core test + * coverage complementing Scan at Field (SAF) testing. SBAF mimics the + * manufacturing screening environment and leverages the same test suite. + * It makes use of Design For Test (DFT) observation sites and features + * to maximize coverage in minimum time. + * + * Similar to the SAF test, SBAF isolates the core under test from the + * rest of the system during execution. Upon completion, the core + * seamlessly resets to its pre-test state and resumes normal operation. + * Any machine checks or hangs encountered during the test are confined to + * the isolated core, preventing disruption to the overall system. + * + * Like the SAF test, the SBAF test is also divided into multiple batches, + * and each batch test can take hundreds of milliseconds (100-200 ms) to + * complete. If such a lengthy interruption is undesirable, it is + * recommended to relocate the time-sensitive applications to other cores. */ #include #include #define MSR_ARRAY_BIST 0x0105 + +#define MSR_COPY_SBAF_HASHES 0x02b8 +#define MSR_SBAF_HASHES_STATUS 0x02b9 +#define MSR_AUTHENTICATE_AND_COPY_SBAF_CHUNK 0x02ba +#define MSR_SBAF_CHUNKS_AUTHENTICATION_STATUS 0x02bb + #define MSR_COPY_SCAN_HASHES 0x02c2 #define MSR_SCAN_HASHES_STATUS 0x02c3 #define MSR_AUTHENTICATE_AND_COPY_CHUNK0x02c4 @@ -140,6 +167,7 @@ #define MSR_ARRAY_TRIGGER 0x02d6 #define MSR_ARRAY_STATUS 0x02d7 #define MSR_SAF_CTRL 0x04f0 +#define MSR_SBAF_CTRL 0x04f8 #define SCAN_NOT_TESTED0 #define SCAN_TEST_PASS 1 @@ -147,6 +175,7 @@ #define IFS_TYPE_SAF 0 #define IFS_TYPE_ARRAY_BIST1 +#define IFS_TYPE_SBAF 2 #define ARRAY_GEN0 0 #define ARRAY_GEN1 1 @@ -196,7 +225,8 @@ union ifs_chunks_auth_status_gen2 { u16 valid_chunks; u16
[PATCH v3 1/4] platform/x86/intel/ifs: Refactor MSR usage in IFS test code
IFS tests such as Scan at Field (SAF) or Structural Based Functional Test at Field (SBAF), require the user to load a test image. The image loading process is similar across these tests, with the only difference being MSR addresses used. To reuse the code between these tests, remove the hard coding of MSR addresses and allow the driver to pass the MSR addresses per IFS test (via driver device data). Add a new structure named "struct ifs_test_msrs" to specify the test-specific MSR addresses. Each IFS test will provide this structure, enabling them to reuse the common code. This is a preliminary patch in preparation for the addition of SBAF support. Reviewed-by: Ashok Raj Reviewed-by: Tony Luck Reviewed-by: Ilpo Järvinen Signed-off-by: Kuppuswamy Sathyanarayanan --- drivers/platform/x86/intel/ifs/ifs.h | 25 + drivers/platform/x86/intel/ifs/core.c | 9 + drivers/platform/x86/intel/ifs/load.c | 24 ++-- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h index 56b9f3e3cf76..738cbc7a5d00 100644 --- a/drivers/platform/x86/intel/ifs/ifs.h +++ b/drivers/platform/x86/intel/ifs/ifs.h @@ -266,6 +266,22 @@ struct ifs_test_caps { int test_num; }; +/** + * struct ifs_test_msrs - MSRs used in IFS tests + * @copy_hashes: Copy test hash data + * @copy_hashes_status: Status of copied test hash data + * @copy_chunks: Copy chunks of the test data + * @copy_chunks_status: Status of the copied test data chunks + * @test_ctrl: Control the test attributes + */ +struct ifs_test_msrs { + u32 copy_hashes; + u32 copy_hashes_status; + u32 copy_chunks; + u32 copy_chunks_status; + u32 test_ctrl; +}; + /** * struct ifs_data - attributes related to intel IFS driver * @loaded_version: stores the currently loaded ifs image version. @@ -299,6 +315,7 @@ struct ifs_work { struct ifs_device { const struct ifs_test_caps *test_caps; + const struct ifs_test_msrs *test_msrs; struct ifs_data rw_data; struct miscdevice misc; }; @@ -319,6 +336,14 @@ static inline const struct ifs_test_caps *ifs_get_test_caps(struct device *dev) return d->test_caps; } +static inline const struct ifs_test_msrs *ifs_get_test_msrs(struct device *dev) +{ + struct miscdevice *m = dev_get_drvdata(dev); + struct ifs_device *d = container_of(m, struct ifs_device, misc); + + return d->test_msrs; +} + extern bool *ifs_pkg_auth; int ifs_load_firmware(struct device *dev); int do_core_test(int cpu, struct device *dev); diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c index 7b11198d85a1..1a7ca74abb61 100644 --- a/drivers/platform/x86/intel/ifs/core.c +++ b/drivers/platform/x86/intel/ifs/core.c @@ -40,9 +40,18 @@ static const struct ifs_test_caps array_test = { .test_num = IFS_TYPE_ARRAY_BIST, }; +static const struct ifs_test_msrs scan_msrs = { + .copy_hashes = MSR_COPY_SCAN_HASHES, + .copy_hashes_status = MSR_SCAN_HASHES_STATUS, + .copy_chunks = MSR_AUTHENTICATE_AND_COPY_CHUNK, + .copy_chunks_status = MSR_CHUNKS_AUTHENTICATION_STATUS, + .test_ctrl = MSR_SAF_CTRL, +}; + static struct ifs_device ifs_devices[] = { [IFS_TYPE_SAF] = { .test_caps = &scan_test, + .test_msrs = &scan_msrs, .misc = { .name = "intel_ifs_0", .minor = MISC_DYNAMIC_MINOR, diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c index 39f19cb51749..ad0c107f0922 100644 --- a/drivers/platform/x86/intel/ifs/load.c +++ b/drivers/platform/x86/intel/ifs/load.c @@ -118,15 +118,17 @@ static void copy_hashes_authenticate_chunks(struct work_struct *work) union ifs_scan_hashes_status hashes_status; union ifs_chunks_auth_status chunk_status; struct device *dev = local_work->dev; + const struct ifs_test_msrs *msrs; int i, num_chunks, chunk_size; struct ifs_data *ifsd; u64 linear_addr, base; u32 err_code; ifsd = ifs_get_data(dev); + msrs = ifs_get_test_msrs(dev); /* run scan hash copy */ - wrmsrl(MSR_COPY_SCAN_HASHES, ifs_hash_ptr); - rdmsrl(MSR_SCAN_HASHES_STATUS, hashes_status.data); + wrmsrl(msrs->copy_hashes, ifs_hash_ptr); + rdmsrl(msrs->copy_hashes_status, hashes_status.data); /* enumerate the scan image information */ num_chunks = hashes_status.num_chunks; @@ -147,8 +149,8 @@ static void copy_hashes_authenticate_chunks(struct work_struct *work) linear_addr = base + i * chunk_size; linear_addr |= i; - wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, linear_addr); - rdmsrl(MSR_CHUN
[PATCH v3 0/4] Add SBAF test to IFS
This patch series adds support for Structural Based Functional Test at Field (SBAF) in the IFS driver. SBAF is a new type of testing that provides comprehensive core test coverage, complementing existing IFS tests like Scan at Field (SAF) and ArrayBist. Granite Rapids (GNR) is the first platform that supports SBAF. SBAF mimics the manufacturing screening environment and leverages the same test suite. It makes use of Design For Test (DFT) observation sites and features to maximize coverage in minimum time. Similar to the SAF test, SBAF isolates the core under test from the rest of the system during execution. Upon completion, the core seamlessly resets to its pre-test state and resumes normal operation. Any machine checks or hangs encountered during the test are confined to the isolated core, preventing disruption to the overall system. Like SAF test, the SBAF test is also divided into multiple batches, and each batch test can take hundreds of milliseconds (100-200 ms) to complete. If such a lengthy interruption is undesirable, it is recommended to relocate the time-sensitive applications to other cores for the duration of the test. Patch Details: Patch 1/4: Refactors MSR usage in IFS image loading code to share the code between SBAF and SAF tests. Patch 2/4: Leverages SAF image loading logic and adds SBAF image loading support. Patch 3/4: Adds support for user to trigger SBAF test. Patch 4/4: Adds trace support for SBAF tests. This series is originally authored by Jithu Joseph. I have made cleanups related to code reuse between the SBAF and SAF tests and resubmitting it for review. Changes since v2: * Added Reviewed-by tags from Ilpo and Steven. * Fixed minor issues raised by Ilpo. Changes since v1: * Addressed trace struct hole issue (Steven) * Fixed initialization issue in ifs_sbaf_test_core() (Ilpo) Jithu Joseph (3): platform/x86/intel/ifs: Add SBAF test image loading support platform/x86/intel/ifs: Add SBAF test support trace: platform/x86/intel/ifs: Add SBAF trace support Kuppuswamy Sathyanarayanan (1): platform/x86/intel/ifs: Refactor MSR usage in IFS test code arch/x86/include/asm/msr-index.h | 2 + drivers/platform/x86/intel/ifs/ifs.h | 92 - include/trace/events/intel_ifs.h | 27 +++ drivers/platform/x86/intel/ifs/core.c| 33 drivers/platform/x86/intel/ifs/load.c| 39 ++-- drivers/platform/x86/intel/ifs/runtest.c | 233 +++ 6 files changed, 411 insertions(+), 15 deletions(-) -- 2.25.1
Re: [PATCH 2/2] selftests/bpf: Change uretprobe syscall number in uprobe_syscall test
On Fri, Jul 12, 2024 at 6:53 AM Jiri Olsa wrote: > > Fixing the syscall number value. > > Fixes: 9e7f74e64ae5 ("selftests/bpf: Add uretprobe syscall call from user > space test") > Signed-off-by: Jiri Olsa > --- > tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > is this selftest in probes/for-next already? If yes, I'd combine these two patches to avoid any bisection problems but either way Acked-by: Andrii Nakryiko > diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c > b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c > index c8517c8f5313..bd8c75b620c2 100644 > --- a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c > +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c > @@ -216,7 +216,7 @@ static void test_uretprobe_regs_change(void) > } > > #ifndef __NR_uretprobe > -#define __NR_uretprobe 463 > +#define __NR_uretprobe 467 > #endif > > __naked unsigned long uretprobe_syscall_call_1(void) > -- > 2.45.2 >
[PATCH 2/2] selftests/bpf: Change uretprobe syscall number in uprobe_syscall test
Fixing the syscall number value. Fixes: 9e7f74e64ae5 ("selftests/bpf: Add uretprobe syscall call from user space test") Signed-off-by: Jiri Olsa --- tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c index c8517c8f5313..bd8c75b620c2 100644 --- a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c @@ -216,7 +216,7 @@ static void test_uretprobe_regs_change(void) } #ifndef __NR_uretprobe -#define __NR_uretprobe 463 +#define __NR_uretprobe 467 #endif __naked unsigned long uretprobe_syscall_call_1(void) -- 2.45.2
Re: [PATCH] test/vsock: add install target
On Thu, Jul 11, 2024 at 07:14:55AM GMT, Jakub Kicinski wrote: On Thu, 11 Jul 2024 15:38:01 +0200 Stefan Hajnoczi wrote: > Usually vsock tests test both the driver (virtio-vsock) in the guest and the > device in the host kernel (vhost-vsock). So I usually run the tests in 2 > nested VMs to test the latest changes for both the guest and the host. > > I don't know enough selftests, but do you think it is possible to integrate > them? > > CCing Stefan who is the original author and may remember more reasons about > this choice. It's probably because of the manual steps in tools/testing/vsock/README: The following prerequisite steps are not automated and must be performed prior to running tests: 1. Build the kernel, make headers_install, and build these tests. 2. Install the kernel and tests on the host. 3. Install the kernel and tests inside the guest. 4. Boot the guest and ensure that the AF_VSOCK transport is enabled. If you want to automate this for QEMU, VMware, and Hyper-V that would be great. It relies on having a guest running under these hypervisors and that's not trivial to automate (plus it involves proprietary software for VMware and Hyper-V that may not be available without additional license agreements and/or payment). Not sure if there's a requirement that full process is automated. Or at least if there is we are already breaking it in networking because for some tests we need user to export some env variables to point the test to the right interfaces and even a remote machine to generate traffic. If the env isn't set up tests return 4 (SKIP). I don't feel strongly that ksft + env approach is better but at least it gives us easy access to the basic build and packaging features from ksft. Up to you but thought I'd ask. Yeah, I'll try to allocate some cycles to look into that. Tracking it here: https://gitlab.com/vsock/vsock/-/issues/13 What about this patch, can we queue it for now? Thanks, Stefano
Re: [PATCH] test/vsock: add install target
On Thu, 11 Jul 2024 15:38:01 +0200 Stefan Hajnoczi wrote: > > Usually vsock tests test both the driver (virtio-vsock) in the guest and the > > device in the host kernel (vhost-vsock). So I usually run the tests in 2 > > nested VMs to test the latest changes for both the guest and the host. > > > > I don't know enough selftests, but do you think it is possible to integrate > > them? > > > > CCing Stefan who is the original author and may remember more reasons about > > this choice. > > It's probably because of the manual steps in tools/testing/vsock/README: > > The following prerequisite steps are not automated and must be performed > prior > to running tests: > > 1. Build the kernel, make headers_install, and build these tests. > 2. Install the kernel and tests on the host. > 3. Install the kernel and tests inside the guest. > 4. Boot the guest and ensure that the AF_VSOCK transport is enabled. > > If you want to automate this for QEMU, VMware, and Hyper-V that would be > great. It relies on having a guest running under these hypervisors and > that's not trivial to automate (plus it involves proprietary software > for VMware and Hyper-V that may not be available without additional > license agreements and/or payment). Not sure if there's a requirement that full process is automated. Or at least if there is we are already breaking it in networking because for some tests we need user to export some env variables to point the test to the right interfaces and even a remote machine to generate traffic. If the env isn't set up tests return 4 (SKIP). I don't feel strongly that ksft + env approach is better but at least it gives us easy access to the basic build and packaging features from ksft. Up to you but thought I'd ask.
Re: [PATCH] test/vsock: add install target
On Thu, Jul 11, 2024 at 09:07:04AM +0200, Stefano Garzarella wrote: > CCing Stefan. > > On Wed, Jul 10, 2024 at 07:00:59PM GMT, Jakub Kicinski wrote: > > On Wed, 10 Jul 2024 13:58:39 +0200 Stefano Garzarella wrote: > > > There is a comment there: > > > > > > # Avoid changing the rest of the logic here and lib.mk. > > > > > > Added by commit 17eac6c2db8b2cdfe33d40229bdda2acd86b304a. > > > > > > IIUC they re-used INSTALL_PATH, just to avoid too many changes in that > > > file and in tools/testing/selftests/lib.mk > > > > > > So, IMHO we should not care about it and only use VSOCK_INSTALL_PATH if > > > you don't want to conflict with INSTALL_PATH. > > > > Any reason why vsock isn't part of selftests in the first place? > > > > Usually vsock tests test both the driver (virtio-vsock) in the guest and the > device in the host kernel (vhost-vsock). So I usually run the tests in 2 > nested VMs to test the latest changes for both the guest and the host. > > I don't know enough selftests, but do you think it is possible to integrate > them? > > CCing Stefan who is the original author and may remember more reasons about > this choice. It's probably because of the manual steps in tools/testing/vsock/README: The following prerequisite steps are not automated and must be performed prior to running tests: 1. Build the kernel, make headers_install, and build these tests. 2. Install the kernel and tests on the host. 3. Install the kernel and tests inside the guest. 4. Boot the guest and ensure that the AF_VSOCK transport is enabled. If you want to automate this for QEMU, VMware, and Hyper-V that would be great. It relies on having a guest running under these hypervisors and that's not trivial to automate (plus it involves proprietary software for VMware and Hyper-V that may not be available without additional license agreements and/or payment). Stefan signature.asc Description: PGP signature