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 { 29*0b9e64c4SGleb 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 133eda71b28SAvi Kivity static void ple_round_robin(void) 134eda71b28SAvi Kivity { 135eda71b28SAvi Kivity struct counter { 136eda71b28SAvi Kivity volatile int n1; 137eda71b28SAvi Kivity int n2; 138eda71b28SAvi Kivity } __attribute__((aligned(64))); 139eda71b28SAvi Kivity static struct counter counters[64] = { { -1, 0 } }; 140eda71b28SAvi Kivity int me = smp_id(); 141eda71b28SAvi Kivity int you; 142eda71b28SAvi Kivity volatile struct counter *p = &counters[me]; 143eda71b28SAvi Kivity 144eda71b28SAvi Kivity while (p->n1 == p->n2) 145eda71b28SAvi Kivity asm volatile ("pause"); 146eda71b28SAvi Kivity 147eda71b28SAvi Kivity p->n2 = p->n1; 148eda71b28SAvi Kivity you = me + 1; 149eda71b28SAvi Kivity if (you == nr_cpus) 150eda71b28SAvi Kivity you = 0; 151eda71b28SAvi Kivity ++counters[you].n1; 152eda71b28SAvi Kivity } 153eda71b28SAvi Kivity 1545fecf5d8SWill Auld static void rd_tsc_adjust_msr(void) 1555fecf5d8SWill Auld { 1565fecf5d8SWill Auld rdmsr(MSR_TSC_ADJUST); 1575fecf5d8SWill Auld } 1585fecf5d8SWill Auld 1595fecf5d8SWill Auld static void wr_tsc_adjust_msr(void) 1605fecf5d8SWill Auld { 1615fecf5d8SWill Auld wrmsr(MSR_TSC_ADJUST, 0x0); 1625fecf5d8SWill Auld } 1635fecf5d8SWill Auld 1645292dbf7SMichael S. Tsirkin struct pci_test_dev_hdr { 1655292dbf7SMichael S. Tsirkin uint8_t test; 1665292dbf7SMichael S. Tsirkin uint8_t width; 1675292dbf7SMichael S. Tsirkin uint8_t pad0[2]; 1685292dbf7SMichael S. Tsirkin uint32_t offset; 1695292dbf7SMichael S. Tsirkin uint32_t data; 1705292dbf7SMichael S. Tsirkin uint32_t count; 1715292dbf7SMichael S. Tsirkin uint8_t name[]; 1725292dbf7SMichael S. Tsirkin }; 1735292dbf7SMichael S. Tsirkin 1745292dbf7SMichael S. Tsirkin static struct pci_test { 1755292dbf7SMichael S. Tsirkin unsigned iobar; 1765292dbf7SMichael S. Tsirkin unsigned ioport; 1775292dbf7SMichael S. Tsirkin volatile void *memaddr; 1785292dbf7SMichael S. Tsirkin volatile void *mem; 1795292dbf7SMichael S. Tsirkin int test_idx; 1805292dbf7SMichael S. Tsirkin uint32_t data; 1815292dbf7SMichael S. Tsirkin uint32_t offset; 1825292dbf7SMichael S. Tsirkin } pci_test = { 1835292dbf7SMichael S. Tsirkin .test_idx = -1 1845292dbf7SMichael S. Tsirkin }; 1855292dbf7SMichael S. Tsirkin 1865292dbf7SMichael S. Tsirkin static void pci_mem_testb(void) 1875292dbf7SMichael S. Tsirkin { 1885292dbf7SMichael S. Tsirkin *(volatile uint8_t *)pci_test.mem = pci_test.data; 1895292dbf7SMichael S. Tsirkin } 1905292dbf7SMichael S. Tsirkin 1915292dbf7SMichael S. Tsirkin static void pci_mem_testw(void) 1925292dbf7SMichael S. Tsirkin { 1935292dbf7SMichael S. Tsirkin *(volatile uint16_t *)pci_test.mem = pci_test.data; 1945292dbf7SMichael S. Tsirkin } 1955292dbf7SMichael S. Tsirkin 1965292dbf7SMichael S. Tsirkin static void pci_mem_testl(void) 1975292dbf7SMichael S. Tsirkin { 1985292dbf7SMichael S. Tsirkin *(volatile uint32_t *)pci_test.mem = pci_test.data; 1995292dbf7SMichael S. Tsirkin } 2005292dbf7SMichael S. Tsirkin 2015292dbf7SMichael S. Tsirkin static void pci_io_testb(void) 2025292dbf7SMichael S. Tsirkin { 2035292dbf7SMichael S. Tsirkin outb(pci_test.ioport, pci_test.data); 2045292dbf7SMichael S. Tsirkin } 2055292dbf7SMichael S. Tsirkin 2065292dbf7SMichael S. Tsirkin static void pci_io_testw(void) 2075292dbf7SMichael S. Tsirkin { 2085292dbf7SMichael S. Tsirkin outw(pci_test.ioport, pci_test.data); 2095292dbf7SMichael S. Tsirkin } 2105292dbf7SMichael S. Tsirkin 2115292dbf7SMichael S. Tsirkin static void pci_io_testl(void) 2125292dbf7SMichael S. Tsirkin { 2135292dbf7SMichael S. Tsirkin outl(pci_test.ioport, pci_test.data); 2145292dbf7SMichael S. Tsirkin } 2155292dbf7SMichael S. Tsirkin 2165292dbf7SMichael S. Tsirkin static uint8_t ioreadb(unsigned long addr, bool io) 2175292dbf7SMichael S. Tsirkin { 2185292dbf7SMichael S. Tsirkin if (io) { 2195292dbf7SMichael S. Tsirkin return inb(addr); 2205292dbf7SMichael S. Tsirkin } else { 2215292dbf7SMichael S. Tsirkin return *(volatile uint8_t *)addr; 2225292dbf7SMichael S. Tsirkin } 2235292dbf7SMichael S. Tsirkin } 2245292dbf7SMichael S. Tsirkin 2255292dbf7SMichael S. Tsirkin static uint32_t ioreadl(unsigned long addr, bool io) 2265292dbf7SMichael S. Tsirkin { 2275292dbf7SMichael S. Tsirkin /* Note: assumes little endian */ 2285292dbf7SMichael S. Tsirkin if (io) { 2295292dbf7SMichael S. Tsirkin return inl(addr); 2305292dbf7SMichael S. Tsirkin } else { 2315292dbf7SMichael S. Tsirkin return *(volatile uint32_t *)addr; 2325292dbf7SMichael S. Tsirkin } 2335292dbf7SMichael S. Tsirkin } 2345292dbf7SMichael S. Tsirkin 2355292dbf7SMichael S. Tsirkin static void iowriteb(unsigned long addr, uint8_t data, bool io) 2365292dbf7SMichael S. Tsirkin { 2375292dbf7SMichael S. Tsirkin if (io) { 2385292dbf7SMichael S. Tsirkin outb(addr, data); 2395292dbf7SMichael S. Tsirkin } else { 2405292dbf7SMichael S. Tsirkin *(volatile uint8_t *)addr = data; 2415292dbf7SMichael S. Tsirkin } 2425292dbf7SMichael S. Tsirkin } 2435292dbf7SMichael S. Tsirkin 2445292dbf7SMichael S. Tsirkin static bool pci_next(struct test *test, unsigned long addr, bool io) 2455292dbf7SMichael S. Tsirkin { 2465292dbf7SMichael S. Tsirkin int i; 2475292dbf7SMichael S. Tsirkin uint8_t width; 2485292dbf7SMichael S. Tsirkin 2495292dbf7SMichael S. Tsirkin if (!pci_test.memaddr) { 2505292dbf7SMichael S. Tsirkin test->func = NULL; 2515292dbf7SMichael S. Tsirkin return true; 2525292dbf7SMichael S. Tsirkin } 2535292dbf7SMichael S. Tsirkin pci_test.test_idx++; 2545292dbf7SMichael S. Tsirkin iowriteb(addr + offsetof(struct pci_test_dev_hdr, test), 2555292dbf7SMichael S. Tsirkin pci_test.test_idx, io); 2565292dbf7SMichael S. Tsirkin width = ioreadb(addr + offsetof(struct pci_test_dev_hdr, width), 2575292dbf7SMichael S. Tsirkin io); 2585292dbf7SMichael S. Tsirkin switch (width) { 2595292dbf7SMichael S. Tsirkin case 1: 2605292dbf7SMichael S. Tsirkin test->func = io ? pci_io_testb : pci_mem_testb; 2615292dbf7SMichael S. Tsirkin break; 2625292dbf7SMichael S. Tsirkin case 2: 2635292dbf7SMichael S. Tsirkin test->func = io ? pci_io_testw : pci_mem_testw; 2645292dbf7SMichael S. Tsirkin break; 2655292dbf7SMichael S. Tsirkin case 4: 2665292dbf7SMichael S. Tsirkin test->func = io ? pci_io_testl : pci_mem_testl; 2675292dbf7SMichael S. Tsirkin break; 2685292dbf7SMichael S. Tsirkin default: 2695292dbf7SMichael S. Tsirkin /* Reset index for purposes of the next test */ 2705292dbf7SMichael S. Tsirkin pci_test.test_idx = -1; 2715292dbf7SMichael S. Tsirkin test->func = NULL; 2725292dbf7SMichael S. Tsirkin return false; 2735292dbf7SMichael S. Tsirkin } 2745292dbf7SMichael S. Tsirkin pci_test.data = ioreadl(addr + offsetof(struct pci_test_dev_hdr, data), 2755292dbf7SMichael S. Tsirkin io); 2765292dbf7SMichael S. Tsirkin pci_test.offset = ioreadl(addr + offsetof(struct pci_test_dev_hdr, 2775292dbf7SMichael S. Tsirkin offset), io); 2785292dbf7SMichael S. Tsirkin for (i = 0; i < pci_test.offset; ++i) { 2795292dbf7SMichael S. Tsirkin char c = ioreadb(addr + offsetof(struct pci_test_dev_hdr, 2805292dbf7SMichael S. Tsirkin name) + i, io); 2815292dbf7SMichael S. Tsirkin if (!c) { 2825292dbf7SMichael S. Tsirkin break; 2835292dbf7SMichael S. Tsirkin } 2845292dbf7SMichael S. Tsirkin printf("%c",c); 2855292dbf7SMichael S. Tsirkin } 2865292dbf7SMichael S. Tsirkin printf(":"); 2875292dbf7SMichael S. Tsirkin return true; 2885292dbf7SMichael S. Tsirkin } 2895292dbf7SMichael S. Tsirkin 2905292dbf7SMichael S. Tsirkin static bool pci_mem_next(struct test *test) 2915292dbf7SMichael S. Tsirkin { 2925292dbf7SMichael S. Tsirkin bool ret; 2935292dbf7SMichael S. Tsirkin ret = pci_next(test, ((unsigned long)pci_test.memaddr), false); 2945292dbf7SMichael S. Tsirkin if (ret) { 2955292dbf7SMichael S. Tsirkin pci_test.mem = pci_test.memaddr + pci_test.offset; 2965292dbf7SMichael S. Tsirkin } 2975292dbf7SMichael S. Tsirkin return ret; 2985292dbf7SMichael S. Tsirkin } 2995292dbf7SMichael S. Tsirkin 3005292dbf7SMichael S. Tsirkin static bool pci_io_next(struct test *test) 3015292dbf7SMichael S. Tsirkin { 3025292dbf7SMichael S. Tsirkin bool ret; 3035292dbf7SMichael S. Tsirkin ret = pci_next(test, ((unsigned long)pci_test.iobar), true); 3045292dbf7SMichael S. Tsirkin if (ret) { 3055292dbf7SMichael S. Tsirkin pci_test.ioport = pci_test.iobar + pci_test.offset; 3065292dbf7SMichael S. Tsirkin } 3075292dbf7SMichael S. Tsirkin return ret; 3085292dbf7SMichael S. Tsirkin } 3095292dbf7SMichael S. Tsirkin 3105292dbf7SMichael S. Tsirkin static struct test tests[] = { 311850479e3SJason Wang { cpuid_test, "cpuid", .parallel = 1, }, 3127d36db35SAvi Kivity { vmcall, "vmcall", .parallel = 1, }, 3135ada505aSJason Wang #ifdef __x86_64__ 3147d36db35SAvi Kivity { mov_from_cr8, "mov_from_cr8", .parallel = 1, }, 3157d36db35SAvi Kivity { mov_to_cr8, "mov_to_cr8" , .parallel = 1, }, 3165ada505aSJason Wang #endif 3177d36db35SAvi Kivity { inl_pmtimer, "inl_from_pmtimer", .parallel = 1, }, 31800bfecaaSPaolo Bonzini { inl_nop_qemu, "inl_from_qemu", .parallel = 1 }, 31900bfecaaSPaolo Bonzini { inl_nop_kernel, "inl_from_kernel", .parallel = 1 }, 32000bfecaaSPaolo Bonzini { outl_elcr_kernel, "outl_to_kernel", .parallel = 1 }, 3217d36db35SAvi Kivity { ipi, "ipi", is_smp, .parallel = 0, }, 3227d36db35SAvi Kivity { ipi_halt, "ipi+halt", is_smp, .parallel = 0, }, 323eda71b28SAvi Kivity { ple_round_robin, "ple-round-robin", .parallel = 1 }, 3245fecf5d8SWill Auld { wr_tsc_adjust_msr, "wr_tsc_adjust_msr", .parallel = 1 }, 3255fecf5d8SWill Auld { rd_tsc_adjust_msr, "rd_tsc_adjust_msr", .parallel = 1 }, 3265292dbf7SMichael S. Tsirkin { NULL, "pci-mem", .parallel = 0, .next = pci_mem_next }, 3275292dbf7SMichael S. Tsirkin { NULL, "pci-io", .parallel = 0, .next = pci_io_next }, 3287d36db35SAvi Kivity }; 3297d36db35SAvi Kivity 3307d36db35SAvi Kivity unsigned iterations; 3317d641cc5SAvi Kivity static atomic_t nr_cpus_done; 3327d36db35SAvi Kivity 3337d36db35SAvi Kivity static void run_test(void *_func) 3347d36db35SAvi Kivity { 3357d36db35SAvi Kivity int i; 3367d36db35SAvi Kivity void (*func)(void) = _func; 3377d36db35SAvi Kivity 3387d36db35SAvi Kivity for (i = 0; i < iterations; ++i) 3397d36db35SAvi Kivity func(); 3407d36db35SAvi Kivity 3417d641cc5SAvi Kivity atomic_inc(&nr_cpus_done); 3427d36db35SAvi Kivity } 3437d36db35SAvi Kivity 3445292dbf7SMichael S. Tsirkin static bool do_test(struct test *test) 3457d36db35SAvi Kivity { 3467d36db35SAvi Kivity int i; 3477d36db35SAvi Kivity unsigned long long t1, t2; 3485292dbf7SMichael S. Tsirkin void (*func)(void); 3497d36db35SAvi Kivity 3507d36db35SAvi Kivity iterations = 32; 3517d36db35SAvi Kivity 3527d36db35SAvi Kivity if (test->valid && !test->valid()) { 3537d36db35SAvi Kivity printf("%s (skipped)\n", test->name); 3545292dbf7SMichael S. Tsirkin return false; 3555292dbf7SMichael S. Tsirkin } 3565292dbf7SMichael S. Tsirkin 3575292dbf7SMichael S. Tsirkin if (test->next && !test->next(test)) { 3585292dbf7SMichael S. Tsirkin return false; 3595292dbf7SMichael S. Tsirkin } 3605292dbf7SMichael S. Tsirkin 3615292dbf7SMichael S. Tsirkin func = test->func; 3625292dbf7SMichael S. Tsirkin if (!func) { 3635292dbf7SMichael S. Tsirkin printf("%s (skipped)\n", test->name); 3645292dbf7SMichael S. Tsirkin return false; 3657d36db35SAvi Kivity } 3667d36db35SAvi Kivity 3677d36db35SAvi Kivity do { 3687d36db35SAvi Kivity iterations *= 2; 3697d36db35SAvi Kivity t1 = rdtsc(); 3707d36db35SAvi Kivity 3717d36db35SAvi Kivity if (!test->parallel) { 3727d36db35SAvi Kivity for (i = 0; i < iterations; ++i) 3737d36db35SAvi Kivity func(); 3747d36db35SAvi Kivity } else { 3757d641cc5SAvi Kivity atomic_set(&nr_cpus_done, 0); 3767d36db35SAvi Kivity for (i = cpu_count(); i > 0; i--) 3777d36db35SAvi Kivity on_cpu_async(i-1, run_test, func); 3787d641cc5SAvi Kivity while (atomic_read(&nr_cpus_done) < cpu_count()) 3797d36db35SAvi Kivity ; 3807d36db35SAvi Kivity } 3817d36db35SAvi Kivity t2 = rdtsc(); 3827d36db35SAvi Kivity } while ((t2 - t1) < GOAL); 3837d36db35SAvi Kivity printf("%s %d\n", test->name, (int)((t2 - t1) / iterations)); 3845292dbf7SMichael S. Tsirkin return test->next; 3857d36db35SAvi Kivity } 3867d36db35SAvi Kivity 3877d36db35SAvi Kivity static void enable_nx(void *junk) 3887d36db35SAvi Kivity { 389e46b32aaSAvi Kivity if (cpuid(0x80000001).d & (1 << 20)) 3907d36db35SAvi Kivity wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_NX_MASK); 3917d36db35SAvi Kivity } 3927d36db35SAvi Kivity 3930b267183SAvi Kivity bool test_wanted(struct test *test, char *wanted[], int nwanted) 3940b267183SAvi Kivity { 3950b267183SAvi Kivity int i; 3960b267183SAvi Kivity 3970b267183SAvi Kivity if (!nwanted) 3980b267183SAvi Kivity return true; 3990b267183SAvi Kivity 4000b267183SAvi Kivity for (i = 0; i < nwanted; ++i) 4010b267183SAvi Kivity if (strcmp(wanted[i], test->name) == 0) 4020b267183SAvi Kivity return true; 4030b267183SAvi Kivity 4040b267183SAvi Kivity return false; 4050b267183SAvi Kivity } 4060b267183SAvi Kivity 4070b267183SAvi Kivity int main(int ac, char **av) 4087d36db35SAvi Kivity { 4097d36db35SAvi Kivity int i; 4105292dbf7SMichael S. Tsirkin unsigned long membar = 0, base, offset; 4115292dbf7SMichael S. Tsirkin void *m; 4125292dbf7SMichael S. Tsirkin pcidevaddr_t pcidev; 4137d36db35SAvi Kivity 4147d36db35SAvi Kivity smp_init(); 4155292dbf7SMichael S. Tsirkin setup_vm(); 416eda71b28SAvi Kivity nr_cpus = cpu_count(); 4177d36db35SAvi Kivity 4187d36db35SAvi Kivity for (i = cpu_count(); i > 0; i--) 4197d36db35SAvi Kivity on_cpu(i-1, enable_nx, 0); 4207d36db35SAvi Kivity 4215292dbf7SMichael S. Tsirkin pcidev = pci_find_dev(0x1b36, 0x0005); 4225292dbf7SMichael S. Tsirkin if (pcidev) { 4235292dbf7SMichael S. Tsirkin for (i = 0; i < 2; i++) { 4245292dbf7SMichael S. Tsirkin if (!pci_bar_is_valid(pcidev, i)) { 4255292dbf7SMichael S. Tsirkin continue; 4265292dbf7SMichael S. Tsirkin } 4275292dbf7SMichael S. Tsirkin if (pci_bar_is_memory(pcidev, i)) { 4285292dbf7SMichael S. Tsirkin membar = pci_bar_addr(pcidev, i); 4295292dbf7SMichael S. Tsirkin base = membar & ~4095; 4305292dbf7SMichael S. Tsirkin offset = membar - base; 4315292dbf7SMichael S. Tsirkin m = alloc_vpages(1); 4325292dbf7SMichael S. Tsirkin 4335292dbf7SMichael S. Tsirkin install_page((void *)read_cr3(), base, m); 4345292dbf7SMichael S. Tsirkin pci_test.memaddr = m + offset; 4355292dbf7SMichael S. Tsirkin } else { 4365292dbf7SMichael S. Tsirkin pci_test.iobar = pci_bar_addr(pcidev, i); 4375292dbf7SMichael S. Tsirkin } 4385292dbf7SMichael S. Tsirkin } 4395292dbf7SMichael S. Tsirkin printf("pci-testdev at 0x%x membar %lx iobar %x\n", 4405292dbf7SMichael S. Tsirkin pcidev, membar, pci_test.iobar); 4415292dbf7SMichael S. Tsirkin } 4425292dbf7SMichael S. Tsirkin 4437d36db35SAvi Kivity for (i = 0; i < ARRAY_SIZE(tests); ++i) 4440b267183SAvi Kivity if (test_wanted(&tests[i], av + 1, ac - 1)) 4455292dbf7SMichael S. Tsirkin while (do_test(&tests[i])) {} 4467d36db35SAvi Kivity 4477d36db35SAvi Kivity return 0; 4487d36db35SAvi Kivity } 449