From patchwork Tue Apr 27 12:57:43 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naphtali Sprei X-Patchwork-Id: 95415 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o3RCvxe4022323 for ; Tue, 27 Apr 2010 12:57:59 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753510Ab0D0M5v (ORCPT ); Tue, 27 Apr 2010 08:57:51 -0400 Received: from mx1.redhat.com ([209.132.183.28]:15040 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752318Ab0D0M5s (ORCPT ); Tue, 27 Apr 2010 08:57:48 -0400 Received: from int-mx04.intmail.prod.int.phx2.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.17]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o3RCvmAc023972 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 27 Apr 2010 08:57:48 -0400 Received: from localhost.localdomain (dhcp-0-60.tlv.redhat.com [10.35.0.60]) by int-mx04.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o3RCvj9r016249 for ; Tue, 27 Apr 2010 08:57:47 -0400 From: Naphtali Sprei To: kvm@vger.kernel.org Subject: [qemu-kvm tests PATCH v2 1/3] qemu-kvm tests cleanup Date: Tue, 27 Apr 2010 15:57:43 +0300 Message-Id: <1272373065-3162-2-git-send-email-nsprei@redhat.com> In-Reply-To: <1272373065-3162-1-git-send-email-nsprei@redhat.com> References: <1272373065-3162-1-git-send-email-nsprei@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.17 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Tue, 27 Apr 2010 12:57:59 +0000 (UTC) diff --git a/kvm/user/README b/kvm/user/README new file mode 100644 index 0000000..6a83831 --- /dev/null +++ b/kvm/user/README @@ -0,0 +1,23 @@ +This directory contains sources for a kvm test suite. + +Tests for x86 architecture are run as kernel images for qemu that supports multiboot format. +Tests uses an infrastructure called from the bios code. The infrastructure initialize the system/cpu's, +switch to long-mode and calls the 'main' function of the individual test. +Tests uses a qemu's virtual test device, named testdev, for services like printing, exiting, query memory size etc. +See file testdev.txt for more details. + +To create the tests' images just type 'make' in this directory. +Tests' images created in ./test//*.flat + +An example of a test invocation: +qemu-system-x86_64 -device testdev,chardev=testlog -chardev file,id=testlog,path=msr.out -kernel ./test/x86/msr.flat +This invocation runs the msr test case. The test output is in file msr.out. + + + +Directory structure: +.: Makefile and config files for the tests +./test/lib: general services for the tests +./test/lib/: architecture dependent services for the tests +./test/: the sources of the tests and the created objects/images + diff --git a/kvm/user/balloon_ctl.c b/kvm/user/balloon_ctl.c deleted file mode 100755 index e65b08d..0000000 --- a/kvm/user/balloon_ctl.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This binary provides access to the guest's balloon driver - * module. - * - * Copyright (C) 2007 Qumranet - * - * Author: - * - * Dor Laor - * - * This work is licensed under the GNU LGPL license, version 2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define __user -#include - -#define PAGE_SIZE 4096ul - - -static int balloon_op(int *fd, int bytes) -{ - struct kvm_balloon_op bop; - int r; - - bop.npages = bytes/PAGE_SIZE; - r = ioctl(*fd, KVM_BALLOON_OP, &bop); - if (r == -1) - return -errno; - printf("Ballon handled %d pages successfully\n", bop.npages); - - return 0; -} - -static int balloon_init(int *fd) -{ - *fd = open("/dev/kvm_balloon", O_RDWR); - if (*fd == -1) { - perror("open /dev/kvm_balloon"); - return -1; - } - - return 0; -} - -int main(int argc, char *argv[]) -{ - int fd; - int r; - int bytes; - - if (argc != 3) { - perror("Please provide op=[i|d], bytes\n"); - return 1; - } - bytes = atoi(argv[2]); - - switch (*argv[1]) { - case 'i': - break; - case 'd': - bytes = -bytes; - break; - default: - perror("Wrong op param\n"); - return 1; - } - - if (balloon_init(&fd)) { - perror("balloon_init failed\n"); - return 1; - } - - if ((r = balloon_op(&fd, bytes))) { - perror("balloon_op failed\n"); - goto out; - } - -out: - close(fd); - - return r; -} - diff --git a/kvm/user/bootstrap.lds b/kvm/user/bootstrap.lds deleted file mode 100644 index fd0a4f8..0000000 --- a/kvm/user/bootstrap.lds +++ /dev/null @@ -1,15 +0,0 @@ -OUTPUT_FORMAT(binary) - -SECTIONS -{ - . = 0; - stext = .; - .text : { *(.init) *(.text) } - . = ALIGN(4K); - .data : { *(.data) } - . = ALIGN(16); - .bss : { *(.bss) } - . = ALIGN(4K); - edata = .; -} - diff --git a/kvm/user/config-x86-common.mak b/kvm/user/config-x86-common.mak index 63cca42..960741e 100644 --- a/kvm/user/config-x86-common.mak +++ b/kvm/user/config-x86-common.mak @@ -2,9 +2,7 @@ CFLAGS += -I../include/x86 -all: kvmtrace test_cases - -balloon_ctl: balloon_ctl.o +all: test_cases cflatobjs += \ test/lib/x86/io.o \ @@ -19,21 +17,17 @@ $(libcflat): CFLAGS += -ffreestanding -I test/lib CFLAGS += -m$(bits) FLATLIBS = test/lib/libcflat.a $(libgcc) -%.flat: %.o $(FLATLIBS) +%.flat: %.o $(FLATLIBS) flat.lds $(CC) $(CFLAGS) -nostdlib -o $@ -Wl,-T,flat.lds $^ $(FLATLIBS) -tests-common = $(TEST_DIR)/bootstrap \ - $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \ - $(TEST_DIR)/smptest.flat $(TEST_DIR)/port80.flat \ - $(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.flat +tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \ + $(TEST_DIR)/smptest.flat $(TEST_DIR)/port80.flat \ + $(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.flat test_cases: $(tests-common) $(tests) $(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I test/lib -I test/lib/x86 -$(TEST_DIR)/bootstrap: $(TEST_DIR)/bootstrap.o - $(CC) -nostdlib -o $@ -Wl,-T,bootstrap.lds $^ - $(TEST_DIR)/access.flat: $(cstart.o) $(TEST_DIR)/access.o $(TEST_DIR)/print.o $(TEST_DIR)/hypercall.flat: $(cstart.o) $(TEST_DIR)/hypercall.o $(TEST_DIR)/print.o @@ -43,8 +37,6 @@ $(TEST_DIR)/sieve.flat: $(cstart.o) $(TEST_DIR)/sieve.o \ $(TEST_DIR)/vmexit.flat: $(cstart.o) $(TEST_DIR)/vmexit.o -$(TEST_DIR)/test32.flat: $(TEST_DIR)/test32.o - $(TEST_DIR)/smptest.flat: $(cstart.o) $(TEST_DIR)/smptest.o $(TEST_DIR)/emulator.flat: $(cstart.o) $(TEST_DIR)/emulator.o \ @@ -62,16 +54,12 @@ $(TEST_DIR)/realmode.flat: $(TEST_DIR)/realmode.o $(TEST_DIR)/realmode.o: bits = 32 -$(TEST_DIR)/memtest1.flat: $(TEST_DIR)/memtest1.o - $(TEST_DIR)/stringio.flat: $(TEST_DIR)/stringio.o -$(TEST_DIR)/simple.flat: $(TEST_DIR)/simple.o - $(TEST_DIR)/msr.flat: $(cstart.o) $(TEST_DIR)/msr.o arch_clean: - $(RM) $(TEST_DIR)/bootstrap $(TEST_DIR)/*.o $(TEST_DIR)/*.flat \ + $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat \ $(TEST_DIR)/.*.d $(TEST_DIR)/lib/.*.d $(TEST_DIR)/lib/*.o -include $(TEST_DIR)/.*.d test/lib/.*.d test/lib/x86/.*.d diff --git a/kvm/user/config-x86_64.mak b/kvm/user/config-x86_64.mak index 97990bb..03c91f2 100644 --- a/kvm/user/config-x86_64.mak +++ b/kvm/user/config-x86_64.mak @@ -5,8 +5,7 @@ ldarch = elf64-x86-64 CFLAGS += -D__x86_64__ tests = $(TEST_DIR)/access.flat $(TEST_DIR)/sieve.flat \ - $(TEST_DIR)/simple.flat $(TEST_DIR)/stringio.flat \ - $(TEST_DIR)/memtest1.flat $(TEST_DIR)/emulator.flat \ - $(TEST_DIR)/hypercall.flat $(TEST_DIR)/apic.flat + $(TEST_DIR)/stringio.flat $(TEST_DIR)/emulator.flat \ + $(TEST_DIR)/hypercall.flat $(TEST_DIR)/apic.flat include config-x86-common.mak diff --git a/kvm/user/main.c b/kvm/user/main.c deleted file mode 100644 index 1530ae2..0000000 --- a/kvm/user/main.c +++ /dev/null @@ -1,611 +0,0 @@ -/* - * Kernel-based Virtual Machine test driver - * - * This test driver provides a simple way of testing kvm, without a full - * device model. - * - * Copyright (C) 2006 Qumranet - * - * Authors: - * - * Avi Kivity - * Yaniv Kamay - * - * This work is licensed under the GNU LGPL license, version 2. - */ - -#define _GNU_SOURCE - -#include -#include "test/lib/x86/fake-apic.h" -#include "test/x86/ioram.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iotable.h" - -static uint8_t ioram[IORAM_LEN]; - -static int gettid(void) -{ - return syscall(__NR_gettid); -} - -static int tkill(int pid, int sig) -{ - return syscall(__NR_tkill, pid, sig); -} - -kvm_context_t kvm; - -#define MAX_VCPUS 4 - -#define IPI_SIGNAL (SIGRTMIN + 4) - -static int ncpus = 1; -static sem_t init_sem; -static __thread int vcpu; -static int apic_ipi_vector = 0xff; -static sigset_t kernel_sigmask; -static sigset_t ipi_sigmask; -static uint64_t memory_size = 128 * 1024 * 1024; - -static struct io_table pio_table; - -struct vcpu_info { - int id; - pid_t tid; - sem_t sipi_sem; -}; - -struct vcpu_info *vcpus; - -static uint32_t apic_sipi_addr; - -static void apic_send_sipi(int vcpu) -{ - sem_post(&vcpus[vcpu].sipi_sem); -} - -static void apic_send_ipi(int vcpu) -{ - struct vcpu_info *v; - - if (vcpu < 0 || vcpu >= ncpus) - return; - v = &vcpus[vcpu]; - tkill(v->tid, IPI_SIGNAL); -} - -static int apic_io(void *opaque, int size, int is_write, - uint64_t addr, uint64_t *value) -{ - if (!is_write) - *value = -1u; - - switch (addr - APIC_BASE) { - case APIC_REG_NCPU: - if (!is_write) - *value = ncpus; - break; - case APIC_REG_ID: - if (!is_write) - *value = vcpu; - break; - case APIC_REG_SIPI_ADDR: - if (!is_write) - *value = apic_sipi_addr; - else - apic_sipi_addr = *value; - break; - case APIC_REG_SEND_SIPI: - if (is_write) - apic_send_sipi(*value); - break; - case APIC_REG_IPI_VECTOR: - if (!is_write) - *value = apic_ipi_vector; - else - apic_ipi_vector = *value; - break; - case APIC_REG_SEND_IPI: - if (is_write) - apic_send_ipi(*value); - break; - } - - return 0; -} - -static int apic_init(void) -{ - return io_table_register(&pio_table, APIC_BASE, - APIC_SIZE, apic_io, NULL); -} - -static int misc_io(void *opaque, int size, int is_write, - uint64_t addr, uint64_t *value) -{ - static int newline = 1; - - if (!is_write) - *value = -1; - - switch (addr) { - case 0xff: // irq injector - if (is_write) { - printf("injecting interrupt 0x%x\n", (uint8_t)*value); - kvm_inject_irq(kvm, 0, *value); - } - break; - case 0xf1: // serial - if (is_write) { - if (newline) - fputs("GUEST: ", stdout); - putchar(*value); - newline = *value == '\n'; - } - break; - case 0xd1: - if (!is_write) - *value = memory_size; - break; - case 0xf4: // exit - if (is_write) - exit(*value); - break; - } - - return 0; -} - -static int misc_init(void) -{ - int err; - - err = io_table_register(&pio_table, 0xff, 1, misc_io, NULL); - if (err < 0) - return err; - - err = io_table_register(&pio_table, 0xf1, 1, misc_io, NULL); - if (err < 0) - return err; - - err = io_table_register(&pio_table, 0xf4, 1, misc_io, NULL); - if (err < 0) - return err; - - return io_table_register(&pio_table, 0xd1, 1, misc_io, NULL); -} - -#define IRQCHIP_IO_BASE 0x2000 - -static int irqchip_io(void *opaque, int size, int is_write, - uint64_t addr, uint64_t *value) -{ - addr -= IRQCHIP_IO_BASE; - - if (is_write) { - kvm_set_irq_level(kvm, addr, *value, NULL); - } - return 0; -} - -static int test_inb(void *opaque, uint16_t addr, uint8_t *value) -{ - struct io_table_entry *entry; - - entry = io_table_lookup(&pio_table, addr); - if (entry) { - uint64_t val; - entry->handler(entry->opaque, 1, 0, addr, &val); - *value = val; - } else { - *value = -1; - printf("inb 0x%x\n", addr); - } - - return 0; -} - -static int test_inw(void *opaque, uint16_t addr, uint16_t *value) -{ - struct io_table_entry *entry; - - entry = io_table_lookup(&pio_table, addr); - if (entry) { - uint64_t val; - entry->handler(entry->opaque, 2, 0, addr, &val); - *value = val; - } else { - *value = -1; - printf("inw 0x%x\n", addr); - } - - return 0; -} - -static int test_inl(void *opaque, uint16_t addr, uint32_t *value) -{ - struct io_table_entry *entry; - - entry = io_table_lookup(&pio_table, addr); - if (entry) { - uint64_t val; - entry->handler(entry->opaque, 4, 0, addr, &val); - *value = val; - } else { - *value = -1; - printf("inl 0x%x\n", addr); - } - - return 0; -} - -static int test_outb(void *opaque, uint16_t addr, uint8_t value) -{ - struct io_table_entry *entry; - - entry = io_table_lookup(&pio_table, addr); - if (entry) { - uint64_t val = value; - entry->handler(entry->opaque, 1, 1, addr, &val); - } else - printf("outb $0x%x, 0x%x\n", value, addr); - - return 0; -} - -static int test_outw(void *opaque, uint16_t addr, uint16_t value) -{ - struct io_table_entry *entry; - - entry = io_table_lookup(&pio_table, addr); - if (entry) { - uint64_t val = value; - entry->handler(entry->opaque, 2, 1, addr, &val); - } else - printf("outw $0x%x, 0x%x\n", value, addr); - - return 0; -} - -static int test_outl(void *opaque, uint16_t addr, uint32_t value) -{ - struct io_table_entry *entry; - - entry = io_table_lookup(&pio_table, addr); - if (entry) { - uint64_t val = value; - entry->handler(entry->opaque, 4, 1, addr, &val); - } else - printf("outl $0x%x, 0x%x\n", value, addr); - - return 0; -} - -#ifdef KVM_CAP_SET_GUEST_DEBUG -static int test_debug(void *opaque, void *vcpu, - struct kvm_debug_exit_arch *arch_info) -{ - printf("test_debug\n"); - return 0; -} -#endif - -static int test_halt(void *opaque, int vcpu) -{ - int n; - - sigwait(&ipi_sigmask, &n); - kvm_inject_irq(kvm, vcpus[vcpu].id, apic_ipi_vector); - return 0; -} - -static int test_io_window(void *opaque) -{ - return 0; -} - -static int test_try_push_interrupts(void *opaque) -{ - return 0; -} - -#ifdef KVM_CAP_USER_NMI -static void test_push_nmi(void *opaque) -{ -} -#endif - -static void test_post_kvm_run(void *opaque, void *vcpu) -{ -} - -static int test_pre_kvm_run(void *opaque, void *vcpu) -{ - return 0; -} - -static int test_mem_read(void *opaque, uint64_t addr, uint8_t *data, int len) -{ - if (addr < IORAM_BASE_PHYS || addr + len > IORAM_BASE_PHYS + IORAM_LEN) - return 1; - memcpy(data, ioram + addr - IORAM_BASE_PHYS, len); - return 0; -} - -static int test_mem_write(void *opaque, uint64_t addr, uint8_t *data, int len) -{ - if (addr < IORAM_BASE_PHYS || addr + len > IORAM_BASE_PHYS + IORAM_LEN) - return 1; - memcpy(ioram + addr - IORAM_BASE_PHYS, data, len); - return 0; -} - -static int test_shutdown(void *opaque, void *env) -{ - printf("shutdown\n"); - kvm_show_regs(kvm, 0); - exit(1); - return 1; -} - -static struct kvm_callbacks test_callbacks = { - .inb = test_inb, - .inw = test_inw, - .inl = test_inl, - .outb = test_outb, - .outw = test_outw, - .outl = test_outl, - .mmio_read = test_mem_read, - .mmio_write = test_mem_write, -#ifdef KVM_CAP_SET_GUEST_DEBUG - .debug = test_debug, -#endif - .halt = test_halt, - .io_window = test_io_window, - .try_push_interrupts = test_try_push_interrupts, -#ifdef KVM_CAP_USER_NMI - .push_nmi = test_push_nmi, -#endif - .post_kvm_run = test_post_kvm_run, - .pre_kvm_run = test_pre_kvm_run, - .shutdown = test_shutdown, -}; - -static void load_file(void *mem, const char *fname) -{ - int r; - int fd; - - fd = open(fname, O_RDONLY); - if (fd == -1) { - perror("open"); - exit(1); - } - while ((r = read(fd, mem, 4096)) != -1 && r != 0) - mem += r; - if (r == -1) { - perror("read"); - exit(1); - } -} - -static void enter_32(kvm_context_t kvm) -{ - struct kvm_regs regs = { - .rsp = 0x80000, /* 512KB */ - .rip = 0x100000, /* 1MB */ - .rflags = 2, - }; - struct kvm_sregs sregs = { - .cs = { 0, -1u, 8, 11, 1, 0, 1, 1, 0, 1, 0, 0 }, - .ds = { 0, -1u, 16, 3, 1, 0, 1, 1, 0, 1, 0, 0 }, - .es = { 0, -1u, 16, 3, 1, 0, 1, 1, 0, 1, 0, 0 }, - .fs = { 0, -1u, 16, 3, 1, 0, 1, 1, 0, 1, 0, 0 }, - .gs = { 0, -1u, 16, 3, 1, 0, 1, 1, 0, 1, 0, 0 }, - .ss = { 0, -1u, 16, 3, 1, 0, 1, 1, 0, 1, 0, 0 }, - - .tr = { 0, 10000, 24, 11, 1, 0, 0, 0, 0, 0, 0, 0 }, - .ldt = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, - .gdt = { 0, 0 }, - .idt = { 0, 0 }, - .cr0 = 0x37, - .cr3 = 0, - .cr4 = 0, - .efer = 0, - .apic_base = 0, - .interrupt_bitmap = { 0 }, - }; - - kvm_set_regs(kvm, 0, ®s); - kvm_set_sregs(kvm, 0, &sregs); -} - -static void init_vcpu(int n) -{ - sigemptyset(&ipi_sigmask); - sigaddset(&ipi_sigmask, IPI_SIGNAL); - sigprocmask(SIG_UNBLOCK, &ipi_sigmask, NULL); - sigprocmask(SIG_BLOCK, &ipi_sigmask, &kernel_sigmask); - vcpus[n].id = n; - vcpus[n].tid = gettid(); - vcpu = n; - kvm_set_signal_mask(kvm, n, &kernel_sigmask); - sem_post(&init_sem); -} - -static void *do_create_vcpu(void *_n) -{ - int n = (long)_n; - struct kvm_regs regs; - - kvm_create_vcpu(kvm, n); - init_vcpu(n); - sem_wait(&vcpus[n].sipi_sem); - kvm_get_regs(kvm, n, ®s); - regs.rip = apic_sipi_addr; - kvm_set_regs(kvm, n, ®s); - kvm_run(kvm, n, &vcpus[n]); - return NULL; -} - -static void start_vcpu(int n) -{ - pthread_t thread; - - sem_init(&vcpus[n].sipi_sem, 0, 0); - pthread_create(&thread, NULL, do_create_vcpu, (void *)(long)n); -} - -static void usage(const char *progname) -{ - fprintf(stderr, -"Usage: %s [OPTIONS] [bootstrap] flatfile\n" -"KVM test harness.\n" -"\n" -" -s, --smp=NUM create a VM with NUM virtual CPUs\n" -" -p, --protected-mode start VM in protected mode\n" -" -m, --memory=NUM[GMKB] allocate NUM memory for virtual machine. A suffix\n" -" can be used to change the unit (default: `M')\n" -" -h, --help display this help screen and exit\n" -"\n" -"Report bugs to .\n" - , progname); -} - -static void sig_ignore(int sig) -{ - write(1, "boo\n", 4); -} - -int main(int argc, char **argv) -{ - void *vm_mem; - int i; - const char *sopts = "s:phm:"; - struct option lopts[] = { - { "smp", 1, 0, 's' }, - { "protected-mode", 0, 0, 'p' }, - { "memory", 1, 0, 'm' }, - { "help", 0, 0, 'h' }, - { 0 }, - }; - int opt_ind, ch; - bool enter_protected_mode = false; - int nb_args; - char *endptr; - - while ((ch = getopt_long(argc, argv, sopts, lopts, &opt_ind)) != -1) { - switch (ch) { - case 's': - ncpus = atoi(optarg); - break; - case 'p': - enter_protected_mode = true; - break; - case 'm': - memory_size = strtoull(optarg, &endptr, 0); - switch (*endptr) { - case 'G': case 'g': - memory_size <<= 30; - break; - case '\0': - case 'M': case 'm': - memory_size <<= 20; - break; - case 'K': case 'k': - memory_size <<= 10; - break; - default: - fprintf(stderr, - "Unrecongized memory suffix: %c\n", - *endptr); - exit(1); - } - if (memory_size == 0) { - fprintf(stderr, - "Invalid memory size: 0\n"); - exit(1); - } - break; - case 'h': - usage(argv[0]); - exit(0); - case '?': - default: - fprintf(stderr, - "Try `%s --help' for more information.\n", - argv[0]); - exit(1); - } - } - - nb_args = argc - optind; - if (nb_args < 1 || nb_args > 2) { - fprintf(stderr, - "Incorrect number of arguments.\n" - "Try `%s --help' for more information.\n", - argv[0]); - exit(1); - } - - signal(IPI_SIGNAL, sig_ignore); - - vcpus = calloc(ncpus, sizeof *vcpus); - if (!vcpus) { - fprintf(stderr, "calloc failed\n"); - return 1; - } - - kvm = kvm_init(&test_callbacks, 0); - if (!kvm) { - fprintf(stderr, "kvm_init failed\n"); - return 1; - } - if (kvm_create(kvm, memory_size, &vm_mem) < 0) { - kvm_finalize(kvm); - fprintf(stderr, "kvm_create failed\n"); - return 1; - } - - vm_mem = kvm_create_phys_mem(kvm, 0, memory_size, 0, 1); - - if (enter_protected_mode) - enter_32(kvm); - else - load_file(vm_mem + 0xf0000, argv[optind]); - - if (nb_args > 1) - load_file(vm_mem + 0x100000, argv[optind + 1]); - - apic_init(); - misc_init(); - - io_table_register(&pio_table, IRQCHIP_IO_BASE, 0x20, irqchip_io, NULL); - - sem_init(&init_sem, 0, 0); - for (i = 0; i < ncpus; ++i) - start_vcpu(i); - for (i = 0; i < ncpus; ++i) - sem_wait(&init_sem); - - kvm_run(kvm, 0, &vcpus[0]); - - return 0; -} diff --git a/kvm/user/test/x86/README b/kvm/user/test/x86/README new file mode 100644 index 0000000..e2ede5c --- /dev/null +++ b/kvm/user/test/x86/README @@ -0,0 +1,15 @@ +Tests in this directory and what they do: + +access: lots of page table related access (pte/pde) (read/write) +apic: enable x2apic, self ipi, ioapic intr, ioapic simultaneous +emulator: move to/from regs, cmps, push, pop, to/from cr8, smsw and lmsw +hypercall: intel and amd hypercall insn +msr: write to msr (only KERNEL_GS_BASE for now) +port80: lots of out to port 80 +realmode: goes back to realmode, shld, push/pop, mov immediate, cmp immediate, add immediate, + io, eflags instructions (clc, cli, etc.), jcc short, jcc near, call, long jmp, xchg +sieve: heavy memory access with no paging and with paging static and with paging vmalloc'ed +smptest: run smp_id() on every cpu and compares return value to number +stringio: outs forward and backward +tsc: write to tsc(0) and write to tsc(100000000000) and read it back +vmexit: long loops for each: cpuid, vmcall, mov_from_cr8, mov_to_cr8, inl_pmtimer, ipi, ipi+halt diff --git a/kvm/user/test/x86/bootstrap.S b/kvm/user/test/x86/bootstrap.S deleted file mode 100644 index e32fea9..0000000 --- a/kvm/user/test/x86/bootstrap.S +++ /dev/null @@ -1,137 +0,0 @@ -/* - * minimal bootstrap to set up flat 32-bit protected mode - */ - -#include "fake-apic.h" - -bstart = 0xf0000 - -.code16 - -stack_top = 0x1000 -cpu_up = 0x1000 -cpu_up_pmode = 0x1004 - -pmode_stack_start = 0x10000 -pmode_stack_shift = 16 -pmode_stack_size = (1 << pmode_stack_shift) - -ipi_vec = 0xf0 - -start: - mov $stack_top, %sp - call smp_init - - cs lidtl idt_desc - cs lgdtl gdt_desc - mov %cr0, %eax - or $1, %eax - mov %eax, %cr0 - ljmpl $8, $pmode + bstart - -smp_init: - mov $ipi_vec, %eax - mov $(APIC_BASE + APIC_REG_IPI_VECTOR), %dx - out %eax, %dx - movw $ap_switch_to_pmode, ipi_vec*4 - movw %cs, %ax - mov %ax, ipi_vec*4+2 - mov $sipi, %eax - mov $(APIC_BASE + APIC_REG_SIPI_ADDR), %dx - outl %eax, %dx - mov $(APIC_BASE + APIC_REG_NCPU), %dx - inl %dx, %eax - mov %eax, %ecx - mov $1, %esi -smp_loop: - cmp %esi, %ecx - jbe smp_done - mov %esi, %eax - mov $(APIC_BASE + APIC_REG_SEND_SIPI), %dx - outl %eax, %dx -wait_for_cpu: - cmp cpu_up, %esi - jne wait_for_cpu - mov %esi, %eax - mov $(APIC_BASE + APIC_REG_SEND_IPI), %dx - out %eax, %dx -wait_for_cpu_pmode: - cmp cpu_up_pmode, %esi - jne wait_for_cpu_pmode - - inc %esi - jmp smp_loop -smp_done: - ret - -sipi: - mov $(APIC_BASE + APIC_REG_ID), %dx - inl %dx, %eax - mov %eax, cpu_up - shl $12, %eax - addl $stack_top, %eax - movl %eax, %esp - sti - nop -1: hlt - jmp 1b - -ap_switch_to_pmode: - cs lidtl idt_desc - cs lgdtl gdt_desc - mov %cr0, %eax - or $1, %eax - mov %eax, %cr0 - ljmpl $8, $ap_pmode + bstart - -.code32 -ap_pmode: - mov $0x10, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - mov %ax, %ss - mov $(APIC_BASE + APIC_REG_ID), %dx - in %dx, %eax - mov %eax, cpu_up_pmode - shl $pmode_stack_shift, %eax - lea pmode_stack_start + pmode_stack_size(%eax), %esp - sti - nop -ap_pmode_wait: - hlt - jmp ap_pmode_wait - -pmode: - mov $0x10, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - mov %ax, %ss - mov $pmode_stack_start + pmode_stack_size, %esp - ljmp $8, $0x100000 - -.align 16 - -idt_desc: - .word 8*256-1 - .long 0 - -gdt_desc: - .word gdt_end - gdt - 1 - .long gdt + bstart - -.align 16 - -gdt: - .quad 0 - .quad 0x00cf9b000000ffff // flat 32-bit code segment - .quad 0x00cf93000000ffff // flat 32-bit data segment -gdt_end: - -. = 0xfff0 - .code16 - ljmp $0xf000, $start -.align 65536 diff --git a/kvm/user/test/x86/exit.c b/kvm/user/test/x86/exit.c deleted file mode 100644 index 8903621..0000000 --- a/kvm/user/test/x86/exit.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "runtime.h" - -void exit(unsigned code) -{ - asm volatile("out %al, %dx" : : "a"(code), "d"(0xf4)); - asm volatile("cli; hlt"); -} diff --git a/kvm/user/test/x86/memtest1.S b/kvm/user/test/x86/memtest1.S deleted file mode 100644 index 3821e86..0000000 --- a/kvm/user/test/x86/memtest1.S +++ /dev/null @@ -1,44 +0,0 @@ -.text - -start: - mov $0x1000,%r8 - mov $0x0a,%ecx - -init_page: - dec %ecx - jne no_io - mov $0x0,%al - out %al,$0x80 - mov $0x0a,%ecx - -no_io: - mov %r8,(%r8) - add $0x1000,%r8 - cmp $0x8000000,%r8 - jne init_page - mov $0x1000,%r8 - mov $0x0a,%ecx - -test_loop: - dec %ecx - jne no_io2 - mov $0x0,%al - out %al,$0x80 - mov $0x0a,%ecx - -no_io2: - mov (%r8),%r9 - cmp %r8,%r9 - jne err - add $0x1000,%r8 - cmp $0x8000000,%r8 - jne test_loop - mov $0x1000,%r8 - jmp test_loop - -err: - mov $0xffffffffffffffff,%r12 - mov $0xffffffffffffffff,%r13 - mov $0x0,%al - out %al,$0x80 - jmp err diff --git a/kvm/user/test/x86/runtime.h b/kvm/user/test/x86/runtime.h deleted file mode 100644 index 4b4c302..0000000 --- a/kvm/user/test/x86/runtime.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef H_RUNTIME -#define H_RUNTIME - -void exit(unsigned code) __attribute__((__noreturn__)); - -#endif diff --git a/kvm/user/test/x86/simple.S b/kvm/user/test/x86/simple.S deleted file mode 100644 index f3c844f..0000000 --- a/kvm/user/test/x86/simple.S +++ /dev/null @@ -1,13 +0,0 @@ - - .text - - mov $0, %al - mov $10000, %ebx -1: - mov %rbx, %rcx -2: - loop 2b - out %al, $0x80 - inc %al - add $10000, %rbx - jmp 1b diff --git a/kvm/user/test/x86/test32.S b/kvm/user/test/x86/test32.S deleted file mode 100644 index a2e0fd7..0000000 --- a/kvm/user/test/x86/test32.S +++ /dev/null @@ -1,8 +0,0 @@ -.code32 - -.text - -1: - mov $0x12, %al - out %al, $0x80 - jmp 1b diff --git a/kvm/user/testdev.txt b/kvm/user/testdev.txt new file mode 100644 index 0000000..ac436ef --- /dev/null +++ b/kvm/user/testdev.txt @@ -0,0 +1,14 @@ +This file describes the virtual device of qemu for supporting this test suite. + +Services supplied by the testdev device: + +serial output: write only, on io port 0xf1 +exit process: write only, on io port 0xf4, value used as exit code +ram size: read-only, on io port 0xd1, 4 bytes' size +irq line setting: write only, on io ports 0x2000 - 0x2018, value to set/clear +simple io: read/write, on io port 0xe0, 1/2/4 bytes + +Test device used a char device for actual output + + +