Fix apic build with kvm disabled
[qemu/qemu-dev-zwu.git] / kvm / test / x86 / vmexit.c
blob707d5c6f80e56126dd85bdd2d35bf8f5e39aeac2
2 #include "libcflat.h"
3 #include "smp.h"
5 static inline unsigned long long rdtsc()
7 long long r;
9 #ifdef __x86_64__
10 unsigned a, d;
12 asm volatile ("rdtsc" : "=a"(a), "=d"(d));
13 r = a | ((long long)d << 32);
14 #else
15 asm volatile ("rdtsc" : "=A"(r));
16 #endif
17 return r;
20 static unsigned int inl(unsigned short port)
22 unsigned int val;
23 asm volatile("inl %w1, %0" : "=a"(val) : "Nd"(port));
24 return val;
27 #define GOAL (1ull << 30)
29 #ifdef __x86_64__
30 # define R "r"
31 #else
32 # define R "e"
33 #endif
35 static void cpuid(void)
37 asm volatile ("push %%"R "bx; cpuid; pop %%"R "bx"
38 : : : "eax", "ecx", "edx");
41 static void vmcall(void)
43 unsigned long a = 0, b, c, d;
45 asm volatile ("vmcall" : "+a"(a), "=b"(b), "=c"(c), "=d"(d));
48 #define MSR_EFER 0xc0000080
49 #define EFER_NX_MASK (1ull << 11)
51 unsigned long long rdmsr(unsigned index)
53 unsigned a, d;
55 asm volatile("rdmsr" : "=a"(a), "=d"(d) : "c"(index));
56 return ((unsigned long long)d << 32) | a;
59 void wrmsr(unsigned index, unsigned long long val)
61 unsigned a = val, d = val >> 32;
63 asm volatile("wrmsr" : : "a"(a), "d"(d), "c"(index));
66 static void mov_from_cr8(void)
68 unsigned long cr8;
70 asm volatile ("mov %%cr8, %0" : "=r"(cr8));
73 static void mov_to_cr8(void)
75 unsigned long cr8 = 0;
77 asm volatile ("mov %0, %%cr8" : : "r"(cr8));
80 static int is_smp(void)
82 return cpu_count() > 1;
85 static void nop(void *junk)
89 static void ipi(void)
91 on_cpu(1, nop, 0);
94 static void ipi_halt(void)
96 unsigned long long t;
98 on_cpu(1, nop, 0);
99 t = rdtsc() + 2000;
100 while (rdtsc() < t)
104 static void inl_pmtimer(void)
106 inl(0xb008);
109 static struct test {
110 void (*func)(void);
111 const char *name;
112 int (*valid)(void);
113 int parallel;
114 } tests[] = {
115 { cpuid, "cpuid", .parallel = 1, },
116 { vmcall, "vmcall", .parallel = 1, },
117 { mov_from_cr8, "mov_from_cr8", .parallel = 1, },
118 { mov_to_cr8, "mov_to_cr8" , .parallel = 1, },
119 { inl_pmtimer, "inl_from_pmtimer", .parallel = 1, },
120 { ipi, "ipi", is_smp, .parallel = 0, },
121 { ipi_halt, "ipi+halt", is_smp, .parallel = 0, },
124 unsigned iterations;
125 volatile int nr_cpus_done;
127 static void run_test(void *_func)
129 int i;
130 void (*func)(void) = _func;
132 for (i = 0; i < iterations; ++i)
133 func();
135 nr_cpus_done++;
138 static void do_test(struct test *test)
140 int i;
141 unsigned long long t1, t2;
142 void (*func)(void) = test->func;
144 iterations = 32;
146 if (test->valid && !test->valid()) {
147 printf("%s (skipped)\n", test->name);
148 return;
151 do {
152 iterations *= 2;
153 t1 = rdtsc();
155 if (!test->parallel) {
156 for (i = 0; i < iterations; ++i)
157 func();
158 } else {
159 nr_cpus_done = 0;
160 for (i = cpu_count(); i > 0; i--)
161 on_cpu_async(i-1, run_test, func);
162 while (nr_cpus_done < cpu_count())
165 t2 = rdtsc();
166 } while ((t2 - t1) < GOAL);
167 printf("%s %d\n", test->name, (int)((t2 - t1) / iterations));
170 static void enable_nx(void *junk)
172 wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_NX_MASK);
175 int main(void)
177 int i;
179 smp_init();
181 for (i = cpu_count(); i > 0; i--)
182 on_cpu(i-1, enable_nx, 0);
184 for (i = 0; i < ARRAY_SIZE(tests); ++i)
185 do_test(&tests[i]);
187 return 0;