Device-assignment: free device if hotplug fails
[qemu-kvm/fedora.git] / kvm / user / main.c
blob55639b51cb178def383737787306e5a9b84b20d5
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);
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 static int test_debug(void *opaque, void *vcpu)
303 printf("test_debug\n");
304 return 0;
307 static int test_halt(void *opaque, int vcpu)
309 int n;
311 sigwait(&ipi_sigmask, &n);
312 kvm_inject_irq(kvm, vcpus[vcpu].id, apic_ipi_vector);
313 return 0;
316 static int test_io_window(void *opaque)
318 return 0;
321 static int test_try_push_interrupts(void *opaque)
323 return 0;
326 static void test_push_nmi(void *opaque)
330 static void test_post_kvm_run(void *opaque, void *vcpu)
334 static int test_pre_kvm_run(void *opaque, void *vcpu)
336 return 0;
339 static int test_mem_read(void *opaque, uint64_t addr, uint8_t *data, int len)
341 if (addr < IORAM_BASE_PHYS || addr + len > IORAM_BASE_PHYS + IORAM_LEN)
342 return 1;
343 memcpy(data, ioram + addr - IORAM_BASE_PHYS, len);
344 return 0;
347 static int test_mem_write(void *opaque, uint64_t addr, uint8_t *data, int len)
349 if (addr < IORAM_BASE_PHYS || addr + len > IORAM_BASE_PHYS + IORAM_LEN)
350 return 1;
351 memcpy(ioram + addr - IORAM_BASE_PHYS, data, len);
352 return 0;
355 static int test_shutdown(void *opaque, void *env)
357 printf("shutdown\n");
358 kvm_show_regs(kvm, 0);
359 exit(1);
360 return 1;
363 static struct kvm_callbacks test_callbacks = {
364 .inb = test_inb,
365 .inw = test_inw,
366 .inl = test_inl,
367 .outb = test_outb,
368 .outw = test_outw,
369 .outl = test_outl,
370 .mmio_read = test_mem_read,
371 .mmio_write = test_mem_write,
372 .debug = test_debug,
373 .halt = test_halt,
374 .io_window = test_io_window,
375 .try_push_interrupts = test_try_push_interrupts,
376 .push_nmi = test_push_nmi,
377 .post_kvm_run = test_post_kvm_run,
378 .pre_kvm_run = test_pre_kvm_run,
379 .shutdown = test_shutdown,
382 static void load_file(void *mem, const char *fname)
384 int r;
385 int fd;
387 fd = open(fname, O_RDONLY);
388 if (fd == -1) {
389 perror("open");
390 exit(1);
392 while ((r = read(fd, mem, 4096)) != -1 && r != 0)
393 mem += r;
394 if (r == -1) {
395 perror("read");
396 exit(1);
400 static void enter_32(kvm_context_t kvm)
402 struct kvm_regs regs = {
403 .rsp = 0x80000, /* 512KB */
404 .rip = 0x100000, /* 1MB */
405 .rflags = 2,
407 struct kvm_sregs sregs = {
408 .cs = { 0, -1u, 8, 11, 1, 0, 1, 1, 0, 1, 0, 0 },
409 .ds = { 0, -1u, 16, 3, 1, 0, 1, 1, 0, 1, 0, 0 },
410 .es = { 0, -1u, 16, 3, 1, 0, 1, 1, 0, 1, 0, 0 },
411 .fs = { 0, -1u, 16, 3, 1, 0, 1, 1, 0, 1, 0, 0 },
412 .gs = { 0, -1u, 16, 3, 1, 0, 1, 1, 0, 1, 0, 0 },
413 .ss = { 0, -1u, 16, 3, 1, 0, 1, 1, 0, 1, 0, 0 },
415 .tr = { 0, 10000, 24, 11, 1, 0, 0, 0, 0, 0, 0, 0 },
416 .ldt = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
417 .gdt = { 0, 0 },
418 .idt = { 0, 0 },
419 .cr0 = 0x37,
420 .cr3 = 0,
421 .cr4 = 0,
422 .efer = 0,
423 .apic_base = 0,
424 .interrupt_bitmap = { 0 },
427 kvm_set_regs(kvm, 0, &regs);
428 kvm_set_sregs(kvm, 0, &sregs);
431 static void init_vcpu(int n)
433 sigemptyset(&ipi_sigmask);
434 sigaddset(&ipi_sigmask, IPI_SIGNAL);
435 sigprocmask(SIG_UNBLOCK, &ipi_sigmask, NULL);
436 sigprocmask(SIG_BLOCK, &ipi_sigmask, &kernel_sigmask);
437 vcpus[n].id = n;
438 vcpus[n].tid = gettid();
439 vcpu = n;
440 kvm_set_signal_mask(kvm, n, &kernel_sigmask);
441 sem_post(&init_sem);
444 static void *do_create_vcpu(void *_n)
446 int n = (long)_n;
447 struct kvm_regs regs;
449 kvm_create_vcpu(kvm, n);
450 init_vcpu(n);
451 sem_wait(&vcpus[n].sipi_sem);
452 kvm_get_regs(kvm, n, &regs);
453 regs.rip = apic_sipi_addr;
454 kvm_set_regs(kvm, n, &regs);
455 kvm_run(kvm, n, &vcpus[n]);
456 return NULL;
459 static void start_vcpu(int n)
461 pthread_t thread;
463 sem_init(&vcpus[n].sipi_sem, 0, 0);
464 pthread_create(&thread, NULL, do_create_vcpu, (void *)(long)n);
467 static void usage(const char *progname)
469 fprintf(stderr,
470 "Usage: %s [OPTIONS] [bootstrap] flatfile\n"
471 "KVM test harness.\n"
472 "\n"
473 " -s, --smp=NUM create a VM with NUM virtual CPUs\n"
474 " -p, --protected-mode start VM in protected mode\n"
475 " -m, --memory=NUM[GMKB] allocate NUM memory for virtual machine. A suffix\n"
476 " can be used to change the unit (default: `M')\n"
477 " -h, --help display this help screen and exit\n"
478 "\n"
479 "Report bugs to <kvm-devel@lists.sourceforge.net>.\n"
480 , progname);
483 static void sig_ignore(int sig)
485 write(1, "boo\n", 4);
488 int main(int argc, char **argv)
490 void *vm_mem;
491 int i;
492 const char *sopts = "s:phm:";
493 struct option lopts[] = {
494 { "smp", 1, 0, 's' },
495 { "protected-mode", 0, 0, 'p' },
496 { "memory", 1, 0, 'm' },
497 { "help", 0, 0, 'h' },
498 { 0 },
500 int opt_ind, ch;
501 bool enter_protected_mode = false;
502 int nb_args;
503 char *endptr;
505 while ((ch = getopt_long(argc, argv, sopts, lopts, &opt_ind)) != -1) {
506 switch (ch) {
507 case 's':
508 ncpus = atoi(optarg);
509 break;
510 case 'p':
511 enter_protected_mode = true;
512 break;
513 case 'm':
514 memory_size = strtoull(optarg, &endptr, 0);
515 switch (*endptr) {
516 case 'G': case 'g':
517 memory_size <<= 30;
518 break;
519 case '\0':
520 case 'M': case 'm':
521 memory_size <<= 20;
522 break;
523 case 'K': case 'k':
524 memory_size <<= 10;
525 break;
526 default:
527 fprintf(stderr,
528 "Unrecongized memory suffix: %c\n",
529 *endptr);
530 exit(1);
532 if (memory_size == 0) {
533 fprintf(stderr,
534 "Invalid memory size: 0\n");
535 exit(1);
537 break;
538 case 'h':
539 usage(argv[0]);
540 exit(0);
541 case '?':
542 default:
543 fprintf(stderr,
544 "Try `%s --help' for more information.\n",
545 argv[0]);
546 exit(1);
550 nb_args = argc - optind;
551 if (nb_args < 1 || nb_args > 2) {
552 fprintf(stderr,
553 "Incorrect number of arguments.\n"
554 "Try `%s --help' for more information.\n",
555 argv[0]);
556 exit(1);
559 signal(IPI_SIGNAL, sig_ignore);
561 vcpus = calloc(ncpus, sizeof *vcpus);
562 if (!vcpus) {
563 fprintf(stderr, "calloc failed\n");
564 return 1;
567 kvm = kvm_init(&test_callbacks, 0);
568 if (!kvm) {
569 fprintf(stderr, "kvm_init failed\n");
570 return 1;
572 if (kvm_create(kvm, memory_size, &vm_mem) < 0) {
573 kvm_finalize(kvm);
574 fprintf(stderr, "kvm_create failed\n");
575 return 1;
578 vm_mem = kvm_create_phys_mem(kvm, 0, memory_size, 0, 1);
580 if (enter_protected_mode)
581 enter_32(kvm);
582 else
583 load_file(vm_mem + 0xf0000, argv[optind]);
585 if (nb_args > 1)
586 load_file(vm_mem + 0x100000, argv[optind + 1]);
588 apic_init();
589 misc_init();
591 io_table_register(&pio_table, IRQCHIP_IO_BASE, 0x20, irqchip_io, NULL);
593 sem_init(&init_sem, 0, 0);
594 for (i = 0; i < ncpus; ++i)
595 start_vcpu(i);
596 for (i = 0; i < ncpus; ++i)
597 sem_wait(&init_sem);
599 kvm_run(kvm, 0, &vcpus[0]);
601 return 0;