On 5/17/2025 12:58 AM, Sean Christopherson wrote: > On Fri, May 02, 2025, Manali Shukla wrote: >> diff --git a/tools/testing/selftests/kvm/x86/kvm_buslock_test.c b/tools/testing/selftests/kvm/x86/kvm_buslock_test.c >> new file mode 100644 >> index 000000000000..9c081525ac2a >> --- /dev/null >> +++ b/tools/testing/selftests/kvm/x86/kvm_buslock_test.c >> @@ -0,0 +1,135 @@ >> +// SPDX-License-Identifier: GPL-2.0-only >> +/* >> + * Copyright (C) 2024 Advanced Micro Devices, Inc. >> + */ >> + >> +#include "test_util.h" >> +#include "kvm_util.h" >> +#include "processor.h" >> +#include "svm_util.h" >> +#include "vmx.h" >> + >> +#define NR_ITERATIONS 100 >> +#define L2_GUEST_STACK_SIZE 64 >> + >> +#pragma GCC diagnostic push >> +#pragma GCC diagnostic ignored "-Waddress-of-packed-member" > > Eww. > >> + >> +struct buslock_test { >> + unsigned char pad[PAGE_SIZE - 2]; >> + atomic_long_t val; >> +} __packed; > > You don't need an entire page to generate a bus lock, two cache lines will do > nicely. And there's certain no need for __packed. > >> +struct buslock_test test __aligned(PAGE_SIZE); >> + >> +static __always_inline void buslock_atomic_add(int i, atomic_long_t *v) >> +{ >> + asm volatile(LOCK_PREFIX "addl %1,%0" >> + : "+m" (v->counter) >> + : "ir" (i) : "memory"); >> +} > > If only there were utilities for atomics... > >> +static void buslock_add(void) > > guest_generate_buslocks() > >> +{ >> + /* >> + * Increment a page unaligned variable atomically. >> + * This should generate a bus lock exit. > > Not should, will. > >> + */ >> + for (int i = 0; i < NR_ITERATIONS; i++) >> + buslock_atomic_add(2, &test.val); > > Don't do weird and completely arbitrary things like adding '2' instead of '1', > it makes readers look for intent and purpose that doesn't exist. > Got it. Thanks for the feedback. >> +} > > ... > >> +int main(int argc, char *argv[]) >> +{ >> + struct kvm_vcpu *vcpu; >> + struct kvm_run *run; >> + struct kvm_vm *vm; >> + vm_vaddr_t nested_test_data_gva; >> + >> + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM) || kvm_cpu_has(X86_FEATURE_VMX)); > > There's no reason to make nested support a hard dependency, it's just as easy to > make it conditional. > >> + TEST_REQUIRE(kvm_has_cap(KVM_CAP_X86_BUS_LOCK_EXIT)); >> + >> + vm = vm_create(1); >> + vm_enable_cap(vm, KVM_CAP_X86_BUS_LOCK_EXIT, KVM_BUS_LOCK_DETECTION_EXIT); >> + vcpu = vm_vcpu_add(vm, 0, guest_code); >> + >> + if (kvm_cpu_has(X86_FEATURE_SVM)) >> + vcpu_alloc_svm(vm, &nested_test_data_gva); >> + else >> + vcpu_alloc_vmx(vm, &nested_test_data_gva); >> + >> + vcpu_args_set(vcpu, 1, nested_test_data_gva); >> + >> + run = vcpu->run; >> + >> + for (;;) { >> + struct ucall uc; >> + >> + vcpu_run(vcpu); >> + >> + if (run->exit_reason == KVM_EXIT_IO) { >> + switch (get_ucall(vcpu, &uc)) { >> + case UCALL_ABORT: >> + REPORT_GUEST_ASSERT(uc); >> + /* NOT REACHED */ >> + case UCALL_SYNC: >> + continue; >> + case UCALL_DONE: >> + goto done; >> + default: >> + TEST_FAIL("Unknown ucall 0x%lx.", uc.cmd); >> + } >> + } >> + >> + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_X86_BUS_LOCK); >> + } > > *sigh* > > This doesn't actually ****VERIFY**** that the expected number of bus lock exits > were generated. KVM could literally do nothing and the test will pass. E.g. the > test passes if I do this: > > diff --git a/tools/testing/selftests/kvm/x86/kvm_buslock_test.c b/tools/testing/selftests/kvm/x86/kvm_buslock_test.c > index 9c081525ac2a..aa65d6be0f13 100644 > --- a/tools/testing/selftests/kvm/x86/kvm_buslock_test.c > +++ b/tools/testing/selftests/kvm/x86/kvm_buslock_test.c > @@ -93,10 +93,10 @@ int main(int argc, char *argv[]) > vm_vaddr_t nested_test_data_gva; > > TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM) || kvm_cpu_has(X86_FEATURE_VMX)); > - TEST_REQUIRE(kvm_has_cap(KVM_CAP_X86_BUS_LOCK_EXIT)); > +// TEST_REQUIRE(kvm_has_cap(KVM_CAP_X86_BUS_LOCK_EXIT)); > > vm = vm_create(1); > - vm_enable_cap(vm, KVM_CAP_X86_BUS_LOCK_EXIT, KVM_BUS_LOCK_DETECTION_EXIT); > +// vm_enable_cap(vm, KVM_CAP_X86_BUS_LOCK_EXIT, KVM_BUS_LOCK_DETECTION_EXIT); > vcpu = vm_vcpu_add(vm, 0, guest_code); > > if (kvm_cpu_has(X86_FEATURE_SVM)) > -- > > The test would also fail to detect if KVM completely skipped the instruction. > > This is not rocket science. If you can't make your test fail by introducing bugs > in what you're testing, then your test is worthless. > > No need for a v6, I'm going to do surgery when I apply, this series has dragged > on for far too long. Understood. I agree the test should catch such failures — I’ll take that into account in future work. Thanks for the review and for pushing this forward. -Manali