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, &regs);
+
+       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

Reply via email to