1
2
3
4
5
6
7
8
9
10
11
12
13
14#define _GNU_SOURCE
15#include <fcntl.h>
16#include <kvm_util.h>
17#include <linux/kvm.h>
18#include <processor.h>
19#include <pthread.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <sys/ioctl.h>
24#include <sys/mman.h>
25#include <sys/stat.h>
26#include <sys/types.h>
27#include <sys/wait.h>
28#include <test_util.h>
29#include <unistd.h>
30
31#define NTHREAD 4
32#define NPROCESS 5
33
34struct thread_context {
35 int kvmcpu;
36 struct kvm_run *run;
37};
38
39void *thr(void *arg)
40{
41 struct thread_context *tc = (struct thread_context *)arg;
42 int res;
43 int kvmcpu = tc->kvmcpu;
44 struct kvm_run *run = tc->run;
45
46 res = ioctl(kvmcpu, KVM_RUN, 0);
47 pr_info("ret1=%d exit_reason=%d suberror=%d\n",
48 res, run->exit_reason, run->internal.suberror);
49
50 return 0;
51}
52
53void test(void)
54{
55 int i, kvm, kvmvm, kvmcpu;
56 pthread_t th[NTHREAD];
57 struct kvm_run *run;
58 struct thread_context tc;
59
60 kvm = open("/dev/kvm", O_RDWR);
61 TEST_ASSERT(kvm != -1, "failed to open /dev/kvm");
62 kvmvm = ioctl(kvm, KVM_CREATE_VM, 0);
63 TEST_ASSERT(kvmvm != -1, "KVM_CREATE_VM failed");
64 kvmcpu = ioctl(kvmvm, KVM_CREATE_VCPU, 0);
65 TEST_ASSERT(kvmcpu != -1, "KVM_CREATE_VCPU failed");
66 run = (struct kvm_run *)mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED,
67 kvmcpu, 0);
68 tc.kvmcpu = kvmcpu;
69 tc.run = run;
70 srand(getpid());
71 for (i = 0; i < NTHREAD; i++) {
72 pthread_create(&th[i], NULL, thr, (void *)(uintptr_t)&tc);
73 usleep(rand() % 10000);
74 }
75 for (i = 0; i < NTHREAD; i++)
76 pthread_join(th[i], NULL);
77}
78
79int get_warnings_count(void)
80{
81 int warnings;
82 FILE *f;
83
84 f = popen("dmesg | grep \"WARNING:\" | wc -l", "r");
85 if (fscanf(f, "%d", &warnings) < 1)
86 warnings = 0;
87 fclose(f);
88
89 return warnings;
90}
91
92int main(void)
93{
94 int warnings_before, warnings_after;
95
96 if (!is_intel_cpu()) {
97 print_skip("Must be run on an Intel CPU");
98 exit(KSFT_SKIP);
99 }
100
101 if (vm_is_unrestricted_guest(NULL)) {
102 print_skip("Unrestricted guest must be disabled");
103 exit(KSFT_SKIP);
104 }
105
106 warnings_before = get_warnings_count();
107
108 for (int i = 0; i < NPROCESS; ++i) {
109 int status;
110 int pid = fork();
111
112 if (pid < 0)
113 exit(1);
114 if (pid == 0) {
115 test();
116 exit(0);
117 }
118 while (waitpid(pid, &status, __WALL) != pid)
119 ;
120 }
121
122 warnings_after = get_warnings_count();
123 TEST_ASSERT(warnings_before == warnings_after,
124 "Warnings found in kernel. Run 'dmesg' to inspect them.");
125
126 return 0;
127}
128