Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Test edge cases and race conditions in kvm_recalculate_apic_map().
4 */
5
6#include <sys/ioctl.h>
7#include <pthread.h>
8#include <time.h>
9
10#include "processor.h"
11#include "test_util.h"
12#include "kvm_util.h"
13#include "apic.h"
14
15#define TIMEOUT 5 /* seconds */
16
17#define LAPIC_DISABLED 0
18#define LAPIC_X2APIC (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE)
19#define MAX_XAPIC_ID 0xff
20
21static void *race(void *arg)
22{
23 struct kvm_lapic_state lapic = {};
24 struct kvm_vcpu *vcpu = arg;
25
26 while (1) {
27 /* Trigger kvm_recalculate_apic_map(). */
28 vcpu_ioctl(vcpu, KVM_SET_LAPIC, &lapic);
29 pthread_testcancel();
30 }
31
32 return NULL;
33}
34
35int main(void)
36{
37 struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
38 struct kvm_vcpu *vcpuN;
39 struct kvm_vm *vm;
40 pthread_t thread;
41 time_t t;
42 int i;
43
44 kvm_static_assert(KVM_MAX_VCPUS > MAX_XAPIC_ID);
45
46 /*
47 * Create the max number of vCPUs supported by selftests so that KVM
48 * has decent amount of work to do when recalculating the map, i.e. to
49 * make the problematic window large enough to hit.
50 */
51 vm = vm_create_with_vcpus(KVM_MAX_VCPUS, NULL, vcpus);
52
53 /*
54 * Enable x2APIC on all vCPUs so that KVM doesn't bail from the recalc
55 * due to vCPUs having aliased xAPIC IDs (truncated to 8 bits).
56 */
57 for (i = 0; i < KVM_MAX_VCPUS; i++)
58 vcpu_set_msr(vcpus[i], MSR_IA32_APICBASE, LAPIC_X2APIC);
59
60 TEST_ASSERT_EQ(pthread_create(&thread, NULL, race, vcpus[0]), 0);
61
62 vcpuN = vcpus[KVM_MAX_VCPUS - 1];
63 for (t = time(NULL) + TIMEOUT; time(NULL) < t;) {
64 vcpu_set_msr(vcpuN, MSR_IA32_APICBASE, LAPIC_X2APIC);
65 vcpu_set_msr(vcpuN, MSR_IA32_APICBASE, LAPIC_DISABLED);
66 }
67
68 TEST_ASSERT_EQ(pthread_cancel(thread), 0);
69 TEST_ASSERT_EQ(pthread_join(thread, NULL), 0);
70
71 kvm_vm_free(vm);
72
73 return 0;
74}