* [PATCH 1/9] KVM: selftests: Return the target CPU from pin_task_to_random_cpu()
2026-07-30 19:18 [PATCH 0/9] KVM: selftests: Add more syscall wrappers, fix hardware_disable_test Sean Christopherson
@ 2026-07-30 19:19 ` Sean Christopherson
2026-07-30 19:19 ` [PATCH 2/9] KVM: selftests: Extract picking of random CPU from cpu_set_t to separate API Sean Christopherson
` (7 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: Sean Christopherson @ 2026-07-30 19:19 UTC (permalink / raw)
To: Paolo Bonzini, Marc Zyngier, Oliver Upton, Christian Borntraeger,
Janosch Frank, Claudio Imbrenda, Sean Christopherson
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
David Hildenbrand, kvm, linux-arm-kernel, kvmarm, linux-kernel
When pinning a task to a random CPU, return which CPU the task was pinned
to so that the caller can do things like avoid running other tasks on the
target CPU.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
tools/testing/selftests/kvm/include/kvm_util.h | 2 +-
tools/testing/selftests/kvm/lib/kvm_util.c | 5 +++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index b39e713c30a4..61d72e1e7601 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -1094,7 +1094,7 @@ static inline void pin_task_to_cpu(pthread_t task, int cpu)
TEST_ASSERT(!r, "Failed to set thread affinity to pCPU '%u'", cpu);
}
-void pin_task_to_random_cpu(pthread_t task, cpu_set_t *possible_cpus);
+int pin_task_to_random_cpu(pthread_t task, cpu_set_t *possible_cpus);
static inline int pin_task_to_any_cpu(pthread_t task)
{
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index 3794575d2ca0..af2bad0553f9 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -668,7 +668,7 @@ void kvm_print_vcpu_pinning_help(void)
" (default: no pinning)\n", name, name);
}
-void pin_task_to_random_cpu(pthread_t task, cpu_set_t *possible_cpus)
+int pin_task_to_random_cpu(pthread_t task, cpu_set_t *possible_cpus)
{
int target_idx;
int nr_cpus;
@@ -682,11 +682,12 @@ void pin_task_to_random_cpu(pthread_t task, cpu_set_t *possible_cpus)
for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
if (CPU_ISSET(cpu, possible_cpus) && target_idx-- == 0) {
pin_task_to_cpu(task, cpu);
- return;
+ return cpu;
}
}
TEST_FAIL("Failed to find random CPU in possible_cpus");
+ return -1;
}
void kvm_parse_vcpu_pinning(const char *pcpus_string, u32 vcpu_to_pcpu[],
--
2.55.0.508.g3f0d502094-goog
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 2/9] KVM: selftests: Extract picking of random CPU from cpu_set_t to separate API
2026-07-30 19:18 [PATCH 0/9] KVM: selftests: Add more syscall wrappers, fix hardware_disable_test Sean Christopherson
2026-07-30 19:19 ` [PATCH 1/9] KVM: selftests: Return the target CPU from pin_task_to_random_cpu() Sean Christopherson
@ 2026-07-30 19:19 ` Sean Christopherson
2026-07-30 19:19 ` [PATCH 3/9] KVM: selftests: Affine child tasks to other pCPUs in hardware disable test Sean Christopherson
` (6 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: Sean Christopherson @ 2026-07-30 19:19 UTC (permalink / raw)
To: Paolo Bonzini, Marc Zyngier, Oliver Upton, Christian Borntraeger,
Janosch Frank, Claudio Imbrenda, Sean Christopherson
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
David Hildenbrand, kvm, linux-arm-kernel, kvmarm, linux-kernel
Extract kvm_pick_random_cpu() out of pin_task_to_random_cpu() so that tests
can choose a random CPU without having to immediately pin a task to that
CPU.
No functional change intended.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
tools/testing/selftests/kvm/include/kvm_util.h | 11 ++++++++++-
tools/testing/selftests/kvm/lib/kvm_util.c | 7 ++-----
2 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index 61d72e1e7601..5a7a455b5387 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -1084,6 +1084,8 @@ struct kvm_vcpu *vm_recreate_with_one_vcpu(struct kvm_vm *vm);
void kvm_set_files_rlimit(u32 nr_vcpus);
+int kvm_pick_random_cpu(cpu_set_t *possible_cpus);
+
int __pin_task_to_cpu(pthread_t task, int cpu);
static inline void pin_task_to_cpu(pthread_t task, int cpu)
@@ -1094,7 +1096,14 @@ static inline void pin_task_to_cpu(pthread_t task, int cpu)
TEST_ASSERT(!r, "Failed to set thread affinity to pCPU '%u'", cpu);
}
-int pin_task_to_random_cpu(pthread_t task, cpu_set_t *possible_cpus);
+static inline int pin_task_to_random_cpu(pthread_t task, cpu_set_t *possible_cpus)
+{
+ int cpu;
+
+ cpu = kvm_pick_random_cpu(possible_cpus);
+ pin_task_to_cpu(task, cpu);
+ return cpu;
+}
static inline int pin_task_to_any_cpu(pthread_t task)
{
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index af2bad0553f9..9ddc047d5c27 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -668,7 +668,7 @@ void kvm_print_vcpu_pinning_help(void)
" (default: no pinning)\n", name, name);
}
-int pin_task_to_random_cpu(pthread_t task, cpu_set_t *possible_cpus)
+int kvm_pick_random_cpu(cpu_set_t *possible_cpus)
{
int target_idx;
int nr_cpus;
@@ -680,12 +680,9 @@ int pin_task_to_random_cpu(pthread_t task, cpu_set_t *possible_cpus)
target_idx = kvm_random_u64(&kvm_rng) % nr_cpus;
for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
- if (CPU_ISSET(cpu, possible_cpus) && target_idx-- == 0) {
- pin_task_to_cpu(task, cpu);
+ if (CPU_ISSET(cpu, possible_cpus) && target_idx-- == 0)
return cpu;
- }
}
-
TEST_FAIL("Failed to find random CPU in possible_cpus");
return -1;
}
--
2.55.0.508.g3f0d502094-goog
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 3/9] KVM: selftests: Affine child tasks to other pCPUs in hardware disable test
2026-07-30 19:18 [PATCH 0/9] KVM: selftests: Add more syscall wrappers, fix hardware_disable_test Sean Christopherson
2026-07-30 19:19 ` [PATCH 1/9] KVM: selftests: Return the target CPU from pin_task_to_random_cpu() Sean Christopherson
2026-07-30 19:19 ` [PATCH 2/9] KVM: selftests: Extract picking of random CPU from cpu_set_t to separate API Sean Christopherson
@ 2026-07-30 19:19 ` Sean Christopherson
2026-07-30 19:33 ` sashiko-bot
2026-07-30 19:19 ` [PATCH 4/9] KVM: selftests: Drop unreachable, dead code from " Sean Christopherson
` (5 subsequent siblings)
8 siblings, 1 reply; 15+ messages in thread
From: Sean Christopherson @ 2026-07-30 19:19 UTC (permalink / raw)
To: Paolo Bonzini, Marc Zyngier, Oliver Upton, Christian Borntraeger,
Janosch Frank, Claudio Imbrenda, Sean Christopherson
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
David Hildenbrand, kvm, linux-arm-kernel, kvmarm, linux-kernel
When possible, affine child tasks to a different pCPU than the parent task
in the hardware disable test. On preemptible kernels, running 4 + 4*16
child tasks on the same 4 pCPUs as the parent can result in runtimes of
several minutes due to the children making it difficult for the parent to
make forward progress.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
.../selftests/kvm/hardware_disable_test.c | 28 ++++++++++++++-----
1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/tools/testing/selftests/kvm/hardware_disable_test.c b/tools/testing/selftests/kvm/hardware_disable_test.c
index 3147f5c97e94..1bcbd13e9994 100644
--- a/tools/testing/selftests/kvm/hardware_disable_test.c
+++ b/tools/testing/selftests/kvm/hardware_disable_test.c
@@ -22,6 +22,7 @@
#define DELAY_US_MAX 2000
sem_t *sem;
+static cpu_set_t child_cpu_set;
static void guest_code(void)
{
@@ -84,16 +85,11 @@ static void run_test(u32 run)
{
struct kvm_vcpu *vcpu;
struct kvm_vm *vm;
- cpu_set_t cpu_set;
pthread_t threads[VCPU_NUM];
pthread_t throw_away;
void *b;
u32 i, j;
- CPU_ZERO(&cpu_set);
- for (i = 0; i < VCPU_NUM; i++)
- CPU_SET(i, &cpu_set);
-
vm = vm_create(VCPU_NUM);
pr_debug("%s: [%d] start vcpus\n", __func__, run);
@@ -101,12 +97,12 @@ static void run_test(u32 run)
vcpu = vm_vcpu_add(vm, i, guest_code);
check_create_thread(&threads[i], NULL, run_vcpu, vcpu);
- check_set_affinity(threads[i], &cpu_set);
+ check_set_affinity(threads[i], &child_cpu_set);
for (j = 0; j < SLEEPING_THREAD_NUM; ++j) {
check_create_thread(&throw_away, NULL, sleeping_thread,
(void *)NULL);
- check_set_affinity(throw_away, &cpu_set);
+ check_set_affinity(throw_away, &child_cpu_set);
}
}
pr_debug("%s: [%d] all threads launched\n", __func__, run);
@@ -147,12 +143,30 @@ void wait_for_child_setup(pid_t pid)
}
}
+static void setup_child_cpu_set(void)
+{
+ int cpu;
+
+ kvm_sched_getaffinity(0, sizeof(child_cpu_set), &child_cpu_set);
+
+ if (CPU_COUNT(&child_cpu_set) < 2)
+ return;
+
+ cpu = pin_task_to_random_cpu(pthread_self(), &child_cpu_set);
+ CPU_CLR(cpu, &child_cpu_set);
+
+ while (CPU_COUNT(&child_cpu_set) > VCPU_NUM)
+ CPU_CLR(kvm_pick_random_cpu(&child_cpu_set), &child_cpu_set);
+}
+
int main(int argc, char **argv)
{
u32 i;
int s, r;
pid_t pid;
+ setup_child_cpu_set();
+
sem = sem_open("vm_sem", O_CREAT | O_EXCL, 0644, 0);
sem_unlink("vm_sem");
--
2.55.0.508.g3f0d502094-goog
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 3/9] KVM: selftests: Affine child tasks to other pCPUs in hardware disable test
2026-07-30 19:19 ` [PATCH 3/9] KVM: selftests: Affine child tasks to other pCPUs in hardware disable test Sean Christopherson
@ 2026-07-30 19:33 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-07-30 19:33 UTC (permalink / raw)
To: Sean Christopherson; +Cc: kvmarm, Oliver Upton, Marc Zyngier, kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Thread initialization race causing severe CPU contention on the parent's single CPU, defeating the patch's purpose.
--
--- Patch [3]: [PATCH 3/9] KVM: selftests: Affine child tasks to other pCPUs in hardware disable test ---
commit b00682d387a4f6e1d76a822e983d388f7469a322
Author: Sean Christopherson <seanjc@google.com>
KVM: selftests: Affine child tasks to other pCPUs in hardware disable test
This commit modifies the hardware disable test to affine child tasks to
different pCPUs than the parent task. This is intended to prevent the
child tasks from starving the parent task on preemptible kernels.
> diff --git a/tools/testing/selftests/kvm/hardware_disable_test.c b/tools/testing/selftests/kvm/hardware_disable_test.c
> index 3147f5c97e943..1bcbd13e99947 100644
> --- a/tools/testing/selftests/kvm/hardware_disable_test.c
> +++ b/tools/testing/selftests/kvm/hardware_disable_test.c
[ ... ]
> @@ -84,16 +85,11 @@ static void run_test(u32 run)
[ ... ]
> check_create_thread(&threads[i], NULL, run_vcpu, vcpu);
> - check_set_affinity(threads[i], &cpu_set);
> + check_set_affinity(threads[i], &child_cpu_set);
>
> for (j = 0; j < SLEEPING_THREAD_NUM; ++j) {
> check_create_thread(&throw_away, NULL, sleeping_thread,
> (void *)NULL);
> - check_set_affinity(throw_away, &cpu_set);
> + check_set_affinity(throw_away, &child_cpu_set);
> }
> }
[ ... ]
> @@ -147,12 +143,30 @@ void wait_for_child_setup(pid_t pid)
[ ... ]
> +static void setup_child_cpu_set(void)
> +{
> + int cpu;
> +
> + kvm_sched_getaffinity(0, sizeof(child_cpu_set), &child_cpu_set);
> +
> + if (CPU_COUNT(&child_cpu_set) < 2)
> + return;
> +
> + cpu = pin_task_to_random_cpu(pthread_self(), &child_cpu_set);
> + CPU_CLR(cpu, &child_cpu_set);
> +
> + while (CPU_COUNT(&child_cpu_set) > VCPU_NUM)
> + CPU_CLR(kvm_pick_random_cpu(&child_cpu_set), &child_cpu_set);
> +}
[Severity: Medium]
Since setup_child_cpu_set() pins the parent thread to a single random CPU
prior to spawning children, won't the newly created threads in run_test()
inherit this single-CPU affinity upon creation?
Because check_create_thread() spawns the threads before their affinity is
explicitly updated to child_cpu_set, they might immediately begin executing
on the exact same CPU as the parent.
Could this result in the child threads starving the parent on that single CPU
before the parent gets a chance to execute check_set_affinity()? This seems
like it might heavily delay the migration and trigger the same CPU contention
that this patch aims to fix.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730191908.2084803-1-seanjc@google.com?part=3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 4/9] KVM: selftests: Drop unreachable, dead code from hardware disable test
2026-07-30 19:18 [PATCH 0/9] KVM: selftests: Add more syscall wrappers, fix hardware_disable_test Sean Christopherson
` (2 preceding siblings ...)
2026-07-30 19:19 ` [PATCH 3/9] KVM: selftests: Affine child tasks to other pCPUs in hardware disable test Sean Christopherson
@ 2026-07-30 19:19 ` Sean Christopherson
2026-07-30 19:30 ` sashiko-bot
2026-07-30 19:19 ` [PATCH 5/9] KVM: selftests: Add KVM syscall wrapper for pthread_create() Sean Christopherson
` (4 subsequent siblings)
8 siblings, 1 reply; 15+ messages in thread
From: Sean Christopherson @ 2026-07-30 19:19 UTC (permalink / raw)
To: Paolo Bonzini, Marc Zyngier, Oliver Upton, Christian Borntraeger,
Janosch Frank, Claudio Imbrenda, Sean Christopherson
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
David Hildenbrand, kvm, linux-arm-kernel, kvmarm, linux-kernel
Drop all of the code that is unreachable in the hardware disable test, as
it adds a lot of noise that makes the test seem far more complicated than
it actually is.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
.../selftests/kvm/hardware_disable_test.c | 42 +++++++------------
1 file changed, 14 insertions(+), 28 deletions(-)
diff --git a/tools/testing/selftests/kvm/hardware_disable_test.c b/tools/testing/selftests/kvm/hardware_disable_test.c
index 1bcbd13e9994..e08aef94382f 100644
--- a/tools/testing/selftests/kvm/hardware_disable_test.c
+++ b/tools/testing/selftests/kvm/hardware_disable_test.c
@@ -15,6 +15,7 @@
#include <test_util.h>
#include "kvm_util.h"
+#include "ucall_common.h"
#define VCPU_NUM 4
#define SLEEPING_THREAD_NUM (1 << 4)
@@ -28,7 +29,7 @@ static void guest_code(void)
{
for (;;)
; /* Some busy work */
- printf("Should not be reached.\n");
+ GUEST_ASSERT(0);
}
static void *run_vcpu(void *arg)
@@ -38,22 +39,19 @@ static void *run_vcpu(void *arg)
vcpu_run(vcpu);
- TEST_ASSERT(false, "%s: exited with reason %d: %s",
- __func__, run->exit_reason,
- exit_reason_str(run->exit_reason));
- pthread_exit(NULL);
+ TEST_FAIL("vCPU%d exited with reason %d: %s",
+ vcpu->id, run->exit_reason, exit_reason_str(run->exit_reason));
}
static void *sleeping_thread(void *arg)
{
int fd;
- while (true) {
+ while (1) {
fd = open("/dev/null", O_RDWR);
close(fd);
}
- TEST_ASSERT(false, "%s: exited", __func__);
- pthread_exit(NULL);
+ TEST_FAIL("%s: exited", __func__);
}
static inline void check_create_thread(pthread_t *thread, pthread_attr_t *attr,
@@ -73,21 +71,11 @@ static inline void check_set_affinity(pthread_t thread, cpu_set_t *cpu_set)
TEST_ASSERT(r == 0, "%s: failed set affinity", __func__);
}
-static inline void check_join(pthread_t thread, void **retval)
-{
- int r;
-
- r = pthread_join(thread, retval);
- TEST_ASSERT(r == 0, "%s: failed to join thread", __func__);
-}
-
static void run_test(u32 run)
{
struct kvm_vcpu *vcpu;
struct kvm_vm *vm;
- pthread_t threads[VCPU_NUM];
- pthread_t throw_away;
- void *b;
+ pthread_t thread;
u32 i, j;
vm = vm_create(VCPU_NUM);
@@ -96,21 +84,19 @@ static void run_test(u32 run)
for (i = 0; i < VCPU_NUM; ++i) {
vcpu = vm_vcpu_add(vm, i, guest_code);
- check_create_thread(&threads[i], NULL, run_vcpu, vcpu);
- check_set_affinity(threads[i], &child_cpu_set);
+ check_create_thread(&thread, NULL, run_vcpu, vcpu);
+ check_set_affinity(thread, &child_cpu_set);
for (j = 0; j < SLEEPING_THREAD_NUM; ++j) {
- check_create_thread(&throw_away, NULL, sleeping_thread,
- (void *)NULL);
- check_set_affinity(throw_away, &child_cpu_set);
+ check_create_thread(&thread, NULL, sleeping_thread, (void *)NULL);
+ check_set_affinity(thread, &child_cpu_set);
}
}
pr_debug("%s: [%d] all threads launched\n", __func__, run);
sem_post(sem);
- for (i = 0; i < VCPU_NUM; ++i)
- check_join(threads[i], &b);
- /* Should not be reached */
- TEST_ASSERT(false, "%s: [%d] child escaped the ninja", __func__, run);
+
+ /* Wait for the parent to SIGKILL this child. */
+ while (1);
}
void wait_for_child_setup(pid_t pid)
--
2.55.0.508.g3f0d502094-goog
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 4/9] KVM: selftests: Drop unreachable, dead code from hardware disable test
2026-07-30 19:19 ` [PATCH 4/9] KVM: selftests: Drop unreachable, dead code from " Sean Christopherson
@ 2026-07-30 19:30 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-07-30 19:30 UTC (permalink / raw)
To: Sean Christopherson; +Cc: Oliver Upton, Marc Zyngier, kvm, kvmarm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Replacing a blocking `pthread_join` with an infinite busy-wait loop (`while (1);`) in the child process unnecessarily burns CPU and causes scheduler contention with the parent process.
--
--- Patch [4]: [PATCH 4/9] KVM: selftests: Drop unreachable, dead code from hardware disable test ---
commit 80b1aa13e14f4a3f65225bf79adc03a7a8eda318
Author: Sean Christopherson <seanjc@google.com>
KVM: selftests: Drop unreachable, dead code from hardware disable test
This commit removes unreachable code from the hardware disable test to reduce
noise and simplify the test logic. It refactors thread creation and replaces
a blocking wait with a busy loop in the child process.
> diff --git a/tools/testing/selftests/kvm/hardware_disable_test.c b/tools/testing/selftests/kvm/hardware_disable_test.c
> index 1bcbd13e99947..e08aef94382f3 100644
> --- a/tools/testing/selftests/kvm/hardware_disable_test.c
> +++ b/tools/testing/selftests/kvm/hardware_disable_test.c
[ ... ]
> @@ -96,21 +84,19 @@ static void run_test(u32 run)
[ ... ]
> pr_debug("%s: [%d] all threads launched\n", __func__, run);
> sem_post(sem);
> - for (i = 0; i < VCPU_NUM; ++i)
> - check_join(threads[i], &b);
> - /* Should not be reached */
> - TEST_ASSERT(false, "%s: [%d] child escaped the ninja", __func__, run);
> +
> + /* Wait for the parent to SIGKILL this child. */
> + while (1);
[Severity: Medium]
Since the child and parent share the same CPU affinity, will this busy spin
loop cause unnecessary scheduler contention with the parent process when the
parent's timer fires?
Because the processes are pinned to a single CPU core, spinning in this loop
burns CPU cycles and forces the parent to contend with the spinning child for
CPU time.
Would it be better to use a blocking wait like pause() or sleep() here to
reduce scheduler latency and avoid 100% CPU utilization?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730191908.2084803-1-seanjc@google.com?part=4
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 5/9] KVM: selftests: Add KVM syscall wrapper for pthread_create()
2026-07-30 19:18 [PATCH 0/9] KVM: selftests: Add more syscall wrappers, fix hardware_disable_test Sean Christopherson
` (3 preceding siblings ...)
2026-07-30 19:19 ` [PATCH 4/9] KVM: selftests: Drop unreachable, dead code from " Sean Christopherson
@ 2026-07-30 19:19 ` Sean Christopherson
2026-07-30 19:30 ` sashiko-bot
2026-07-30 19:19 ` [PATCH 6/9] KVM: selftests: Add KVM syscall wrappers for pthread_{cancel,join}() Sean Christopherson
` (3 subsequent siblings)
8 siblings, 1 reply; 15+ messages in thread
From: Sean Christopherson @ 2026-07-30 19:19 UTC (permalink / raw)
To: Paolo Bonzini, Marc Zyngier, Oliver Upton, Christian Borntraeger,
Janosch Frank, Claudio Imbrenda, Sean Christopherson
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
David Hildenbrand, kvm, linux-arm-kernel, kvmarm, linux-kernel
Add and use a KVM wrapper for pthread_create() syscall so that selftests
don't need to manually assert that the syscall succeeded.
Note, most tests don't actually assert success, but they all obviously
rely on the syscall to succeed.
Other than explicitly failing if pthread_create() fails, no functional
change intended.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
tools/testing/selftests/kvm/arch_timer.c | 14 ++++----------
tools/testing/selftests/kvm/arm64/vgic_irq.c | 10 +++-------
.../testing/selftests/kvm/arm64/vgic_lpi_stress.c | 4 ++--
tools/testing/selftests/kvm/dirty_log_test.c | 2 +-
.../testing/selftests/kvm/hardware_disable_test.c | 15 +++------------
.../testing/selftests/kvm/include/kvm_syscalls.h | 5 +++++
tools/testing/selftests/kvm/irq_test.c | 2 +-
tools/testing/selftests/kvm/irqfd_test.c | 2 +-
tools/testing/selftests/kvm/kvm_page_table_test.c | 4 ++--
tools/testing/selftests/kvm/lib/memstress.c | 2 +-
.../testing/selftests/kvm/lib/userfaultfd_util.c | 4 ++--
tools/testing/selftests/kvm/memslot_perf_test.c | 2 +-
tools/testing/selftests/kvm/mmu_stress_test.c | 2 +-
.../testing/selftests/kvm/pre_fault_memory_test.c | 2 +-
tools/testing/selftests/kvm/rseq_test.c | 4 ++--
tools/testing/selftests/kvm/s390/memop.c | 2 +-
.../selftests/kvm/set_memory_region_test.c | 2 +-
tools/testing/selftests/kvm/steal_time.c | 2 +-
tools/testing/selftests/kvm/x86/hyperv_ipi.c | 11 ++++-------
.../testing/selftests/kvm/x86/hyperv_tlb_flush.c | 9 +++------
.../kvm/x86/private_mem_conversions_test.c | 2 +-
.../kvm/x86/private_mem_kvm_exits_test.c | 5 ++---
.../selftests/kvm/x86/recalc_apic_map_test.c | 2 +-
.../testing/selftests/kvm/x86/sev_migrate_tests.c | 2 +-
tools/testing/selftests/kvm/x86/sync_regs_test.c | 2 +-
.../testing/selftests/kvm/x86/tsc_scaling_sync.c | 2 +-
tools/testing/selftests/kvm/x86/xapic_ipi_test.c | 8 ++------
tools/testing/selftests/kvm/x86/xen_shinfo_test.c | 3 +--
28 files changed, 50 insertions(+), 76 deletions(-)
diff --git a/tools/testing/selftests/kvm/arch_timer.c b/tools/testing/selftests/kvm/arch_timer.c
index f8b02597897b..a6a66b5b7ea9 100644
--- a/tools/testing/selftests/kvm/arch_timer.c
+++ b/tools/testing/selftests/kvm/arch_timer.c
@@ -141,28 +141,22 @@ static void test_run(struct kvm_vm *vm)
{
pthread_t pt_vcpu_migration;
unsigned int i;
- int ret;
pthread_mutex_init(&vcpu_done_map_lock, NULL);
vcpu_done_map = bitmap_zalloc(test_args.nr_vcpus);
TEST_ASSERT(vcpu_done_map, "Failed to allocate vcpu done bitmap");
- for (i = 0; i < (unsigned long)test_args.nr_vcpus; i++) {
- ret = pthread_create(&pt_vcpu_run[i], NULL, test_vcpu_run,
- (void *)(unsigned long)i);
- TEST_ASSERT(!ret, "Failed to create vCPU-%d pthread", i);
- }
+ for (i = 0; i < (unsigned long)test_args.nr_vcpus; i++)
+ kvm_pthread_create(&pt_vcpu_run[i], NULL, test_vcpu_run,
+ (void *)(unsigned long)i);
/* Spawn a thread to control the vCPU migrations */
if (test_args.migration_freq_ms) {
srand(time(NULL));
- ret = pthread_create(&pt_vcpu_migration, NULL,
- test_vcpu_migration, NULL);
- TEST_ASSERT(!ret, "Failed to create the migration pthread");
+ kvm_pthread_create(&pt_vcpu_migration, NULL, test_vcpu_migration, NULL);
}
-
for (i = 0; i < test_args.nr_vcpus; i++)
pthread_join(pt_vcpu_run[i], NULL);
diff --git a/tools/testing/selftests/kvm/arm64/vgic_irq.c b/tools/testing/selftests/kvm/arm64/vgic_irq.c
index 5e231998617e..2d6f20d5c117 100644
--- a/tools/testing/selftests/kvm/arm64/vgic_irq.c
+++ b/tools/testing/selftests/kvm/arm64/vgic_irq.c
@@ -988,7 +988,7 @@ static void test_vgic_two_cpus(void *gcode)
struct test_args args = {};
struct kvm_vm *vm;
gva_t args_gva;
- int gic_fd, ret;
+ int gic_fd;
vm = vm_create_with_vcpus(2, gcode, vcpus);
@@ -1004,12 +1004,8 @@ static void test_vgic_two_cpus(void *gcode)
gic_fd = vgic_v3_setup(vm, 2, 64);
- ret = pthread_create(&thr[0], NULL, test_vcpu_run, vcpus[0]);
- if (ret)
- TEST_FAIL("Can't create thread for vcpu 0 (%d)\n", ret);
- ret = pthread_create(&thr[1], NULL, test_vcpu_run, vcpus[1]);
- if (ret)
- TEST_FAIL("Can't create thread for vcpu 1 (%d)\n", ret);
+ kvm_pthread_create(&thr[0], NULL, test_vcpu_run, vcpus[0]);
+ kvm_pthread_create(&thr[1], NULL, test_vcpu_run, vcpus[1]);
pthread_join(thr[0], NULL);
pthread_join(thr[1], NULL);
diff --git a/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c b/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
index d64d434d3f06..549e0547d905 100644
--- a/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
+++ b/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
@@ -311,10 +311,10 @@ static void run_test(void)
pthread_barrier_init(&test_setup_barrier, NULL, nr_vcpus + nr_devices + 1);
for (i = 0; i < nr_vcpus; i++)
- pthread_create(&vcpu_threads[i], NULL, vcpu_worker_thread, vcpus[i]);
+ kvm_pthread_create(&vcpu_threads[i], NULL, vcpu_worker_thread, vcpus[i]);
for (i = 0; i < nr_devices; i++)
- pthread_create(&lpi_threads[i], NULL, lpi_worker_thread, (void *)i);
+ kvm_pthread_create(&lpi_threads[i], NULL, lpi_worker_thread, (void *)i);
pthread_barrier_wait(&test_setup_barrier);
diff --git a/tools/testing/selftests/kvm/dirty_log_test.c b/tools/testing/selftests/kvm/dirty_log_test.c
index e8419d7da1ea..ca22e5f09ac2 100644
--- a/tools/testing/selftests/kvm/dirty_log_test.c
+++ b/tools/testing/selftests/kvm/dirty_log_test.c
@@ -691,7 +691,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
TEST_ASSERT_EQ(vcpu_stop, false);
- pthread_create(&vcpu_thread, NULL, vcpu_worker, vcpu);
+ kvm_pthread_create(&vcpu_thread, NULL, vcpu_worker, vcpu);
for (iteration = 1; iteration <= p->iterations; iteration++) {
unsigned long i, reap_i;
diff --git a/tools/testing/selftests/kvm/hardware_disable_test.c b/tools/testing/selftests/kvm/hardware_disable_test.c
index e08aef94382f..38ebacaa0fce 100644
--- a/tools/testing/selftests/kvm/hardware_disable_test.c
+++ b/tools/testing/selftests/kvm/hardware_disable_test.c
@@ -5,7 +5,6 @@
* return notifiers.
*/
#include <fcntl.h>
-#include <pthread.h>
#include <semaphore.h>
#include <stdint.h>
#include <stdlib.h>
@@ -14,6 +13,7 @@
#include <test_util.h>
+#include "kvm_syscalls.h"
#include "kvm_util.h"
#include "ucall_common.h"
@@ -54,15 +54,6 @@ static void *sleeping_thread(void *arg)
TEST_FAIL("%s: exited", __func__);
}
-static inline void check_create_thread(pthread_t *thread, pthread_attr_t *attr,
- void *(*f)(void *), void *arg)
-{
- int r;
-
- r = pthread_create(thread, attr, f, arg);
- TEST_ASSERT(r == 0, "%s: failed to create thread", __func__);
-}
-
static inline void check_set_affinity(pthread_t thread, cpu_set_t *cpu_set)
{
int r;
@@ -84,11 +75,11 @@ static void run_test(u32 run)
for (i = 0; i < VCPU_NUM; ++i) {
vcpu = vm_vcpu_add(vm, i, guest_code);
- check_create_thread(&thread, NULL, run_vcpu, vcpu);
+ kvm_pthread_create(&thread, NULL, run_vcpu, vcpu);
check_set_affinity(thread, &child_cpu_set);
for (j = 0; j < SLEEPING_THREAD_NUM; ++j) {
- check_create_thread(&thread, NULL, sleeping_thread, (void *)NULL);
+ kvm_pthread_create(&thread, NULL, sleeping_thread, (void *)NULL);
check_set_affinity(thread, &child_cpu_set);
}
}
diff --git a/tools/testing/selftests/kvm/include/kvm_syscalls.h b/tools/testing/selftests/kvm/include/kvm_syscalls.h
index 5dae6143ddb0..3c22d4f3a485 100644
--- a/tools/testing/selftests/kvm/include/kvm_syscalls.h
+++ b/tools/testing/selftests/kvm/include/kvm_syscalls.h
@@ -12,6 +12,7 @@
#include <sys/mman.h>
#include <sys/syscall.h>
+#include <pthread.h>
#include <sched.h>
#include <test_util.h>
@@ -96,6 +97,10 @@ __KVM_SYSCALL_DEFINE(ftruncate, 2, unsigned int, fd, off_t, length);
__KVM_SYSCALL_DEFINE(madvise, 3, void *, addr, size_t, length, int, advice);
__KVM_SYSCALL_DEFINE(sched_getaffinity, 3, pid_t, pid, size_t, cpusetsize, cpu_set_t *, mask);
+typedef void *(*pthread_fn_t)(void *);
+__KVM_SYSCALL_DEFINE(pthread_create, 4, pthread_t *, thread,
+ const pthread_attr_t *, attr, pthread_fn_t, fn, void *, arg);
+
#define kvm_free_fd(fd) \
do { \
kvm_close(fd); \
diff --git a/tools/testing/selftests/kvm/irq_test.c b/tools/testing/selftests/kvm/irq_test.c
index 240f6f0fdbe4..7da5f8d75e85 100644
--- a/tools/testing/selftests/kvm/irq_test.c
+++ b/tools/testing/selftests/kvm/irq_test.c
@@ -296,7 +296,7 @@ int main(int argc, char **argv)
kvm_sched_getaffinity(0, sizeof(available_cpus), &available_cpus);
for (i = 0; i < nr_vcpus; i++)
- pthread_create(&vcpu_threads[i], NULL, vcpu_thread_main, vcpus[i]);
+ kvm_pthread_create(&vcpu_threads[i], NULL, vcpu_thread_main, vcpus[i]);
for (i = 0; i < nr_vcpus; i++) {
struct kvm_vcpu *vcpu = vcpus[i];
diff --git a/tools/testing/selftests/kvm/irqfd_test.c b/tools/testing/selftests/kvm/irqfd_test.c
index 5d7590d01868..8b39144a2834 100644
--- a/tools/testing/selftests/kvm/irqfd_test.c
+++ b/tools/testing/selftests/kvm/irqfd_test.c
@@ -128,7 +128,7 @@ int main(int argc, char *argv[])
close(__eventfd);
- pthread_create(&racing_thread, NULL, secondary_irqfd_juggler, vm2);
+ kvm_pthread_create(&racing_thread, NULL, secondary_irqfd_juggler, vm2);
for (i = 0; i < 10000; i++) {
WRITE_ONCE(__eventfd, kvm_new_eventfd());
diff --git a/tools/testing/selftests/kvm/kvm_page_table_test.c b/tools/testing/selftests/kvm/kvm_page_table_test.c
index a910e3abb8c7..8222bdb63e49 100644
--- a/tools/testing/selftests/kvm/kvm_page_table_test.c
+++ b/tools/testing/selftests/kvm/kvm_page_table_test.c
@@ -364,8 +364,8 @@ static void run_test(enum vm_guest_mode mode, void *arg)
*current_stage = KVM_BEFORE_MAPPINGS;
for (i = 0; i < nr_vcpus; i++)
- pthread_create(&vcpu_threads[i], NULL, vcpu_worker,
- test_args.vcpus[i]);
+ kvm_pthread_create(&vcpu_threads[i], NULL, vcpu_worker,
+ test_args.vcpus[i]);
vcpus_complete_new_stage(*current_stage);
pr_info("Started all vCPUs successfully\n");
diff --git a/tools/testing/selftests/kvm/lib/memstress.c b/tools/testing/selftests/kvm/lib/memstress.c
index 3599b75d97c9..0bfa623ce9b5 100644
--- a/tools/testing/selftests/kvm/lib/memstress.c
+++ b/tools/testing/selftests/kvm/lib/memstress.c
@@ -294,7 +294,7 @@ void memstress_start_vcpu_threads(int nr_vcpus,
vcpu->vcpu_idx = i;
WRITE_ONCE(vcpu->running, false);
- pthread_create(&vcpu->thread, NULL, vcpu_thread_main, vcpu);
+ kvm_pthread_create(&vcpu->thread, NULL, vcpu_thread_main, vcpu);
}
for (i = 0; i < nr_vcpus; i++) {
diff --git a/tools/testing/selftests/kvm/lib/userfaultfd_util.c b/tools/testing/selftests/kvm/lib/userfaultfd_util.c
index ef8d76f71f83..4b3e3158ed87 100644
--- a/tools/testing/selftests/kvm/lib/userfaultfd_util.c
+++ b/tools/testing/selftests/kvm/lib/userfaultfd_util.c
@@ -167,8 +167,8 @@ struct uffd_desc *uffd_setup_demand_paging(int uffd_mode, useconds_t delay,
uffd_desc->reader_args[i].handler = handler;
uffd_desc->reader_args[i].pipe = pipes[0];
- pthread_create(&uffd_desc->readers[i], NULL, uffd_handler_thread_fn,
- &uffd_desc->reader_args[i]);
+ kvm_pthread_create(&uffd_desc->readers[i], NULL, uffd_handler_thread_fn,
+ &uffd_desc->reader_args[i]);
PER_VCPU_DEBUG("Created uffd thread %i for HVA range [%p, %p)\n",
i, hva, hva + len);
diff --git a/tools/testing/selftests/kvm/memslot_perf_test.c b/tools/testing/selftests/kvm/memslot_perf_test.c
index 4d9ad6104a6e..eb49305db404 100644
--- a/tools/testing/selftests/kvm/memslot_perf_test.c
+++ b/tools/testing/selftests/kvm/memslot_perf_test.c
@@ -366,7 +366,7 @@ static void launch_vm(struct vm_data *data)
{
pr_info_v("Launching the test VM\n");
- pthread_create(&data->vcpu_thread, NULL, vcpu_worker, data);
+ kvm_pthread_create(&data->vcpu_thread, NULL, vcpu_worker, data);
/* Ensure the guest thread is spun up. */
wait_for_vcpu();
diff --git a/tools/testing/selftests/kvm/mmu_stress_test.c b/tools/testing/selftests/kvm/mmu_stress_test.c
index 3d5f33a63b2b..9448498849ff 100644
--- a/tools/testing/selftests/kvm/mmu_stress_test.c
+++ b/tools/testing/selftests/kvm/mmu_stress_test.c
@@ -222,7 +222,7 @@ static pthread_t *spawn_workers(struct kvm_vm *vm, struct kvm_vcpu **vcpus,
info[i].vcpu = vcpus[i];
info[i].start_gpa = gpa;
info[i].end_gpa = gpa + nr_bytes;
- pthread_create(&threads[i], NULL, vcpu_worker, &info[i]);
+ kvm_pthread_create(&threads[i], NULL, vcpu_worker, &info[i]);
}
return threads;
}
diff --git a/tools/testing/selftests/kvm/pre_fault_memory_test.c b/tools/testing/selftests/kvm/pre_fault_memory_test.c
index a0fcae3cb7a8..88287ccb9093 100644
--- a/tools/testing/selftests/kvm/pre_fault_memory_test.c
+++ b/tools/testing/selftests/kvm/pre_fault_memory_test.c
@@ -84,7 +84,7 @@ static void pre_fault_memory(struct kvm_vcpu *vcpu, u64 base_gpa, u64 offset,
* Concurrently delete (and recreate) the slot to test KVM's handling
* of a racing memslot deletion with prefaulting.
*/
- pthread_create(&slot_worker, NULL, delete_slot_worker, &data);
+ kvm_pthread_create(&slot_worker, NULL, delete_slot_worker, &data);
while (!READ_ONCE(data.worker_ready))
cpu_relax();
diff --git a/tools/testing/selftests/kvm/rseq_test.c b/tools/testing/selftests/kvm/rseq_test.c
index 557e393c223b..9a1851203544 100644
--- a/tools/testing/selftests/kvm/rseq_test.c
+++ b/tools/testing/selftests/kvm/rseq_test.c
@@ -241,8 +241,8 @@ int main(int argc, char *argv[])
*/
vm = vm_create_with_one_vcpu(&vcpu, guest_code);
- pthread_create(&migration_thread, NULL, migration_worker,
- (void *)(unsigned long)kvm_gettid());
+ kvm_pthread_create(&migration_thread, NULL, migration_worker,
+ (void *)(unsigned long)kvm_gettid());
if (latency >= 0) {
/*
diff --git a/tools/testing/selftests/kvm/s390/memop.c b/tools/testing/selftests/kvm/s390/memop.c
index 0244848621b3..96b32bd74009 100644
--- a/tools/testing/selftests/kvm/s390/memop.c
+++ b/tools/testing/selftests/kvm/s390/memop.c
@@ -678,7 +678,7 @@ static void test_cmpxchg_key_concurrent(void)
HOST_SYNC(t.vcpu, STAGE_SKEYS_SET);
prepare_mem12();
MOP(t.vcpu, LOGICAL, WRITE, mem1, max_block, GADDR_V(mem2));
- pthread_create(&thread, NULL, run_guest, &t.vcpu);
+ kvm_pthread_create(&thread, NULL, run_guest, &t.vcpu);
for (int i = 0; i < cmpxchg_iter_outer; i++) {
do {
diff --git a/tools/testing/selftests/kvm/set_memory_region_test.c b/tools/testing/selftests/kvm/set_memory_region_test.c
index a152ab65c657..12f5022bb164 100644
--- a/tools/testing/selftests/kvm/set_memory_region_test.c
+++ b/tools/testing/selftests/kvm/set_memory_region_test.c
@@ -133,7 +133,7 @@ static struct kvm_vm *spawn_vm(struct kvm_vcpu **vcpu, pthread_t *vcpu_thread,
hva = addr_gpa2hva(vm, MEM_REGION_GPA);
memset(hva, 0, 2 * 4096);
- pthread_create(vcpu_thread, NULL, vcpu_worker, *vcpu);
+ kvm_pthread_create(vcpu_thread, NULL, vcpu_worker, *vcpu);
/* Ensure the guest thread is spun up. */
wait_for_vcpu();
diff --git a/tools/testing/selftests/kvm/steal_time.c b/tools/testing/selftests/kvm/steal_time.c
index 0b88c743ee7d..f5f708be5aa0 100644
--- a/tools/testing/selftests/kvm/steal_time.c
+++ b/tools/testing/selftests/kvm/steal_time.c
@@ -548,7 +548,7 @@ int main(int ac, char **av)
/* Steal time from the VCPU. The steal time thread has the same CPU affinity as the VCPUs. */
run_delay = get_run_delay();
- pthread_create(&thread, NULL, do_steal_time, NULL);
+ kvm_pthread_create(&thread, NULL, do_steal_time, NULL);
pthread_getaffinity_np(thread, sizeof(cpuset), &cpuset);
TEST_ASSERT(CPU_COUNT(&cpuset) == 1 && CPU_ISSET(cpu, &cpuset),
"Worker failed to inherit parent's CPU affinity");
diff --git a/tools/testing/selftests/kvm/x86/hyperv_ipi.c b/tools/testing/selftests/kvm/x86/hyperv_ipi.c
index 771535f9aad3..3cf451f3153e 100644
--- a/tools/testing/selftests/kvm/x86/hyperv_ipi.c
+++ b/tools/testing/selftests/kvm/x86/hyperv_ipi.c
@@ -245,7 +245,7 @@ int main(int argc, char *argv[])
struct kvm_vcpu *vcpu[3];
gva_t hcall_page;
pthread_t threads[2];
- int stage = 1, r;
+ int stage = 1;
struct ucall uc;
TEST_REQUIRE(kvm_has_cap(KVM_CAP_HYPERV_SEND_IPI));
@@ -272,11 +272,8 @@ int main(int argc, char *argv[])
vcpu_args_set(vcpu[0], 2, hcall_page, addr_gva2gpa(vm, hcall_page));
vcpu_set_hv_cpuid(vcpu[0]);
- r = pthread_create(&threads[0], NULL, vcpu_thread, vcpu[1]);
- TEST_ASSERT(!r, "pthread_create failed errno=%d", r);
-
- r = pthread_create(&threads[1], NULL, vcpu_thread, vcpu[2]);
- TEST_ASSERT(!r, "pthread_create failed errno=%d", errno);
+ kvm_pthread_create(&threads[0], NULL, vcpu_thread, vcpu[1]);
+ kvm_pthread_create(&threads[1], NULL, vcpu_thread, vcpu[2]);
while (true) {
vcpu_run(vcpu[0]);
@@ -306,5 +303,5 @@ int main(int argc, char *argv[])
cancel_join_vcpu_thread(threads[1], vcpu[2]);
kvm_vm_free(vm);
- return r;
+ return 0;
}
diff --git a/tools/testing/selftests/kvm/x86/hyperv_tlb_flush.c b/tools/testing/selftests/kvm/x86/hyperv_tlb_flush.c
index b4be9a175379..87fac1968a47 100644
--- a/tools/testing/selftests/kvm/x86/hyperv_tlb_flush.c
+++ b/tools/testing/selftests/kvm/x86/hyperv_tlb_flush.c
@@ -575,7 +575,7 @@ int main(int argc, char *argv[])
u64 *pte;
struct test_data *data;
struct ucall uc;
- int stage = 1, r, i;
+ int stage = 1, i;
TEST_REQUIRE(kvm_has_cap(KVM_CAP_HYPERV_TLBFLUSH));
@@ -632,11 +632,8 @@ int main(int argc, char *argv[])
vcpu_set_msr(vcpu[2], HV_X64_MSR_VP_INDEX, WORKER_VCPU_ID_2);
vcpu_set_hv_cpuid(vcpu[2]);
- r = pthread_create(&threads[0], NULL, vcpu_thread, vcpu[1]);
- TEST_ASSERT(!r, "pthread_create() failed");
-
- r = pthread_create(&threads[1], NULL, vcpu_thread, vcpu[2]);
- TEST_ASSERT(!r, "pthread_create() failed");
+ kvm_pthread_create(&threads[0], NULL, vcpu_thread, vcpu[1]);
+ kvm_pthread_create(&threads[1], NULL, vcpu_thread, vcpu[2]);
while (true) {
vcpu_run(vcpu[0]);
diff --git a/tools/testing/selftests/kvm/x86/private_mem_conversions_test.c b/tools/testing/selftests/kvm/x86/private_mem_conversions_test.c
index 1d2f5d4fd45d..e419b08f1fa6 100644
--- a/tools/testing/selftests/kvm/x86/private_mem_conversions_test.c
+++ b/tools/testing/selftests/kvm/x86/private_mem_conversions_test.c
@@ -412,7 +412,7 @@ static void test_mem_conversions(enum vm_mem_backing_src_type src_type, u32 nr_v
*/
virt_map(vm, gpa, gpa, PER_CPU_DATA_SIZE / vm->page_size);
- pthread_create(&threads[i], NULL, __test_mem_conversions, vcpus[i]);
+ kvm_pthread_create(&threads[i], NULL, __test_mem_conversions, vcpus[i]);
}
WRITE_ONCE(run_vcpus, true);
diff --git a/tools/testing/selftests/kvm/x86/private_mem_kvm_exits_test.c b/tools/testing/selftests/kvm/x86/private_mem_kvm_exits_test.c
index 10db9fe6d906..e26524fb4b50 100644
--- a/tools/testing/selftests/kvm/x86/private_mem_kvm_exits_test.c
+++ b/tools/testing/selftests/kvm/x86/private_mem_kvm_exits_test.c
@@ -65,9 +65,8 @@ static void test_private_access_memslot_deleted(void)
/* Request to access page privately */
vm_mem_set_private(vm, EXITS_TEST_GPA, EXITS_TEST_SIZE);
- pthread_create(&vm_thread, NULL,
- (void *(*)(void *))run_vcpu_get_exit_reason,
- (void *)vcpu);
+ kvm_pthread_create(&vm_thread, NULL,
+ (pthread_fn_t)run_vcpu_get_exit_reason, (void *)vcpu);
vm_mem_region_delete(vm, EXITS_TEST_SLOT);
diff --git a/tools/testing/selftests/kvm/x86/recalc_apic_map_test.c b/tools/testing/selftests/kvm/x86/recalc_apic_map_test.c
index cbc92a862ea9..13abb65620d5 100644
--- a/tools/testing/selftests/kvm/x86/recalc_apic_map_test.c
+++ b/tools/testing/selftests/kvm/x86/recalc_apic_map_test.c
@@ -57,7 +57,7 @@ int main(void)
for (i = 0; i < KVM_MAX_VCPUS; i++)
vcpu_set_msr(vcpus[i], MSR_IA32_APICBASE, LAPIC_X2APIC);
- TEST_ASSERT_EQ(pthread_create(&thread, NULL, race, vcpus[0]), 0);
+ kvm_pthread_create(&thread, NULL, race, vcpus[0]);
vcpuN = vcpus[KVM_MAX_VCPUS - 1];
for (t = time(NULL) + TIMEOUT; time(NULL) < t;) {
diff --git a/tools/testing/selftests/kvm/x86/sev_migrate_tests.c b/tools/testing/selftests/kvm/x86/sev_migrate_tests.c
index d59abb198d86..66c7ce49620a 100644
--- a/tools/testing/selftests/kvm/x86/sev_migrate_tests.c
+++ b/tools/testing/selftests/kvm/x86/sev_migrate_tests.c
@@ -128,7 +128,7 @@ static void test_sev_migrate_locking(void)
sizeof(input[i].source_vms));
for (i = 0; i < NR_LOCK_TESTING_THREADS; ++i)
- pthread_create(&pt[i], NULL, locking_test_thread, &input[i]);
+ kvm_pthread_create(&pt[i], NULL, locking_test_thread, &input[i]);
for (i = 0; i < NR_LOCK_TESTING_THREADS; ++i)
pthread_join(pt[i], NULL);
diff --git a/tools/testing/selftests/kvm/x86/sync_regs_test.c b/tools/testing/selftests/kvm/x86/sync_regs_test.c
index 5b0c2359bbb4..f7228af7d594 100644
--- a/tools/testing/selftests/kvm/x86/sync_regs_test.c
+++ b/tools/testing/selftests/kvm/x86/sync_regs_test.c
@@ -181,7 +181,7 @@ static void race_sync_regs(struct kvm_vcpu *vcpu, void *racer)
!!(run->s.regs.sregs.cr4 & X86_CR4_PAE),
!!(run->s.regs.sregs.efer & EFER_LME));
- TEST_ASSERT_EQ(pthread_create(&thread, NULL, racer, (void *)run), 0);
+ kvm_pthread_create(&thread, NULL, racer, (void *)run);
for (t = time(NULL) + TIMEOUT; time(NULL) < t;) {
/*
diff --git a/tools/testing/selftests/kvm/x86/tsc_scaling_sync.c b/tools/testing/selftests/kvm/x86/tsc_scaling_sync.c
index 59da8d4da607..54b4b8d06d3b 100644
--- a/tools/testing/selftests/kvm/x86/tsc_scaling_sync.c
+++ b/tools/testing/selftests/kvm/x86/tsc_scaling_sync.c
@@ -94,7 +94,7 @@ int main(int argc, char *argv[])
pthread_t cpu_threads[NR_TEST_VCPUS];
unsigned long cpu;
for (cpu = 0; cpu < NR_TEST_VCPUS; cpu++)
- pthread_create(&cpu_threads[cpu], NULL, run_vcpu, (void *)cpu);
+ kvm_pthread_create(&cpu_threads[cpu], NULL, run_vcpu, (void *)cpu);
unsigned long failures = 0;
for (cpu = 0; cpu < NR_TEST_VCPUS; cpu++) {
diff --git a/tools/testing/selftests/kvm/x86/xapic_ipi_test.c b/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
index 3a326c5e74ca..271ec09c629e 100644
--- a/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
+++ b/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
@@ -387,7 +387,6 @@ void get_cmdline_args(int argc, char *argv[], int *run_secs,
int main(int argc, char *argv[])
{
- int r;
int wait_secs;
const int max_halter_wait = 10;
int run_secs = 0;
@@ -428,9 +427,7 @@ int main(int argc, char *argv[])
params[1].pipis_rcvd = pipis_rcvd;
/* Start halter vCPU thread and wait for it to execute first HLT. */
- r = pthread_create(&threads[0], NULL, vcpu_thread, ¶ms[0]);
- TEST_ASSERT(r == 0,
- "pthread_create halter failed errno=%d", errno);
+ kvm_pthread_create(&threads[0], NULL, vcpu_thread, ¶ms[0]);
fprintf(stderr, "Halter vCPU thread started\n");
wait_secs = 0;
@@ -447,8 +444,7 @@ int main(int argc, char *argv[])
"Halter vCPU thread reported its APIC ID: %u after %d seconds.\n",
data->halter_apic_id, wait_secs);
- r = pthread_create(&threads[1], NULL, vcpu_thread, ¶ms[1]);
- TEST_ASSERT(r == 0, "pthread_create sender failed errno=%d", errno);
+ kvm_pthread_create(&threads[1], NULL, vcpu_thread, ¶ms[1]);
fprintf(stderr,
"IPI sender vCPU thread started. Letting vCPUs run for %d seconds.\n",
diff --git a/tools/testing/selftests/kvm/x86/xen_shinfo_test.c b/tools/testing/selftests/kvm/x86/xen_shinfo_test.c
index 5076f6a75455..20f518fe2450 100644
--- a/tools/testing/selftests/kvm/x86/xen_shinfo_test.c
+++ b/tools/testing/selftests/kvm/x86/xen_shinfo_test.c
@@ -894,8 +894,7 @@ int main(int argc, char *argv[])
if (verbose)
printf("Testing shinfo lock corruption (KVM_XEN_HVM_EVTCHN_SEND)\n");
- ret = pthread_create(&thread, NULL, &juggle_shinfo_state, (void *)vm);
- TEST_ASSERT(ret == 0, "pthread_create() failed: %s", strerror(ret));
+ kvm_pthread_create(&thread, NULL, &juggle_shinfo_state, (void *)vm);
struct kvm_irq_routing_xen_evtchn uxe = {
.port = 1,
--
2.55.0.508.g3f0d502094-goog
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 5/9] KVM: selftests: Add KVM syscall wrapper for pthread_create()
2026-07-30 19:19 ` [PATCH 5/9] KVM: selftests: Add KVM syscall wrapper for pthread_create() Sean Christopherson
@ 2026-07-30 19:30 ` sashiko-bot
0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-07-30 19:30 UTC (permalink / raw)
To: Sean Christopherson; +Cc: kvmarm, kvm, Marc Zyngier, Oliver Upton
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Misleading error reporting when pthread_create fails due to reliance on errno.
--
--- Patch [5]: [PATCH 5/9] KVM: selftests: Add KVM syscall wrapper for pthread_create() ---
commit c5c266b1e7b797f8b82c5a3cecf097ba6720b060
Author: Sean Christopherson <seanjc@google.com>
KVM: selftests: Add KVM syscall wrapper for pthread_create()
This commit adds a KVM wrapper for pthread_create() to eliminate manual
success assertions in selftests. It replaces direct calls to pthread_create()
with kvm_pthread_create() across multiple test files.
> diff --git a/tools/testing/selftests/kvm/include/kvm_syscalls.h b/tools/testing/selftests/kvm/include/kvm_syscalls.h
> --- a/tools/testing/selftests/kvm/include/kvm_syscalls.h
> +++ b/tools/testing/selftests/kvm/include/kvm_syscalls.h
[ ... ]
> @@ -96,6 +97,10 @@ __KVM_SYSCALL_DEFINE(ftruncate, 2, unsigned int, fd, off_t, length);
> __KVM_SYSCALL_DEFINE(madvise, 3, void *, addr, size_t, length, int, advice);
> __KVM_SYSCALL_DEFINE(sched_getaffinity, 3, pid_t, pid, size_t, cpusetsize, cpu_set_t *, mask);
>
> +typedef void *(*pthread_fn_t)(void *);
> +__KVM_SYSCALL_DEFINE(pthread_create, 4, pthread_t *, thread,
> + const pthread_attr_t *, attr, pthread_fn_t, fn, void *, arg);
[Severity: Low]
Does this lead to misleading error messages on failure?
The __KVM_SYSCALL_DEFINE macro seems to assume the wrapped function sets errno
on failure, which gets printed when the test asserts via __KVM_SYSCALL_ERROR.
However, pthread_create() returns its error code directly rather than setting
errno.
If thread creation fails, it looks like the test framework might print a
misleading message containing "errno: 0 (Success)" alongside the actual
non-zero return code. Should this use a different wrapper or assert strategy
that handles direct error returns?
> +
> #define kvm_free_fd(fd) \
> do { \
> kvm_close(fd); \
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730191908.2084803-1-seanjc@google.com?part=5
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 6/9] KVM: selftests: Add KVM syscall wrappers for pthread_{cancel,join}()
2026-07-30 19:18 [PATCH 0/9] KVM: selftests: Add more syscall wrappers, fix hardware_disable_test Sean Christopherson
` (4 preceding siblings ...)
2026-07-30 19:19 ` [PATCH 5/9] KVM: selftests: Add KVM syscall wrapper for pthread_create() Sean Christopherson
@ 2026-07-30 19:19 ` Sean Christopherson
2026-07-30 19:19 ` [PATCH 7/9] KVM: selftests: Add helper APIs to cancel+join pthreads Sean Christopherson
` (2 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: Sean Christopherson @ 2026-07-30 19:19 UTC (permalink / raw)
To: Paolo Bonzini, Marc Zyngier, Oliver Upton, Christian Borntraeger,
Janosch Frank, Claudio Imbrenda, Sean Christopherson
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
David Hildenbrand, kvm, linux-arm-kernel, kvmarm, linux-kernel
Add and use KVM wrappers for pthread_{cancel,join}() so that selftests
don't need to manually assert that the syscalls succeeded.
Note, the vast majority tests don't actually assert success, but they all
obviously rely on the syscall to succeed.
Other than explicitly failing if a syscall fails, no functional change
intended.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
tools/testing/selftests/kvm/arch_timer.c | 4 ++--
tools/testing/selftests/kvm/arm64/vgic_irq.c | 4 ++--
tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c | 4 ++--
tools/testing/selftests/kvm/dirty_log_test.c | 2 +-
tools/testing/selftests/kvm/include/kvm_syscalls.h | 2 ++
tools/testing/selftests/kvm/irq_test.c | 2 +-
tools/testing/selftests/kvm/irqfd_test.c | 2 +-
tools/testing/selftests/kvm/kvm_page_table_test.c | 2 +-
tools/testing/selftests/kvm/lib/memstress.c | 2 +-
tools/testing/selftests/kvm/lib/userfaultfd_util.c | 3 +--
tools/testing/selftests/kvm/memslot_perf_test.c | 2 +-
tools/testing/selftests/kvm/mmu_stress_test.c | 2 +-
tools/testing/selftests/kvm/pre_fault_memory_test.c | 2 +-
tools/testing/selftests/kvm/rseq_test.c | 2 +-
tools/testing/selftests/kvm/s390/memop.c | 2 +-
tools/testing/selftests/kvm/set_memory_region_test.c | 4 ++--
tools/testing/selftests/kvm/steal_time.c | 2 +-
tools/testing/selftests/kvm/x86/hyperv_ipi.c | 10 ++--------
tools/testing/selftests/kvm/x86/hyperv_tlb_flush.c | 10 ++--------
.../selftests/kvm/x86/private_mem_conversions_test.c | 2 +-
.../selftests/kvm/x86/private_mem_kvm_exits_test.c | 2 +-
.../testing/selftests/kvm/x86/recalc_apic_map_test.c | 4 ++--
tools/testing/selftests/kvm/x86/sev_migrate_tests.c | 2 +-
tools/testing/selftests/kvm/x86/sync_regs_test.c | 4 ++--
tools/testing/selftests/kvm/x86/tsc_scaling_sync.c | 2 +-
tools/testing/selftests/kvm/x86/xapic_ipi_test.c | 12 ++----------
tools/testing/selftests/kvm/x86/xen_shinfo_test.c | 8 ++------
27 files changed, 38 insertions(+), 61 deletions(-)
diff --git a/tools/testing/selftests/kvm/arch_timer.c b/tools/testing/selftests/kvm/arch_timer.c
index a6a66b5b7ea9..03160ad666f5 100644
--- a/tools/testing/selftests/kvm/arch_timer.c
+++ b/tools/testing/selftests/kvm/arch_timer.c
@@ -158,10 +158,10 @@ static void test_run(struct kvm_vm *vm)
}
for (i = 0; i < test_args.nr_vcpus; i++)
- pthread_join(pt_vcpu_run[i], NULL);
+ kvm_pthread_join(pt_vcpu_run[i], NULL);
if (test_args.migration_freq_ms)
- pthread_join(pt_vcpu_migration, NULL);
+ kvm_pthread_join(pt_vcpu_migration, NULL);
bitmap_free(vcpu_done_map);
}
diff --git a/tools/testing/selftests/kvm/arm64/vgic_irq.c b/tools/testing/selftests/kvm/arm64/vgic_irq.c
index 2d6f20d5c117..3cb85932ee85 100644
--- a/tools/testing/selftests/kvm/arm64/vgic_irq.c
+++ b/tools/testing/selftests/kvm/arm64/vgic_irq.c
@@ -1007,8 +1007,8 @@ static void test_vgic_two_cpus(void *gcode)
kvm_pthread_create(&thr[0], NULL, test_vcpu_run, vcpus[0]);
kvm_pthread_create(&thr[1], NULL, test_vcpu_run, vcpus[1]);
- pthread_join(thr[0], NULL);
- pthread_join(thr[1], NULL);
+ kvm_pthread_join(thr[0], NULL);
+ kvm_pthread_join(thr[1], NULL);
close(gic_fd);
kvm_vm_free(vm);
diff --git a/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c b/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
index 549e0547d905..9a69c439a0f8 100644
--- a/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
+++ b/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
@@ -321,13 +321,13 @@ static void run_test(void)
clock_gettime(CLOCK_MONOTONIC, &start);
for (i = 0; i < nr_devices; i++)
- pthread_join(lpi_threads[i], NULL);
+ kvm_pthread_join(lpi_threads[i], NULL);
delta = timespec_elapsed(start);
write_guest_global(vm, test_data.request_vcpus_stop, true);
for (i = 0; i < nr_vcpus; i++)
- pthread_join(vcpu_threads[i], NULL);
+ kvm_pthread_join(vcpu_threads[i], NULL);
report_stats(delta);
}
diff --git a/tools/testing/selftests/kvm/dirty_log_test.c b/tools/testing/selftests/kvm/dirty_log_test.c
index ca22e5f09ac2..af5eb0334a74 100644
--- a/tools/testing/selftests/kvm/dirty_log_test.c
+++ b/tools/testing/selftests/kvm/dirty_log_test.c
@@ -805,7 +805,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
WRITE_ONCE(host_quit, true);
sem_post(&sem_vcpu_cont);
- pthread_join(vcpu_thread, NULL);
+ kvm_pthread_join(vcpu_thread, NULL);
pr_info("Total bits checked: dirty (%lu), clear (%lu)\n",
host_dirty_count, host_clear_count);
diff --git a/tools/testing/selftests/kvm/include/kvm_syscalls.h b/tools/testing/selftests/kvm/include/kvm_syscalls.h
index 3c22d4f3a485..abfd89372f19 100644
--- a/tools/testing/selftests/kvm/include/kvm_syscalls.h
+++ b/tools/testing/selftests/kvm/include/kvm_syscalls.h
@@ -100,6 +100,8 @@ __KVM_SYSCALL_DEFINE(sched_getaffinity, 3, pid_t, pid, size_t, cpusetsize, cpu_s
typedef void *(*pthread_fn_t)(void *);
__KVM_SYSCALL_DEFINE(pthread_create, 4, pthread_t *, thread,
const pthread_attr_t *, attr, pthread_fn_t, fn, void *, arg);
+__KVM_SYSCALL_DEFINE(pthread_join, 2, pthread_t, thread, void **, thread_return);
+__KVM_SYSCALL_DEFINE(pthread_cancel, 1, pthread_t, thread);
#define kvm_free_fd(fd) \
do { \
diff --git a/tools/testing/selftests/kvm/irq_test.c b/tools/testing/selftests/kvm/irq_test.c
index 7da5f8d75e85..168c52734fef 100644
--- a/tools/testing/selftests/kvm/irq_test.c
+++ b/tools/testing/selftests/kvm/irq_test.c
@@ -356,7 +356,7 @@ int main(int argc, char **argv)
WRITE_AND_SYNC_TO_GUEST(vm, done, true);
for (i = 0; i < nr_vcpus; i++)
- pthread_join(vcpu_threads[i], NULL);
+ kvm_pthread_join(vcpu_threads[i], NULL);
return 0;
}
diff --git a/tools/testing/selftests/kvm/irqfd_test.c b/tools/testing/selftests/kvm/irqfd_test.c
index 8b39144a2834..ebb2478878de 100644
--- a/tools/testing/selftests/kvm/irqfd_test.c
+++ b/tools/testing/selftests/kvm/irqfd_test.c
@@ -139,5 +139,5 @@ int main(int argc, char *argv[])
}
WRITE_ONCE(done, true);
- pthread_join(racing_thread, NULL);
+ kvm_pthread_join(racing_thread, NULL);
}
diff --git a/tools/testing/selftests/kvm/kvm_page_table_test.c b/tools/testing/selftests/kvm/kvm_page_table_test.c
index 8222bdb63e49..974813ea8953 100644
--- a/tools/testing/selftests/kvm/kvm_page_table_test.c
+++ b/tools/testing/selftests/kvm/kvm_page_table_test.c
@@ -413,7 +413,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
}
for (i = 0; i < nr_vcpus; i++)
- pthread_join(vcpu_threads[i], NULL);
+ kvm_pthread_join(vcpu_threads[i], NULL);
ret = sem_destroy(&test_stage_updated);
TEST_ASSERT(ret == 0, "Error in sem_destroy");
diff --git a/tools/testing/selftests/kvm/lib/memstress.c b/tools/testing/selftests/kvm/lib/memstress.c
index 0bfa623ce9b5..2864562f57b4 100644
--- a/tools/testing/selftests/kvm/lib/memstress.c
+++ b/tools/testing/selftests/kvm/lib/memstress.c
@@ -312,7 +312,7 @@ void memstress_join_vcpu_threads(int nr_vcpus)
WRITE_ONCE(memstress_args.stop_vcpus, true);
for (i = 0; i < nr_vcpus; i++)
- pthread_join(vcpu_threads[i].thread, NULL);
+ kvm_pthread_join(vcpu_threads[i].thread, NULL);
}
static void toggle_dirty_logging(struct kvm_vm *vm, int slots, bool enable)
diff --git a/tools/testing/selftests/kvm/lib/userfaultfd_util.c b/tools/testing/selftests/kvm/lib/userfaultfd_util.c
index 4b3e3158ed87..f7ce5a6ddcc2 100644
--- a/tools/testing/selftests/kvm/lib/userfaultfd_util.c
+++ b/tools/testing/selftests/kvm/lib/userfaultfd_util.c
@@ -187,8 +187,7 @@ void uffd_stop_demand_paging(struct uffd_desc *uffd)
"Unable to write to pipefd %i for uffd_desc %p", i, uffd);
for (i = 0; i < uffd->num_readers; ++i)
- TEST_ASSERT(!pthread_join(uffd->readers[i], NULL),
- "Pthread_join failed on reader %i for uffd_desc %p", i, uffd);
+ kvm_pthread_join(uffd->readers[i], NULL);
close(uffd->uffd);
diff --git a/tools/testing/selftests/kvm/memslot_perf_test.c b/tools/testing/selftests/kvm/memslot_perf_test.c
index eb49305db404..e1299611be32 100644
--- a/tools/testing/selftests/kvm/memslot_perf_test.c
+++ b/tools/testing/selftests/kvm/memslot_perf_test.c
@@ -381,7 +381,7 @@ static void free_vm(struct vm_data *data)
static void wait_guest_exit(struct vm_data *data)
{
- pthread_join(data->vcpu_thread, NULL);
+ kvm_pthread_join(data->vcpu_thread, NULL);
}
static void let_guest_run(struct sync_area *sync)
diff --git a/tools/testing/selftests/kvm/mmu_stress_test.c b/tools/testing/selftests/kvm/mmu_stress_test.c
index 9448498849ff..741e343962ed 100644
--- a/tools/testing/selftests/kvm/mmu_stress_test.c
+++ b/tools/testing/selftests/kvm/mmu_stress_test.c
@@ -409,7 +409,7 @@ int main(int argc, char *argv[])
/* Sanity check that the vCPUs actually ran. */
for (i = 0; i < nr_vcpus; i++)
- pthread_join(threads[i], NULL);
+ kvm_pthread_join(threads[i], NULL);
/*
* Deliberately exit without deleting the remaining memslots or closing
diff --git a/tools/testing/selftests/kvm/pre_fault_memory_test.c b/tools/testing/selftests/kvm/pre_fault_memory_test.c
index 88287ccb9093..c57631aab3d3 100644
--- a/tools/testing/selftests/kvm/pre_fault_memory_test.c
+++ b/tools/testing/selftests/kvm/pre_fault_memory_test.c
@@ -116,7 +116,7 @@ static void pre_fault_memory(struct kvm_vcpu *vcpu, u64 base_gpa, u64 offset,
*/
if (!slot_recreated) {
WRITE_ONCE(data.recreate_slot, true);
- pthread_join(slot_worker, NULL);
+ kvm_pthread_join(slot_worker, NULL);
slot_recreated = true;
/*
diff --git a/tools/testing/selftests/kvm/rseq_test.c b/tools/testing/selftests/kvm/rseq_test.c
index 9a1851203544..df3e5ad1c393 100644
--- a/tools/testing/selftests/kvm/rseq_test.c
+++ b/tools/testing/selftests/kvm/rseq_test.c
@@ -314,7 +314,7 @@ int main(int argc, char *argv[])
" e.g. via cpuidle.off=1 or via -l <latency>, or run with -u to\n"
" disable this sanity check.", i);
- pthread_join(migration_thread, NULL);
+ kvm_pthread_join(migration_thread, NULL);
kvm_vm_free(vm);
diff --git a/tools/testing/selftests/kvm/s390/memop.c b/tools/testing/selftests/kvm/s390/memop.c
index 96b32bd74009..ce8db96ccf7e 100644
--- a/tools/testing/selftests/kvm/s390/memop.c
+++ b/tools/testing/selftests/kvm/s390/memop.c
@@ -701,7 +701,7 @@ static void test_cmpxchg_key_concurrent(void)
}
}
- pthread_join(thread, NULL);
+ kvm_pthread_join(thread, NULL);
MOP(t.vcpu, LOGICAL, READ, mem2, max_block, GADDR_V(mem2));
TEST_ASSERT(popcount_eq(*(__uint128_t *)mem1, *(__uint128_t *)mem2),
diff --git a/tools/testing/selftests/kvm/set_memory_region_test.c b/tools/testing/selftests/kvm/set_memory_region_test.c
index 12f5022bb164..dffe9654f45b 100644
--- a/tools/testing/selftests/kvm/set_memory_region_test.c
+++ b/tools/testing/selftests/kvm/set_memory_region_test.c
@@ -216,7 +216,7 @@ static void test_move_memory_region(bool disable_slot_zap_quirk)
/* Defered sync from when the memslot was misaligned (above). */
wait_for_vcpu();
- pthread_join(vcpu_thread, NULL);
+ kvm_pthread_join(vcpu_thread, NULL);
kvm_vm_free(vm);
}
@@ -302,7 +302,7 @@ static void test_delete_memory_region(bool disable_slot_zap_quirk)
*/
vm_mem_region_delete(vm, 0);
- pthread_join(vcpu_thread, NULL);
+ kvm_pthread_join(vcpu_thread, NULL);
run = vcpu->run;
diff --git a/tools/testing/selftests/kvm/steal_time.c b/tools/testing/selftests/kvm/steal_time.c
index f5f708be5aa0..6cb1eb4c40c9 100644
--- a/tools/testing/selftests/kvm/steal_time.c
+++ b/tools/testing/selftests/kvm/steal_time.c
@@ -556,7 +556,7 @@ int main(int ac, char **av)
do
sched_yield();
while (get_run_delay() - run_delay < MIN_RUN_DELAY_NS);
- pthread_join(thread, NULL);
+ kvm_pthread_join(thread, NULL);
run_delay = get_run_delay() - run_delay;
TEST_ASSERT(run_delay >= MIN_RUN_DELAY_NS,
"Expected run_delay >= %ld, got %ld",
diff --git a/tools/testing/selftests/kvm/x86/hyperv_ipi.c b/tools/testing/selftests/kvm/x86/hyperv_ipi.c
index 3cf451f3153e..d2efb1043534 100644
--- a/tools/testing/selftests/kvm/x86/hyperv_ipi.c
+++ b/tools/testing/selftests/kvm/x86/hyperv_ipi.c
@@ -225,15 +225,9 @@ static void *vcpu_thread(void *arg)
static void cancel_join_vcpu_thread(pthread_t thread, struct kvm_vcpu *vcpu)
{
void *retval;
- int r;
- r = pthread_cancel(thread);
- TEST_ASSERT(!r, "pthread_cancel on vcpu_id=%d failed with errno=%d",
- vcpu->id, r);
-
- r = pthread_join(thread, &retval);
- TEST_ASSERT(!r, "pthread_join on vcpu_id=%d failed with errno=%d",
- vcpu->id, r);
+ kvm_pthread_cancel(thread);
+ kvm_pthread_join(thread, &retval);
TEST_ASSERT(retval == PTHREAD_CANCELED,
"expected retval=%p, got %p", PTHREAD_CANCELED,
retval);
diff --git a/tools/testing/selftests/kvm/x86/hyperv_tlb_flush.c b/tools/testing/selftests/kvm/x86/hyperv_tlb_flush.c
index 87fac1968a47..e4fc9bb6f329 100644
--- a/tools/testing/selftests/kvm/x86/hyperv_tlb_flush.c
+++ b/tools/testing/selftests/kvm/x86/hyperv_tlb_flush.c
@@ -551,15 +551,9 @@ static void *vcpu_thread(void *arg)
static void cancel_join_vcpu_thread(pthread_t thread, struct kvm_vcpu *vcpu)
{
void *retval;
- int r;
- r = pthread_cancel(thread);
- TEST_ASSERT(!r, "pthread_cancel on vcpu_id=%d failed with errno=%d",
- vcpu->id, r);
-
- r = pthread_join(thread, &retval);
- TEST_ASSERT(!r, "pthread_join on vcpu_id=%d failed with errno=%d",
- vcpu->id, r);
+ kvm_pthread_cancel(thread);
+ kvm_pthread_join(thread, &retval);
TEST_ASSERT(retval == PTHREAD_CANCELED,
"expected retval=%p, got %p", PTHREAD_CANCELED,
retval);
diff --git a/tools/testing/selftests/kvm/x86/private_mem_conversions_test.c b/tools/testing/selftests/kvm/x86/private_mem_conversions_test.c
index e419b08f1fa6..3aa0673f79f3 100644
--- a/tools/testing/selftests/kvm/x86/private_mem_conversions_test.c
+++ b/tools/testing/selftests/kvm/x86/private_mem_conversions_test.c
@@ -418,7 +418,7 @@ static void test_mem_conversions(enum vm_mem_backing_src_type src_type, u32 nr_v
WRITE_ONCE(run_vcpus, true);
for (i = 0; i < nr_vcpus; i++)
- pthread_join(threads[i], NULL);
+ kvm_pthread_join(threads[i], NULL);
kvm_vm_free(vm);
diff --git a/tools/testing/selftests/kvm/x86/private_mem_kvm_exits_test.c b/tools/testing/selftests/kvm/x86/private_mem_kvm_exits_test.c
index e26524fb4b50..e6d16e9d6120 100644
--- a/tools/testing/selftests/kvm/x86/private_mem_kvm_exits_test.c
+++ b/tools/testing/selftests/kvm/x86/private_mem_kvm_exits_test.c
@@ -70,7 +70,7 @@ static void test_private_access_memslot_deleted(void)
vm_mem_region_delete(vm, EXITS_TEST_SLOT);
- pthread_join(vm_thread, &thread_return);
+ kvm_pthread_join(vm_thread, &thread_return);
exit_reason = (u32)(u64)thread_return;
TEST_ASSERT_EQ(exit_reason, KVM_EXIT_MEMORY_FAULT);
diff --git a/tools/testing/selftests/kvm/x86/recalc_apic_map_test.c b/tools/testing/selftests/kvm/x86/recalc_apic_map_test.c
index 13abb65620d5..e3e397f32bff 100644
--- a/tools/testing/selftests/kvm/x86/recalc_apic_map_test.c
+++ b/tools/testing/selftests/kvm/x86/recalc_apic_map_test.c
@@ -65,8 +65,8 @@ int main(void)
vcpu_set_msr(vcpuN, MSR_IA32_APICBASE, LAPIC_DISABLED);
}
- TEST_ASSERT_EQ(pthread_cancel(thread), 0);
- TEST_ASSERT_EQ(pthread_join(thread, NULL), 0);
+ kvm_pthread_cancel(thread);
+ kvm_pthread_join(thread, NULL);
kvm_vm_free(vm);
diff --git a/tools/testing/selftests/kvm/x86/sev_migrate_tests.c b/tools/testing/selftests/kvm/x86/sev_migrate_tests.c
index 66c7ce49620a..de006e1c861c 100644
--- a/tools/testing/selftests/kvm/x86/sev_migrate_tests.c
+++ b/tools/testing/selftests/kvm/x86/sev_migrate_tests.c
@@ -131,7 +131,7 @@ static void test_sev_migrate_locking(void)
kvm_pthread_create(&pt[i], NULL, locking_test_thread, &input[i]);
for (i = 0; i < NR_LOCK_TESTING_THREADS; ++i)
- pthread_join(pt[i], NULL);
+ kvm_pthread_join(pt[i], NULL);
for (i = 0; i < NR_LOCK_TESTING_THREADS; ++i)
kvm_vm_free(input[i].vm);
}
diff --git a/tools/testing/selftests/kvm/x86/sync_regs_test.c b/tools/testing/selftests/kvm/x86/sync_regs_test.c
index f7228af7d594..99a5bbeffc5d 100644
--- a/tools/testing/selftests/kvm/x86/sync_regs_test.c
+++ b/tools/testing/selftests/kvm/x86/sync_regs_test.c
@@ -199,8 +199,8 @@ static void race_sync_regs(struct kvm_vcpu *vcpu, void *racer)
}
}
- TEST_ASSERT_EQ(pthread_cancel(thread), 0);
- TEST_ASSERT_EQ(pthread_join(thread, NULL), 0);
+ kvm_pthread_cancel(thread);
+ kvm_pthread_join(thread, NULL);
kvm_x86_state_cleanup(state);
}
diff --git a/tools/testing/selftests/kvm/x86/tsc_scaling_sync.c b/tools/testing/selftests/kvm/x86/tsc_scaling_sync.c
index 54b4b8d06d3b..2a3a9bd8b338 100644
--- a/tools/testing/selftests/kvm/x86/tsc_scaling_sync.c
+++ b/tools/testing/selftests/kvm/x86/tsc_scaling_sync.c
@@ -99,7 +99,7 @@ int main(int argc, char *argv[])
unsigned long failures = 0;
for (cpu = 0; cpu < NR_TEST_VCPUS; cpu++) {
void *this_cpu_failures;
- pthread_join(cpu_threads[cpu], &this_cpu_failures);
+ kvm_pthread_join(cpu_threads[cpu], &this_cpu_failures);
failures += (unsigned long)this_cpu_failures;
}
diff --git a/tools/testing/selftests/kvm/x86/xapic_ipi_test.c b/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
index 271ec09c629e..33e78b284c67 100644
--- a/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
+++ b/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
@@ -231,17 +231,9 @@ static void *vcpu_thread(void *arg)
static void cancel_join_vcpu_thread(pthread_t thread, struct kvm_vcpu *vcpu)
{
void *retval;
- int r;
- r = pthread_cancel(thread);
- TEST_ASSERT(r == 0,
- "pthread_cancel on vcpu_id=%d failed with errno=%d",
- vcpu->id, r);
-
- r = pthread_join(thread, &retval);
- TEST_ASSERT(r == 0,
- "pthread_join on vcpu_id=%d failed with errno=%d",
- vcpu->id, r);
+ kvm_pthread_cancel(thread);
+ kvm_pthread_join(thread, &retval);
TEST_ASSERT(retval == PTHREAD_CANCELED,
"expected retval=%p, got %p", PTHREAD_CANCELED,
retval);
diff --git a/tools/testing/selftests/kvm/x86/xen_shinfo_test.c b/tools/testing/selftests/kvm/x86/xen_shinfo_test.c
index 20f518fe2450..3ec5e67b21ef 100644
--- a/tools/testing/selftests/kvm/x86/xen_shinfo_test.c
+++ b/tools/testing/selftests/kvm/x86/xen_shinfo_test.c
@@ -437,7 +437,6 @@ int main(int argc, char *argv[])
struct kvm_vm *vm;
pthread_t thread;
bool verbose;
- int ret;
verbose = argc > 1 && (!strncmp(argv[1], "-v", 3) ||
!strncmp(argv[1], "--verbose", 10));
@@ -948,11 +947,8 @@ int main(int argc, char *argv[])
TEST_ASSERT(!evtchn_irq_expected,
"Expected event channel IRQ but it didn't happen");
- ret = pthread_cancel(thread);
- TEST_ASSERT(ret == 0, "pthread_cancel() failed: %s", strerror(ret));
-
- ret = pthread_join(thread, 0);
- TEST_ASSERT(ret == 0, "pthread_join() failed: %s", strerror(ret));
+ kvm_pthread_cancel(thread);
+ kvm_pthread_join(thread, 0);
goto done;
case TEST_GUEST_SAW_IRQ:
--
2.55.0.508.g3f0d502094-goog
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 7/9] KVM: selftests: Add helper APIs to cancel+join pthreads
2026-07-30 19:18 [PATCH 0/9] KVM: selftests: Add more syscall wrappers, fix hardware_disable_test Sean Christopherson
` (5 preceding siblings ...)
2026-07-30 19:19 ` [PATCH 6/9] KVM: selftests: Add KVM syscall wrappers for pthread_{cancel,join}() Sean Christopherson
@ 2026-07-30 19:19 ` Sean Christopherson
2026-07-30 19:19 ` [PATCH 8/9] KVM: selftests: Add KVM syscall wrappers for pthread_{g,s}etaffinity_np() Sean Christopherson
2026-07-30 19:19 ` [PATCH 9/9] KVM: selftests: Clean up global constants in hardware disable test Sean Christopherson
8 siblings, 0 replies; 15+ messages in thread
From: Sean Christopherson @ 2026-07-30 19:19 UTC (permalink / raw)
To: Paolo Bonzini, Marc Zyngier, Oliver Upton, Christian Borntraeger,
Janosch Frank, Claudio Imbrenda, Sean Christopherson
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
David Hildenbrand, kvm, linux-arm-kernel, kvmarm, linux-kernel
Deduplicate test code that does cancel()+join() on pthreads by adding a
collection of syscall wrappers. The tests that asynchronously cancel
pthreads, i.e. use PTHREAD_CANCEL_ASYNCHRONOUS, are particularly ugly,
especially since it's not immediately obvious why those tests assert on
the thread being CANCELED, whereas others do not.
No functional change intended.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
.../selftests/kvm/include/kvm_syscalls.h | 24 +++++++++++++++++++
tools/testing/selftests/kvm/x86/hyperv_ipi.c | 15 ++----------
.../selftests/kvm/x86/hyperv_tlb_flush.c | 15 ++----------
.../selftests/kvm/x86/recalc_apic_map_test.c | 3 +--
.../selftests/kvm/x86/sync_regs_test.c | 3 +--
.../selftests/kvm/x86/xapic_ipi_test.c | 15 ++----------
.../selftests/kvm/x86/xen_shinfo_test.c | 3 +--
7 files changed, 33 insertions(+), 45 deletions(-)
diff --git a/tools/testing/selftests/kvm/include/kvm_syscalls.h b/tools/testing/selftests/kvm/include/kvm_syscalls.h
index abfd89372f19..002b5a4e59eb 100644
--- a/tools/testing/selftests/kvm/include/kvm_syscalls.h
+++ b/tools/testing/selftests/kvm/include/kvm_syscalls.h
@@ -103,6 +103,30 @@ __KVM_SYSCALL_DEFINE(pthread_create, 4, pthread_t *, thread,
__KVM_SYSCALL_DEFINE(pthread_join, 2, pthread_t, thread, void **, thread_return);
__KVM_SYSCALL_DEFINE(pthread_cancel, 1, pthread_t, thread);
+static inline void __kvm_cancel_join_pthread(pthread_t thread, void **r)
+{
+ kvm_pthread_cancel(thread);
+ kvm_pthread_join(thread, r);
+}
+
+static inline void kvm_cancel_join_pthread(pthread_t thread)
+{
+ __kvm_cancel_join_pthread(thread, NULL);
+}
+
+/*
+ * Cancel+Join a pthread that was configured with PTHREAD_CANCEL_ASYNCHRONOUS
+ * and is expected to exit only in response to cancellation.
+ */
+static inline void kvm_cancel_join_pthread_async(pthread_t thread)
+{
+ void *r;
+
+ __kvm_cancel_join_pthread(thread, &r);
+ TEST_ASSERT(r == PTHREAD_CANCELED,
+ "expected retval=%p, got %p", PTHREAD_CANCELED, r);
+}
+
#define kvm_free_fd(fd) \
do { \
kvm_close(fd); \
diff --git a/tools/testing/selftests/kvm/x86/hyperv_ipi.c b/tools/testing/selftests/kvm/x86/hyperv_ipi.c
index d2efb1043534..fe38cc4cba05 100644
--- a/tools/testing/selftests/kvm/x86/hyperv_ipi.c
+++ b/tools/testing/selftests/kvm/x86/hyperv_ipi.c
@@ -222,17 +222,6 @@ static void *vcpu_thread(void *arg)
return NULL;
}
-static void cancel_join_vcpu_thread(pthread_t thread, struct kvm_vcpu *vcpu)
-{
- void *retval;
-
- kvm_pthread_cancel(thread);
- kvm_pthread_join(thread, &retval);
- TEST_ASSERT(retval == PTHREAD_CANCELED,
- "expected retval=%p, got %p", PTHREAD_CANCELED,
- retval);
-}
-
int main(int argc, char *argv[])
{
struct kvm_vm *vm;
@@ -293,8 +282,8 @@ int main(int argc, char *argv[])
}
done:
- cancel_join_vcpu_thread(threads[0], vcpu[1]);
- cancel_join_vcpu_thread(threads[1], vcpu[2]);
+ kvm_cancel_join_pthread_async(threads[0]);
+ kvm_cancel_join_pthread_async(threads[1]);
kvm_vm_free(vm);
return 0;
diff --git a/tools/testing/selftests/kvm/x86/hyperv_tlb_flush.c b/tools/testing/selftests/kvm/x86/hyperv_tlb_flush.c
index e4fc9bb6f329..84f22f39c8f2 100644
--- a/tools/testing/selftests/kvm/x86/hyperv_tlb_flush.c
+++ b/tools/testing/selftests/kvm/x86/hyperv_tlb_flush.c
@@ -548,17 +548,6 @@ static void *vcpu_thread(void *arg)
return NULL;
}
-static void cancel_join_vcpu_thread(pthread_t thread, struct kvm_vcpu *vcpu)
-{
- void *retval;
-
- kvm_pthread_cancel(thread);
- kvm_pthread_join(thread, &retval);
- TEST_ASSERT(retval == PTHREAD_CANCELED,
- "expected retval=%p, got %p", PTHREAD_CANCELED,
- retval);
-}
-
int main(int argc, char *argv[])
{
struct kvm_vm *vm;
@@ -652,8 +641,8 @@ int main(int argc, char *argv[])
}
done:
- cancel_join_vcpu_thread(threads[0], vcpu[1]);
- cancel_join_vcpu_thread(threads[1], vcpu[2]);
+ kvm_cancel_join_pthread_async(threads[0]);
+ kvm_cancel_join_pthread_async(threads[1]);
kvm_vm_free(vm);
return 0;
diff --git a/tools/testing/selftests/kvm/x86/recalc_apic_map_test.c b/tools/testing/selftests/kvm/x86/recalc_apic_map_test.c
index e3e397f32bff..7a0bd9f7ba6c 100644
--- a/tools/testing/selftests/kvm/x86/recalc_apic_map_test.c
+++ b/tools/testing/selftests/kvm/x86/recalc_apic_map_test.c
@@ -65,8 +65,7 @@ int main(void)
vcpu_set_msr(vcpuN, MSR_IA32_APICBASE, LAPIC_DISABLED);
}
- kvm_pthread_cancel(thread);
- kvm_pthread_join(thread, NULL);
+ kvm_cancel_join_pthread(thread);
kvm_vm_free(vm);
diff --git a/tools/testing/selftests/kvm/x86/sync_regs_test.c b/tools/testing/selftests/kvm/x86/sync_regs_test.c
index 99a5bbeffc5d..9d76c2ed784b 100644
--- a/tools/testing/selftests/kvm/x86/sync_regs_test.c
+++ b/tools/testing/selftests/kvm/x86/sync_regs_test.c
@@ -199,8 +199,7 @@ static void race_sync_regs(struct kvm_vcpu *vcpu, void *racer)
}
}
- kvm_pthread_cancel(thread);
- kvm_pthread_join(thread, NULL);
+ kvm_cancel_join_pthread(thread);
kvm_x86_state_cleanup(state);
}
diff --git a/tools/testing/selftests/kvm/x86/xapic_ipi_test.c b/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
index 33e78b284c67..78e7aae8fab8 100644
--- a/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
+++ b/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
@@ -228,17 +228,6 @@ static void *vcpu_thread(void *arg)
return NULL;
}
-static void cancel_join_vcpu_thread(pthread_t thread, struct kvm_vcpu *vcpu)
-{
- void *retval;
-
- kvm_pthread_cancel(thread);
- kvm_pthread_join(thread, &retval);
- TEST_ASSERT(retval == PTHREAD_CANCELED,
- "expected retval=%p, got %p", PTHREAD_CANCELED,
- retval);
-}
-
void do_migrations(struct test_data_page *data, int run_secs, int delay_usecs,
u64 *pipis_rcvd)
{
@@ -450,8 +439,8 @@ int main(int argc, char *argv[])
/*
* Cancel threads and wait for them to stop.
*/
- cancel_join_vcpu_thread(threads[0], params[0].vcpu);
- cancel_join_vcpu_thread(threads[1], params[1].vcpu);
+ kvm_cancel_join_pthread_async(threads[0]);
+ kvm_cancel_join_pthread_async(threads[1]);
/*
* If the host support Idle HLT, i.e. KVM *might* be using Idle HLT,
diff --git a/tools/testing/selftests/kvm/x86/xen_shinfo_test.c b/tools/testing/selftests/kvm/x86/xen_shinfo_test.c
index 3ec5e67b21ef..a226a2fd61d9 100644
--- a/tools/testing/selftests/kvm/x86/xen_shinfo_test.c
+++ b/tools/testing/selftests/kvm/x86/xen_shinfo_test.c
@@ -947,8 +947,7 @@ int main(int argc, char *argv[])
TEST_ASSERT(!evtchn_irq_expected,
"Expected event channel IRQ but it didn't happen");
- kvm_pthread_cancel(thread);
- kvm_pthread_join(thread, 0);
+ kvm_cancel_join_pthread(thread);
goto done;
case TEST_GUEST_SAW_IRQ:
--
2.55.0.508.g3f0d502094-goog
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 8/9] KVM: selftests: Add KVM syscall wrappers for pthread_{g,s}etaffinity_np()
2026-07-30 19:18 [PATCH 0/9] KVM: selftests: Add more syscall wrappers, fix hardware_disable_test Sean Christopherson
` (6 preceding siblings ...)
2026-07-30 19:19 ` [PATCH 7/9] KVM: selftests: Add helper APIs to cancel+join pthreads Sean Christopherson
@ 2026-07-30 19:19 ` Sean Christopherson
2026-07-30 19:29 ` sashiko-bot
2026-07-30 19:19 ` [PATCH 9/9] KVM: selftests: Clean up global constants in hardware disable test Sean Christopherson
8 siblings, 1 reply; 15+ messages in thread
From: Sean Christopherson @ 2026-07-30 19:19 UTC (permalink / raw)
To: Paolo Bonzini, Marc Zyngier, Oliver Upton, Christian Borntraeger,
Janosch Frank, Claudio Imbrenda, Sean Christopherson
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
David Hildenbrand, kvm, linux-arm-kernel, kvmarm, linux-kernel
Add and use KVM wrappers for pthread_{g,s}etaffinity_np() so that selftests
don't need to manually assert that the syscalls succeeded, and so that they
don't need to manually pass in sizeof(cpu_set_t) for the size.
Note, the steal time test didn't assert success, but the TEST_ASSERT() one
line later makes it quite clear the test relies on pthread_getaffinity_np()
succeeding.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
.../selftests/kvm/hardware_disable_test.c | 12 ++----------
.../testing/selftests/kvm/include/kvm_syscalls.h | 16 ++++++++++++++++
tools/testing/selftests/kvm/steal_time.c | 2 +-
3 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/tools/testing/selftests/kvm/hardware_disable_test.c b/tools/testing/selftests/kvm/hardware_disable_test.c
index 38ebacaa0fce..bcca42182656 100644
--- a/tools/testing/selftests/kvm/hardware_disable_test.c
+++ b/tools/testing/selftests/kvm/hardware_disable_test.c
@@ -54,14 +54,6 @@ static void *sleeping_thread(void *arg)
TEST_FAIL("%s: exited", __func__);
}
-static inline void check_set_affinity(pthread_t thread, cpu_set_t *cpu_set)
-{
- int r;
-
- r = pthread_setaffinity_np(thread, sizeof(cpu_set_t), cpu_set);
- TEST_ASSERT(r == 0, "%s: failed set affinity", __func__);
-}
-
static void run_test(u32 run)
{
struct kvm_vcpu *vcpu;
@@ -76,11 +68,11 @@ static void run_test(u32 run)
vcpu = vm_vcpu_add(vm, i, guest_code);
kvm_pthread_create(&thread, NULL, run_vcpu, vcpu);
- check_set_affinity(thread, &child_cpu_set);
+ kvm_pthread_setaffinity(thread, &child_cpu_set);
for (j = 0; j < SLEEPING_THREAD_NUM; ++j) {
kvm_pthread_create(&thread, NULL, sleeping_thread, (void *)NULL);
- check_set_affinity(thread, &child_cpu_set);
+ kvm_pthread_setaffinity(thread, &child_cpu_set);
}
}
pr_debug("%s: [%d] all threads launched\n", __func__, run);
diff --git a/tools/testing/selftests/kvm/include/kvm_syscalls.h b/tools/testing/selftests/kvm/include/kvm_syscalls.h
index 002b5a4e59eb..3d82351bef92 100644
--- a/tools/testing/selftests/kvm/include/kvm_syscalls.h
+++ b/tools/testing/selftests/kvm/include/kvm_syscalls.h
@@ -97,6 +97,22 @@ __KVM_SYSCALL_DEFINE(ftruncate, 2, unsigned int, fd, off_t, length);
__KVM_SYSCALL_DEFINE(madvise, 3, void *, addr, size_t, length, int, advice);
__KVM_SYSCALL_DEFINE(sched_getaffinity, 3, pid_t, pid, size_t, cpusetsize, cpu_set_t *, mask);
+__KVM_SYSCALL_DEFINE(pthread_getaffinity_np, 3, pthread_t, thread,
+ size_t, cpusetsize, cpu_set_t *, cpuset);
+__KVM_SYSCALL_DEFINE(pthread_setaffinity_np, 3, pthread_t, thread,
+ size_t, cpusetsize, const cpu_set_t *, cpuset);
+
+static inline void kvm_pthread_getaffinity(pthread_t thread, cpu_set_t *cpuset)
+{
+ kvm_pthread_getaffinity_np(thread, sizeof(cpu_set_t), cpuset);
+}
+
+static inline void kvm_pthread_setaffinity(pthread_t thread,
+ const cpu_set_t *cpuset)
+{
+ kvm_pthread_setaffinity_np(thread, sizeof(cpu_set_t), cpuset);
+}
+
typedef void *(*pthread_fn_t)(void *);
__KVM_SYSCALL_DEFINE(pthread_create, 4, pthread_t *, thread,
const pthread_attr_t *, attr, pthread_fn_t, fn, void *, arg);
diff --git a/tools/testing/selftests/kvm/steal_time.c b/tools/testing/selftests/kvm/steal_time.c
index 6cb1eb4c40c9..bc3c62b72c58 100644
--- a/tools/testing/selftests/kvm/steal_time.c
+++ b/tools/testing/selftests/kvm/steal_time.c
@@ -549,7 +549,7 @@ int main(int ac, char **av)
/* Steal time from the VCPU. The steal time thread has the same CPU affinity as the VCPUs. */
run_delay = get_run_delay();
kvm_pthread_create(&thread, NULL, do_steal_time, NULL);
- pthread_getaffinity_np(thread, sizeof(cpuset), &cpuset);
+ kvm_pthread_getaffinity(thread, &cpuset);
TEST_ASSERT(CPU_COUNT(&cpuset) == 1 && CPU_ISSET(cpu, &cpuset),
"Worker failed to inherit parent's CPU affinity");
--
2.55.0.508.g3f0d502094-goog
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 8/9] KVM: selftests: Add KVM syscall wrappers for pthread_{g,s}etaffinity_np()
2026-07-30 19:19 ` [PATCH 8/9] KVM: selftests: Add KVM syscall wrappers for pthread_{g,s}etaffinity_np() Sean Christopherson
@ 2026-07-30 19:29 ` sashiko-bot
2026-07-30 20:24 ` Sean Christopherson
0 siblings, 1 reply; 15+ messages in thread
From: sashiko-bot @ 2026-07-30 19:29 UTC (permalink / raw)
To: Sean Christopherson; +Cc: Oliver Upton, kvm, kvmarm, Marc Zyngier
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] KVM syscall wrappers for pthread functions produce misleading error messages on failure.
--
--- Patch [8]: [PATCH 8/9] KVM: selftests: Add KVM syscall wrappers for pthread_{g,s}etaffinity_np() ---
commit 9fc7623d339b95135fb5ecb9685356bc8dff9829
Author: Sean Christopherson <seanjc@google.com>
KVM: selftests: Add KVM syscall wrappers for pthread_{g,s}etaffinity_np()
This commit adds KVM wrappers for pthread_getaffinity_np() and
pthread_setaffinity_np() to simplify selftest code. It removes the need
to manually check for success or supply the size of cpu_set_t in the tests.
[ ... ]
> diff --git a/tools/testing/selftests/kvm/include/kvm_syscalls.h b/tools/testing/selftests/kvm/include/kvm_syscalls.h
> index 002b5a4e59eb2..3d82351bef92e 100644
> --- a/tools/testing/selftests/kvm/include/kvm_syscalls.h
> +++ b/tools/testing/selftests/kvm/include/kvm_syscalls.h
> @@ -97,6 +97,22 @@ __KVM_SYSCALL_DEFINE(ftruncate, 2, unsigned int, fd, off_t, length);
> __KVM_SYSCALL_DEFINE(madvise, 3, void *, addr, size_t, length, int, advice);
> __KVM_SYSCALL_DEFINE(sched_getaffinity, 3, pid_t, pid, size_t, cpusetsize, cpu_set_t *, mask);
>
> +__KVM_SYSCALL_DEFINE(pthread_getaffinity_np, 3, pthread_t, thread,
> + size_t, cpusetsize, cpu_set_t *, cpuset);
> +__KVM_SYSCALL_DEFINE(pthread_setaffinity_np, 3, pthread_t, thread,
> + size_t, cpusetsize, const cpu_set_t *, cpuset);
[Severity: Medium]
Will these pthread wrappers print misleading error messages on failure?
The pthread_* functions return positive error codes directly on failure
rather than returning -1 and setting errno. If __KVM_SYSCALL_DEFINE formats
its failure messages assuming errno is set, failing to set affinity could
result in printing a stale or unrelated error string (such as "Success")
alongside the return code, which might impede debugging.
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730191908.2084803-1-seanjc@google.com?part=8
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH 8/9] KVM: selftests: Add KVM syscall wrappers for pthread_{g,s}etaffinity_np()
2026-07-30 19:29 ` sashiko-bot
@ 2026-07-30 20:24 ` Sean Christopherson
0 siblings, 0 replies; 15+ messages in thread
From: Sean Christopherson @ 2026-07-30 20:24 UTC (permalink / raw)
To: sashiko-reviews; +Cc: Oliver Upton, kvm, kvmarm, Marc Zyngier
On Thu, Jul 30, 2026, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Medium] KVM syscall wrappers for pthread functions produce misleading error messages on failure.
> --
>
> --- Patch [8]: [PATCH 8/9] KVM: selftests: Add KVM syscall wrappers for pthread_{g,s}etaffinity_np() ---
> commit 9fc7623d339b95135fb5ecb9685356bc8dff9829
> Author: Sean Christopherson <seanjc@google.com>
>
> KVM: selftests: Add KVM syscall wrappers for pthread_{g,s}etaffinity_np()
>
> This commit adds KVM wrappers for pthread_getaffinity_np() and
> pthread_setaffinity_np() to simplify selftest code. It removes the need
> to manually check for success or supply the size of cpu_set_t in the tests.
>
> [ ... ]
>
> > diff --git a/tools/testing/selftests/kvm/include/kvm_syscalls.h b/tools/testing/selftests/kvm/include/kvm_syscalls.h
> > index 002b5a4e59eb2..3d82351bef92e 100644
> > --- a/tools/testing/selftests/kvm/include/kvm_syscalls.h
> > +++ b/tools/testing/selftests/kvm/include/kvm_syscalls.h
> > @@ -97,6 +97,22 @@ __KVM_SYSCALL_DEFINE(ftruncate, 2, unsigned int, fd, off_t, length);
> > __KVM_SYSCALL_DEFINE(madvise, 3, void *, addr, size_t, length, int, advice);
> > __KVM_SYSCALL_DEFINE(sched_getaffinity, 3, pid_t, pid, size_t, cpusetsize, cpu_set_t *, mask);
> >
> > +__KVM_SYSCALL_DEFINE(pthread_getaffinity_np, 3, pthread_t, thread,
> > + size_t, cpusetsize, cpu_set_t *, cpuset);
> > +__KVM_SYSCALL_DEFINE(pthread_setaffinity_np, 3, pthread_t, thread,
> > + size_t, cpusetsize, const cpu_set_t *, cpuset);
>
> [Severity: Medium]
> Will these pthread wrappers print misleading error messages on failure?
>
> The pthread_* functions return positive error codes directly on failure
> rather than returning -1 and setting errno. If __KVM_SYSCALL_DEFINE formats
> its failure messages assuming errno is set, failing to set affinity could
> result in printing a stale or unrelated error string (such as "Success")
> alongside the return code, which might impede debugging.
Empirically, no. Just because they _also_ return an exact error code doesn't
make errno invalid.
==== Test Assertion Failure ====
include/kvm_syscalls.h:117: !r
pid=155681 tid=155681 errno=11 - Resource temporarily unavailable
pthread_create failed, rc: 11 errno: 11 (Resource temporarily unavailable)
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 9/9] KVM: selftests: Clean up global constants in hardware disable test
2026-07-30 19:18 [PATCH 0/9] KVM: selftests: Add more syscall wrappers, fix hardware_disable_test Sean Christopherson
` (7 preceding siblings ...)
2026-07-30 19:19 ` [PATCH 8/9] KVM: selftests: Add KVM syscall wrappers for pthread_{g,s}etaffinity_np() Sean Christopherson
@ 2026-07-30 19:19 ` Sean Christopherson
8 siblings, 0 replies; 15+ messages in thread
From: Sean Christopherson @ 2026-07-30 19:19 UTC (permalink / raw)
To: Paolo Bonzini, Marc Zyngier, Oliver Upton, Christian Borntraeger,
Janosch Frank, Claudio Imbrenda, Sean Christopherson
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
David Hildenbrand, kvm, linux-arm-kernel, kvmarm, linux-kernel
Rename the global constants in the hardware disable test to better
capture what they control, and open code the literal number of sleeping
tasks and iterations instead of using power-of-2 math to express values
that are 100% arbitrary.
No functional change intended.
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
.../selftests/kvm/hardware_disable_test.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/tools/testing/selftests/kvm/hardware_disable_test.c b/tools/testing/selftests/kvm/hardware_disable_test.c
index bcca42182656..4abad7158989 100644
--- a/tools/testing/selftests/kvm/hardware_disable_test.c
+++ b/tools/testing/selftests/kvm/hardware_disable_test.c
@@ -17,10 +17,10 @@
#include "kvm_util.h"
#include "ucall_common.h"
-#define VCPU_NUM 4
-#define SLEEPING_THREAD_NUM (1 << 4)
-#define FORK_NUM (1ULL << 9)
-#define DELAY_US_MAX 2000
+#define NR_VCPUS 4
+#define NR_SLEEPERS_PER_VCPU 16
+#define NR_ITERATIONS 512
+#define DELAY_US_MAX 2000
sem_t *sem;
static cpu_set_t child_cpu_set;
@@ -61,16 +61,16 @@ static void run_test(u32 run)
pthread_t thread;
u32 i, j;
- vm = vm_create(VCPU_NUM);
+ vm = vm_create(NR_VCPUS);
pr_debug("%s: [%d] start vcpus\n", __func__, run);
- for (i = 0; i < VCPU_NUM; ++i) {
+ for (i = 0; i < NR_VCPUS; ++i) {
vcpu = vm_vcpu_add(vm, i, guest_code);
kvm_pthread_create(&thread, NULL, run_vcpu, vcpu);
kvm_pthread_setaffinity(thread, &child_cpu_set);
- for (j = 0; j < SLEEPING_THREAD_NUM; ++j) {
+ for (j = 0; j < NR_SLEEPERS_PER_VCPU; ++j) {
kvm_pthread_create(&thread, NULL, sleeping_thread, (void *)NULL);
kvm_pthread_setaffinity(thread, &child_cpu_set);
}
@@ -124,7 +124,7 @@ static void setup_child_cpu_set(void)
cpu = pin_task_to_random_cpu(pthread_self(), &child_cpu_set);
CPU_CLR(cpu, &child_cpu_set);
- while (CPU_COUNT(&child_cpu_set) > VCPU_NUM)
+ while (CPU_COUNT(&child_cpu_set) > NR_VCPUS)
CPU_CLR(kvm_pick_random_cpu(&child_cpu_set), &child_cpu_set);
}
@@ -139,7 +139,7 @@ int main(int argc, char **argv)
sem = sem_open("vm_sem", O_CREAT | O_EXCL, 0644, 0);
sem_unlink("vm_sem");
- for (i = 0; i < FORK_NUM; ++i) {
+ for (i = 0; i < NR_ITERATIONS; ++i) {
pid = fork();
TEST_ASSERT(pid >= 0, "%s: unable to fork", __func__);
if (pid == 0)
--
2.55.0.508.g3f0d502094-goog
^ permalink raw reply related [flat|nested] 15+ messages in thread