5 static inline unsigned long long rdtsc()
12 asm volatile ("rdtsc" : "=a"(a
), "=d"(d
));
13 r
= a
| ((long long)d
<< 32);
15 asm volatile ("rdtsc" : "=A"(r
));
20 static unsigned int inl(unsigned short port
)
23 asm volatile("inl %w1, %0" : "=a"(val
) : "Nd"(port
));
27 #define GOAL (1ull << 30)
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 static void mov_from_cr8(void)
52 asm volatile ("mov %%cr8, %0" : "=r"(cr8
));
55 static void mov_to_cr8(void)
57 unsigned long cr8
= 0;
59 asm volatile ("mov %0, %%cr8" : : "r"(cr8
));
62 static int is_smp(void)
64 return cpu_count() > 1;
67 static void nop(void *junk
)
76 static void ipi_halt(void)
86 static void inl_pmtimer(void)
97 { cpuid
, "cpuid", .parallel
= 1, },
98 { vmcall
, "vmcall", .parallel
= 1, },
99 { mov_from_cr8
, "mov_from_cr8", .parallel
= 1, },
100 { mov_to_cr8
, "mov_to_cr8" , .parallel
= 1, },
101 { inl_pmtimer
, "inl_from_pmtimer", .parallel
= 1, },
102 { ipi
, "ipi", is_smp
, .parallel
= 0, },
103 { ipi_halt
, "ipi+halt", is_smp
, .parallel
= 0, },
107 volatile int nr_cpus_done
;
109 static void run_test(void *_func
)
112 void (*func
)(void) = _func
;
114 for (i
= 0; i
< iterations
; ++i
)
120 static void do_test(struct test
*test
)
123 unsigned long long t1
, t2
;
124 void (*func
)(void) = test
->func
;
128 if (test
->valid
&& !test
->valid()) {
129 printf("%s (skipped)\n", test
->name
);
137 if (!test
->parallel
) {
138 for (i
= 0; i
< iterations
; ++i
)
142 for (i
= cpu_count(); i
> 0; i
--)
143 on_cpu_async(i
-1, run_test
, func
);
144 while (nr_cpus_done
< cpu_count())
148 } while ((t2
- t1
) < GOAL
);
149 printf("%s %d\n", test
->name
, (int)((t2
- t1
) / iterations
));
152 #define ARRAY_SIZE(_x) (sizeof(_x) / sizeof((_x)[0]))
160 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)