Skip to content

Commit cd5a0c2

Browse files
committed
KVM: selftests: Manage CPUID array in Hyper-V CPUID test's core helper
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>
1 parent 0b6db0d commit cd5a0c2

File tree

1 file changed

+17
-13
lines changed

1 file changed

+17
-13
lines changed

tools/testing/selftests/kvm/x86/hyperv_cpuid.c

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,18 @@ static bool smt_possible(void)
4141
return res;
4242
}
4343

44-
static void test_hv_cpuid(const struct kvm_cpuid2 *hv_cpuid_entries,
45-
bool evmcs_expected)
44+
static void test_hv_cpuid(struct kvm_vcpu *vcpu, bool evmcs_expected)
4645
{
46+
const struct kvm_cpuid2 *hv_cpuid_entries;
4747
int i;
4848
int nent_expected = 10;
4949
u32 test_val;
5050

51+
if (vcpu)
52+
hv_cpuid_entries = vcpu_get_supported_hv_cpuid(vcpu);
53+
else
54+
hv_cpuid_entries = kvm_get_supported_hv_cpuid();
55+
5156
TEST_ASSERT(hv_cpuid_entries->nent == nent_expected,
5257
"KVM_GET_SUPPORTED_HV_CPUID should return %d entries"
5358
" (returned %d)",
@@ -109,6 +114,13 @@ static void test_hv_cpuid(const struct kvm_cpuid2 *hv_cpuid_entries,
109114
* entry->edx);
110115
*/
111116
}
117+
118+
/*
119+
* Note, the CPUID array returned by the system-scoped helper is a one-
120+
* time allocation, i.e. must not be freed.
121+
*/
122+
if (vcpu)
123+
free((void *)hv_cpuid_entries);
112124
}
113125

114126
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)
129141
int main(int argc, char *argv[])
130142
{
131143
struct kvm_vm *vm;
132-
const struct kvm_cpuid2 *hv_cpuid_entries;
133144
struct kvm_vcpu *vcpu;
134145

135146
TEST_REQUIRE(kvm_has_cap(KVM_CAP_HYPERV_CPUID));
@@ -138,20 +149,15 @@ int main(int argc, char *argv[])
138149

139150
/* Test vCPU ioctl version */
140151
test_hv_cpuid_e2big(vm, vcpu);
141-
142-
hv_cpuid_entries = vcpu_get_supported_hv_cpuid(vcpu);
143-
test_hv_cpuid(hv_cpuid_entries, false);
144-
free((void *)hv_cpuid_entries);
152+
test_hv_cpuid(vcpu, false);
145153

146154
if (!kvm_cpu_has(X86_FEATURE_VMX) ||
147155
!kvm_has_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS)) {
148156
print_skip("Enlightened VMCS is unsupported");
149157
goto do_sys;
150158
}
151159
vcpu_enable_evmcs(vcpu);
152-
hv_cpuid_entries = vcpu_get_supported_hv_cpuid(vcpu);
153-
test_hv_cpuid(hv_cpuid_entries, true);
154-
free((void *)hv_cpuid_entries);
160+
test_hv_cpuid(vcpu, true);
155161

156162
do_sys:
157163
/* Test system ioctl version */
@@ -161,9 +167,7 @@ int main(int argc, char *argv[])
161167
}
162168

163169
test_hv_cpuid_e2big(vm, NULL);
164-
165-
hv_cpuid_entries = kvm_get_supported_hv_cpuid();
166-
test_hv_cpuid(hv_cpuid_entries, kvm_cpu_has(X86_FEATURE_VMX));
170+
test_hv_cpuid(NULL, kvm_cpu_has(X86_FEATURE_VMX));
167171

168172
out:
169173
kvm_vm_free(vm);

0 commit comments

Comments
 (0)