17d36db35SAvi Kivity #include "libcflat.h" 27d36db35SAvi Kivity #include "smp.h" 3850479e3SJason Wang #include "processor.h" 47d641cc5SAvi Kivity #include "atomic.h" 55292dbf7SMichael S. Tsirkin #include "x86/vm.h" 65292dbf7SMichael S. Tsirkin #include "x86/desc.h" 75292dbf7SMichael S. Tsirkin #include "x86/pci.h" 87d36db35SAvi Kivity 95292dbf7SMichael S. Tsirkin struct test { 105292dbf7SMichael S. Tsirkin void (*func)(void); 115292dbf7SMichael S. Tsirkin const char *name; 125292dbf7SMichael S. Tsirkin int (*valid)(void); 135292dbf7SMichael S. Tsirkin int parallel; 145292dbf7SMichael S. Tsirkin bool (*next)(struct test *); 155292dbf7SMichael S. Tsirkin }; 165292dbf7SMichael S. Tsirkin 175292dbf7SMichael S. Tsirkin static void outb(unsigned short port, unsigned val) 1800bfecaaSPaolo Bonzini { 195292dbf7SMichael S. Tsirkin asm volatile("outb %b0, %w1" : : "a"(val), "Nd"(port)); 205292dbf7SMichael S. Tsirkin } 215292dbf7SMichael S. Tsirkin 225292dbf7SMichael S. Tsirkin static void outw(unsigned short port, unsigned val) 235292dbf7SMichael S. Tsirkin { 245292dbf7SMichael S. Tsirkin asm volatile("outw %w0, %w1" : : "a"(val), "Nd"(port)); 255292dbf7SMichael S. Tsirkin } 265292dbf7SMichael S. Tsirkin 275292dbf7SMichael S. Tsirkin static void outl(unsigned short port, unsigned val) 285292dbf7SMichael S. Tsirkin { 290b9e64c4SGleb Natapov asm volatile("outl %0, %w1" : : "a"(val), "Nd"(port)); 3000bfecaaSPaolo Bonzini } 3100bfecaaSPaolo Bonzini 3200bfecaaSPaolo Bonzini static unsigned int inb(unsigned short port) 3300bfecaaSPaolo Bonzini { 3400bfecaaSPaolo Bonzini unsigned int val; 3500bfecaaSPaolo Bonzini asm volatile("xorl %0, %0; inb %w1, %b0" : "=a"(val) : "Nd"(port)); 3600bfecaaSPaolo Bonzini return val; 3700bfecaaSPaolo Bonzini } 3800bfecaaSPaolo Bonzini 397d36db35SAvi Kivity static unsigned int inl(unsigned short port) 407d36db35SAvi Kivity { 417d36db35SAvi Kivity unsigned int val; 427d36db35SAvi Kivity asm volatile("inl %w1, %0" : "=a"(val) : "Nd"(port)); 437d36db35SAvi Kivity return val; 447d36db35SAvi Kivity } 457d36db35SAvi Kivity 467d36db35SAvi Kivity #define GOAL (1ull << 30) 477d36db35SAvi Kivity 48eda71b28SAvi Kivity static int nr_cpus; 49eda71b28SAvi Kivity 507d36db35SAvi Kivity #ifdef __x86_64__ 517d36db35SAvi Kivity # define R "r" 527d36db35SAvi Kivity #else 537d36db35SAvi Kivity # define R "e" 547d36db35SAvi Kivity #endif 557d36db35SAvi Kivity 56850479e3SJason Wang static void cpuid_test(void) 577d36db35SAvi Kivity { 587d36db35SAvi Kivity asm volatile ("push %%"R "bx; cpuid; pop %%"R "bx" 597d36db35SAvi Kivity : : : "eax", "ecx", "edx"); 607d36db35SAvi Kivity } 617d36db35SAvi Kivity 627d36db35SAvi Kivity static void vmcall(void) 637d36db35SAvi Kivity { 647d36db35SAvi Kivity unsigned long a = 0, b, c, d; 657d36db35SAvi Kivity 667d36db35SAvi Kivity asm volatile ("vmcall" : "+a"(a), "=b"(b), "=c"(c), "=d"(d)); 677d36db35SAvi Kivity } 687d36db35SAvi Kivity 695fecf5d8SWill Auld #define MSR_TSC_ADJUST 0x3b 707d36db35SAvi Kivity #define MSR_EFER 0xc0000080 717d36db35SAvi Kivity #define EFER_NX_MASK (1ull << 11) 727d36db35SAvi Kivity 735ada505aSJason Wang #ifdef __x86_64__ 747d36db35SAvi Kivity static void mov_from_cr8(void) 757d36db35SAvi Kivity { 767d36db35SAvi Kivity unsigned long cr8; 777d36db35SAvi Kivity 787d36db35SAvi Kivity asm volatile ("mov %%cr8, %0" : "=r"(cr8)); 797d36db35SAvi Kivity } 807d36db35SAvi Kivity 817d36db35SAvi Kivity static void mov_to_cr8(void) 827d36db35SAvi Kivity { 837d36db35SAvi Kivity unsigned long cr8 = 0; 847d36db35SAvi Kivity 857d36db35SAvi Kivity asm volatile ("mov %0, %%cr8" : : "r"(cr8)); 867d36db35SAvi Kivity } 875ada505aSJason Wang #endif 887d36db35SAvi Kivity 897d36db35SAvi Kivity static int is_smp(void) 907d36db35SAvi Kivity { 917d36db35SAvi Kivity return cpu_count() > 1; 927d36db35SAvi Kivity } 937d36db35SAvi Kivity 947d36db35SAvi Kivity static void nop(void *junk) 957d36db35SAvi Kivity { 967d36db35SAvi Kivity } 977d36db35SAvi Kivity 987d36db35SAvi Kivity static void ipi(void) 997d36db35SAvi Kivity { 1007d36db35SAvi Kivity on_cpu(1, nop, 0); 1017d36db35SAvi Kivity } 1027d36db35SAvi Kivity 1037d36db35SAvi Kivity static void ipi_halt(void) 1047d36db35SAvi Kivity { 1057d36db35SAvi Kivity unsigned long long t; 1067d36db35SAvi Kivity 1077d36db35SAvi Kivity on_cpu(1, nop, 0); 1087d36db35SAvi Kivity t = rdtsc() + 2000; 1097d36db35SAvi Kivity while (rdtsc() < t) 1107d36db35SAvi Kivity ; 1117d36db35SAvi Kivity } 1127d36db35SAvi Kivity 1137d36db35SAvi Kivity static void inl_pmtimer(void) 1147d36db35SAvi Kivity { 1157d36db35SAvi Kivity inl(0xb008); 1167d36db35SAvi Kivity } 1177d36db35SAvi Kivity 11800bfecaaSPaolo Bonzini static void inl_nop_qemu(void) 11900bfecaaSPaolo Bonzini { 12000bfecaaSPaolo Bonzini inl(0x1234); 12100bfecaaSPaolo Bonzini } 12200bfecaaSPaolo Bonzini 12300bfecaaSPaolo Bonzini static void inl_nop_kernel(void) 12400bfecaaSPaolo Bonzini { 12500bfecaaSPaolo Bonzini inb(0x4d0); 12600bfecaaSPaolo Bonzini } 12700bfecaaSPaolo Bonzini 12800bfecaaSPaolo Bonzini static void outl_elcr_kernel(void) 12900bfecaaSPaolo Bonzini { 13000bfecaaSPaolo Bonzini outb(0x4d0, 0); 13100bfecaaSPaolo Bonzini } 13200bfecaaSPaolo Bonzini 133*8a544409SPaolo Bonzini static void mov_dr(void) 134*8a544409SPaolo Bonzini { 135*8a544409SPaolo Bonzini asm volatile("mov %0, %%dr7" : : "r" (0x400L)); 136*8a544409SPaolo Bonzini } 137*8a544409SPaolo Bonzini 138eda71b28SAvi Kivity static void ple_round_robin(void) 139eda71b28SAvi Kivity { 140eda71b28SAvi Kivity struct counter { 141eda71b28SAvi Kivity volatile int n1; 142eda71b28SAvi Kivity int n2; 143eda71b28SAvi Kivity } __attribute__((aligned(64))); 144eda71b28SAvi Kivity static struct counter counters[64] = { { -1, 0 } }; 145eda71b28SAvi Kivity int me = smp_id(); 146eda71b28SAvi Kivity int you; 147eda71b28SAvi Kivity volatile struct counter *p = &counters[me]; 148eda71b28SAvi Kivity 149eda71b28SAvi Kivity while (p->n1 == p->n2) 150eda71b28SAvi Kivity asm volatile ("pause"); 151eda71b28SAvi Kivity 152eda71b28SAvi Kivity p->n2 = p->n1; 153eda71b28SAvi Kivity you = me + 1; 154eda71b28SAvi Kivity if (you == nr_cpus) 155eda71b28SAvi Kivity you = 0; 156eda71b28SAvi Kivity ++counters[you].n1; 157eda71b28SAvi Kivity } 158eda71b28SAvi Kivity 1595fecf5d8SWill Auld static void rd_tsc_adjust_msr(void) 1605fecf5d8SWill Auld { 1615fecf5d8SWill Auld rdmsr(MSR_TSC_ADJUST); 1625fecf5d8SWill Auld } 1635fecf5d8SWill Auld 1645fecf5d8SWill Auld static void wr_tsc_adjust_msr(void) 1655fecf5d8SWill Auld { 1665fecf5d8SWill Auld wrmsr(MSR_TSC_ADJUST, 0x0); 1675fecf5d8SWill Auld } 1685fecf5d8SWill Auld 1695292dbf7SMichael S. Tsirkin struct pci_test_dev_hdr { 1705292dbf7SMichael S. Tsirkin uint8_t test; 1715292dbf7SMichael S. Tsirkin uint8_t width; 1725292dbf7SMichael S. Tsirkin uint8_t pad0[2]; 1735292dbf7SMichael S. Tsirkin uint32_t offset; 1745292dbf7SMichael S. Tsirkin uint32_t data; 1755292dbf7SMichael S. Tsirkin uint32_t count; 1765292dbf7SMichael S. Tsirkin uint8_t name[]; 1775292dbf7SMichael S. Tsirkin }; 1785292dbf7SMichael S. Tsirkin 1795292dbf7SMichael S. Tsirkin static struct pci_test { 1805292dbf7SMichael S. Tsirkin unsigned iobar; 1815292dbf7SMichael S. Tsirkin unsigned ioport; 1825292dbf7SMichael S. Tsirkin volatile void *memaddr; 1835292dbf7SMichael S. Tsirkin volatile void *mem; 1845292dbf7SMichael S. Tsirkin int test_idx; 1855292dbf7SMichael S. Tsirkin uint32_t data; 1865292dbf7SMichael S. Tsirkin uint32_t offset; 1875292dbf7SMichael S. Tsirkin } pci_test = { 1885292dbf7SMichael S. Tsirkin .test_idx = -1 1895292dbf7SMichael S. Tsirkin }; 1905292dbf7SMichael S. Tsirkin 1915292dbf7SMichael S. Tsirkin static void pci_mem_testb(void) 1925292dbf7SMichael S. Tsirkin { 1935292dbf7SMichael S. Tsirkin *(volatile uint8_t *)pci_test.mem = pci_test.data; 1945292dbf7SMichael S. Tsirkin } 1955292dbf7SMichael S. Tsirkin 1965292dbf7SMichael S. Tsirkin static void pci_mem_testw(void) 1975292dbf7SMichael S. Tsirkin { 1985292dbf7SMichael S. Tsirkin *(volatile uint16_t *)pci_test.mem = pci_test.data; 1995292dbf7SMichael S. Tsirkin } 2005292dbf7SMichael S. Tsirkin 2015292dbf7SMichael S. Tsirkin static void pci_mem_testl(void) 2025292dbf7SMichael S. Tsirkin { 2035292dbf7SMichael S. Tsirkin *(volatile uint32_t *)pci_test.mem = pci_test.data; 2045292dbf7SMichael S. Tsirkin } 2055292dbf7SMichael S. Tsirkin 2065292dbf7SMichael S. Tsirkin static void pci_io_testb(void) 2075292dbf7SMichael S. Tsirkin { 2085292dbf7SMichael S. Tsirkin outb(pci_test.ioport, pci_test.data); 2095292dbf7SMichael S. Tsirkin } 2105292dbf7SMichael S. Tsirkin 2115292dbf7SMichael S. Tsirkin static void pci_io_testw(void) 2125292dbf7SMichael S. Tsirkin { 2135292dbf7SMichael S. Tsirkin outw(pci_test.ioport, pci_test.data); 2145292dbf7SMichael S. Tsirkin } 2155292dbf7SMichael S. Tsirkin 2165292dbf7SMichael S. Tsirkin static void pci_io_testl(void) 2175292dbf7SMichael S. Tsirkin { 2185292dbf7SMichael S. Tsirkin outl(pci_test.ioport, pci_test.data); 2195292dbf7SMichael S. Tsirkin } 2205292dbf7SMichael S. Tsirkin 2215292dbf7SMichael S. Tsirkin static uint8_t ioreadb(unsigned long addr, bool io) 2225292dbf7SMichael S. Tsirkin { 2235292dbf7SMichael S. Tsirkin if (io) { 2245292dbf7SMichael S. Tsirkin return inb(addr); 2255292dbf7SMichael S. Tsirkin } else { 2265292dbf7SMichael S. Tsirkin return *(volatile uint8_t *)addr; 2275292dbf7SMichael S. Tsirkin } 2285292dbf7SMichael S. Tsirkin } 2295292dbf7SMichael S. Tsirkin 2305292dbf7SMichael S. Tsirkin static uint32_t ioreadl(unsigned long addr, bool io) 2315292dbf7SMichael S. Tsirkin { 2325292dbf7SMichael S. Tsirkin /* Note: assumes little endian */ 2335292dbf7SMichael S. Tsirkin if (io) { 2345292dbf7SMichael S. Tsirkin return inl(addr); 2355292dbf7SMichael S. Tsirkin } else { 2365292dbf7SMichael S. Tsirkin return *(volatile uint32_t *)addr; 2375292dbf7SMichael S. Tsirkin } 2385292dbf7SMichael S. Tsirkin } 2395292dbf7SMichael S. Tsirkin 2405292dbf7SMichael S. Tsirkin static void iowriteb(unsigned long addr, uint8_t data, bool io) 2415292dbf7SMichael S. Tsirkin { 2425292dbf7SMichael S. Tsirkin if (io) { 2435292dbf7SMichael S. Tsirkin outb(addr, data); 2445292dbf7SMichael S. Tsirkin } else { 2455292dbf7SMichael S. Tsirkin *(volatile uint8_t *)addr = data; 2465292dbf7SMichael S. Tsirkin } 2475292dbf7SMichael S. Tsirkin } 2485292dbf7SMichael S. Tsirkin 2495292dbf7SMichael S. Tsirkin static bool pci_next(struct test *test, unsigned long addr, bool io) 2505292dbf7SMichael S. Tsirkin { 2515292dbf7SMichael S. Tsirkin int i; 2525292dbf7SMichael S. Tsirkin uint8_t width; 2535292dbf7SMichael S. Tsirkin 2545292dbf7SMichael S. Tsirkin if (!pci_test.memaddr) { 2555292dbf7SMichael S. Tsirkin test->func = NULL; 2565292dbf7SMichael S. Tsirkin return true; 2575292dbf7SMichael S. Tsirkin } 2585292dbf7SMichael S. Tsirkin pci_test.test_idx++; 2595292dbf7SMichael S. Tsirkin iowriteb(addr + offsetof(struct pci_test_dev_hdr, test), 2605292dbf7SMichael S. Tsirkin pci_test.test_idx, io); 2615292dbf7SMichael S. Tsirkin width = ioreadb(addr + offsetof(struct pci_test_dev_hdr, width), 2625292dbf7SMichael S. Tsirkin io); 2635292dbf7SMichael S. Tsirkin switch (width) { 2645292dbf7SMichael S. Tsirkin case 1: 2655292dbf7SMichael S. Tsirkin test->func = io ? pci_io_testb : pci_mem_testb; 2665292dbf7SMichael S. Tsirkin break; 2675292dbf7SMichael S. Tsirkin case 2: 2685292dbf7SMichael S. Tsirkin test->func = io ? pci_io_testw : pci_mem_testw; 2695292dbf7SMichael S. Tsirkin break; 2705292dbf7SMichael S. Tsirkin case 4: 2715292dbf7SMichael S. Tsirkin test->func = io ? pci_io_testl : pci_mem_testl; 2725292dbf7SMichael S. Tsirkin break; 2735292dbf7SMichael S. Tsirkin default: 2745292dbf7SMichael S. Tsirkin /* Reset index for purposes of the next test */ 2755292dbf7SMichael S. Tsirkin pci_test.test_idx = -1; 2765292dbf7SMichael S. Tsirkin test->func = NULL; 2775292dbf7SMichael S. Tsirkin return false; 2785292dbf7SMichael S. Tsirkin } 2795292dbf7SMichael S. Tsirkin pci_test.data = ioreadl(addr + offsetof(struct pci_test_dev_hdr, data), 2805292dbf7SMichael S. Tsirkin io); 2815292dbf7SMichael S. Tsirkin pci_test.offset = ioreadl(addr + offsetof(struct pci_test_dev_hdr, 2825292dbf7SMichael S. Tsirkin offset), io); 2835292dbf7SMichael S. Tsirkin for (i = 0; i < pci_test.offset; ++i) { 2845292dbf7SMichael S. Tsirkin char c = ioreadb(addr + offsetof(struct pci_test_dev_hdr, 2855292dbf7SMichael S. Tsirkin name) + i, io); 2865292dbf7SMichael S. Tsirkin if (!c) { 2875292dbf7SMichael S. Tsirkin break; 2885292dbf7SMichael S. Tsirkin } 2895292dbf7SMichael S. Tsirkin printf("%c",c); 2905292dbf7SMichael S. Tsirkin } 2915292dbf7SMichael S. Tsirkin printf(":"); 2925292dbf7SMichael S. Tsirkin return true; 2935292dbf7SMichael S. Tsirkin } 2945292dbf7SMichael S. Tsirkin 2955292dbf7SMichael S. Tsirkin static bool pci_mem_next(struct test *test) 2965292dbf7SMichael S. Tsirkin { 2975292dbf7SMichael S. Tsirkin bool ret; 2985292dbf7SMichael S. Tsirkin ret = pci_next(test, ((unsigned long)pci_test.memaddr), false); 2995292dbf7SMichael S. Tsirkin if (ret) { 3005292dbf7SMichael S. Tsirkin pci_test.mem = pci_test.memaddr + pci_test.offset; 3015292dbf7SMichael S. Tsirkin } 3025292dbf7SMichael S. Tsirkin return ret; 3035292dbf7SMichael S. Tsirkin } 3045292dbf7SMichael S. Tsirkin 3055292dbf7SMichael S. Tsirkin static bool pci_io_next(struct test *test) 3065292dbf7SMichael S. Tsirkin { 3075292dbf7SMichael S. Tsirkin bool ret; 3085292dbf7SMichael S. Tsirkin ret = pci_next(test, ((unsigned long)pci_test.iobar), true); 3095292dbf7SMichael S. Tsirkin if (ret) { 3105292dbf7SMichael S. Tsirkin pci_test.ioport = pci_test.iobar + pci_test.offset; 3115292dbf7SMichael S. Tsirkin } 3125292dbf7SMichael S. Tsirkin return ret; 3135292dbf7SMichael S. Tsirkin } 3145292dbf7SMichael S. Tsirkin 3155292dbf7SMichael S. Tsirkin static struct test tests[] = { 316850479e3SJason Wang { cpuid_test, "cpuid", .parallel = 1, }, 3177d36db35SAvi Kivity { vmcall, "vmcall", .parallel = 1, }, 3185ada505aSJason Wang #ifdef __x86_64__ 3197d36db35SAvi Kivity { mov_from_cr8, "mov_from_cr8", .parallel = 1, }, 3207d36db35SAvi Kivity { mov_to_cr8, "mov_to_cr8" , .parallel = 1, }, 3215ada505aSJason Wang #endif 3227d36db35SAvi Kivity { inl_pmtimer, "inl_from_pmtimer", .parallel = 1, }, 32300bfecaaSPaolo Bonzini { inl_nop_qemu, "inl_from_qemu", .parallel = 1 }, 32400bfecaaSPaolo Bonzini { inl_nop_kernel, "inl_from_kernel", .parallel = 1 }, 32500bfecaaSPaolo Bonzini { outl_elcr_kernel, "outl_to_kernel", .parallel = 1 }, 326*8a544409SPaolo Bonzini { mov_dr, "mov_dr", .parallel = 1 }, 3277d36db35SAvi Kivity { ipi, "ipi", is_smp, .parallel = 0, }, 3287d36db35SAvi Kivity { ipi_halt, "ipi+halt", is_smp, .parallel = 0, }, 329eda71b28SAvi Kivity { ple_round_robin, "ple-round-robin", .parallel = 1 }, 3305fecf5d8SWill Auld { wr_tsc_adjust_msr, "wr_tsc_adjust_msr", .parallel = 1 }, 3315fecf5d8SWill Auld { rd_tsc_adjust_msr, "rd_tsc_adjust_msr", .parallel = 1 }, 3325292dbf7SMichael S. Tsirkin { NULL, "pci-mem", .parallel = 0, .next = pci_mem_next }, 3335292dbf7SMichael S. Tsirkin { NULL, "pci-io", .parallel = 0, .next = pci_io_next }, 3347d36db35SAvi Kivity }; 3357d36db35SAvi Kivity 3367d36db35SAvi Kivity unsigned iterations; 3377d641cc5SAvi Kivity static atomic_t nr_cpus_done; 3387d36db35SAvi Kivity 3397d36db35SAvi Kivity static void run_test(void *_func) 3407d36db35SAvi Kivity { 3417d36db35SAvi Kivity int i; 3427d36db35SAvi Kivity void (*func)(void) = _func; 3437d36db35SAvi Kivity 3447d36db35SAvi Kivity for (i = 0; i < iterations; ++i) 3457d36db35SAvi Kivity func(); 3467d36db35SAvi Kivity 3477d641cc5SAvi Kivity atomic_inc(&nr_cpus_done); 3487d36db35SAvi Kivity } 3497d36db35SAvi Kivity 3505292dbf7SMichael S. Tsirkin static bool do_test(struct test *test) 3517d36db35SAvi Kivity { 3527d36db35SAvi Kivity int i; 3537d36db35SAvi Kivity unsigned long long t1, t2; 3545292dbf7SMichael S. Tsirkin void (*func)(void); 3557d36db35SAvi Kivity 3567d36db35SAvi Kivity iterations = 32; 3577d36db35SAvi Kivity 3587d36db35SAvi Kivity if (test->valid && !test->valid()) { 3597d36db35SAvi Kivity printf("%s (skipped)\n", test->name); 3605292dbf7SMichael S. Tsirkin return false; 3615292dbf7SMichael S. Tsirkin } 3625292dbf7SMichael S. Tsirkin 3635292dbf7SMichael S. Tsirkin if (test->next && !test->next(test)) { 3645292dbf7SMichael S. Tsirkin return false; 3655292dbf7SMichael S. Tsirkin } 3665292dbf7SMichael S. Tsirkin 3675292dbf7SMichael S. Tsirkin func = test->func; 3685292dbf7SMichael S. Tsirkin if (!func) { 3695292dbf7SMichael S. Tsirkin printf("%s (skipped)\n", test->name); 3705292dbf7SMichael S. Tsirkin return false; 3717d36db35SAvi Kivity } 3727d36db35SAvi Kivity 3737d36db35SAvi Kivity do { 3747d36db35SAvi Kivity iterations *= 2; 3757d36db35SAvi Kivity t1 = rdtsc(); 3767d36db35SAvi Kivity 3777d36db35SAvi Kivity if (!test->parallel) { 3787d36db35SAvi Kivity for (i = 0; i < iterations; ++i) 3797d36db35SAvi Kivity func(); 3807d36db35SAvi Kivity } else { 3817d641cc5SAvi Kivity atomic_set(&nr_cpus_done, 0); 3827d36db35SAvi Kivity for (i = cpu_count(); i > 0; i--) 3837d36db35SAvi Kivity on_cpu_async(i-1, run_test, func); 3847d641cc5SAvi Kivity while (atomic_read(&nr_cpus_done) < cpu_count()) 3857d36db35SAvi Kivity ; 3867d36db35SAvi Kivity } 3877d36db35SAvi Kivity t2 = rdtsc(); 3887d36db35SAvi Kivity } while ((t2 - t1) < GOAL); 3897d36db35SAvi Kivity printf("%s %d\n", test->name, (int)((t2 - t1) / iterations)); 3905292dbf7SMichael S. Tsirkin return test->next; 3917d36db35SAvi Kivity } 3927d36db35SAvi Kivity 3937d36db35SAvi Kivity static void enable_nx(void *junk) 3947d36db35SAvi Kivity { 395e46b32aaSAvi Kivity if (cpuid(0x80000001).d & (1 << 20)) 3967d36db35SAvi Kivity wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_NX_MASK); 3977d36db35SAvi Kivity } 3987d36db35SAvi Kivity 3990b267183SAvi Kivity bool test_wanted(struct test *test, char *wanted[], int nwanted) 4000b267183SAvi Kivity { 4010b267183SAvi Kivity int i; 4020b267183SAvi Kivity 4030b267183SAvi Kivity if (!nwanted) 4040b267183SAvi Kivity return true; 4050b267183SAvi Kivity 4060b267183SAvi Kivity for (i = 0; i < nwanted; ++i) 4070b267183SAvi Kivity if (strcmp(wanted[i], test->name) == 0) 4080b267183SAvi Kivity return true; 4090b267183SAvi Kivity 4100b267183SAvi Kivity return false; 4110b267183SAvi Kivity } 4120b267183SAvi Kivity 4130b267183SAvi Kivity int main(int ac, char **av) 4147d36db35SAvi Kivity { 4157d36db35SAvi Kivity int i; 4165292dbf7SMichael S. Tsirkin unsigned long membar = 0, base, offset; 4175292dbf7SMichael S. Tsirkin void *m; 4185292dbf7SMichael S. Tsirkin pcidevaddr_t pcidev; 4197d36db35SAvi Kivity 4207d36db35SAvi Kivity smp_init(); 4215292dbf7SMichael S. Tsirkin setup_vm(); 422eda71b28SAvi Kivity nr_cpus = cpu_count(); 4237d36db35SAvi Kivity 4247d36db35SAvi Kivity for (i = cpu_count(); i > 0; i--) 4257d36db35SAvi Kivity on_cpu(i-1, enable_nx, 0); 4267d36db35SAvi Kivity 4275292dbf7SMichael S. Tsirkin pcidev = pci_find_dev(0x1b36, 0x0005); 4285292dbf7SMichael S. Tsirkin if (pcidev) { 4295292dbf7SMichael S. Tsirkin for (i = 0; i < 2; i++) { 4305292dbf7SMichael S. Tsirkin if (!pci_bar_is_valid(pcidev, i)) { 4315292dbf7SMichael S. Tsirkin continue; 4325292dbf7SMichael S. Tsirkin } 4335292dbf7SMichael S. Tsirkin if (pci_bar_is_memory(pcidev, i)) { 4345292dbf7SMichael S. Tsirkin membar = pci_bar_addr(pcidev, i); 4355292dbf7SMichael S. Tsirkin base = membar & ~4095; 4365292dbf7SMichael S. Tsirkin offset = membar - base; 4375292dbf7SMichael S. Tsirkin m = alloc_vpages(1); 4385292dbf7SMichael S. Tsirkin 4395292dbf7SMichael S. Tsirkin install_page((void *)read_cr3(), base, m); 4405292dbf7SMichael S. Tsirkin pci_test.memaddr = m + offset; 4415292dbf7SMichael S. Tsirkin } else { 4425292dbf7SMichael S. Tsirkin pci_test.iobar = pci_bar_addr(pcidev, i); 4435292dbf7SMichael S. Tsirkin } 4445292dbf7SMichael S. Tsirkin } 4455292dbf7SMichael S. Tsirkin printf("pci-testdev at 0x%x membar %lx iobar %x\n", 4465292dbf7SMichael S. Tsirkin pcidev, membar, pci_test.iobar); 4475292dbf7SMichael S. Tsirkin } 4485292dbf7SMichael S. Tsirkin 4497d36db35SAvi Kivity for (i = 0; i < ARRAY_SIZE(tests); ++i) 4500b267183SAvi Kivity if (test_wanted(&tests[i], av + 1, ac - 1)) 4515292dbf7SMichael S. Tsirkin while (do_test(&tests[i])) {} 4527d36db35SAvi Kivity 4537d36db35SAvi Kivity return 0; 4547d36db35SAvi Kivity } 455