kvm: qemu: don't check per-vector mask bit before enable MSI-X
[kvm-userspace.git] / user / main.c
blob1530ae2f4f4bd1b6200e732f201322dbaa117c62
1 /*
2 * Kernel-based Virtual Machine test driver
4 * This test driver provides a simple way of testing kvm, without a full
5 * device model.
7 * Copyright (C) 2006 Qumranet
9 * Authors:
11 * Avi Kivity <avi@qumranet.com>
12 * Yaniv Kamay <yaniv@qumranet.com>
14 * This work is licensed under the GNU LGPL license, version 2.
17 #define _GNU_SOURCE
19 #include <libkvm.h>
20 #include "test/lib/x86/fake-apic.h"
21 #include "test/x86/ioram.h"
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <semaphore.h>
29 #include <sys/types.h>
30 #include <errno.h>
31 #include <pthread.h>
32 #include <signal.h>
33 #include <pthread.h>
34 #include <sys/syscall.h>
35 #include <linux/unistd.h>
36 #include <getopt.h>
37 #include <stdbool.h>
39 #include "iotable.h"
41 static uint8_t ioram[IORAM_LEN];
43 static int gettid(void)
45 return syscall(__NR_gettid);
48 static int tkill(int pid, int sig)
50 return syscall(__NR_tkill, pid, sig);
53 kvm_context_t kvm;
55 #define MAX_VCPUS 4
57 #define IPI_SIGNAL (SIGRTMIN + 4)
59 static int ncpus = 1;
60 static sem_t init_sem;
61 static __thread int vcpu;
62 static int apic_ipi_vector = 0xff;
63 static sigset_t kernel_sigmask;
64 static sigset_t ipi_sigmask;
65 static uint64_t memory_size = 128 * 1024 * 1024;
67 static struct io_table pio_table;
69 struct vcpu_info {
70 int id;
71 pid_t tid;
72 sem_t sipi_sem;
75 struct vcpu_info *vcpus;
77 static uint32_t apic_sipi_addr;
79 static void apic_send_sipi(int vcpu)
81 sem_post(&vcpus[vcpu].sipi_sem);
84 static void apic_send_ipi(int vcpu)
86 struct vcpu_info *v;
88 if (vcpu < 0 || vcpu >= ncpus)
89 return;
90 v = &vcpus[vcpu];
91 tkill(v->tid, IPI_SIGNAL);
94 static int apic_io(void *opaque, int size, int is_write,
95 uint64_t addr, uint64_t *value)
97 if (!is_write)
98 *value = -1u;
100 switch (addr - APIC_BASE) {
101 case APIC_REG_NCPU:
102 if (!is_write)
103 *value = ncpus;
104 break;
105 case APIC_REG_ID:
106 if (!is_write)
107 *value = vcpu;
108 break;
109 case APIC_REG_SIPI_ADDR:
110 if (!is_write)
111 *value = apic_sipi_addr;
112 else
113 apic_sipi_addr = *value;
114 break;
115 case APIC_REG_SEND_SIPI:
116 if (is_write)
117 apic_send_sipi(*value);
118 break;
119 case APIC_REG_IPI_VECTOR:
120 if (!is_write)
121 *value = apic_ipi_vector;
122 else
123 apic_ipi_vector = *value;
124 break;
125 case APIC_REG_SEND_IPI:
126 if (is_write)
127 apic_send_ipi(*value);
128 break;
131 return 0;
134 static int apic_init(void)
136 return io_table_register(&pio_table, APIC_BASE,
137 APIC_SIZE, apic_io, NULL);
140 static int misc_io(void *opaque, int size, int is_write,
141 uint64_t addr, uint64_t *value)
143 static int newline = 1;
145 if (!is_write)
146 *value = -1;
148 switch (addr) {
149 case 0xff: // irq injector
150 if (is_write) {
151 printf("injecting interrupt 0x%x\n", (uint8_t)*value);
152 kvm_inject_irq(kvm, 0, *value);
154 break;
155 case 0xf1: // serial
156 if (is_write) {
157 if (newline)
158 fputs("GUEST: ", stdout);
159 putchar(*value);
160 newline = *value == '\n';
162 break;
163 case 0xd1:
164 if (!is_write)
165 *value = memory_size;
166 break;
167 case 0xf4: // exit
168 if (is_write)
169 exit(*value);
170 break;
173 return 0;
176 static int misc_init(void)
178 int err;
180 err = io_table_register(&pio_table, 0xff, 1, misc_io, NULL);
181 if (err < 0)
182 return err;
184 err = io_table_register(&pio_table, 0xf1, 1, misc_io, NULL);
185 if (err < 0)
186 return err;
188 err = io_table_register(&pio_table, 0xf4, 1, misc_io, NULL);
189 if (err < 0)
190 return err;
192 return io_table_register(&pio_table, 0xd1, 1, misc_io, NULL);
195 #define IRQCHIP_IO_BASE 0x2000
197 static int irqchip_io(void *opaque, int size, int is_write,
198 uint64_t addr, uint64_t *value)
200 addr -= IRQCHIP_IO_BASE;
202 if (is_write) {
203 kvm_set_irq_level(kvm, addr, *value, NULL);
205 return 0;
208 static int test_inb(void *opaque, uint16_t addr, uint8_t *value)
210 struct io_table_entry *entry;
212 entry = io_table_lookup(&pio_table, addr);
213 if (entry) {
214 uint64_t val;
215 entry->handler(entry->opaque, 1, 0, addr, &val);
216 *value = val;
217 } else {
218 *value = -1;
219 printf("inb 0x%x\n", addr);
222 return 0;
225 static int test_inw(void *opaque, uint16_t addr, uint16_t *value)
227 struct io_table_entry *entry;
229 entry = io_table_lookup(&pio_table, addr);
230 if (entry) {
231 uint64_t val;
232 entry->handler(entry->opaque, 2, 0, addr, &val);
233 *value = val;
234 } else {
235 *value = -1;
236 printf("inw 0x%x\n", addr);
239 return 0;
242 static int test_inl(void *opaque, uint16_t addr, uint32_t *value)
244 struct io_table_entry *entry;
246 entry = io_table_lookup(&pio_table, addr);
247 if (entry) {
248 uint64_t val;
249 entry->handler(entry->opaque, 4, 0, addr, &val);
250 *value = val;
251 } else {
252 *value = -1;
253 printf("inl 0x%x\n", addr);
256 return 0;
259 static int test_outb(void *opaque, uint16_t addr, uint8_t value)
261 struct io_table_entry *entry;
263 entry = io_table_lookup(&pio_table, addr);
264 if (entry) {
265 uint64_t val = value;
266 entry->handler(entry->opaque, 1, 1, addr, &val);
267 } else
268 printf("outb $0x%x, 0x%x\n", value, addr);
270 return 0;
273 static int test_outw(void *opaque, uint16_t addr, uint16_t value)
275 struct io_table_entry *entry;
277 entry = io_table_lookup(&pio_table, addr);
278 if (entry) {
279 uint64_t val = value;
280 entry->handler(entry->opaque, 2, 1, addr, &val);
281 } else
282 printf("outw $0x%x, 0x%x\n", value, addr);
284 return 0;
287 static int test_outl(void *opaque, uint16_t addr, uint32_t value)
289 struct io_table_entry *entry;
291 entry = io_table_lookup(&pio_table, addr);
292 if (entry) {
293 uint64_t val = value;
294 entry->handler(entry->opaque, 4, 1, addr, &val);
295 } else
296 printf("outl $0x%x, 0x%x\n", value, addr);
298 return 0;
301 #ifdef KVM_CAP_SET_GUEST_DEBUG
302 static int test_debug(void *opaque, void *vcpu,
303 struct kvm_debug_exit_arch *arch_info)
305 printf("test_debug\n");
306 return 0;
308 #endif
310 static int test_halt(void *opaque, int vcpu)
312 int n;
314 sigwait(&ipi_sigmask, &n);
315 kvm_inject_irq(kvm, vcpus[vcpu].id, apic_ipi_vector);
316 return 0;
319 static int test_io_window(void *opaque)
321 return 0;
324 static int test_try_push_interrupts(void *opaque)
326 return 0;
329 #ifdef KVM_CAP_USER_NMI
330 static void test_push_nmi(void *opaque)
333 #endif
335 static void test_post_kvm_run(void *opaque, void *vcpu)
339 static int test_pre_kvm_run(void *opaque, void *vcpu)
341 return 0;
344 static int test_mem_read(void *opaque, uint64_t addr, uint8_t *data, int len)
346 if (addr < IORAM_BASE_PHYS || addr + len > IORAM_BASE_PHYS + IORAM_LEN)
347 return 1;
348 memcpy(data, ioram + addr - IORAM_BASE_PHYS, len);
349 return 0;
352 static int test_mem_write(void *opaque, uint64_t addr, uint8_t *data, int len)
354 if (addr < IORAM_BASE_PHYS || addr + len > IORAM_BASE_PHYS + IORAM_LEN)
355 return 1;
356 memcpy(ioram + addr - IORAM_BASE_PHYS, data, len);
357 return 0;
360 static int test_shutdown(void *opaque, void *env)
362 printf("shutdown\n");
363 kvm_show_regs(kvm, 0);
364 exit(1);
365 return 1;
368 static struct kvm_callbacks test_callbacks = {
369 .inb = test_inb,
370 .inw = test_inw,
371 .inl = test_inl,
372 .outb = test_outb,
373 .outw = test_outw,
374 .outl = test_outl,
375 .mmio_read = test_mem_read,
376 .mmio_write = test_mem_write,
377 #ifdef KVM_CAP_SET_GUEST_DEBUG
378 .debug = test_debug,
379 #endif
380 .halt = test_halt,
381 .io_window = test_io_window,
382 .try_push_interrupts = test_try_push_interrupts,
383 #ifdef KVM_CAP_USER_NMI
384 .push_nmi = test_push_nmi,
385 #endif
386 .post_kvm_run = test_post_kvm_run,
387 .pre_kvm_run = test_pre_kvm_run,
388 .shutdown = test_shutdown,
391 static void load_file(void *mem, const char *fname)
393 int r;
394 int fd;
396 fd = open(fname, O_RDONLY);
397 if (fd == -1) {
398 perror("open");
399 exit(1);
401 while ((r = read(fd, mem, 4096)) != -1 && r != 0)
402 mem += r;
403 if (r == -1) {
404 perror("read");
405 exit(1);
409 static void enter_32(kvm_context_t kvm)
411 struct kvm_regs regs = {
412 .rsp = 0x80000, /* 512KB */
413 .rip = 0x100000, /* 1MB */
414 .rflags = 2,
416 struct kvm_sregs sregs = {
417 .cs = { 0, -1u, 8, 11, 1, 0, 1, 1, 0, 1, 0, 0 },
418 .ds = { 0, -1u, 16, 3, 1, 0, 1, 1, 0, 1, 0, 0 },
419 .es = { 0, -1u, 16, 3, 1, 0, 1, 1, 0, 1, 0, 0 },
420 .fs = { 0, -1u, 16, 3, 1, 0, 1, 1, 0, 1, 0, 0 },
421 .gs = { 0, -1u, 16, 3, 1, 0, 1, 1, 0, 1, 0, 0 },
422 .ss = { 0, -1u, 16, 3, 1, 0, 1, 1, 0, 1, 0, 0 },
424 .tr = { 0, 10000, 24, 11, 1, 0, 0, 0, 0, 0, 0, 0 },
425 .ldt = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
426 .gdt = { 0, 0 },
427 .idt = { 0, 0 },
428 .cr0 = 0x37,
429 .cr3 = 0,
430 .cr4 = 0,
431 .efer = 0,
432 .apic_base = 0,
433 .interrupt_bitmap = { 0 },
436 kvm_set_regs(kvm, 0, &regs);
437 kvm_set_sregs(kvm, 0, &sregs);
440 static void init_vcpu(int n)
442 sigemptyset(&ipi_sigmask);
443 sigaddset(&ipi_sigmask, IPI_SIGNAL);
444 sigprocmask(SIG_UNBLOCK, &ipi_sigmask, NULL);
445 sigprocmask(SIG_BLOCK, &ipi_sigmask, &kernel_sigmask);
446 vcpus[n].id = n;
447 vcpus[n].tid = gettid();
448 vcpu = n;
449 kvm_set_signal_mask(kvm, n, &kernel_sigmask);
450 sem_post(&init_sem);
453 static void *do_create_vcpu(void *_n)
455 int n = (long)_n;
456 struct kvm_regs regs;
458 kvm_create_vcpu(kvm, n);
459 init_vcpu(n);
460 sem_wait(&vcpus[n].sipi_sem);
461 kvm_get_regs(kvm, n, &regs);
462 regs.rip = apic_sipi_addr;
463 kvm_set_regs(kvm, n, &regs);
464 kvm_run(kvm, n, &vcpus[n]);
465 return NULL;
468 static void start_vcpu(int n)
470 pthread_t thread;
472 sem_init(&vcpus[n].sipi_sem, 0, 0);
473 pthread_create(&thread, NULL, do_create_vcpu, (void *)(long)n);
476 static void usage(const char *progname)
478 fprintf(stderr,
479 "Usage: %s [OPTIONS] [bootstrap] flatfile\n"
480 "KVM test harness.\n"
481 "\n"
482 " -s, --smp=NUM create a VM with NUM virtual CPUs\n"
483 " -p, --protected-mode start VM in protected mode\n"
484 " -m, --memory=NUM[GMKB] allocate NUM memory for virtual machine. A suffix\n"
485 " can be used to change the unit (default: `M')\n"
486 " -h, --help display this help screen and exit\n"
487 "\n"
488 "Report bugs to <kvm@vger.kernel.org>.\n"
489 , progname);
492 static void sig_ignore(int sig)
494 write(1, "boo\n", 4);
497 int main(int argc, char **argv)
499 void *vm_mem;
500 int i;
501 const char *sopts = "s:phm:";
502 struct option lopts[] = {
503 { "smp", 1, 0, 's' },
504 { "protected-mode", 0, 0, 'p' },
505 { "memory", 1, 0, 'm' },
506 { "help", 0, 0, 'h' },
507 { 0 },
509 int opt_ind, ch;
510 bool enter_protected_mode = false;
511 int nb_args;
512 char *endptr;
514 while ((ch = getopt_long(argc, argv, sopts, lopts, &opt_ind)) != -1) {
515 switch (ch) {
516 case 's':
517 ncpus = atoi(optarg);
518 break;
519 case 'p':
520 enter_protected_mode = true;
521 break;
522 case 'm':
523 memory_size = strtoull(optarg, &endptr, 0);
524 switch (*endptr) {
525 case 'G': case 'g':
526 memory_size <<= 30;
527 break;
528 case '\0':
529 case 'M': case 'm':
530 memory_size <<= 20;
531 break;
532 case 'K': case 'k':
533 memory_size <<= 10;
534 break;
535 default:
536 fprintf(stderr,
537 "Unrecongized memory suffix: %c\n",
538 *endptr);
539 exit(1);
541 if (memory_size == 0) {
542 fprintf(stderr,
543 "Invalid memory size: 0\n");
544 exit(1);
546 break;
547 case 'h':
548 usage(argv[0]);
549 exit(0);
550 case '?':
551 default:
552 fprintf(stderr,
553 "Try `%s --help' for more information.\n",
554 argv[0]);
555 exit(1);
559 nb_args = argc - optind;
560 if (nb_args < 1 || nb_args > 2) {
561 fprintf(stderr,
562 "Incorrect number of arguments.\n"
563 "Try `%s --help' for more information.\n",
564 argv[0]);
565 exit(1);
568 signal(IPI_SIGNAL, sig_ignore);
570 vcpus = calloc(ncpus, sizeof *vcpus);
571 if (!vcpus) {
572 fprintf(stderr, "calloc failed\n");
573 return 1;
576 kvm = kvm_init(&test_callbacks, 0);
577 if (!kvm) {
578 fprintf(stderr, "kvm_init failed\n");
579 return 1;
581 if (kvm_create(kvm, memory_size, &vm_mem) < 0) {
582 kvm_finalize(kvm);
583 fprintf(stderr, "kvm_create failed\n");
584 return 1;
587 vm_mem = kvm_create_phys_mem(kvm, 0, memory_size, 0, 1);
589 if (enter_protected_mode)
590 enter_32(kvm);
591 else
592 load_file(vm_mem + 0xf0000, argv[optind]);
594 if (nb_args > 1)
595 load_file(vm_mem + 0x100000, argv[optind + 1]);
597 apic_init();
598 misc_init();
600 io_table_register(&pio_table, IRQCHIP_IO_BASE, 0x20, irqchip_io, NULL);
602 sem_init(&init_sem, 0, 0);
603 for (i = 0; i < ncpus; ++i)
604 start_vcpu(i);
605 for (i = 0; i < ncpus; ++i)
606 sem_wait(&init_sem);
608 kvm_run(kvm, 0, &vcpus[0]);
610 return 0;