[PATCH 0/2] timers test fix and duplicate defines cleanup

2024-09-24 Thread Shuah Khan
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

2024-09-24 Thread Petr Mladek
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

2024-09-24 Thread Petr Mladek
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

2024-09-23 Thread Guenter Roeck
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

2024-09-23 Thread Shuah Khan

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

2024-09-23 Thread Marcos Paulo de Souza
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

2024-09-23 Thread Ivan Orlov
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()"

2024-09-22 Thread Guenter Roeck
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

2024-09-20 Thread Wasim Nazir
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.

2024-09-20 Thread Tiago Lam
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

2024-09-20 Thread Michael Vetter
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

2024-09-20 Thread Michael Vetter
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

2024-09-18 Thread Colton Lewis
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

2024-09-18 Thread Colton Lewis
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

2024-09-18 Thread Colton Lewis
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

2024-09-18 Thread Feng zhou
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()

2024-09-18 Thread David Gow
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

2024-09-17 Thread patchwork-bot+linux-riscv
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.

2024-09-17 Thread Tiago Lam
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

2024-09-17 Thread Boqun Feng
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

2024-09-16 Thread mitchell . augustin
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

2024-09-15 Thread Muhammad Usama Anjum
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

2024-09-15 Thread Neeraj Upadhyay
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

2024-09-15 Thread Neeraj Upadhyay
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

2024-09-14 Thread Feng zhou
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.

2024-09-13 Thread Philo Lu

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.

2024-09-13 Thread Tiago Lam
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

2024-09-12 Thread Reinette Chatre
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

2024-09-12 Thread Shuah Khan

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

2024-09-12 Thread Shuah Khan

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

2024-09-12 Thread Ricardo Ribalda Delgado
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

2024-09-12 Thread Muhammad Usama Anjum
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

2024-09-11 Thread Yunsheng Lin
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

2024-09-10 Thread Ackerley Tng
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

2024-09-10 Thread Ackerley Tng
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

2024-09-10 Thread Ackerley Tng
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

2024-09-10 Thread Ackerley Tng
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

2024-09-10 Thread Ackerley Tng
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

2024-09-10 Thread Benjamin Tissoires
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

2024-09-10 Thread Benjamin Tissoires
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

2024-09-10 Thread Benjamin Tissoires
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

2024-09-10 Thread Jesper Dangaard Brouer




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

2024-09-10 Thread Yunsheng Lin
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()

2024-09-09 Thread I Hsin Cheng
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()

2024-09-09 Thread I Hsin Cheng
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*()

2024-09-09 Thread I Hsin Cheng
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

2024-09-09 Thread Nícolas F . R . A . Prado
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

2024-09-09 Thread Nícolas F . R . A . Prado
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

2024-09-09 Thread Mina Almasry
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

2024-09-09 Thread Yunsheng Lin
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

2024-09-07 Thread kernel test robot
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()

2024-09-06 Thread David Gow
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

2024-09-06 Thread Matthieu Baerts (NGI0)
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

2024-09-06 Thread Adrian Hunter
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

2024-09-06 Thread Yunsheng Lin
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

2024-09-05 Thread Pratik R. Sampat
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

2024-09-05 Thread Pratik R. Sampat
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

2024-09-05 Thread Pratik R. Sampat
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

2024-09-05 Thread Pratik R. Sampat
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

2024-09-05 Thread Pratik R. Sampat
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

2024-09-05 Thread Uros Bizjak
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

2024-09-04 Thread Shuah Khan

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

2024-09-04 Thread Alexander Duyck
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()

2024-09-04 Thread Zhen Lei
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

2024-09-03 Thread André Almeida
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

2024-09-02 Thread bajing
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

2024-09-02 Thread André Apitzsch via B4 Relay
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

2024-08-30 Thread Andrii Nakryiko
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

2024-08-30 Thread Stanislav Fomichev
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

2024-08-29 Thread Jiri Olsa
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

2024-08-29 Thread Jiri Olsa
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

2024-08-27 Thread Lukas Hruska
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

2024-08-27 Thread Lukas Hruska
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

2024-08-18 Thread Masami Hiramatsu (Google)
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

2024-08-18 Thread Masami Hiramatsu (Google)
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

2024-08-12 Thread Hans de Goede
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

2024-08-05 Thread Bibo Mao
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

2024-08-02 Thread Marco Elver
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

2024-08-02 Thread syzbot
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

2024-07-31 Thread Kuppuswamy Sathyanarayanan
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

2024-07-31 Thread Kuppuswamy Sathyanarayanan
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

2024-07-31 Thread Kuppuswamy Sathyanarayanan
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

2024-07-31 Thread Kuppuswamy Sathyanarayanan
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

2024-07-31 Thread Bibo Mao
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

2024-07-31 Thread Stefano Garzarella

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

2024-07-30 Thread Luigi Leonardi via B4 Relay
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

2024-07-24 Thread Puranjay Mohan
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

2024-07-15 Thread Stefano Garzarella

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

2024-07-15 Thread Jiri Olsa
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

2024-07-14 Thread Google
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

2024-07-13 Thread patchwork-bot+netdevbpf
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

2024-07-12 Thread Kuppuswamy Sathyanarayanan
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

2024-07-12 Thread Kuppuswamy Sathyanarayanan
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

2024-07-12 Thread Kuppuswamy Sathyanarayanan
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

2024-07-12 Thread Kuppuswamy Sathyanarayanan
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

2024-07-12 Thread Andrii Nakryiko
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

2024-07-12 Thread Jiri Olsa
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

2024-07-12 Thread Stefano Garzarella

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

2024-07-11 Thread Jakub Kicinski
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

2024-07-11 Thread Stefan Hajnoczi
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


  1   2   3   4   5   6   7   8   9   10   >