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 |