From mboxrd@z Thu Jan 1 00:00:00 1970 From: Anthony Liguori Subject: [PATCH 7/7] Allow KVM from a normal QEMU binary Date: Fri, 03 Nov 2006 00:35:15 -0600 Message-ID: <454AE323.8090309@cs.utexas.edu> References: <454AE007.5070905@cs.utexas.edu> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------050207090508020308020101" Return-path: To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org In-Reply-To: <454AE007.5070905-NZpS4cJIG2HvQtjrzfazuQ@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: kvm-devel-bounces-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org Errors-To: kvm-devel-bounces-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org List-Id: kvm.vger.kernel.org This is a multi-part message in MIME format. --------------050207090508020308020101 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit This patch depends on patch 6 and modifies the KVM changes to be an "accelerator" for QEMU in much the same way kqemu is. The basic idea was to introduce a use_kvm flag in CPUState and, where appropriate, check for use_kvm before doing KVM specific things. There are a number of places where a valid CPUState is not available or simply not created yet. In these cases, we use the global kvm_allowed variable. This isn't a very pretty approach but it seems to work. Figuring out how to make this all work with SMP is going to largely depend on how SMP gets implemented in KVM. Regards, Anthony Liguori --------------050207090508020308020101 Content-Type: text/x-patch; name="kvm-same-binary.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="kvm-same-binary.diff" diff -r 29c67b2ba36e cpu-exec.c --- a/cpu-exec.c Thu Nov 02 21:11:52 2006 -0600 +++ b/cpu-exec.c Thu Nov 02 21:11:52 2006 -0600 @@ -454,8 +454,10 @@ int cpu_exec(CPUState *env1) #endif #ifdef USE_KVM - kvm_cpu_exec(env); - longjmp(env->jmp_env, 1); + if (env->use_kvm) { + kvm_cpu_exec(env); + longjmp(env->jmp_env, 1); + } #endif T0 = 0; /* force lookup of first TB */ for(;;) { diff -r 29c67b2ba36e exec.c --- a/exec.c Thu Nov 02 21:11:52 2006 -0600 +++ b/exec.c Thu Nov 02 21:11:52 2006 -0600 @@ -1045,7 +1045,8 @@ int cpu_breakpoint_insert(CPUState *env, env->breakpoints[env->nb_breakpoints++] = pc; #ifdef USE_KVM - kvm_update_debugger(env); + if (env->use_kvm) + kvm_update_debugger(env); #endif breakpoint_invalidate(env, pc); @@ -1071,7 +1072,8 @@ int cpu_breakpoint_remove(CPUState *env, env->breakpoints[i] = env->breakpoints[env->nb_breakpoints]; #ifdef USE_KVM - kvm_update_debugger(env); + if (env->use_kvm) + kvm_update_debugger(env); #endif breakpoint_invalidate(env, pc); @@ -1093,7 +1095,8 @@ void cpu_single_step(CPUState *env, int tb_flush(env); } #ifdef USE_KVM - kvm_update_debugger(env); + if (env->use_kvm) + kvm_update_debugger(env); #endif #endif } diff -r 29c67b2ba36e hw/cirrus_vga.c --- a/hw/cirrus_vga.c Thu Nov 02 21:11:52 2006 -0600 +++ b/hw/cirrus_vga.c Thu Nov 02 21:11:52 2006 -0600 @@ -2596,7 +2596,9 @@ static void cirrus_update_memory_access( mode = s->gr[0x05] & 0x7; if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { #ifdef USE_KVM - if (s->cirrus_lfb_addr && s->cirrus_lfb_end && !s->map_addr) { + CPUState *env = cpu_single_env; /* XXX: SMP support */ + if (env->use_kvm && s->cirrus_lfb_addr && s->cirrus_lfb_end && + !s->map_addr) { void *vram_pointer, *old_vram; vram_pointer = set_vram_mapping(s->cirrus_lfb_addr, @@ -2616,9 +2618,14 @@ static void cirrus_update_memory_access( s->cirrus_linear_write[1] = cirrus_linear_mem_writew; s->cirrus_linear_write[2] = cirrus_linear_mem_writel; } else { +#ifdef USE_KVM + CPUState *env; +#endif generic_io: #ifdef USE_KVM - if (s->cirrus_lfb_addr && s->cirrus_lfb_end && s->map_addr) { + env = cpu_single_env; + if (env->use_kvm && s->cirrus_lfb_addr && s->cirrus_lfb_end && + s->map_addr) { int error; void *old_vram = NULL; @@ -2993,6 +3000,9 @@ static void cirrus_vga_save(QEMUFile *f, static void cirrus_vga_save(QEMUFile *f, void *opaque) { CirrusVGAState *s = opaque; +#ifdef USE_KVM + CPUState *env = cpu_single_env; +#endif qemu_put_be32s(f, &s->latch); qemu_put_8s(f, &s->sr_index); @@ -3029,14 +3039,19 @@ static void cirrus_vga_save(QEMUFile *f, the state when the blitter is active */ #ifdef USE_KVM - qemu_put_be32s(f, &s->real_vram_size); - qemu_put_buffer(f, s->vram_ptr, s->real_vram_size); + if (env->use_kvm) { /* XXX: KVM images ought to be loadable in QEMU */ + qemu_put_be32s(f, &s->real_vram_size); + qemu_put_buffer(f, s->vram_ptr, s->real_vram_size); + } #endif } static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id) { CirrusVGAState *s = opaque; +#ifdef USE_KVM + CPUState *env = cpu_single_env; +#endif if (version_id != 1) return -EINVAL; @@ -3076,7 +3091,7 @@ static int cirrus_vga_load(QEMUFile *f, qemu_get_be32s(f, &s->hw_cursor_y); #ifdef USE_KVM - { + if (env->use_kvm) { int real_vram_size; qemu_get_be32s(f, &real_vram_size); if (real_vram_size != s->real_vram_size) { @@ -3247,12 +3262,14 @@ static void cirrus_pci_lfb_map(PCIDevice cpu_register_physical_memory(addr, s->vram_size, s->cirrus_linear_io_addr); #ifdef USE_KVM - s->cirrus_lfb_addr = addr; - s->cirrus_lfb_end = addr + VGA_RAM_SIZE; - - if (s->map_addr && (s->cirrus_lfb_addr != s->map_addr) && - (s->cirrus_lfb_end != s->map_end)) - printf("cirrus vga map change while on lfb mode\n"); + if (kqemu_allowed) { + s->cirrus_lfb_addr = addr; + s->cirrus_lfb_end = addr + VGA_RAM_SIZE; + + if (s->map_addr && (s->cirrus_lfb_addr != s->map_addr) && + (s->cirrus_lfb_end != s->map_end)) + printf("cirrus vga map change while on lfb mode\n"); + } #endif cpu_register_physical_memory(addr + 0x1000000, 0x400000, diff -r 29c67b2ba36e hw/pc.c --- a/hw/pc.c Thu Nov 02 21:11:52 2006 -0600 +++ b/hw/pc.c Thu Nov 02 21:11:52 2006 -0600 @@ -610,6 +610,7 @@ static void pc_init_ne2k_isa(NICInfo *nd #ifdef USE_KVM extern kvm_context_t kvm_context; +extern int kvm_allowed; #endif /* PC hardware initialisation */ @@ -682,7 +683,9 @@ static void pc_init1(int ram_size, int v cpu_register_physical_memory(0xc0000, 0x10000, vga_bios_offset | IO_MEM_ROM); #ifdef USE_KVM - memcpy(phys_ram_base + 0xc0000, phys_ram_base + vga_bios_offset, 0x10000); + if (kvm_allowed) + memcpy(phys_ram_base + 0xc0000, phys_ram_base + vga_bios_offset, + 0x10000); #endif /* map the last 128KB of the BIOS in ISA space */ @@ -695,21 +698,25 @@ static void pc_init1(int ram_size, int v isa_bios_size, (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM); #ifdef USE_KVM - memcpy(phys_ram_base + 0x100000 - isa_bios_size, phys_ram_base + (bios_offset + bios_size - isa_bios_size), isa_bios_size); + if (kvm_allowed) + memcpy(phys_ram_base + 0x100000 - isa_bios_size, + phys_ram_base + (bios_offset + bios_size - isa_bios_size), + isa_bios_size); #endif /* map all the bios at the top of memory */ cpu_register_physical_memory((uint32_t)(-bios_size), bios_size, bios_offset | IO_MEM_ROM); #ifdef USE_KVM - bios_mem = kvm_create_phys_mem(kvm_context, (uint32_t)(-bios_size), - bios_size, 2, 0, 1); - if (!bios_mem) { - exit(1); - } - memcpy(bios_mem, phys_ram_base + bios_offset, bios_size); - - cpu_register_physical_memory(phys_ram_size - KVM_EXTRA_PAGES * 4096, KVM_EXTRA_PAGES * 4096, - (phys_ram_size - KVM_EXTRA_PAGES * 4096) | IO_MEM_ROM); + if (kvm_allowed) { + bios_mem = kvm_create_phys_mem(kvm_context, (uint32_t)(-bios_size), + bios_size, 2, 0, 1); + if (!bios_mem) + exit(1); + memcpy(bios_mem, phys_ram_base + bios_offset, bios_size); + + cpu_register_physical_memory(phys_ram_size - KVM_EXTRA_PAGES * 4096, KVM_EXTRA_PAGES * 4096, + (phys_ram_size - KVM_EXTRA_PAGES * 4096) | IO_MEM_ROM); + } #endif diff -r 29c67b2ba36e hw/vga.c --- a/hw/vga.c Thu Nov 02 21:11:52 2006 -0600 +++ b/hw/vga.c Thu Nov 02 21:12:55 2006 -0600 @@ -1375,6 +1375,10 @@ static int bitmap_get_dirty(unsigned lon #endif +#ifdef USE_KVM +extern int kvm_allowed; +#endif + /* * graphic modes */ @@ -1393,11 +1397,8 @@ static void vga_draw_graphic(VGAState *s #define BITMAP_SIZE ((8*1024*1024) / 4096 / 8 / sizeof(long)) unsigned long bitmap[BITMAP_SIZE]; - kvm_get_dirty_pages(kvm_context, 1, &bitmap); - -#define cpu_physical_memory_get_dirty(addr, type) \ - (bitmap_get_dirty(bitmap, (addr - s->vram_offset) >> TARGET_PAGE_BITS) \ - | cpu_physical_memory_get_dirty(addr, type)) + if (kvm_allowed) + kvm_get_dirty_pages(kvm_context, 1, &bitmap); #endif full_update |= update_basic_params(s); @@ -1506,10 +1507,16 @@ static void vga_draw_graphic(VGAState *s update = full_update | cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) | cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG); + if (kvm_allowed) { + update |= bitmap_get_dirty(bitmap, (page0 - s->vram_offset) >> TARGET_PAGE_BITS); + update |= bitmap_get_dirty(bitmap, (page1 - s->vram_offset) >> TARGET_PAGE_BITS); + } if ((page1 - page0) > TARGET_PAGE_SIZE) { /* if wide line, can use another page */ update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE, VGA_DIRTY_FLAG); + if (kvm_allowed) + update |= bitmap_get_dirty(bitmap, (page0 - s->vram_offset) >> TARGET_PAGE_BITS); } /* explicit invalidation for the hardware cursor */ update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1; @@ -1751,6 +1758,10 @@ static void vga_map(PCIDevice *pci_dev, } } +#ifdef USE_KVM +extern int kvm_allowed; +#endif + /* when used on xen/kvm environment, the vga_ram_base is not used */ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, unsigned long vga_ram_offset, int vga_ram_size) @@ -1785,7 +1796,10 @@ void vga_common_init(VGAState *s, Displa #ifndef USE_KVM s->vram_ptr = vga_ram_base; #else - s->vram_ptr = qemu_malloc(vga_ram_size); + if (kvm_allowed) + s->vram_ptr = qemu_malloc(vga_ram_size); + else + s->vram_ptr = vga_ram_base; #endif s->vram_offset = vga_ram_offset; s->vram_size = vga_ram_size; diff -r 29c67b2ba36e target-i386/cpu.h --- a/target-i386/cpu.h Thu Nov 02 21:11:52 2006 -0600 +++ b/target-i386/cpu.h Thu Nov 02 21:11:52 2006 -0600 @@ -532,6 +532,7 @@ typedef struct CPUX86State { #ifdef USE_KVM int kvm_pending_int; + int use_kvm; #endif /* in order to simplify APIC support, we leave this pointer to the diff -r 29c67b2ba36e target-i386/helper.c --- a/target-i386/helper.c Thu Nov 02 21:11:52 2006 -0600 +++ b/target-i386/helper.c Thu Nov 02 21:11:52 2006 -0600 @@ -189,7 +189,7 @@ static inline void get_ss_esp_from_tss(u * Bit 1 is the Busy bit. We believe it is legal to interrupt into a busy * segment */ - if ((type & 5) != 1) + if ((env->use_kvm && (type & 5) != 1) || (type & 7) != 1) #else if ((type & 7) != 1) #endif @@ -838,8 +838,10 @@ static void do_interrupt64(int intno, in target_ulong old_eip, esp, offset; #ifdef USE_KVM - printf("%s: unexpect\n", __FUNCTION__); - exit(-1); + if (env->use_kvm) { + printf("%s: unexpect\n", __FUNCTION__); + exit(-1); + } #endif has_error_code = 0; @@ -1126,8 +1128,10 @@ void do_interrupt_user(int intno, int is uint32_t e2; #ifdef USE_KVM - printf("%s: unexpect\n", __FUNCTION__); - exit(-1); + if (env->use_kvm) { + printf("%s: unexpect\n", __FUNCTION__); + exit(-1); + } #endif dt = &env->idt; ptr = dt->base + (intno * 8); @@ -1155,8 +1159,10 @@ void do_interrupt(int intno, int is_int, target_ulong next_eip, int is_hw) { #ifdef USE_KVM - printf("%s: unexpect\n", __FUNCTION__); - exit(-1); + if (env->use_kvm) { + printf("%s: unexpect\n", __FUNCTION__); + exit(-1); + } #endif if (loglevel & CPU_LOG_INT) { if ((env->cr[0] & CR0_PE_MASK)) { @@ -1687,7 +1693,7 @@ void helper_ljmp_protected_T0_T1(int nex get_seg_base(e1, e2), limit, e2); EIP = new_eip; #ifdef USE_KVM - if (e2 & DESC_L_MASK) { + if (env->use_kvm && (e2 & DESC_L_MASK)) { env->exception_index = -1; cpu_loop_exit(); } diff -r 29c67b2ba36e target-i386/helper2.c --- a/target-i386/helper2.c Thu Nov 02 21:11:52 2006 -0600 +++ b/target-i386/helper2.c Thu Nov 02 21:11:52 2006 -0600 @@ -140,6 +140,12 @@ CPUX86State *cpu_x86_init(void) cpu_reset(env); #ifdef USE_KQEMU kqemu_init(env); +#endif +#ifdef USE_KVM + { + extern int kvm_allowed; + env->use_kvm = kvm_allowed; + } #endif return env; } diff -r 29c67b2ba36e vl.c --- a/vl.c Thu Nov 02 21:11:52 2006 -0600 +++ b/vl.c Thu Nov 02 21:11:52 2006 -0600 @@ -4594,7 +4594,8 @@ int cpu_load(QEMUFile *f, void *opaque, env->hflags = hflags; tlb_flush(env, 1); #ifdef USE_KVM - kvm_load_registers(env); + if (env->use_kvm) + kvm_load_registers(env); #endif return 0; } @@ -4761,7 +4762,7 @@ static void ram_save(QEMUFile *f, void * qemu_put_be32(f, phys_ram_size); for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) { #ifdef USE_KVM - if ((i>=0xa0000) && (i<0xc0000)) /* do not access video-addresses */ + if (kvm_allowed && (i>=0xa0000) && (i<0xc0000)) /* do not access video-addresses */ continue; #endif ram_put_page(f, phys_ram_base + i, TARGET_PAGE_SIZE); @@ -4771,14 +4772,13 @@ static int ram_load(QEMUFile *f, void *o static int ram_load(QEMUFile *f, void *opaque, int version_id) { int i, ret; - if (version_id != 1) return -EINVAL; if (qemu_get_be32(f) != phys_ram_size) return -EINVAL; for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) { #ifdef USE_KVM - if ((i>=0xa0000) && (i<0xc0000)) /* do not access video-addresses */ + if (kqemu_allowed && (i>=0xa0000) && (i<0xc0000)) /* do not access video-addresses */ continue; #endif ret = ram_get_page(f, phys_ram_base + i, TARGET_PAGE_SIZE); @@ -5230,6 +5230,9 @@ void help(void) #ifdef USE_KQEMU "-kernel-kqemu enable KQEMU full virtualization (default is user mode only)\n" "-no-kqemu disable KQEMU kernel module usage\n" +#endif +#ifdef USE_KVM + "-enable-kvm enable KVM full virtualization\n" #endif #ifdef USE_CODE_COPY "-no-code-copy disable code copy acceleration\n" @@ -5319,6 +5322,7 @@ enum { QEMU_OPTION_smp, QEMU_OPTION_vnc, QEMU_OPTION_no_acpi, + QEMU_OPTION_enable_kvm, }; typedef struct QEMUOption { @@ -5374,6 +5378,9 @@ const QEMUOption qemu_options[] = { #ifdef USE_KQEMU { "no-kqemu", 0, QEMU_OPTION_no_kqemu }, { "kernel-kqemu", 0, QEMU_OPTION_kernel_kqemu }, +#endif +#ifdef USE_KVM + { "enable-kvm", 0, QEMU_OPTION_enable_kvm }, #endif #if defined(TARGET_PPC) || defined(TARGET_SPARC) { "g", 1, QEMU_OPTION_g }, @@ -6007,6 +6014,11 @@ int main(int argc, char **argv) kqemu_allowed = 2; break; #endif +#ifdef USE_KVM + case QEMU_OPTION_enable_kvm: + kvm_allowed = 1; + break; +#endif case QEMU_OPTION_usb: usb_enabled = 1; break; @@ -6088,8 +6100,17 @@ int main(int argc, char **argv) /* init the memory */ #if USE_KVM - phys_ram_size = ram_size + vga_ram_size + bios_size + KVM_EXTRA_PAGES * 4096; - kvm_qemu_init(); + phys_ram_size = ram_size + vga_ram_size + bios_size; + if (kvm_allowed) { + phys_ram_size += KVM_EXTRA_PAGES * 4096; + kvm_qemu_init(); + } else { + phys_ram_base = qemu_vmalloc(phys_ram_size); + if (!phys_ram_base) { + fprintf(stderr, "Could not allocate physical memory\n"); + exit(1); + } + } #else phys_ram_size = ram_size + vga_ram_size + bios_size; phys_ram_base = qemu_vmalloc(phys_ram_size); diff -r 29c67b2ba36e vl.h --- a/vl.h Thu Nov 02 21:11:52 2006 -0600 +++ b/vl.h Thu Nov 02 21:11:52 2006 -0600 @@ -148,6 +148,7 @@ extern int graphic_depth; extern int graphic_depth; extern const char *keyboard_layout; extern int kqemu_allowed; +extern int kvm_allowed; extern int win2k_install_hack; extern int usb_enabled; extern int smp_cpus; --------------050207090508020308020101 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 --------------050207090508020308020101 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ kvm-devel mailing list kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org https://lists.sourceforge.net/lists/listinfo/kvm-devel --------------050207090508020308020101--