]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
KVM: selftests: Manage CPUID array in Hyper-V CPUID test's core helper
authorSean Christopherson <seanjc@google.com>
Sat, 18 Jan 2025 00:34:53 +0000 (16:34 -0800)
committerSean Christopherson <seanjc@google.com>
Wed, 12 Feb 2025 16:53:59 +0000 (08:53 -0800)
Allocate, get, and free the CPUID array in the Hyper-V CPUID test in the
test's core helper, instead of copy+pasting code at each call site.  In
addition to deduplicating a small amount of code, restricting visibility
of the array to a single invocation of the core test prevents "leaking" an
array across test cases.  Passing in @vcpu to the helper will also allow
pivoting on VM-scoped information without needing to pass more booleans,
e.g. to conditionally assert on features that require an in-kernel APIC.

To avoid use-after-free bugs due to overzealous and careless developers,
opportunstically add a comment to explain that the system-scoped helper
caches the Hyper-V CPUID entries, i.e. that the caller is not responsible
for freeing the memory.

Cc: Vitaly Kuznetsov <vkuznets@redhat.com>
Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Link: https://lore.kernel.org/r/20250118003454.2619573-4-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
tools/testing/selftests/kvm/x86/hyperv_cpuid.c

index 9a0fcc7133503a84b817f6a23fd13c275477b4fe..3188749ec6e12211d97eb0db57a81cafdafc8930 100644 (file)
@@ -41,13 +41,18 @@ static bool smt_possible(void)
        return res;
 }
 
-static void test_hv_cpuid(const struct kvm_cpuid2 *hv_cpuid_entries,
-                         bool evmcs_expected)
+static void test_hv_cpuid(struct kvm_vcpu *vcpu, bool evmcs_expected)
 {
+       const struct kvm_cpuid2 *hv_cpuid_entries;
        int i;
        int nent_expected = 10;
        u32 test_val;
 
+       if (vcpu)
+               hv_cpuid_entries = vcpu_get_supported_hv_cpuid(vcpu);
+       else
+               hv_cpuid_entries = kvm_get_supported_hv_cpuid();
+
        TEST_ASSERT(hv_cpuid_entries->nent == nent_expected,
                    "KVM_GET_SUPPORTED_HV_CPUID should return %d entries"
                    " (returned %d)",
@@ -109,6 +114,13 @@ static void test_hv_cpuid(const struct kvm_cpuid2 *hv_cpuid_entries,
                 *      entry->edx);
                 */
        }
+
+       /*
+        * Note, the CPUID array returned by the system-scoped helper is a one-
+        * time allocation, i.e. must not be freed.
+        */
+       if (vcpu)
+               free((void *)hv_cpuid_entries);
 }
 
 static void test_hv_cpuid_e2big(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
@@ -129,7 +141,6 @@ static void test_hv_cpuid_e2big(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
 int main(int argc, char *argv[])
 {
        struct kvm_vm *vm;
-       const struct kvm_cpuid2 *hv_cpuid_entries;
        struct kvm_vcpu *vcpu;
 
        TEST_REQUIRE(kvm_has_cap(KVM_CAP_HYPERV_CPUID));
@@ -138,10 +149,7 @@ int main(int argc, char *argv[])
 
        /* Test vCPU ioctl version */
        test_hv_cpuid_e2big(vm, vcpu);
-
-       hv_cpuid_entries = vcpu_get_supported_hv_cpuid(vcpu);
-       test_hv_cpuid(hv_cpuid_entries, false);
-       free((void *)hv_cpuid_entries);
+       test_hv_cpuid(vcpu, false);
 
        if (!kvm_cpu_has(X86_FEATURE_VMX) ||
            !kvm_has_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS)) {
@@ -149,9 +157,7 @@ int main(int argc, char *argv[])
                goto do_sys;
        }
        vcpu_enable_evmcs(vcpu);
-       hv_cpuid_entries = vcpu_get_supported_hv_cpuid(vcpu);
-       test_hv_cpuid(hv_cpuid_entries, true);
-       free((void *)hv_cpuid_entries);
+       test_hv_cpuid(vcpu, true);
 
 do_sys:
        /* Test system ioctl version */
@@ -161,9 +167,7 @@ do_sys:
        }
 
        test_hv_cpuid_e2big(vm, NULL);
-
-       hv_cpuid_entries = kvm_get_supported_hv_cpuid();
-       test_hv_cpuid(hv_cpuid_entries, kvm_cpu_has(X86_FEATURE_VMX));
+       test_hv_cpuid(NULL, kvm_cpu_has(X86_FEATURE_VMX));
 
 out:
        kvm_vm_free(vm);