Subject: [PATCH 2/3] Add PowerPC kvmctl harness and fix building the testcases From: Hollis Blanchard <[EMAIL PROTECTED]> From: Christian Ehrhardt <[EMAIL PROTECTED]>
These patches get the kvm-userspace/user/ test harness building and somewhat working for PowerPC. For the moment it's just a simply binary loader (hence the need for objcopy), but in the future it should be easy to add an ELF or even uImage loader. This patch version removed x86 pio,io_table,misc_io code and some unused defines according to avi's comments. Signed-off-by: Hollis Blanchard <[EMAIL PROTECTED]> Signed-off-by: Christian Ehrhardt <[EMAIL PROTECTED]> --- b/user/main-ppc.c | 355 ++++++++++++++++++++++++++++++++++++++++++++++++ user/config-powerpc.mak | 30 ++-- 2 files changed, 376 insertions(+), 9 deletions(-) diff -r f5bbfeaedb2c user/config-powerpc.mak --- a/user/config-powerpc.mak Wed Jan 09 13:35:00 2008 +0100 +++ b/user/config-powerpc.mak Wed Jan 09 14:38:20 2008 +0100 @@ -1,14 +1,26 @@ TEST_DIR=test/powerpc -TEST_DIR=test/powerpc CFLAGS += -m32 CFLAGS += -D__powerpc__ CFLAGS += -I $(KERNELDIR)/include +# for some reaons binutils hates tlbsx unless we say we're 405 :( +CFLAGS += -Wa,-mregnames,-m405 -tests= $(TEST_DIR)/io.S \ - $(TEST_DIR)/spin.S \ - $(TEST_DIR)/sprg.S \ - $(TEST_DIR)/44x/tlbsx.S \ - $(TEST_DIR)/44x/tlbwe_16KB.S \ - $(TEST_DIR)/44x/tlbwe_hole.S \ - $(TEST_DIR)/44x/tlbwe.S +%.bin: %.o + $(OBJCOPY) -O binary $^ $@ -kvmctl_objs = main.o ../libkvm/libkvm.a +testobjs := \ + io.bin \ + spin.bin \ + sprg.bin \ + 44x/tlbsx.bin \ + 44x/tlbwe_16KB.bin \ + 44x/tlbwe_hole.bin \ + 44x/tlbwe.bin + +tests := $(addprefix test/powerpc/, $(testobjs)) + +all: kvmctl $(tests) + +kvmctl_objs = main-ppc.o ../libkvm/libkvm.a + +arch_clean: + rm -f $(tests) diff -r f5bbfeaedb2c user/main-ppc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/user/main-ppc.c Wed Jan 09 14:38:20 2008 +0100 @@ -0,0 +1,315 @@ +/* + * 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 + * Copyright IBM Corp. 2008 + * + * Authors: + * + * Avi Kivity <[EMAIL PROTECTED]> + * Yaniv Kamay <[EMAIL PROTECTED]> + * Hollis Blanchard <[EMAIL PROTECTED]> + * + * This work is licensed under the GNU LGPL license, version 2. + */ + +#define _GNU_SOURCE + +#include <libkvm.h> + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <semaphore.h> +#include <sys/types.h> +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <pthread.h> +#include <sys/syscall.h> +#include <linux/unistd.h> +#include <getopt.h> +#include <stdbool.h> +#include <inttypes.h> + +static int gettid(void) +{ + return syscall(__NR_gettid); +} + +kvm_context_t kvm; + +#define IPI_SIGNAL (SIGRTMIN + 4) + +static int ncpus = 1; +static sem_t init_sem; +static __thread int vcpu; +static sigset_t kernel_sigmask; +static sigset_t ipi_sigmask; +static uint64_t memory_size = 128 * 1024 * 1024; + +struct vcpu_info { + pid_t tid; +}; + +struct vcpu_info *vcpus; + +static int test_debug(void *opaque, int vcpu) +{ + printf("test_debug\n"); + return 0; +} + +static int test_halt(void *opaque, int vcpu) +{ + int n; + + sigwait(&ipi_sigmask, &n); + return 0; +} + +static int test_io_window(void *opaque) +{ + return 0; +} + +static int test_try_push_interrupts(void *opaque) +{ + return 0; +} + +static void test_post_kvm_run(void *opaque, int vcpu) +{ +} + +static int test_pre_kvm_run(void *opaque, int vcpu) +{ + return 0; +} + +static int test_mem_read(void *opaque, uint64_t addr, uint8_t *data, int len) +{ + printf("%s: addr %"PRIx64" len %d\n", __func__, addr, len); + memset(data, 0, len); + return 0; +} + +static int test_mem_write(void *opaque, uint64_t addr, uint8_t *data, int len) +{ + printf("%s: addr %"PRIx64" len %d data %"PRIx64"\n", + __func__, addr, len, *(uint64_t *)data); + return 0; +} + +static struct kvm_callbacks test_callbacks = { + .mmio_read = test_mem_read, + .mmio_write = test_mem_write, + .debug = test_debug, + .halt = test_halt, + .io_window = test_io_window, + .try_push_interrupts = test_try_push_interrupts, + .post_kvm_run = test_post_kvm_run, + .pre_kvm_run = test_pre_kvm_run, +}; + +static unsigned long load_file(void *mem, const char *fname, int inval_icache) +{ + int r; + int fd; + unsigned long bytes = 0; + + fd = open(fname, O_RDONLY); + if (fd == -1) { + perror("open"); + exit(1); + } + + while ((r = read(fd, mem, 4096)) != -1 && r != 0) { + mem += r; + bytes += r; + } + + if (r == -1) { + perror("read"); + exit(1); + } + + return bytes; +} + +#define ICACHE_LINE_SIZE 32 + +void sync_caches(void *mem, unsigned long len) +{ + unsigned long i; + + for (i = 0; i < len; i += ICACHE_LINE_SIZE) + asm volatile ("dcbst %0, %1" : : "g"(mem), "r"(i)); + asm volatile ("sync"); + for (i = 0; i < len; i += ICACHE_LINE_SIZE) + asm volatile ("icbi %0, %1" : : "g"(mem), "r"(i)); + asm volatile ("sync; isync"); +} + +static void init_vcpu(int n, unsigned long entry) +{ + struct kvm_regs regs = { + .pc = entry, + }; + + kvm_set_regs(kvm, 0, ®s); + + sigemptyset(&ipi_sigmask); + sigaddset(&ipi_sigmask, IPI_SIGNAL); + sigprocmask(SIG_UNBLOCK, &ipi_sigmask, NULL); + sigprocmask(SIG_BLOCK, &ipi_sigmask, &kernel_sigmask); + 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; + + kvm_create_vcpu(kvm, n); + init_vcpu(n, 0x0); + kvm_run(kvm, n); + return NULL; +} + +static void start_vcpu(int n) +{ + pthread_t thread; + + 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" +" -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 <kvm-devel@lists.sourceforge.net>.\n" + , progname); +} + +static void sig_ignore(int sig) +{ + write(1, "boo\n", 4); +} + +int main(int argc, char **argv) +{ + void *vm_mem; + unsigned long len; + int i; + const char *sopts = "s:phm:"; + struct option lopts[] = { + { "smp", 1, 0, 's' }, + { "memory", 1, 0, 'm' }, + { "help", 0, 0, 'h' }, + { 0 }, + }; + int opt_ind, ch; + 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 '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); + + len = load_file(vm_mem, argv[optind], 1); + sync_caches(vm_mem, len); + + sem_init(&init_sem, 0, 0); + init_vcpu(0, 0x0); + for (i = 1; i < ncpus; ++i) + start_vcpu(i); + for (i = 0; i < ncpus; ++i) + sem_wait(&init_sem); + + kvm_run(kvm, 0); + + return 0; +} ------------------------------------------------------------------------- Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace _______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel