17d36db35SAvi Kivity 27d36db35SAvi Kivity #include "libcflat.h" 37d36db35SAvi Kivity #include "smp.h" 4850479e3SJason Wang #include "processor.h" 57d36db35SAvi Kivity 67d36db35SAvi Kivity static inline unsigned long long rdtsc() 77d36db35SAvi Kivity { 87d36db35SAvi Kivity long long r; 97d36db35SAvi Kivity 107d36db35SAvi Kivity #ifdef __x86_64__ 117d36db35SAvi Kivity unsigned a, d; 127d36db35SAvi Kivity 137d36db35SAvi Kivity asm volatile ("rdtsc" : "=a"(a), "=d"(d)); 147d36db35SAvi Kivity r = a | ((long long)d << 32); 157d36db35SAvi Kivity #else 167d36db35SAvi Kivity asm volatile ("rdtsc" : "=A"(r)); 177d36db35SAvi Kivity #endif 187d36db35SAvi Kivity return r; 197d36db35SAvi Kivity } 207d36db35SAvi Kivity 217d36db35SAvi Kivity static unsigned int inl(unsigned short port) 227d36db35SAvi Kivity { 237d36db35SAvi Kivity unsigned int val; 247d36db35SAvi Kivity asm volatile("inl %w1, %0" : "=a"(val) : "Nd"(port)); 257d36db35SAvi Kivity return val; 267d36db35SAvi Kivity } 277d36db35SAvi Kivity 287d36db35SAvi Kivity #define GOAL (1ull << 30) 297d36db35SAvi Kivity 307d36db35SAvi Kivity #ifdef __x86_64__ 317d36db35SAvi Kivity # define R "r" 327d36db35SAvi Kivity #else 337d36db35SAvi Kivity # define R "e" 347d36db35SAvi Kivity #endif 357d36db35SAvi Kivity 36850479e3SJason Wang static void cpuid_test(void) 377d36db35SAvi Kivity { 387d36db35SAvi Kivity asm volatile ("push %%"R "bx; cpuid; pop %%"R "bx" 397d36db35SAvi Kivity : : : "eax", "ecx", "edx"); 407d36db35SAvi Kivity } 417d36db35SAvi Kivity 427d36db35SAvi Kivity static void vmcall(void) 437d36db35SAvi Kivity { 447d36db35SAvi Kivity unsigned long a = 0, b, c, d; 457d36db35SAvi Kivity 467d36db35SAvi Kivity asm volatile ("vmcall" : "+a"(a), "=b"(b), "=c"(c), "=d"(d)); 477d36db35SAvi Kivity } 487d36db35SAvi Kivity 497d36db35SAvi Kivity #define MSR_EFER 0xc0000080 507d36db35SAvi Kivity #define EFER_NX_MASK (1ull << 11) 517d36db35SAvi Kivity 52*5ada505aSJason Wang #ifdef __x86_64__ 537d36db35SAvi Kivity static void mov_from_cr8(void) 547d36db35SAvi Kivity { 557d36db35SAvi Kivity unsigned long cr8; 567d36db35SAvi Kivity 577d36db35SAvi Kivity asm volatile ("mov %%cr8, %0" : "=r"(cr8)); 587d36db35SAvi Kivity } 597d36db35SAvi Kivity 607d36db35SAvi Kivity static void mov_to_cr8(void) 617d36db35SAvi Kivity { 627d36db35SAvi Kivity unsigned long cr8 = 0; 637d36db35SAvi Kivity 647d36db35SAvi Kivity asm volatile ("mov %0, %%cr8" : : "r"(cr8)); 657d36db35SAvi Kivity } 66*5ada505aSJason Wang #endif 677d36db35SAvi Kivity 687d36db35SAvi Kivity static int is_smp(void) 697d36db35SAvi Kivity { 707d36db35SAvi Kivity return cpu_count() > 1; 717d36db35SAvi Kivity } 727d36db35SAvi Kivity 737d36db35SAvi Kivity static void nop(void *junk) 747d36db35SAvi Kivity { 757d36db35SAvi Kivity } 767d36db35SAvi Kivity 777d36db35SAvi Kivity static void ipi(void) 787d36db35SAvi Kivity { 797d36db35SAvi Kivity on_cpu(1, nop, 0); 807d36db35SAvi Kivity } 817d36db35SAvi Kivity 827d36db35SAvi Kivity static void ipi_halt(void) 837d36db35SAvi Kivity { 847d36db35SAvi Kivity unsigned long long t; 857d36db35SAvi Kivity 867d36db35SAvi Kivity on_cpu(1, nop, 0); 877d36db35SAvi Kivity t = rdtsc() + 2000; 887d36db35SAvi Kivity while (rdtsc() < t) 897d36db35SAvi Kivity ; 907d36db35SAvi Kivity } 917d36db35SAvi Kivity 927d36db35SAvi Kivity static void inl_pmtimer(void) 937d36db35SAvi Kivity { 947d36db35SAvi Kivity inl(0xb008); 957d36db35SAvi Kivity } 967d36db35SAvi Kivity 977d36db35SAvi Kivity static struct test { 987d36db35SAvi Kivity void (*func)(void); 997d36db35SAvi Kivity const char *name; 1007d36db35SAvi Kivity int (*valid)(void); 1017d36db35SAvi Kivity int parallel; 1027d36db35SAvi Kivity } tests[] = { 103850479e3SJason Wang { cpuid_test, "cpuid", .parallel = 1, }, 1047d36db35SAvi Kivity { vmcall, "vmcall", .parallel = 1, }, 105*5ada505aSJason Wang #ifdef __x86_64__ 1067d36db35SAvi Kivity { mov_from_cr8, "mov_from_cr8", .parallel = 1, }, 1077d36db35SAvi Kivity { mov_to_cr8, "mov_to_cr8" , .parallel = 1, }, 108*5ada505aSJason Wang #endif 1097d36db35SAvi Kivity { inl_pmtimer, "inl_from_pmtimer", .parallel = 1, }, 1107d36db35SAvi Kivity { ipi, "ipi", is_smp, .parallel = 0, }, 1117d36db35SAvi Kivity { ipi_halt, "ipi+halt", is_smp, .parallel = 0, }, 1127d36db35SAvi Kivity }; 1137d36db35SAvi Kivity 1147d36db35SAvi Kivity unsigned iterations; 1157d36db35SAvi Kivity volatile int nr_cpus_done; 1167d36db35SAvi Kivity 1177d36db35SAvi Kivity static void run_test(void *_func) 1187d36db35SAvi Kivity { 1197d36db35SAvi Kivity int i; 1207d36db35SAvi Kivity void (*func)(void) = _func; 1217d36db35SAvi Kivity 1227d36db35SAvi Kivity for (i = 0; i < iterations; ++i) 1237d36db35SAvi Kivity func(); 1247d36db35SAvi Kivity 1257d36db35SAvi Kivity nr_cpus_done++; 1267d36db35SAvi Kivity } 1277d36db35SAvi Kivity 1287d36db35SAvi Kivity static void do_test(struct test *test) 1297d36db35SAvi Kivity { 1307d36db35SAvi Kivity int i; 1317d36db35SAvi Kivity unsigned long long t1, t2; 1327d36db35SAvi Kivity void (*func)(void) = test->func; 1337d36db35SAvi Kivity 1347d36db35SAvi Kivity iterations = 32; 1357d36db35SAvi Kivity 1367d36db35SAvi Kivity if (test->valid && !test->valid()) { 1377d36db35SAvi Kivity printf("%s (skipped)\n", test->name); 1387d36db35SAvi Kivity return; 1397d36db35SAvi Kivity } 1407d36db35SAvi Kivity 1417d36db35SAvi Kivity do { 1427d36db35SAvi Kivity iterations *= 2; 1437d36db35SAvi Kivity t1 = rdtsc(); 1447d36db35SAvi Kivity 1457d36db35SAvi Kivity if (!test->parallel) { 1467d36db35SAvi Kivity for (i = 0; i < iterations; ++i) 1477d36db35SAvi Kivity func(); 1487d36db35SAvi Kivity } else { 1497d36db35SAvi Kivity nr_cpus_done = 0; 1507d36db35SAvi Kivity for (i = cpu_count(); i > 0; i--) 1517d36db35SAvi Kivity on_cpu_async(i-1, run_test, func); 1527d36db35SAvi Kivity while (nr_cpus_done < cpu_count()) 1537d36db35SAvi Kivity ; 1547d36db35SAvi Kivity } 1557d36db35SAvi Kivity t2 = rdtsc(); 1567d36db35SAvi Kivity } while ((t2 - t1) < GOAL); 1577d36db35SAvi Kivity printf("%s %d\n", test->name, (int)((t2 - t1) / iterations)); 1587d36db35SAvi Kivity } 1597d36db35SAvi Kivity 1607d36db35SAvi Kivity static void enable_nx(void *junk) 1617d36db35SAvi Kivity { 1627d36db35SAvi Kivity wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_NX_MASK); 1637d36db35SAvi Kivity } 1647d36db35SAvi Kivity 1657d36db35SAvi Kivity int main(void) 1667d36db35SAvi Kivity { 1677d36db35SAvi Kivity int i; 1687d36db35SAvi Kivity 1697d36db35SAvi Kivity smp_init(); 1707d36db35SAvi Kivity 1717d36db35SAvi Kivity for (i = cpu_count(); i > 0; i--) 1727d36db35SAvi Kivity on_cpu(i-1, enable_nx, 0); 1737d36db35SAvi Kivity 1747d36db35SAvi Kivity for (i = 0; i < ARRAY_SIZE(tests); ++i) 1757d36db35SAvi Kivity do_test(&tests[i]); 1767d36db35SAvi Kivity 1777d36db35SAvi Kivity return 0; 1787d36db35SAvi Kivity } 179