From: Alexander G. <ag...@su...> - 2010-03-06 10:44:51
|
Recently I started to work on porting KVM to PowerPC Server class CPUs and it turned out that Qemu just didn't work as well with Mac OS X yet. So I made MOL work with KVM. For a more verbose description of what this exactly means, check out patch 3/3. To actually make use of this patch set, please use the latest KVM kernel git plus my patches on kvm-ppc@vger, as long as they're not applied yet. Screenshot: http://alex.csgraf.de/mol/kvm.png Alexander Graf (3): Compile fix for snprintf Make CPU virtualization mode selectable Add KVM backend support (PPC64 host support) config/Kconfig-common | 16 ++- config/configure.in | 2 +- scripts/modload | 2 + src/Makefile | 2 +- src/booter/macho.c | 11 ++ src/cpu/Makefile | 6 +- src/cpu/kvm/.kvm.c.swo | Bin 0 -> 4096 bytes src/cpu/kvm/.kvm.h.swp | Bin 0 -> 12288 bytes src/cpu/kvm/Makefile | 9 ++ src/cpu/kvm/kvm.c | 239 +++++++++++++++++++++++++++++++ src/cpu/kvm/kvm.h | 17 +++ src/cpu/kvm/misc.c | 362 ++++++++++++++++++++++++++++++++++++++++++++++++ src/cpu/mainloop.c | 12 ++ src/molelf/keyremap.c | 2 +- 14 files changed, 672 insertions(+), 8 deletions(-) create mode 100644 src/cpu/kvm/.kvm.c.swo create mode 100644 src/cpu/kvm/.kvm.h.swp create mode 100644 src/cpu/kvm/Makefile create mode 100644 src/cpu/kvm/kvm.c create mode 100644 src/cpu/kvm/kvm.h create mode 100644 src/cpu/kvm/misc.c |
From: Alexander G. <ag...@su...> - 2010-03-06 10:44:50
|
We want to give the user the choice between KVM and MOL kernel modules, so let's make the config option selectable and fix all references to it to actually reference to the config option. Signed-off-by: Alexander Graf <ag...@su...> --- config/Kconfig-common | 11 ++++++++--- src/Makefile | 2 +- src/cpu/Makefile | 4 ++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/config/Kconfig-common b/config/Kconfig-common index 8944dba..0993b1e 100644 --- a/config/Kconfig-common +++ b/config/Kconfig-common @@ -1,11 +1,16 @@ mainmenu "Mac-on-Linux Configuration" menu "Machine Specific Build Targets" -config PPC - bool - default y + +choice + prompt "Virtualization type" + default PPC + +config MOL + bool "MOL kernel module" help No help yet. +endchoice #config MPC107 # bool "MPC107 board (Crescendo)" diff --git a/src/Makefile b/src/Makefile index c5bad18..2733edb 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,7 +1,7 @@ include ../config/Makefile.top -BUILD_MODS := y +BUILD_MODS := $(if $(CONFIG_MOL),y) NETMODS := $(CONFIG_TUN)$(CONFIG_SHEEP) NETDRIVER := $(if $(LINUX),$(if $(NETMODS),$(BUILD_MODS))) diff --git a/src/cpu/Makefile b/src/cpu/Makefile index a4bc0dd..3251973 100644 --- a/src/cpu/Makefile +++ b/src/cpu/Makefile @@ -2,7 +2,7 @@ include ../../config/Makefile.top SUBDIRS-$(MPC107) = mpc107 -SUBDIRS-$(PPC) = ppc +SUBDIRS-$(CONFIG_MOL) = ppc SUBDIRS-$(X86) = i386 XTARGETS = cpu @@ -10,7 +10,7 @@ XTARGETS = cpu cpu-OBJS = mainloop.o molcpu.o $(obj-y) obj-$(CONFIG_DEBUGGER) += breakpoints.o -obj-$(PPC) += ppc/libppc.a +obj-$(CONFIG_MOL) += ppc/libppc.a obj-$(X86) += i386/libi386.a obj-$(MPC107) += ppc/libmpc107.a -- 1.6.0.2 |
From: Alexander G. <ag...@su...> - 2010-03-06 10:44:51
|
While building the linker couldn't find snprintf in the keyboard map application. So let's just use sprintf - should work out too. Signed-off-by: Alexander Graf <ag...@su...> --- src/molelf/keyremap.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/molelf/keyremap.c b/src/molelf/keyremap.c index 2db3b95..325de9d 100644 --- a/src/molelf/keyremap.c +++ b/src/molelf/keyremap.c @@ -507,7 +507,7 @@ print_menu_( mtab_t *t, int offs, int active ) modified = 1; } tc.h = offs; - snprintf( buf, 200, "%s %-20s <0>%s \n", + sprintf( buf, "%s %-20s <0>%s \n", (t->cur == i)? active ? "<5>" : "<4>" : "<3>", m->text, modified ? "<0> Modified" : "" ); draw_str( buf ); -- 1.6.0.2 |
From: Alexander G. <ag...@su...> - 2010-03-06 10:44:53
|
The MOL kernel module was designed with PPC32 hosts and guests in mind. While that's all great when running on PPC32 hosts, it makes life really hard on PPC64 hosts, as the MOL kernel module doesn't work there. Furthermore it also never got upstreamed. So every new kernel revision might break it. Recently I implemented KVM for PowerPC64 though. So we now have a common virtualization framework inside the kernel that gives us easy virtualization access to PPC32 and PPC64 guest VMs. This patch implements a simple backend module to interact with KVM. That way KVM can be used to virtualize the CPU. Everything else still goes through MOL. With this patch applied and my recent patches to KVM (see the kvm-ppc ML archive) I'm happily running a 10.4.11 Mac OS X VM on a 970MP system. This should also enable G5 and PS3 hosts, though I haven't tried it out there yet. Please keep in mind that you need to run 32 bit userspace with a 64 bit kernel for this to work. MOL heavily relies on sizeof(guest GPR) == sizeof(void*) == sizeof(int) Screenshot: http://alex.csgraf.de/mol/kvm.png Signed-off-by: Alexander Graf <ag...@su...> --- config/Kconfig-common | 5 + config/configure.in | 2 +- scripts/modload | 2 + src/booter/macho.c | 11 ++ src/cpu/Makefile | 2 + src/cpu/kvm/.kvm.c.swo | Bin 0 -> 4096 bytes src/cpu/kvm/.kvm.h.swp | Bin 0 -> 12288 bytes src/cpu/kvm/Makefile | 9 ++ src/cpu/kvm/kvm.c | 239 +++++++++++++++++++++++++++++++ src/cpu/kvm/kvm.h | 17 +++ src/cpu/kvm/misc.c | 362 ++++++++++++++++++++++++++++++++++++++++++++++++ src/cpu/mainloop.c | 12 ++ 12 files changed, 660 insertions(+), 1 deletions(-) create mode 100644 src/cpu/kvm/.kvm.c.swo create mode 100644 src/cpu/kvm/.kvm.h.swp create mode 100644 src/cpu/kvm/Makefile create mode 100644 src/cpu/kvm/kvm.c create mode 100644 src/cpu/kvm/kvm.h create mode 100644 src/cpu/kvm/misc.c diff --git a/config/Kconfig-common b/config/Kconfig-common index 0993b1e..1c871c9 100644 --- a/config/Kconfig-common +++ b/config/Kconfig-common @@ -10,6 +10,11 @@ config MOL bool "MOL kernel module" help No help yet. + +config KVM + bool "KVM kernel module" + help + No help yet. endchoice #config MPC107 diff --git a/config/configure.in b/config/configure.in index 17b4a97..da26385 100644 --- a/config/configure.in +++ b/config/configure.in @@ -14,7 +14,7 @@ AC_CONFIG_HEADER(config.h:config.h.in) ###################################################################### # Die if we're trying to build on x86 ###################################################################### -test "$ARCH" != ppc && test "$ARCH" != osx && { +test "$ARCH" != ppc && "$ARCH" != ppc64 && test "$ARCH" != osx && { AC_MSG_ERROR([Sorry, MOL only supports PowerPC processors]) exit 1; } diff --git a/scripts/modload b/scripts/modload index 93c820b..0d43ffb 100755 --- a/scripts/modload +++ b/scripts/modload @@ -14,6 +14,8 @@ echo $2 | grep -q ^1 && unset _EXACT grep -q 198 /proc/misc && unset _SHEEP grep -q 200 /proc/misc && unset _TUN +[ -e /dev/kvm ] && exit 0 + LOADED=`/sbin/lsmod | sed -e 's/\(^\w*\).*/\1/g'` for x in $LOADED ; do [ $x = "mol" ] && unset _MOL diff --git a/src/booter/macho.c b/src/booter/macho.c index 5f29891..8d9d3e6 100644 --- a/src/booter/macho.c +++ b/src/booter/macho.c @@ -19,6 +19,9 @@ #include "mac_registers.h" #include "loader.h" +#ifdef CONFIG_KVM +#include "../cpu/kvm/kvm.h" +#endif static int is_macho( int fd ) @@ -90,6 +93,10 @@ read_thread( int fd ) if( read(fd, &th, sizeof(th)) != sizeof(th) ) fatal("reading macho thread\n"); +#ifdef CONFIG_KVM + kvm_regs_kvm2mol(); +#endif + for( i=0; i<32; i++ ) mregs->gpr[i] = th.gprs[i]; mregs->nip = th.srr0; @@ -99,6 +106,10 @@ read_thread( int fd ) mregs->ctr = th.ctr; /* mregs->vrsave = th.vrsave; */ mregs->msr = 0; + +#ifdef CONFIG_KVM + kvm_regs_mol2kvm(); +#endif } int diff --git a/src/cpu/Makefile b/src/cpu/Makefile index 3251973..5a89db9 100644 --- a/src/cpu/Makefile +++ b/src/cpu/Makefile @@ -4,6 +4,7 @@ include ../../config/Makefile.top SUBDIRS-$(MPC107) = mpc107 SUBDIRS-$(CONFIG_MOL) = ppc SUBDIRS-$(X86) = i386 +SUBDIRS-$(CONFIG_KVM) = kvm XTARGETS = cpu #CFLAGS += -msoft-float @@ -13,6 +14,7 @@ obj-$(CONFIG_DEBUGGER) += breakpoints.o obj-$(CONFIG_MOL) += ppc/libppc.a obj-$(X86) += i386/libi386.a obj-$(MPC107) += ppc/libmpc107.a +obj-$(CONFIG_KVM) += kvm/libkvm.a include $(rules)/Rules.make diff --git a/src/cpu/kvm/.kvm.c.swo b/src/cpu/kvm/.kvm.c.swo new file mode 100644 index 0000000000000000000000000000000000000000..5de134ad29f859addc03866aab835323e2cc5053 GIT binary patch literal 4096 zcmYc?2=nw+FxN9;00IF9h9xqSytNeA8J2l4FeIiIC8mMI34ol+<c!o*0*Zjr`WgAT zsrq13^@~z-QWJ|)^>g!c^oxs<^^*%q^|Q-zL0B)Duu-EbMnhmU1V{;i(vmb?3tk2T vLnC7aMI~h+;ZRa^kE$IFfzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c1|a|dMd%zX literal 0 HcmV?d00001 diff --git a/src/cpu/kvm/.kvm.h.swp b/src/cpu/kvm/.kvm.h.swp new file mode 100644 index 0000000000000000000000000000000000000000..3b4956d851892e859f648b3062d734d40e6dbaa6 GIT binary patch literal 12288 zcmeI2KW@}O6vii16ba$a1x!M*tiTRS0a7YDB18%8$o9UqM|j3&X1w5>00bvU8Y(Wp z6*vP87vL7~JiDtXOORQKCg`*DS)(`Kd-LAUoi*9P%cJMfqj)0txh}-J?T^o%e7Gt; zKNTV^Y&z@X15efECDDM1x0ABgl!U5@rHWEViLR@}**wXcHhDGIz2b7X6dWJ`0-F$M z{p|kZ9dYnr@-Vu+w}122i%qiO1pyEM0T2KI5C8!X009vA4+u0~Y>A&?kSqMY!P;6X z1n~j^5C8!X009sH0T2KI5C8!X009uV`~;?HKf}%*>o{Bh2>$?fzYDSZh4r4LSVydw zwJpT8AFQvePpph}hqcf7-&m)tlSQq|&ju5K00@8p2!H?xfB*=900@A<zac<xJy{bu zZ`<5QeD7J>)<omw;!udCL7By_BQIx}bn2K!eJtxdIoXhvwtjOj>O&=|qV#tU*Ha5l zohs|QzCfi6xsfYt>!YzH@6)WJMSfU@6QnXS9Kglat4*nrt>bew>DqSEQlV-yS`MOh zD|Om5$`sL9|K3YK#^%}cT1^*>sBn@mjZc`<sE?kVaNfiF6ZWlnRxn%Rtttv0LfO}U v@C-YYQGPA?d=slihnhUwUo|-A3-MCbxv#><_Fco@D30R`ociy47Z>{lIb0T@ literal 0 HcmV?d00001 diff --git a/src/cpu/kvm/Makefile b/src/cpu/kvm/Makefile new file mode 100644 index 0000000..5234749 --- /dev/null +++ b/src/cpu/kvm/Makefile @@ -0,0 +1,9 @@ + +include ../../../config/Makefile.top + +XTARGETS = kvm + +kvm-OBJS = $(obj-y) +obj-y += misc.o kvm.o + +include $(rules)/Rules.make diff --git a/src/cpu/kvm/kvm.c b/src/cpu/kvm/kvm.c new file mode 100644 index 0000000..5da6f40 --- /dev/null +++ b/src/cpu/kvm/kvm.c @@ -0,0 +1,239 @@ +/* + * <kvm.c> + * + * Helper code to interface with the Kernel based Virtual Machine. + * + * Copyright (C) 2010 Alexander Graf <al...@cs...> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + */ + +#include "mol_config.h" +#include <sys/mman.h> +#include <sys/time.h> + +#include <unistd.h> +#include <dirent.h> +#include <sys/types.h> + +#include "wrapper.h" +#include "timer.h" +#include "memory.h" +#include "molcpu.h" +#include "mac_registers.h" + +#include <linux/kvm.h> +#include <stdarg.h> +#include "kvm.h" + +static int kvm_fd; +static int vm_fd; +static int vcpu_fd; +struct kvm_run *kvm_run; + +int kvm_init(void) +{ + long mmap_size; + struct kvm_enable_cap cap; + int r; + + kvm_fd = open("/dev/kvm", O_RDWR); + if (kvm_fd < 0) { + fprintf(stderr, "KVM: Couldn't open /dev/kvm\n"); + return -1; + } + + vm_fd = kvm_ioctl(KVM_CREATE_VM, 0); + if (vm_fd < 0) { + fprintf(stderr, "KVM: Couldn't create VM\n"); + return -1; + } + + vcpu_fd = kvm_vm_ioctl(KVM_CREATE_VCPU, 0); + if (vcpu_fd < 0) { + fprintf(stderr, "kvm_create_vcpu failed\n"); + return -1; + } + + cap.cap = KVM_CAP_PPC_OSI; + r = kvm_vcpu_ioctl(KVM_ENABLE_CAP, &cap); + if (r < 0) { + fprintf(stderr, "kvm_enable_cap failed\n"); + return -1; + } + + mmap_size = kvm_ioctl(KVM_GET_VCPU_MMAP_SIZE, 0); + if (mmap_size < 0) { + fprintf(stderr, "KVM_GET_VCPU_MMAP_SIZE failed\n"); + return -1; + } + + kvm_run = (struct kvm_run *)mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, + MAP_SHARED, vcpu_fd, 0); + if (kvm_run == MAP_FAILED) { + fprintf(stderr, "mmap'ing vcpu state failed\n"); + return -1; + } + + return 0; +} + +int kvm_ioctl(int type, ...) +{ + int ret; + void *arg; + va_list ap; + + va_start(ap, type); + arg = va_arg(ap, void *); + va_end(ap); + + ret = ioctl(kvm_fd, type, arg); + if (ret == -1) + ret = -errno; + + return ret; +} + +int kvm_vm_ioctl(int type, ...) +{ + int ret; + void *arg; + va_list ap; + + va_start(ap, type); + arg = va_arg(ap, void *); + va_end(ap); + + ret = ioctl(vm_fd, type, arg); + if (ret == -1) + ret = -errno; + + return ret; +} + +int kvm_vcpu_ioctl(int type, ...) +{ + int ret; + void *arg; + va_list ap; + + va_start(ap, type); + arg = va_arg(ap, void *); + va_end(ap); + + ret = ioctl(vcpu_fd, type, arg); + if (ret == -1) + ret = -errno; + + return ret; +} + +static int kvm_mem_slot = 0; + +int kvm_del_user_memory_region(struct mmu_mapping *m) +{ + printf("XXX KVM unmap %#08lx - %#08lx to %p flags %x\n", m->mbase, + m->mbase + m->size, m->lvbase, m->flags); + + return 0; +} + +int kvm_set_user_memory_region(struct mmu_mapping *m) +{ + struct kvm_userspace_memory_region mem; + + mem.slot = kvm_mem_slot++; + mem.guest_phys_addr = m->mbase; + mem.memory_size = m->size; + mem.userspace_addr = (unsigned long)m->lvbase; + mem.flags = 0; + + printf("KVM mapped %#08lx - %#08lx to %p flags %x\n", m->mbase, + m->mbase + m->size, m->lvbase, m->flags); + + return kvm_vm_ioctl(KVM_SET_USER_MEMORY_REGION, &mem); +} + +int kvm_untrigger_irq(void) +{ + unsigned irq = KVM_INTERRUPT_UNSET; + + kvm_vcpu_ioctl(KVM_INTERRUPT, &irq); + + return 0; +} + +int kvm_trigger_irq(void) +{ + unsigned irq = KVM_INTERRUPT_SET; + + kvm_vcpu_ioctl(KVM_INTERRUPT, &irq); + + return 0; +} + +static int fb_bytes_per_row; +static int fb_height; + +int kvm_set_fb_size(int bytes_per_row, int height) +{ + fb_bytes_per_row = bytes_per_row; + fb_height = height; + + return 0; +} + +int kvm_get_dirty_fb_lines(short *rettable, int table_size_in_bytes) +{ + rettable[0] = 0; // y + rettable[1] = fb_height - 1; // height + + return 1; +} + +void kvm_regs_kvm2mol(void) +{ + struct kvm_regs regs; + int i, ret; + + ret = kvm_vcpu_ioctl(KVM_GET_REGS, ®s); + if (ret < 0) + return; + + mregs->nip = regs.pc; + mregs->msr = regs.msr; + mregs->link = regs.lr; + mregs->cr = regs.cr; + mregs->ctr = regs.ctr; + mregs->xer = regs.xer; + + for (i = 0; i < 32; i++) + mregs->gpr[i] = regs.gpr[i]; +} + +void kvm_regs_mol2kvm(void) +{ + struct kvm_regs regs; + int i, ret; + + ret = kvm_vcpu_ioctl(KVM_GET_REGS, ®s); + if (ret < 0) + return; + + regs.pc = mregs->nip; + regs.msr = mregs->msr; + regs.lr = mregs->link; + regs.cr = mregs->cr; + regs.ctr = mregs->ctr; + regs.xer = mregs->xer; + + for (i = 0; i < 32; i++) + regs.gpr[i] = mregs->gpr[i]; + + ret = kvm_vcpu_ioctl(KVM_SET_REGS, ®s); + + return; +} diff --git a/src/cpu/kvm/kvm.h b/src/cpu/kvm/kvm.h new file mode 100644 index 0000000..7bc19e6 --- /dev/null +++ b/src/cpu/kvm/kvm.h @@ -0,0 +1,17 @@ +extern int kvm_ioctl(int type, ...); +extern int kvm_vm_ioctl(int type, ...); +extern int kvm_vcpu_ioctl(int type, ...); +extern void kvm_regs_kvm2mol(); +extern void kvm_regs_mol2kvm(); +extern int kvm_init(void); +extern int kvm_trigger_irq(void); +extern int kvm_untrigger_irq(void); +extern void kvm_regs_kvm2mol(void); +extern void kvm_regs_mol2kvm(void); +extern int kvm_set_user_memory_region(struct mmu_mapping *m); +extern int kvm_del_user_memory_region(struct mmu_mapping *m); + +extern int kvm_get_dirty_fb_lines(short *rettable, int table_size_in_bytes); +extern int kvm_set_fb_size(int bytes_per_row, int height); + +extern struct kvm_run *kvm_run; diff --git a/src/cpu/kvm/misc.c b/src/cpu/kvm/misc.c new file mode 100644 index 0000000..bdc0b2e --- /dev/null +++ b/src/cpu/kvm/misc.c @@ -0,0 +1,362 @@ +/* + * <misc.c> + * + * MOL glueing code to access the Kernel based Virtual Machine + * + * Copyright (C) 2010 Alexander Graf <al...@cs...> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + */ + +#include "mol_config.h" +#include <sys/mman.h> +#include <sys/time.h> + +#include <unistd.h> +#include <dirent.h> +#include <sys/types.h> +#include <signal.h> + +#include "wrapper.h" +#include "timer.h" +#include "memory.h" +#include "molcpu.h" +#include "mac_registers.h" +#include "rvec.h" +#include "drivers.h" +#include "res_manager.h" + +#include <linux/kvm.h> +#include <pthread.h> + +#include "kvm.h" + +extern priv_rvec_entry_t gRVECtable[NUM_RVECS]; + +int mol_ioctl( int cmd, int p1, int p2, int p3 ) +{ + switch(cmd) { + case MOL_IOCTL_SETUP_FBACCEL: + return kvm_set_fb_size( p2, p3 ); /* ppr, height */ + break; + case MOL_IOCTL_GET_DIRTY_FBLINES: + return kvm_get_dirty_fb_lines( (short*)p1, p2); + break; + case MOL_IOCTL_MMU_MAP: + if (p2) + return kvm_set_user_memory_region((struct mmu_mapping *)p1); + else + return kvm_del_user_memory_region((struct mmu_mapping *)p1); + break; + } + return 0; +} + +int mol_ioctl_simple( int cmd ) +{ + return 0; +} + + +void flush_icache_range( char *start, char *stop ) +{ +} + +void molcpu_arch_init( void ) +{ +} + +void molcpu_arch_cleanup( void ) +{ +} + +void wrapper_init( void ) +{ +} + +void wrapper_cleanup( void ) +{ +} + +int open_session( void ) +{ + int r; + + mregs = (mac_regs_t*)malloc(sizeof(*mregs)); + memset( mregs, 0, sizeof(mac_regs_t) ); + + r = kvm_init(); + if (r) { + fprintf(stderr, "KVM init failed\n"); + return r; + } + + return 0; +} + +static int __kvm_init(void) +{ + struct kvm_sregs sregs; + + memset(&sregs, 0, sizeof(sregs)); + + sregs.pvr = mregs->spr[S_PVR]; + if (kvm_vcpu_ioctl(KVM_SET_SREGS, &sregs)) { + fprintf(stderr, "KVM sregs failed\n"); + return -1; + } + + return 0; +} + +void close_session( void ) +{ +} + +static void alarm_handler(int signal, siginfo_t *info, void *raw_context) +{ +} + +static void *thread_alarm(void *opaque) +{ + pthread_t thread = (pthread_t)opaque; + + while(1) { + usleep(1000); + pthread_kill(thread, SIGALRM); + } + + return NULL; +} + +void molcpu_mainloop_prep( void ) +{ + if (__kvm_init()) { + fprintf(stderr, "KVM init failed\n"); + exit(1); + } + + /* No need for MOL specific accelerations */ + add_res("no_inst_replacements", "yes"); +} + +mol_kmod_info_t *get_mol_kmod_info( void ) +{ + static mol_kmod_info_t info; + static int once=0; + + if( !once ) { + memset( &info, 0, sizeof(info) ); + //_get_info( &info ); + } + return &info; +} + +static void kvm_do_mmio(void) +{ + unsigned long tmp; + + if (kvm_run->mmio.is_write) { + switch(kvm_run->mmio.len) { + case 1: + tmp = *(u8*)kvm_run->mmio.data; + break; + case 2: + tmp = *(u16*)kvm_run->mmio.data; + break; + case 4: + tmp = *(u32*)kvm_run->mmio.data; + break; + } + do_io_write(NULL, kvm_run->mmio.phys_addr, tmp, kvm_run->mmio.len); + } else { + do_io_read(NULL, kvm_run->mmio.phys_addr, kvm_run->mmio.len, &tmp); + switch(kvm_run->mmio.len) { + case 1: + *(u8*)kvm_run->mmio.data = tmp; + break; + case 2: + *(u16*)kvm_run->mmio.data = tmp; + break; + case 4: + *(u32*)kvm_run->mmio.data = tmp; + break; + } + } +} + +static void start_alarm(void) +{ + pthread_t alarm_thread; + struct sigaction sa; + + sa.sa_handler = 0; + sa.sa_sigaction = &alarm_handler; + sa.sa_flags = SA_SIGINFO; + sigemptyset(&sa.sa_mask); + sigaction(SIGALRM, &sa, NULL); + + pthread_create(&alarm_thread, NULL, thread_alarm, (void*)pthread_self()); +} + +extern int mainloop_interrupt( int dummy_rvec ); + +void molcpu_mainloop( void ) +{ + static int inited = 0; + + if (!inited) { + inited = 1; + kvm_regs_mol2kvm(); + start_alarm(); + } + + while (1) { + int r; + int (*osicall)(int); + + if (mregs->interrupt) { + if(mainloop_interrupt(0)) { + printf("mainloop_interrupt wants us to exit the main loop\n"); + return; + } + } + + mregs->in_virtual_mode = 1; + r = kvm_vcpu_ioctl(KVM_RUN, 0); + mregs->in_virtual_mode = 0; + + if (r == -EINTR || r == -EAGAIN) { + osicall = gRVECtable[RVEC_TIMER].rvec; + osicall(0); + continue; + } + + switch (kvm_run->exit_reason) { + case KVM_EXIT_MMIO: + kvm_do_mmio(); + break; + case KVM_EXIT_OSI: + { + __u64 *gprs = kvm_run->osi.gprs; + int i; + + for (i = 0; i < 32; i++) + mregs->gpr[i] = gprs[i]; + + osicall = gRVECtable[RVEC_OSI_SYSCALL].rvec; + osicall(0); + + for (i = 0; i < 32; i++) + gprs[i] = mregs->gpr[i]; + break; + } + default: + fprintf(stderr, "KVM: Unknown exit code: %d\n", + kvm_run->exit_reason); + exit(1); + break; + } + } +} + +void save_fpu_completely( struct mac_regs *mregs ) +{ +} + +void reload_tophalf_fpu( struct mac_regs *mregs ) +{ +} + +void shield_fpu( struct mac_regs *mregs ) +{ +} + +ulong get_cpu_frequency( void ) +{ + static ulong clockf = 0; + char buf[80], *p; + FILE *f; + + if( !clockf ) { + /* Open /proc/cpuinfo to get the clock */ + if( (f=fopen("/proc/cpuinfo", "ro")) ) { + while( !clockf && fgets(buf, sizeof(buf), f) ) + if( !strncmp("clock", buf, 5 ) && (p=strchr(buf,':')) ) + clockf = strtol( p+1, NULL, 10 ); + fclose(f); + } + + /* If /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq + * exists, read the cpu speed from there instead */ + if( (f=fopen("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", "ro")) ) { + if(fgets(buf, sizeof(buf), f) == 0) + clockf = strtol(buf, NULL, 10) / 1000; + + fclose(f); + } + + if( clockf < 30 || clockf > 4000 ) { + printm("Warning: Using hardcoded clock frequency (350 MHz)\n"); + clockf = 350; + } + clockf *= 1000000; + } + return clockf; +} + +/* Tries to read the bus frequency from /proc/device-tree/cpus/<CPU>@0/bus-frequency + * Returns the frequency or 0 on error + */ +ulong get_bus_frequency( void ) +{ + static ulong busf = 0; + int name_len; + char buf[80] = "/proc/device-tree/cpus/"; + FILE *f; + DIR *d; + struct dirent *procdir; + + if( !busf ) { + /* Open /proc/device-tree/cpus */ + d = opendir(buf); + if ( d == NULL ) { + printm ("Warning: Unable to open %s\n",buf); + return 0; + } + + /* Each directory is a cpu, find @0 */ + while ( (procdir = readdir(d)) != NULL ) { + name_len = strlen(procdir->d_name); + if ( name_len > 2 && + (procdir->d_name)[name_len - 1] == '0' && + (procdir->d_name)[name_len - 2] == '@') + break; + } + closedir(d); + + /* Open bus-frequency in that directory */ + if (procdir != NULL) { + strncat(buf, procdir->d_name, 79); + strncat(buf, "/bus-frequency", 79); + f = fopen(buf, "r"); + if ( f == NULL) { + printm ("Warning: Couldn't open the cpu device tree node!\n"); + return 0; + } + if (fread(&busf, 4, 1, f) != 1) { + printm ("Warning: Couldn't read from the cpu device tree node!\n"); + fclose(f); + return 0; + } + fclose(f); + } + else { + printm ("Warning: Couldn't find cpu in device tree!\n"); + return 0; + } + } + return busf; +} diff --git a/src/cpu/mainloop.c b/src/cpu/mainloop.c index 1d94cd6..941dfe2 100644 --- a/src/cpu/mainloop.c +++ b/src/cpu/mainloop.c @@ -33,6 +33,10 @@ #include "osi_calls.h" #endif +#ifdef CONFIG_KVM +#include "kvm/kvm.h" +#endif + /* gRVECtable is also accessed by mainloop.S */ priv_rvec_entry_t gRVECtable[NUM_RVECS]; @@ -160,12 +164,20 @@ static volatile int __cpu_irq_raise; static void set_cpu_irq_private( int raise ) { +#ifdef CONFIG_KVM + if( raise ) { + kvm_trigger_irq(); + } else { + kvm_untrigger_irq(); + } +#else if( raise ) { mregs->flag_bits |= fb_IRQPending; if( mregs->msr & MSR_EE ) irq_exception(); } else mregs->flag_bits &= ~fb_IRQPending; +#endif } void -- 1.6.0.2 |
From: didier <di...@gm...> - 2010-03-07 02:30:20
|
Hi, What are > src/cpu/kvm/.kvm.c.swo | Bin 0 -> 4096 bytes > src/cpu/kvm/.kvm.h.swp | Bin 0 -> 12288 bytes ? Didier |
From: Joseph J. <jo...@ge...> - 2010-03-07 03:00:47
|
didier wrote: > Hi, > > What are > > >> src/cpu/kvm/.kvm.c.swo | Bin 0 -> 4096 bytes >> src/cpu/kvm/.kvm.h.swp | Bin 0 -> 12288 bytes >> > ? > > Didier > They're just junk files, probably from VIM. I didn't add them to the repo. -Joe |
From: Alexander G. <ag...@su...> - 2010-03-07 09:55:04
|
On 07.03.2010, at 03:46, Joseph Jezak wrote: > didier wrote: >> Hi, >> >> What are >> >> >>> src/cpu/kvm/.kvm.c.swo | Bin 0 -> 4096 bytes >>> src/cpu/kvm/.kvm.h.swp | Bin 0 -> 12288 bytes >>> >> ? >> >> Didier >> > They're just junk files, probably from VIM. I didn't add them to the repo. Ugh - that's what you get for doing "git add src/cpu/kvm" while having files open. Thanks for not including them :-). Alex |
From: didier <di...@gm...> - 2010-03-07 20:52:33
|
Hi, On Sun, Mar 7, 2010 at 10:54 AM, Alexander Graf <ag...@su...> wrote: > > On 07.03.2010, at 03:46, Joseph Jezak wrote: > >> didier wrote: >>> Hi, >>> >>> What are >>> >>> >>>> src/cpu/kvm/.kvm.c.swo | Bin 0 -> 4096 bytes >>>> src/cpu/kvm/.kvm.h.swp | Bin 0 -> 12288 bytes >>>> >>> ? >>> >>> Didier >>> >> They're just junk files, probably from VIM. I didn't add them to the repo. > > Ugh - that's what you get for doing "git add src/cpu/kvm" while having files open. Thanks for not including them :-). Ok :) Is using some kind of runtime check rather than a compile time ifdef make sense? I'd allow one userland for both kernel module. Didier PS I'll try to run it on a G5 but currently I have none running Linux thus it may take sometime. |
From: Alexander G. <ag...@su...> - 2010-03-07 20:59:56
|
Am 07.03.2010 um 21:52 schrieb didier <di...@gm...>: > Hi, > > On Sun, Mar 7, 2010 at 10:54 AM, Alexander Graf <ag...@su...> wrote: >> >> On 07.03.2010, at 03:46, Joseph Jezak wrote: >> >>> didier wrote: >>>> Hi, >>>> >>>> What are >>>> >>>> >>>>> src/cpu/kvm/.kvm.c.swo | Bin 0 -> 4096 bytes >>>>> src/cpu/kvm/.kvm.h.swp | Bin 0 -> 12288 bytes >>>>> >>>> ? >>>> >>>> Didier >>>> >>> They're just junk files, probably from VIM. I didn't add them to >>> the repo. >> >> Ugh - that's what you get for doing "git add src/cpu/kvm" while >> having files open. Thanks for not including them :-). > Ok :) > > Is using some kind of runtime check rather than a compile time ifdef > make sense? It probably would. But then again I'd rather see ppc32 kvm host support and accel extension support, deprecating the mol kmod completely. By then there wouldn't be any need to use the mol kmod. > I'd allow one userland for both kernel module. > > Didier > > PS > I'll try to run it on a G5 but currently I have none running Linux > thus it may take sometime. Sure :). If you want to see it live, check out my kvm on ppc presentation at the Chemnitzer Linuxtage (next weekend)! Alex |
From: didier <di...@gm...> - 2010-03-11 22:50:14
|
Hi, On Sun, Mar 7, 2010 at 10:00 PM, Alexander Graf <ag...@su...> wrote: > >> >> Is using some kind of runtime check rather than a compile time ifdef >> make sense? > > It probably would. But then again I'd rather see ppc32 kvm host support and > accel extension support, deprecating the mol kmod completely. By then there > wouldn't be any need to use the mol kmod. Oh it's doable, how hard? I need a closer look at kvm. Didier |
From: Alexander G. <ag...@su...> - 2010-08-04 09:45:08
|
On 11.03.2010, at 23:50, didier wrote: > Hi, > > On Sun, Mar 7, 2010 at 10:00 PM, Alexander Graf <ag...@su...> wrote: >> >>> >>> Is using some kind of runtime check rather than a compile time ifdef >>> make sense? >> >> It probably would. But then again I'd rather see ppc32 kvm host support and >> accel extension support, deprecating the mol kmod completely. By then there >> wouldn't be any need to use the mol kmod. > Oh it's doable, how hard? I need a closer look at kvm. I forgot to update you guys on this. I got around to implement ppc32 host support myself in between and it's all upstream in the kvm.git tree. I also have a bunch of patches partially waiting to get accepted upstream and partially in my local tree still that speed up things by introducing a PV interface very similar to the MOL one. So until those are in, please don't expect MOL for KVM to be uber-fast :). Alex |
From: Alexander G. <ag...@su...> - 2010-03-11 22:57:11
|
On 11.03.2010, at 23:50, didier wrote: > Hi, > > On Sun, Mar 7, 2010 at 10:00 PM, Alexander Graf <ag...@su...> wrote: >> >>> >>> Is using some kind of runtime check rather than a compile time ifdef >>> make sense? >> >> It probably would. But then again I'd rather see ppc32 kvm host support and >> accel extension support, deprecating the mol kmod completely. By then there >> wouldn't be any need to use the mol kmod. > Oh it's doable, how hard? I need a closer look at kvm. For ppc32 host support the infrastructure is mostly there. What's left to do is some cleanup to build correctly, a mechanism to reserve host VSID space, guest entry/exit code and code to fill in pages in the host HTAB. To get accel support some registers need to get moved to a common page that the guest can request to get mapped into its physical address space. Both hypervisor and guest would then access that page, always both using the right values. The patching to use that page should be done inside the guest itself. All in all it shouldn't be hard - just needs to be done :-). For the PPC32 host support I also put up a proposal for Google Summer of Code: http://wiki.qemu.org/Google_Summer_of_Code_2010 Alex |
From: didier <di...@gm...> - 2010-04-01 09:44:12
|
Hi, On Thu, Mar 11, 2010 at 11:57 PM, Alexander Graf <ag...@su...> wrote: > For ppc32 host support the infrastructure is mostly there. What's left to > do is some cleanup to build correctly, a mechanism to reserve host VSID > space, guest entry/exit code and code to fill in pages in the host HTAB. > > To get accel support some registers need to get moved to a common page that > the guest can request to get mapped into its physical address space. Both > hypervisor and guest would then access that page, always both using the > right values. The patching to use that page should be done inside the guest > itself. > > All in all it shouldn't be hard - just needs to be done :-). > Is a git tree with your change available somewhere? > > For the PPC32 host support I also put up a proposal for Google Summer of > Code: http://wiki.qemu.org/Google_Summer_of_Code_2010 > > I'm a bit too old for this one. Didier |
From: Alexander G. <ag...@su...> - 2010-04-01 12:52:53
|
didier wrote: > Hi, > > On Thu, Mar 11, 2010 at 11:57 PM, Alexander Graf <ag...@su... > <mailto:ag...@su...>> wrote: > > For ppc32 host support the infrastructure is mostly there. What's > left to do is some cleanup to build correctly, a mechanism to > reserve host VSID space, guest entry/exit code and code to fill in > pages in the host HTAB. > > To get accel support some registers need to get moved to a common > page that the guest can request to get mapped into its physical > address space. Both hypervisor and guest would then access that > page, always both using the right values. The patching to use that > page should be done inside the guest itself. > > All in all it shouldn't be hard - just needs to be done :-). > > Is a git tree with your change available somewhere? Sure - just git clone git://git.kernel.org/pub/scm/virt/kvm/kvm.git :) Alex |