From a9eab62e5c1bea3c50406390ed6b396177d3657d4c6eeb9c4e152882364a75bb Mon Sep 17 00:00:00 2001 From: OBS User unknown Date: Wed, 1 Apr 2009 16:57:34 +0000 Subject: [PATCH] OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/qemu?expand=0&rev=29 --- .gitattributes | 2 - kvm_bios.bin | 3 - qemu-0.10.1.tar.bz2 | 3 + qemu-0.7.1-jobsignals.patch | 19 - qemu-0.9.0-kvm-bios.patch | 55 - qemu-0.9.0-kvm-kqemu-window-caption.patch | 37 - qemu-0.9.0-kvm.patch | 3703 --------------------- qemu-20081008.tar.bz2 | 3 - qemu-cvs-ia64.patch | 23 - qemu-cvs-ipc.patch | 101 +- qemu-cvs-mmap-amd64.patch | 19 +- qemu-cvs-newpath.patch | 6 +- qemu-cvs-ppcspe.patch | 33 - qemu-cvs-sched_getaffinity.patch | 12 +- qemu-cvs-svm2.patch | 71 - qemu-svn-i386-nptl.patch | 46 + qemu-svn-ncurses.patch | 8 +- qemu-svn-nodyngen.patch | 26 - qemu-svn-pcap.patch | 66 +- qemu-svn-s390.patch | 1481 ++++++++ qemu.changes | 60 + qemu.spec | 113 +- 22 files changed, 1777 insertions(+), 4113 deletions(-) delete mode 100644 kvm_bios.bin create mode 100644 qemu-0.10.1.tar.bz2 delete mode 100644 qemu-0.7.1-jobsignals.patch delete mode 100644 qemu-0.9.0-kvm-bios.patch delete mode 100644 qemu-0.9.0-kvm-kqemu-window-caption.patch delete mode 100644 qemu-0.9.0-kvm.patch delete mode 100644 qemu-20081008.tar.bz2 delete mode 100644 qemu-cvs-ia64.patch delete mode 100644 qemu-cvs-ppcspe.patch delete mode 100644 qemu-cvs-svm2.patch create mode 100644 qemu-svn-i386-nptl.patch delete mode 100644 qemu-svn-nodyngen.patch create mode 100644 qemu-svn-s390.patch diff --git a/.gitattributes b/.gitattributes index 3827e92d..9b03811c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -21,5 +21,3 @@ *.xz filter=lfs diff=lfs merge=lfs -text *.zip filter=lfs diff=lfs merge=lfs -text *.zst filter=lfs diff=lfs merge=lfs -text -## Specific LFS patterns -kvm_bios.bin filter=lfs diff=lfs merge=lfs -text diff --git a/kvm_bios.bin b/kvm_bios.bin deleted file mode 100644 index 01eefd30..00000000 --- a/kvm_bios.bin +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fd82361665a1e5a7fd3bb5f6bc56c145d0f094a09d5f7d059a7a40632043d87a -size 131072 diff --git a/qemu-0.10.1.tar.bz2 b/qemu-0.10.1.tar.bz2 new file mode 100644 index 00000000..8d04fb3e --- /dev/null +++ b/qemu-0.10.1.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c987d50d321cc856b0d98fd227bb26b0764e43f49abe24ae2312dd9eda204591 +size 3068967 diff --git a/qemu-0.7.1-jobsignals.patch b/qemu-0.7.1-jobsignals.patch deleted file mode 100644 index 179a8310..00000000 --- a/qemu-0.7.1-jobsignals.patch +++ /dev/null @@ -1,19 +0,0 @@ ---- linux-user/signal.c -+++ linux-user/signal.c -@@ -364,10 +364,15 @@ - k = &sigact_table[sig - 1]; - handler = k->sa._sa_handler; - if (handler == TARGET_SIG_DFL) { -+ if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) { -+ kill(getpid(),SIGSTOP); -+ return 0; -+ } else - /* default handler : ignore some signal. The other are fatal */ - if (sig != TARGET_SIGCHLD && - sig != TARGET_SIGURG && -- sig != TARGET_SIGWINCH) { -+ sig != TARGET_SIGWINCH && -+ sig != TARGET_SIGCONT) { - force_sig(sig); - } else { - return 0; /* indicate ignored */ diff --git a/qemu-0.9.0-kvm-bios.patch b/qemu-0.9.0-kvm-bios.patch deleted file mode 100644 index e27f04dc..00000000 --- a/qemu-0.9.0-kvm-bios.patch +++ /dev/null @@ -1,55 +0,0 @@ -2007-03-14 Gwenole Beauchesne - - * hw/pc.c (pc_init1): Use the KVM specific BIOS for now. - -================================================================================ ---- qemu-0.9.0/Makefile -+++ qemu-0.9.0/Makefile -@@ -77,7 +77,7 @@ - mkdir -p "$(DESTDIR)$(bindir)" - $(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)" - mkdir -p "$(DESTDIR)$(datadir)" -- for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \ -+ for x in bios.bin kvm_bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \ - video.x openbios-sparc32 linux_boot.bin pxe-ne2k_pci.bin \ - pxe-rtl8139.bin pxe-pcnet.bin; do \ - $(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \ -@@ -157,6 +157,7 @@ - $(bindir)/qemu-mipsel \ - $(bindir)/qemu-img \ - $(datadir)/bios.bin \ -+ $(datadir)/kvm_bios.bin \ - $(datadir)/vgabios.bin \ - $(datadir)/vgabios-cirrus.bin \ - $(datadir)/ppc_rom.bin \ ---- qemu-0.9.0/hw/pc.c -+++ qemu-0.9.0/hw/pc.c -@@ -27,6 +27,7 @@ - //#define DEBUG_BIOS - - #define BIOS_FILENAME "bios.bin" -+#define KVM_BIOS_FILENAME "kvm_bios.bin" - #define VGABIOS_FILENAME "vgabios.bin" - #define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin" - #define LINUX_BOOT_FILENAME "linux_boot.bin" -@@ -460,6 +461,7 @@ - int piix3_devfn = -1; - CPUState *env; - NICInfo *nd; -+ const char *bios_filename = BIOS_FILENAME; - - linux_boot = (kernel_filename != NULL); - -@@ -486,7 +488,11 @@ - bios_offset = ram_size + vga_ram_size; - vga_bios_offset = bios_offset + 256 * 1024; - -- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME); -+#ifdef USE_KVM -+ if (kvm_allowed) -+ bios_filename = KVM_BIOS_FILENAME; -+#endif -+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_filename); - bios_size = get_image_size(buf); - if (bios_size <= 0 || - (bios_size % 65536) != 0 || diff --git a/qemu-0.9.0-kvm-kqemu-window-caption.patch b/qemu-0.9.0-kvm-kqemu-window-caption.patch deleted file mode 100644 index 31ea9c94..00000000 --- a/qemu-0.9.0-kvm-kqemu-window-caption.patch +++ /dev/null @@ -1,37 +0,0 @@ -2007-03-14 Gwenole Beauchesne - - * sdl.c (sdl_update_caption): Report KQEMU accelerator accordingly - in the SDL window. - ---- qemu-0.9.0/sdl.c.kvm-kqemu-window-caption 2007-03-14 17:59:05.000000000 +0100 -+++ qemu-0.9.0/sdl.c 2007-03-14 18:02:55.000000000 +0100 -@@ -212,13 +212,27 @@ static void sdl_process_key(SDL_Keyboard - - static void sdl_update_caption(void) - { -+ int accl_mode = 0; /* 1=kqemu, 2=kvm */ - char buf[1024]; - strcpy(buf, "QEMU"); --#if USE_KVM -+#ifdef USE_KQEMU -+ if (kqemu_allowed) { -+ accl_mode = 1; -+ } -+#endif -+#ifdef USE_KVM - if (kvm_allowed) { -- strcat(buf, "/KVM"); -+ accl_mode = 2; - } - #endif -+ switch (accl_mode) { -+ case 1: -+ strcat(buf, "/KQEMU"); -+ break; -+ case 2: -+ strcat(buf, "/KVM"); -+ break; -+ } - if (!vm_running) { - strcat(buf, " [Stopped]"); - } diff --git a/qemu-0.9.0-kvm.patch b/qemu-0.9.0-kvm.patch deleted file mode 100644 index 6865f817..00000000 --- a/qemu-0.9.0-kvm.patch +++ /dev/null @@ -1,3703 +0,0 @@ -2007-03-13 Gwenole Beauchesne - - * Merge in KVM rev 4486. Requires kernel 2.6.17 >= 12mdv. - -================================================================================ ---- qemu-0.9.0/Makefile.target -+++ qemu-0.9.0/Makefile.target -@@ -1,5 +1,9 @@ -+CFLAGS= -+LDFLAGS= -+ - include config.mak - -+LDFLAGS_BASE:=$(LDFLAGS) - TARGET_BASE_ARCH:=$(TARGET_ARCH) - ifeq ($(TARGET_ARCH), x86_64) - TARGET_BASE_ARCH:=i386 -@@ -227,8 +231,8 @@ - OBJS+= libqemu.a - - # cpu emulator library --LIBOBJS=exec.o kqemu.o translate-op.o translate-all.o cpu-exec.o\ -- translate.o op.o -+LIBOBJS=exec.o kqemu.o qemu-kvm.o translate-op.o translate-all.o cpu-exec.o\ -+ translate.o op.o - ifdef CONFIG_SOFTFLOAT - LIBOBJS+=fpu/softfloat.o - else -@@ -365,6 +369,13 @@ - # PCI network cards - VL_OBJS+= ne2000.o rtl8139.o pcnet.o - -+# KVM layer -+ifeq ($(USE_KVM), yes) -+VL_OBJS+= kvmctl.o -+# PCI Hypercall -+VL_OBJS+= hypercall.o -+endif -+ - ifeq ($(TARGET_BASE_ARCH), i386) - # Hardware support - VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) -@@ -429,7 +440,7 @@ - VL_OBJS+=$(addprefix slirp/, $(SLIRP_OBJS)) - endif - --VL_LDFLAGS= -+VL_LDFLAGS=$(LDFLAGS_BASE) - # specific flags are needed for non soft mmu emulator - ifdef CONFIG_STATIC - VL_LDFLAGS+=-static -@@ -440,7 +451,7 @@ - ifndef CONFIG_DARWIN - ifndef CONFIG_WIN32 - ifndef CONFIG_SOLARIS --VL_LIBS=-lutil -lrt -+VL_LIBS=-lutil -lrt -luuid - endif - endif - endif -@@ -462,7 +473,7 @@ - SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole - endif - --$(QEMU_SYSTEM): $(VL_OBJS) libqemu.a -+$(QEMU_SYSTEM): $(VL_OBJS) libqemu.a $(DEPLIBS) - $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS) - - cocoa.o: cocoa.m -@@ -521,6 +532,9 @@ - cpu-exec.o: cpu-exec.c - $(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $< - -+qemu-kvm.o: qemu-kvm.c -+ $(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $< -+ - # Note: this is a workaround. The real fix is to avoid compiling - # cpu_signal_handler() in cpu-exec.c. - signal.o: signal.c ---- qemu-0.9.0/configure -+++ qemu-0.9.0/configure -@@ -89,7 +89,9 @@ - bsd="no" - linux="no" - kqemu="no" -+kvm="no" - profiler="no" -+kernel_path="" - cocoa="no" - check_gfx="yes" - check_gcc="yes" -@@ -114,6 +116,7 @@ - oss="yes" - if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then - kqemu="yes" -+ kvm="yes" - fi - ;; - NetBSD) -@@ -141,6 +144,7 @@ - linux_user="yes" - if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then - kqemu="yes" -+ kvm="yes" - fi - ;; - esac -@@ -232,8 +236,12 @@ - ;; - --disable-kqemu) kqemu="no" - ;; -+ --enable-kvm) kvm="yes" -+ ;; - --enable-profiler) profiler="yes" - ;; -+ --kernel-path=*) kernel_path="$optarg" -+ ;; - --enable-cocoa) cocoa="yes" ; coreaudio="yes" ; sdl="no" - ;; - --disable-gfx-check) check_gfx="no" -@@ -277,6 +285,8 @@ - echo "" - echo "kqemu kernel acceleration support:" - echo " --disable-kqemu disable kqemu support" -+echo " --kernel-path=PATH set the kernel path (configure probes it)" -+echo " --enable-kvm enable kernel virtual machine support" - echo "" - echo "Advanced options (experts only):" - echo " --source-path=PATH path of source code [$source_path]" -@@ -623,6 +633,7 @@ - fi - echo "FMOD support $fmod $fmod_support" - echo "kqemu support $kqemu" -+echo "kvm support $kvm" - echo "Documentation $build_docs" - [ ! -z "$uname_release" ] && \ - echo "uname -r $uname_release" -@@ -857,6 +868,13 @@ - interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"` - echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h - -+configure_kvm() { -+ if test $kvm = "yes" -a "$target_softmmu" = "yes" -a $cpu = "$target_cpu" ; then -+ echo "#define USE_KVM 1" >> $config_h -+ echo "USE_KVM=yes" >> $config_mak -+ fi -+} -+ - if test "$target_cpu" = "i386" ; then - echo "TARGET_ARCH=i386" >> $config_mak - echo "#define TARGET_ARCH \"i386\"" >> $config_h -@@ -864,6 +882,7 @@ - if test $kqemu = "yes" -a "$target_softmmu" = "yes" -a $cpu = "i386" ; then - echo "#define USE_KQEMU 1" >> $config_h - fi -+ configure_kvm - elif test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" ; then - echo "TARGET_ARCH=arm" >> $config_mak - echo "#define TARGET_ARCH \"arm\"" >> $config_h -@@ -895,6 +914,7 @@ - if test $kqemu = "yes" -a "$target_softmmu" = "yes" -a $cpu = "x86_64" ; then - echo "#define USE_KQEMU 1" >> $config_h - fi -+ configure_kvm - elif test "$target_cpu" = "mips" -o "$target_cpu" = "mipsel" ; then - echo "TARGET_ARCH=mips" >> $config_mak - echo "#define TARGET_ARCH \"mips\"" >> $config_h ---- qemu-0.9.0/cpu-all.h -+++ qemu-0.9.0/cpu-all.h -@@ -834,6 +834,7 @@ - extern int phys_ram_fd; - extern uint8_t *phys_ram_base; - extern uint8_t *phys_ram_dirty; -+extern uint8_t *bios_mem; - - /* physical memory access */ - #define TLB_INVALID_MASK (1 << 3) ---- qemu-0.9.0/cpu-exec.c -+++ qemu-0.9.0/cpu-exec.c -@@ -35,6 +35,11 @@ - #include - #endif - -+#ifdef USE_KVM -+#include "qemu-kvm.h" -+extern int kvm_allowed; -+#endif -+ - int tb_invalidated_flag; - - //#define DEBUG_EXEC -@@ -401,6 +406,12 @@ - } - #endif - -+#ifdef USE_KVM -+ if (kvm_allowed) { -+ kvm_cpu_exec(env); -+ longjmp(env->jmp_env, 1); -+ } -+#endif - T0 = 0; /* force lookup of first TB */ - for(;;) { - #if defined(__sparc__) && !defined(HOST_SOLARIS) ---- qemu-0.9.0/exec.c -+++ qemu-0.9.0/exec.c -@@ -69,6 +69,10 @@ - #define TARGET_PHYS_ADDR_SPACE_BITS 32 - #endif - -+#ifdef USE_KVM -+extern int kvm_allowed; -+#endif -+ - TranslationBlock tbs[CODE_GEN_MAX_BLOCKS]; - TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; - int nb_tbs; -@@ -82,6 +86,7 @@ - int phys_ram_fd; - uint8_t *phys_ram_base; - uint8_t *phys_ram_dirty; -+uint8_t *bios_mem; - static int in_migration; - - CPUState *first_cpu; -@@ -1044,6 +1049,11 @@ - if (env->nb_breakpoints >= MAX_BREAKPOINTS) - return -1; - env->breakpoints[env->nb_breakpoints++] = pc; -+ -+#ifdef USE_KVM -+ if (kvm_allowed) -+ kvm_update_debugger(env); -+#endif - - breakpoint_invalidate(env, pc); - return 0; -@@ -1067,6 +1077,11 @@ - if (i < env->nb_breakpoints) - env->breakpoints[i] = env->breakpoints[env->nb_breakpoints]; - -+#ifdef USE_KVM -+ if (kvm_allowed) -+ kvm_update_debugger(env); -+#endif -+ - breakpoint_invalidate(env, pc); - return 0; - #else -@@ -1085,6 +1100,10 @@ - /* XXX: only flush what is necessary */ - tb_flush(env); - } -+#ifdef USE_KVM -+ if (kvm_allowed) -+ kvm_update_debugger(env); -+#endif - #endif - } - -@@ -1425,6 +1444,9 @@ - { - int r=0; - -+#ifdef USE_KVM -+ r = kvm_physical_memory_set_dirty_tracking(enable); -+#endif - in_migration = enable; - return r; - } ---- qemu-0.9.0/hw/cirrus_vga.c -+++ qemu-0.9.0/hw/cirrus_vga.c -@@ -28,6 +28,9 @@ - */ - #include "vl.h" - #include "vga_int.h" -+#ifndef _WIN32 -+#include -+#endif - - /* - * TODO: -@@ -231,6 +234,10 @@ - int cirrus_linear_io_addr; - int cirrus_linear_bitblt_io_addr; - int cirrus_mmio_io_addr; -+#ifdef USE_KVM -+ unsigned long cirrus_lfb_addr; -+ unsigned long cirrus_lfb_end; -+#endif - uint32_t cirrus_addr_mask; - uint32_t linear_mmio_mask; - uint8_t cirrus_shadow_gr0; -@@ -267,6 +274,10 @@ - int last_hw_cursor_y_end; - int real_vram_size; /* XXX: suppress that */ - CPUWriteMemoryFunc **cirrus_linear_write; -+#ifdef USE_KVM -+ unsigned long map_addr; -+ unsigned long map_end; -+#endif - } CirrusVGAState; - - typedef struct PCICirrusVGAState { -@@ -2525,6 +2536,48 @@ - cirrus_linear_bitblt_writel, - }; - -+#ifdef USE_KVM -+ -+#include "qemu-kvm.h" -+ -+extern kvm_context_t kvm_context; -+ -+static void *set_vram_mapping(unsigned long begin, unsigned long end) -+{ -+ void *vram_pointer = NULL; -+ -+ /* align begin and end address */ -+ begin = begin & TARGET_PAGE_MASK; -+ end = begin + VGA_RAM_SIZE; -+ end = (end + TARGET_PAGE_SIZE -1 ) & TARGET_PAGE_MASK; -+ -+ vram_pointer = kvm_create_phys_mem(kvm_context, begin, end - begin, 1, -+ 1, 1); -+ -+ if (vram_pointer == NULL) { -+ printf("set_vram_mapping: cannot allocate memory: %m\n"); -+ return NULL; -+ } -+ -+ memset(vram_pointer, 0, end - begin); -+ -+ return vram_pointer; -+} -+ -+static int unset_vram_mapping(unsigned long begin, unsigned long end) -+{ -+ /* align begin and end address */ -+ end = begin + VGA_RAM_SIZE; -+ begin = begin & TARGET_PAGE_MASK; -+ end = (end + TARGET_PAGE_SIZE -1 ) & TARGET_PAGE_MASK; -+ -+ kvm_destroy_phys_mem(kvm_context, begin, end - begin); -+ -+ return 0; -+} -+ -+#endif -+ - /* Compute the memory access functions */ - static void cirrus_update_memory_access(CirrusVGAState *s) - { -@@ -2543,11 +2596,45 @@ - - mode = s->gr[0x05] & 0x7; - if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { -+#ifdef USE_KVM -+ if (kvm_allowed && 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, -+ s->cirrus_lfb_end); -+ if (!vram_pointer) -+ fprintf(stderr, "NULL vram_pointer\n"); -+ else { -+ old_vram = vga_update_vram((VGAState *)s, vram_pointer, -+ VGA_RAM_SIZE); -+ qemu_free(old_vram); -+ } -+ s->map_addr = s->cirrus_lfb_addr; -+ s->map_end = s->cirrus_lfb_end; -+ } -+#endif - s->cirrus_linear_write[0] = cirrus_linear_mem_writeb; - s->cirrus_linear_write[1] = cirrus_linear_mem_writew; - s->cirrus_linear_write[2] = cirrus_linear_mem_writel; - } else { - generic_io: -+#ifdef USE_KVM -+ if (kvm_allowed && s->cirrus_lfb_addr && s->cirrus_lfb_end && -+ s->map_addr) { -+ int error; -+ void *old_vram = NULL; -+ -+ error = unset_vram_mapping(s->cirrus_lfb_addr, -+ s->cirrus_lfb_end); -+ if (!error) -+ old_vram = vga_update_vram((VGAState *)s, NULL, -+ VGA_RAM_SIZE); -+ if (old_vram) -+ munmap(old_vram, s->map_addr - s->map_end); -+ s->map_addr = s->map_end = 0; -+ } -+#endif - s->cirrus_linear_write[0] = cirrus_linear_writeb; - s->cirrus_linear_write[1] = cirrus_linear_writew; - s->cirrus_linear_write[2] = cirrus_linear_writel; -@@ -2946,6 +3033,13 @@ - qemu_put_be32s(f, &s->hw_cursor_y); - /* XXX: we do not save the bitblt state - we assume we do not save - the state when the blitter is active */ -+ -+#ifdef USE_KVM -+ if (kvm_allowed) { /* 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) -@@ -2996,6 +3090,22 @@ - qemu_get_be32s(f, &s->hw_cursor_x); - qemu_get_be32s(f, &s->hw_cursor_y); - -+#ifdef USE_KVM -+ if (kvm_allowed) { -+ int real_vram_size; -+ qemu_get_be32s(f, &real_vram_size); -+ if (real_vram_size != s->real_vram_size) { -+ if (real_vram_size > s->real_vram_size) -+ real_vram_size = s->real_vram_size; -+ printf("%s: REAL_VRAM_SIZE MISMATCH !!!!!! SAVED=%d CURRENT=%d", -+ __FUNCTION__, real_vram_size, s->real_vram_size); -+ } -+ qemu_get_buffer(f, s->vram_ptr, real_vram_size); -+ cirrus_update_memory_access(s); -+ } -+#endif -+ -+ - /* force refresh */ - s->graphic_mode = -1; - cirrus_update_bank_ptr(s, 0); -@@ -3151,6 +3261,17 @@ - /* XXX: add byte swapping apertures */ - cpu_register_physical_memory(addr, s->vram_size, - s->cirrus_linear_io_addr); -+#ifdef USE_KVM -+ if (kvm_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, - s->cirrus_linear_bitblt_io_addr); - } ---- qemu-0.9.0/hw/hypercall.c -+++ qemu-0.9.0/hw/hypercall.c -@@ -0,0 +1,302 @@ -+/* -+ * QEMU-KVM Hypercall emulation -+ * -+ * Copyright (c) 2003-2004 Fabrice Bellard -+ * Copyright (c) 2006 Qumranet -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+#include "vl.h" -+#include "hypercall.h" -+#include -+ -+int use_hypercall_dev = 0; -+ -+typedef struct VmChannelCharDriverState { -+ CharDriverState *vmchannel_hd; -+ uint32_t deviceid; -+} VmChannelCharDriverState; -+ -+static VmChannelCharDriverState vmchannel_hds[MAX_VMCHANNEL_DEVICES]; -+ -+typedef struct HypercallState { -+ uint32_t hcr; -+ uint32_t hsr; -+ uint32_t txsize; -+ uint32_t txbuff; -+ uint32_t rxsize; -+ uint8_t RxBuff[HP_MEM_SIZE]; -+ uint8_t txbufferaccu[HP_MEM_SIZE]; -+ int txbufferaccu_offset; -+ int irq; -+ PCIDevice *pci_dev; -+ uint32_t index; -+} HypercallState; -+ -+HypercallState *pHypercallStates[MAX_VMCHANNEL_DEVICES] = {NULL}; -+ -+//#define HYPERCALL_DEBUG 1 -+ -+static void hp_reset(HypercallState *s) -+{ -+ s->hcr = 0; -+ s->hsr = 0; -+ s->txsize = 0; -+ s->txbuff = 0; -+ s->rxsize= 0; -+ s->txbufferaccu_offset = 0; -+} -+ -+static void hypercall_update_irq(HypercallState *s); -+ -+ -+static void hp_ioport_write(void *opaque, uint32_t addr, uint32_t val) -+{ -+ HypercallState *s = opaque; -+ -+#ifdef HYPERCALL_DEBUG -+ printf("%s: addr=0x%x, val=0x%x\n", __FUNCTION__, addr, val); -+#endif -+ addr &= 0xff; -+ -+ switch(addr) -+ { -+ case HCR_REGISTER: -+ { -+ s->hcr = val; -+ if (s->hcr & HCR_DI) -+ hypercall_update_irq(s); -+ if (val & HCR_GRS){ -+ hp_reset(s); -+ } -+ break; -+ } -+ -+ case HP_TXSIZE: -+ { -+ // handle the case when the we are being called when txsize is not 0 -+ if (s->txsize != 0) { -+ printf("txsize is being set, but txsize is not 0!!!\n"); -+ } -+ if (val > HP_MEM_SIZE) { -+ printf("txsize is larger than allowed by hw!!!\n"); -+ } -+ s->txsize = val; -+ s->txbufferaccu_offset = 0; -+ break; -+ } -+ -+ case HP_TXBUFF: -+ { -+ if (s->txsize == 0) { -+ printf("error with txbuff!!!\n"); -+ break; -+ } -+ -+ s->txbufferaccu[s->txbufferaccu_offset] = val; -+ s->txbufferaccu_offset++; -+ if (s->txbufferaccu_offset >= s->txsize) { -+ qemu_chr_write(vmchannel_hds[s->index].vmchannel_hd, s->txbufferaccu, s->txsize); -+ s->txbufferaccu_offset = 0; -+ s->txsize = 0; -+ } -+ break; -+ } -+ default: -+ { -+ printf("hp_ioport_write to unhandled address!!!\n"); -+ } -+ } -+} -+ -+static uint32_t hp_ioport_read(void *opaque, uint32_t addr) -+{ -+ HypercallState *s = opaque; -+ int ret; -+ -+ addr &= 0xff; -+#ifdef HYPERCALL_DEBUG -+ // Since HSR_REGISTER is being repeatedly read in the guest ISR we don't print it -+ if (addr != HSR_REGISTER) -+ printf("%s: addr=0x%x\n", __FUNCTION__, addr); -+#endif -+ -+ if (addr >= offsetof(HypercallState, RxBuff) ) -+ { -+ int RxBuffOffset = addr - (offsetof(HypercallState, RxBuff)); -+ ret = s->RxBuff[RxBuffOffset]; -+ return ret; -+ } -+ -+ switch (addr) -+ { -+ case HSR_REGISTER: -+ ret = s->hsr; -+ if (ret & HSR_VDR) { -+ s->hsr &= ~HSR_VDR; -+ } -+ break; -+ case HP_RXSIZE: -+ ret = s->rxsize; -+ break; -+ -+ default: -+ ret = 0x00; -+ break; -+ } -+ -+ return ret; -+} -+ -+/***********************************************************/ -+/* PCI Hypercall definitions */ -+ -+typedef struct PCIHypercallState { -+ PCIDevice dev; -+ HypercallState hp; -+} PCIHypercallState; -+ -+static void hp_map(PCIDevice *pci_dev, int region_num, -+ uint32_t addr, uint32_t size, int type) -+{ -+ PCIHypercallState *d = (PCIHypercallState *)pci_dev; -+ HypercallState *s = &d->hp; -+ -+ register_ioport_write(addr, 0x100, 1, hp_ioport_write, s); -+ register_ioport_read(addr, 0x100, 1, hp_ioport_read, s); -+ -+} -+ -+ -+static void hypercall_update_irq(HypercallState *s) -+{ -+ /* PCI irq */ -+ pci_set_irq(s->pci_dev, 0, !(s->hcr & HCR_DI)); -+} -+ -+void pci_hypercall_single_init(PCIBus *bus, uint32_t deviceid, uint32_t index) -+{ -+ PCIHypercallState *d; -+ HypercallState *s; -+ uint8_t *pci_conf; -+ char name[sizeof("HypercallX")]; -+ -+#ifdef HYPERCALL_DEBUG -+ printf("%s\n", __FUNCTION__); -+#endif -+ -+ // If the vmchannel wasn't initialized, we don't want the Hypercall device in the guest -+ if (use_hypercall_dev == 0) { -+ return; -+ } -+ -+ d = (PCIHypercallState *)pci_register_device(bus, -+ name, sizeof(PCIHypercallState), -+ -1, -+ NULL, NULL); -+ -+ pci_conf = d->dev.config; -+ pci_conf[0x00] = 0x02; // Qumranet vendor ID 0x5002 -+ pci_conf[0x01] = 0x50; -+ pci_conf[0x02] = deviceid & 0x00ff; -+ pci_conf[0x03] = (deviceid & 0xff00) >> 8; -+ -+ pci_conf[0x09] = 0x00; // ProgIf -+ pci_conf[0x0a] = 0x00; // SubClass -+ pci_conf[0x0b] = 0x05; // BaseClass -+ -+ pci_conf[0x0e] = 0x00; // header_type -+ pci_conf[0x3d] = 1; // interrupt pin 0 -+ -+ pci_register_io_region(&d->dev, 0, 0x100, -+ PCI_ADDRESS_SPACE_IO, hp_map); -+ s = &d->hp; -+ pHypercallStates[index] = s; -+ s->index = index; -+ s->irq = 16; /* PCI interrupt */ -+ s->pci_dev = (PCIDevice *)d; -+ -+ hp_reset(s); -+} -+ -+void pci_hypercall_init(PCIBus *bus) -+{ -+ int i; -+ -+ // loop devices & call pci_hypercall_single_init with device id's -+ for(i = 0; i < MAX_VMCHANNEL_DEVICES; i++){ -+ if (vmchannel_hds[i].vmchannel_hd) { -+ pci_hypercall_single_init(bus, vmchannel_hds[i].deviceid, i); -+ } -+ } -+} -+ -+static int vmchannel_can_read(void *opaque) -+{ -+ return 128; -+} -+ -+static void vmchannel_event(void *opaque, int event) -+{ -+ -+#ifdef HYPERCALL_DEBUG -+ // if index is to be used outside the printf, take it out of the #ifdef block! -+ long index = (long)opaque; -+ printf("%s index:%ld, got event %i\n", __FUNCTION__, index, event); -+#endif -+ -+ return; -+} -+ -+// input from vmchannel outside caller -+static void vmchannel_read(void *opaque, const uint8_t *buf, int size) -+{ -+ int i; -+ long index = (long)opaque; -+ -+#ifdef HYPERCALL_DEBUG -+ printf("vmchannel_read buf size:%d\n", size); -+#endif -+ -+ // if the hypercall device is in interrupts disabled state, don't accept the data -+ if (pHypercallStates[index]->hcr & HCR_DI) { -+ return; -+ } -+ -+ for(i = 0; i < size; i++) { -+ pHypercallStates[index]->RxBuff[i] = buf[i]; -+ } -+ pHypercallStates[index]->rxsize = size; -+ pHypercallStates[index]->hsr = HSR_VDR; -+ hypercall_update_irq(pHypercallStates[index]); -+} -+ -+void vmchannel_init(CharDriverState *hd, uint32_t deviceid, uint32_t index) -+{ -+#ifdef HYPERCALL_DEBUG -+ printf("vmchannel_init, index=%d, deviceid=0x%x\n", index, deviceid); -+#endif -+ -+ vmchannel_hds[index].deviceid = deviceid; -+ vmchannel_hds[index].vmchannel_hd = hd; -+ -+ use_hypercall_dev = 1; -+ qemu_chr_add_handlers(vmchannel_hds[index].vmchannel_hd, vmchannel_can_read, vmchannel_read, -+ vmchannel_event, (void *)(long)index); -+} ---- qemu-0.9.0/hw/hypercall.h -+++ qemu-0.9.0/hw/hypercall.h -@@ -0,0 +1,45 @@ -+/* -+ * QEMU-KVM Hypercall emulation -+ * -+ * Copyright (c) 2003-2004 Fabrice Bellard -+ * Copyright (c) 2006 Qumranet -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+ -+#define HCR_REGISTER 0x00 // Hypercall Command Register WR -+#define HSR_REGISTER 0x04 // Hypercall Status Register RD -+#define HP_TXSIZE 0x08 -+#define HP_TXBUFF 0x0c -+#define HP_RXSIZE 0x10 -+#define HP_RXBUFF 0x14 -+ -+// HCR_REGISTER commands -+#define HCR_DI 1 // disable interrupts -+#define HCR_EI 2 // enable interrupts -+#define HCR_GRS 4 // Global reset -+#define HCR_RESET (HCR_GRS|HCR_DI) -+ -+ -+// Bits in HSR_REGISTER -+#define HSR_VDR 0x01 // vmchannel Data is ready to be read -+ -+#define HP_MEM_SIZE 0xE0 -+ -+ ---- qemu-0.9.0/hw/pc.c -+++ qemu-0.9.0/hw/pc.c -@@ -22,6 +22,10 @@ - * THE SOFTWARE. - */ - #include "vl.h" -+#ifdef USE_KVM -+#include "qemu-kvm.h" -+extern int kvm_allowed; -+#endif - - /* output Bochs bios info messages */ - //#define DEBUG_BIOS -@@ -444,6 +448,11 @@ - nb_ne2k++; - } - -+#ifdef USE_KVM -+extern kvm_context_t kvm_context; -+extern int kvm_allowed; -+#endif -+ - /* PC hardware initialisation */ - static void pc_init1(int ram_size, int vga_ram_size, int boot_device, - DisplayState *ds, const char **fd_filename, int snapshot, -@@ -511,6 +520,11 @@ - /* setup basic memory access */ - cpu_register_physical_memory(0xc0000, 0x10000, - vga_bios_offset | IO_MEM_ROM); -+#ifdef USE_KVM -+ 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 */ - isa_bios_size = bios_size; -@@ -522,6 +536,26 @@ - isa_bios_size, - (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM); - -+#ifdef USE_KVM -+ 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 -+ -+#ifdef USE_KVM -+ 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 -+ - option_rom_offset = 0; - for (i = 0; i < nb_option_roms; i++) { - int offset = bios_offset + bios_size + option_rom_offset; -@@ -718,6 +752,11 @@ - } - } - -+#ifdef USE_KVM -+ if (kvm_allowed) { -+ pci_hypercall_init(pci_bus); -+ } -+#endif - if (pci_enabled) { - pci_piix3_ide_init(pci_bus, bs_table, piix3_devfn + 1); - } else { ---- qemu-0.9.0/hw/vga.c -+++ qemu-0.9.0/hw/vga.c -@@ -1373,6 +1373,26 @@ - } - } - -+#ifdef USE_KVM -+ -+#include "kvmctl.h" -+extern kvm_context_t kvm_context; -+ -+static int bitmap_get_dirty(unsigned long *bitmap, unsigned nr) -+{ -+ unsigned word = nr / ((sizeof bitmap[0]) * 8); -+ unsigned bit = nr % ((sizeof bitmap[0]) * 8); -+ -+ //printf("%x -> %ld\n", nr, (bitmap[word] >> bit) & 1); -+ return (bitmap[word] >> bit) & 1; -+} -+ -+#endif -+ -+#ifdef USE_KVM -+extern int kvm_allowed; -+#endif -+ - /* - * graphic modes - */ -@@ -1385,6 +1405,20 @@ - uint32_t v, addr1, addr; - vga_draw_line_func *vga_draw_line; - -+#ifdef USE_KVM -+ -+ /* HACK ALERT */ -+#define BITMAP_SIZE ((8*1024*1024) / 4096 / 8 / sizeof(long)) -+ unsigned long bitmap[BITMAP_SIZE]; -+ int r; -+ -+ if (kvm_allowed) { -+ r = kvm_get_dirty_pages(kvm_context, 1, &bitmap); -+ if (r < 0) -+ fprintf(stderr, "kvm: get_dirty_pages returned %d\n", r); -+ } -+#endif -+ - full_update |= update_basic_params(s); - - s->get_resolution(s, &width, &height); -@@ -1491,10 +1525,20 @@ - update = full_update | - cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) | - cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG); -+#ifdef USE_KVM -+ 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); -+ } -+#endif - 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); -+#ifdef USE_KVM -+ if (kvm_allowed) -+ update |= bitmap_get_dirty(bitmap, (page0 - s->vram_offset) >> TARGET_PAGE_BITS); -+#endif - } - /* explicit invalidation for the hardware cursor */ - update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1; -@@ -1751,6 +1795,7 @@ - } - } - -+/* 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) - { -@@ -1781,7 +1826,14 @@ - - vga_reset(s); - -+#ifndef USE_KVM - s->vram_ptr = vga_ram_base; -+#else -+ 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; - s->ds = ds; -@@ -1909,6 +1961,31 @@ - return 0; - } - -+void *vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size) -+{ -+ uint8_t *old_pointer; -+ -+ if (s->vram_size != vga_ram_size) { -+ fprintf(stderr, "No support to change vga_ram_size\n"); -+ return NULL; -+ } -+ -+ if (!vga_ram_base) { -+ vga_ram_base = qemu_malloc(vga_ram_size); -+ if (!vga_ram_base) { -+ fprintf(stderr, "reallocate error\n"); -+ return NULL; -+ } -+ } -+ -+ /* XXX lock needed? */ -+ memcpy(vga_ram_base, s->vram_ptr, vga_ram_size); -+ old_pointer = s->vram_ptr; -+ s->vram_ptr = vga_ram_base; -+ -+ return old_pointer; -+} -+ - /********************************************************/ - /* vga screen dump */ - ---- qemu-0.9.0/hw/vga_int.h -+++ qemu-0.9.0/hw/vga_int.h -@@ -174,5 +174,6 @@ - unsigned int color0, unsigned int color1, - unsigned int color_xor); - -+void *vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size); - extern const uint8_t sr_mask[8]; - extern const uint8_t gr_mask[16]; ---- qemu-0.9.0/kvm.h -+++ qemu-0.9.0/kvm.h -@@ -0,0 +1,247 @@ -+#ifndef __LINUX_KVM_H -+#define __LINUX_KVM_H -+ -+/* -+ * Userspace interface for /dev/kvm - kernel based virtual machine -+ * -+ * Note: this interface is considered experimental and may change without -+ * notice. -+ */ -+ -+#include -+#include -+ -+#define KVM_API_VERSION 4 -+ -+/* -+ * Architectural interrupt line count, and the size of the bitmap needed -+ * to hold them. -+ */ -+#define KVM_NR_INTERRUPTS 256 -+#define KVM_IRQ_BITMAP_SIZE_BYTES ((KVM_NR_INTERRUPTS + 7) / 8) -+#define KVM_IRQ_BITMAP_SIZE(type) (KVM_IRQ_BITMAP_SIZE_BYTES / sizeof(type)) -+ -+ -+/* for KVM_CREATE_MEMORY_REGION */ -+struct kvm_memory_region { -+ __u32 slot; -+ __u32 flags; -+ __u64 guest_phys_addr; -+ __u64 memory_size; /* bytes */ -+}; -+ -+/* for kvm_memory_region::flags */ -+#define KVM_MEM_LOG_DIRTY_PAGES 1UL -+ -+ -+#define KVM_EXIT_TYPE_FAIL_ENTRY 1 -+#define KVM_EXIT_TYPE_VM_EXIT 2 -+ -+enum kvm_exit_reason { -+ KVM_EXIT_UNKNOWN = 0, -+ KVM_EXIT_EXCEPTION = 1, -+ KVM_EXIT_IO = 2, -+ KVM_EXIT_CPUID = 3, -+ KVM_EXIT_DEBUG = 4, -+ KVM_EXIT_HLT = 5, -+ KVM_EXIT_MMIO = 6, -+ KVM_EXIT_IRQ_WINDOW_OPEN = 7, -+ KVM_EXIT_SHUTDOWN = 8, -+}; -+ -+/* for KVM_RUN */ -+struct kvm_run { -+ /* in */ -+ __u32 emulated; /* skip current instruction */ -+ __u32 mmio_completed; /* mmio request completed */ -+ __u8 request_interrupt_window; -+ __u8 padding1[7]; -+ -+ /* out */ -+ __u32 exit_type; -+ __u32 exit_reason; -+ __u32 instruction_length; -+ __u8 ready_for_interrupt_injection; -+ __u8 if_flag; -+ __u16 padding2; -+ -+ /* in (pre_kvm_run), out (post_kvm_run) */ -+ __u64 cr8; -+ __u64 apic_base; -+ -+ union { -+ /* KVM_EXIT_UNKNOWN */ -+ struct { -+ __u32 hardware_exit_reason; -+ } hw; -+ /* KVM_EXIT_EXCEPTION */ -+ struct { -+ __u32 exception; -+ __u32 error_code; -+ } ex; -+ /* KVM_EXIT_IO */ -+ struct { -+#define KVM_EXIT_IO_IN 0 -+#define KVM_EXIT_IO_OUT 1 -+ __u8 direction; -+ __u8 size; /* bytes */ -+ __u8 string; -+ __u8 string_down; -+ __u8 rep; -+ __u8 pad; -+ __u16 port; -+ __u64 count; -+ union { -+ __u64 address; -+ __u32 value; -+ }; -+ } io; -+ struct { -+ } debug; -+ /* KVM_EXIT_MMIO */ -+ struct { -+ __u64 phys_addr; -+ __u8 data[8]; -+ __u32 len; -+ __u8 is_write; -+ } mmio; -+ }; -+}; -+ -+/* for KVM_GET_REGS and KVM_SET_REGS */ -+struct kvm_regs { -+ /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */ -+ __u64 rax, rbx, rcx, rdx; -+ __u64 rsi, rdi, rsp, rbp; -+ __u64 r8, r9, r10, r11; -+ __u64 r12, r13, r14, r15; -+ __u64 rip, rflags; -+}; -+ -+struct kvm_segment { -+ __u64 base; -+ __u32 limit; -+ __u16 selector; -+ __u8 type; -+ __u8 present, dpl, db, s, l, g, avl; -+ __u8 unusable; -+ __u8 padding; -+}; -+ -+struct kvm_dtable { -+ __u64 base; -+ __u16 limit; -+ __u16 padding[3]; -+}; -+ -+/* for KVM_GET_SREGS and KVM_SET_SREGS */ -+struct kvm_sregs { -+ /* out (KVM_GET_SREGS) / in (KVM_SET_SREGS) */ -+ struct kvm_segment cs, ds, es, fs, gs, ss; -+ struct kvm_segment tr, ldt; -+ struct kvm_dtable gdt, idt; -+ __u64 cr0, cr2, cr3, cr4, cr8; -+ __u64 efer; -+ __u64 apic_base; -+ __u64 interrupt_bitmap[KVM_IRQ_BITMAP_SIZE(__u64)]; -+}; -+ -+struct kvm_msr_entry { -+ __u32 index; -+ __u32 reserved; -+ __u64 data; -+}; -+ -+/* for KVM_GET_MSRS and KVM_SET_MSRS */ -+struct kvm_msrs { -+ __u32 nmsrs; /* number of msrs in entries */ -+ __u32 pad; -+ -+ struct kvm_msr_entry entries[0]; -+}; -+ -+/* for KVM_GET_MSR_INDEX_LIST */ -+struct kvm_msr_list { -+ __u32 nmsrs; /* number of msrs in entries */ -+ __u32 indices[0]; -+}; -+ -+/* for KVM_TRANSLATE */ -+struct kvm_translation { -+ /* in */ -+ __u64 linear_address; -+ -+ /* out */ -+ __u64 physical_address; -+ __u8 valid; -+ __u8 writeable; -+ __u8 usermode; -+ __u8 pad[5]; -+}; -+ -+/* for KVM_INTERRUPT */ -+struct kvm_interrupt { -+ /* in */ -+ __u32 irq; -+}; -+ -+struct kvm_breakpoint { -+ __u32 enabled; -+ __u32 padding; -+ __u64 address; -+}; -+ -+/* for KVM_DEBUG_GUEST */ -+struct kvm_debug_guest { -+ /* int */ -+ __u32 enabled; -+ __u32 pad; -+ struct kvm_breakpoint breakpoints[4]; -+ __u32 singlestep; -+}; -+ -+/* for KVM_GET_DIRTY_LOG */ -+struct kvm_dirty_log { -+ __u32 slot; -+ __u32 padding; -+ union { -+ void __user *dirty_bitmap; /* one bit per page */ -+ __u64 padding; -+ }; -+}; -+ -+#define KVMIO 0xAE -+ -+/* -+ * ioctls for /dev/kvm fds: -+ */ -+#define KVM_GET_API_VERSION _IO(KVMIO, 1) -+#define KVM_CREATE_VM _IO(KVMIO, 2) /* returns a VM fd */ -+#define KVM_GET_MSR_INDEX_LIST _IOWR(KVMIO, 15, struct kvm_msr_list) -+ -+/* -+ * ioctls for VM fds -+ */ -+#define KVM_SET_MEMORY_REGION _IOW(KVMIO, 10, struct kvm_memory_region) -+/* -+ * KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns -+ * a vcpu fd. -+ */ -+#define KVM_CREATE_VCPU _IOW(KVMIO, 11, int) -+#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 12, struct kvm_dirty_log) -+ -+/* -+ * ioctls for vcpu fds -+ */ -+#define KVM_RUN _IOWR(KVMIO, 2, struct kvm_run) -+#define KVM_GET_REGS _IOR(KVMIO, 3, struct kvm_regs) -+#define KVM_SET_REGS _IOW(KVMIO, 4, struct kvm_regs) -+#define KVM_GET_SREGS _IOR(KVMIO, 5, struct kvm_sregs) -+#define KVM_SET_SREGS _IOW(KVMIO, 6, struct kvm_sregs) -+#define KVM_TRANSLATE _IOWR(KVMIO, 7, struct kvm_translation) -+#define KVM_INTERRUPT _IOW(KVMIO, 8, struct kvm_interrupt) -+#define KVM_DEBUG_GUEST _IOW(KVMIO, 9, struct kvm_debug_guest) -+#define KVM_GET_MSRS _IOWR(KVMIO, 13, struct kvm_msrs) -+#define KVM_SET_MSRS _IOW(KVMIO, 14, struct kvm_msrs) -+ -+#endif ---- qemu-0.9.0/kvmctl.c -+++ qemu-0.9.0/kvmctl.c -@@ -0,0 +1,809 @@ -+/* -+ * Kernel-based Virtual Machine control library -+ * -+ * This library provides an API to control the kvm hardware virtualization -+ * module. -+ * -+ * Copyright (C) 2006 Qumranet -+ * -+ * Authors: -+ * -+ * Avi Kivity -+ * Yaniv Kamay -+ * -+ * This work is licensed under the GNU LGPL license, version 2. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "kvmctl.h" -+ -+#define EXPECTED_KVM_API_VERSION 4 -+ -+#if EXPECTED_KVM_API_VERSION != KVM_API_VERSION -+#error libkvm: userspace and kernel version mismatch -+#endif -+ -+#define PAGE_SIZE 4096ul -+ -+/* FIXME: share this number with kvm */ -+/* FIXME: or dynamically alloc/realloc regions */ -+#define KVM_MAX_NUM_MEM_REGIONS 4u -+ -+/** -+ * \brief The KVM context -+ * -+ * The verbose KVM context -+ */ -+struct kvm_context { -+ /// Filedescriptor to /dev/kvm -+ int fd; -+ int vm_fd; -+ int vcpu_fd[1]; -+ /// Callbacks that KVM uses to emulate various unvirtualizable functionality -+ struct kvm_callbacks *callbacks; -+ void *opaque; -+ /// A pointer to the memory used as the physical memory for the guest -+ void *physical_memory; -+ /// is dirty pages logging enabled for all regions or not -+ int dirty_pages_log_all; -+ /// memory regions parameters -+ struct kvm_memory_region mem_regions[KVM_MAX_NUM_MEM_REGIONS]; -+}; -+ -+struct translation_cache { -+ unsigned long linear; -+ void *physical; -+}; -+ -+static void translation_cache_init(struct translation_cache *tr) -+{ -+ tr->physical = 0; -+} -+ -+static int translate(kvm_context_t kvm, int vcpu, struct translation_cache *tr, -+ unsigned long linear, void **physical) -+{ -+ unsigned long page = linear & ~(PAGE_SIZE-1); -+ unsigned long offset = linear & (PAGE_SIZE-1); -+ -+ if (!(tr->physical && tr->linear == page)) { -+ struct kvm_translation kvm_tr; -+ int r; -+ -+ kvm_tr.linear_address = page; -+ -+ r = ioctl(kvm->vcpu_fd[vcpu], KVM_TRANSLATE, &kvm_tr); -+ if (r == -1) -+ return -errno; -+ -+ if (!kvm_tr.valid) -+ return -EFAULT; -+ -+ tr->linear = page; -+ tr->physical = kvm->physical_memory + kvm_tr.physical_address; -+ } -+ *physical = tr->physical + offset; -+ return 0; -+} -+ -+/* -+ * memory regions parameters -+ */ -+static void kvm_memory_region_save_params(kvm_context_t kvm, -+ struct kvm_memory_region *mem) -+{ -+ if (!mem || (mem->slot >= KVM_MAX_NUM_MEM_REGIONS)) { -+ fprintf(stderr, "BUG: %s: invalid parameters\n", __FUNCTION__); -+ return; -+ } -+ kvm->mem_regions[mem->slot] = *mem; -+} -+ -+static void kvm_memory_region_clear_params(kvm_context_t kvm, int regnum) -+{ -+ if (regnum >= KVM_MAX_NUM_MEM_REGIONS) { -+ fprintf(stderr, "BUG: %s: invalid parameters\n", __FUNCTION__); -+ return; -+ } -+ kvm->mem_regions[regnum].memory_size = 0; -+} -+ -+/* -+ * dirty pages logging control -+ */ -+static int kvm_dirty_pages_log_change(kvm_context_t kvm, int regnum, __u32 flag) -+{ -+ int r; -+ struct kvm_memory_region *mem; -+ -+ if (regnum >= KVM_MAX_NUM_MEM_REGIONS) { -+ fprintf(stderr, "BUG: %s: invalid parameters\n", __FUNCTION__); -+ return 1; -+ } -+ mem = &kvm->mem_regions[regnum]; -+ if (mem->memory_size == 0) /* not used */ -+ return 0; -+ if (mem->flags & KVM_MEM_LOG_DIRTY_PAGES) /* log already enabled */ -+ return 0; -+ mem->flags |= flag; /* temporary turn on flag */ -+ r = ioctl(kvm->vm_fd, KVM_SET_MEMORY_REGION, mem); -+ mem->flags &= ~flag; /* back to previous value */ -+ if (r == -1) { -+ fprintf(stderr, "%s: %m\n", __FUNCTION__); -+ } -+ return r; -+} -+ -+static int kvm_dirty_pages_log_change_all(kvm_context_t kvm, __u32 flag) -+{ -+ int i, r; -+ -+ for (i=r=0; idirty_pages_log_all) -+ return 0; -+ kvm->dirty_pages_log_all = 1; -+ return kvm_dirty_pages_log_change_all(kvm, KVM_MEM_LOG_DIRTY_PAGES); -+} -+ -+/** -+ * Enable dirty page logging only for memory regions that were created with -+ * dirty logging enabled (disable for all other memory regions). -+ */ -+int kvm_dirty_pages_log_reset(kvm_context_t kvm) -+{ -+ if (!kvm->dirty_pages_log_all) -+ return 0; -+ kvm->dirty_pages_log_all = 0; -+ return kvm_dirty_pages_log_change_all(kvm, 0); -+} -+ -+ -+kvm_context_t kvm_init(struct kvm_callbacks *callbacks, -+ void *opaque) -+{ -+ int fd; -+ kvm_context_t kvm; -+ int r; -+ -+ fd = open("/dev/kvm", O_RDWR); -+ if (fd == -1) { -+ perror("open /dev/kvm"); -+ return NULL; -+ } -+ r = ioctl(fd, KVM_GET_API_VERSION, 0); -+ if (r == -1) { -+ fprintf(stderr, "kvm kernel version too old\n"); -+ goto out_close; -+ } -+ if (r < EXPECTED_KVM_API_VERSION) { -+ fprintf(stderr, "kvm kernel version too old\n"); -+ goto out_close; -+ } -+ if (r > EXPECTED_KVM_API_VERSION) { -+ fprintf(stderr, "kvm userspace version too old\n"); -+ goto out_close; -+ } -+ kvm = malloc(sizeof(*kvm)); -+ kvm->fd = fd; -+ kvm->vm_fd = -1; -+ kvm->callbacks = callbacks; -+ kvm->opaque = opaque; -+ kvm->dirty_pages_log_all = 0; -+ memset(&kvm->mem_regions, 0, sizeof(kvm->mem_regions)); -+ -+ return kvm; -+ out_close: -+ close(fd); -+ return NULL; -+} -+ -+void kvm_finalize(kvm_context_t kvm) -+{ -+ if (kvm->vcpu_fd[0] != -1) -+ close(kvm->vcpu_fd[0]); -+ if (kvm->vm_fd != -1) -+ close(kvm->vm_fd); -+ close(kvm->fd); -+ free(kvm); -+} -+ -+int kvm_create(kvm_context_t kvm, unsigned long memory, void **vm_mem) -+{ -+ unsigned long dosmem = 0xa0000; -+ unsigned long exmem = 0xc0000; -+ int fd = kvm->fd; -+ int r; -+ struct kvm_memory_region low_memory = { -+ .slot = 3, -+ .memory_size = memory < dosmem ? memory : dosmem, -+ .guest_phys_addr = 0, -+ }; -+ struct kvm_memory_region extended_memory = { -+ .slot = 0, -+ .memory_size = memory < exmem ? 0 : memory - exmem, -+ .guest_phys_addr = exmem, -+ }; -+ -+ kvm->vcpu_fd[0] = -1; -+ -+ fd = ioctl(fd, KVM_CREATE_VM, 0); -+ if (fd == -1) { -+ fprintf(stderr, "kvm_create_vm: %m\n"); -+ return -1; -+ } -+ kvm->vm_fd = fd; -+ -+ /* 640K should be enough. */ -+ r = ioctl(fd, KVM_SET_MEMORY_REGION, &low_memory); -+ if (r == -1) { -+ fprintf(stderr, "kvm_create_memory_region: %m\n"); -+ return -1; -+ } -+ if (extended_memory.memory_size) { -+ r = ioctl(fd, KVM_SET_MEMORY_REGION, &extended_memory); -+ if (r == -1) { -+ fprintf(stderr, "kvm_create_memory_region: %m\n"); -+ return -1; -+ } -+ } -+ -+ kvm_memory_region_save_params(kvm, &low_memory); -+ kvm_memory_region_save_params(kvm, &extended_memory); -+ -+ *vm_mem = mmap(0, memory, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); -+ if (*vm_mem == MAP_FAILED) { -+ fprintf(stderr, "mmap: %m\n"); -+ return -1; -+ } -+ kvm->physical_memory = *vm_mem; -+ -+ r = ioctl(fd, KVM_CREATE_VCPU, 0); -+ if (r == -1) { -+ fprintf(stderr, "kvm_create_vcpu: %m\n"); -+ return -1; -+ } -+ kvm->vcpu_fd[0] = r; -+ return 0; -+} -+ -+void *kvm_create_phys_mem(kvm_context_t kvm, unsigned long phys_start, -+ unsigned long len, int slot, int log, int writable) -+{ -+ void *ptr; -+ int r; -+ int fd = kvm->vm_fd; -+ int prot = PROT_READ; -+ struct kvm_memory_region memory = { -+ .slot = slot, -+ .memory_size = len, -+ .guest_phys_addr = phys_start, -+ .flags = log ? KVM_MEM_LOG_DIRTY_PAGES : 0, -+ }; -+ -+ r = ioctl(fd, KVM_SET_MEMORY_REGION, &memory); -+ if (r == -1) -+ return 0; -+ -+ kvm_memory_region_save_params(kvm, &memory); -+ -+ if (writable) -+ prot |= PROT_WRITE; -+ -+ ptr = mmap(0, len, prot, MAP_SHARED, fd, phys_start); -+ if (ptr == MAP_FAILED) -+ return 0; -+ return ptr; -+} -+ -+void kvm_destroy_phys_mem(kvm_context_t kvm, unsigned long phys_start, -+ unsigned long len) -+{ -+ //for each memory region in (phys_start, phys_start+len) do -+ // kvm_memory_region_clear_params(kvm, region); -+ kvm_memory_region_clear_params(kvm, 0); /* avoid compiler warning */ -+ printf("kvm_destroy_phys_mem: implement me\n"); -+ exit(1); -+} -+ -+ -+int kvm_get_dirty_pages(kvm_context_t kvm, int slot, void *buf) -+{ -+ int r; -+ struct kvm_dirty_log log = { -+ .slot = slot, -+ }; -+ -+ log.dirty_bitmap = buf; -+ -+ r = ioctl(kvm->vm_fd, KVM_GET_DIRTY_LOG, &log); -+ if (r == -1) -+ return -errno; -+ return 0; -+} -+ -+static int more_io(struct kvm_run *run, int first_time) -+{ -+ if (!run->io.rep) -+ return first_time; -+ else -+ return run->io.count != 0; -+} -+ -+static int handle_io(kvm_context_t kvm, struct kvm_run *run, int vcpu) -+{ -+ uint16_t addr = run->io.port; -+ struct kvm_regs regs; -+ int first_time = 1; -+ int delta; -+ struct translation_cache tr; -+ int _in = (run->io.direction == KVM_EXIT_IO_IN); -+ int r; -+ -+ translation_cache_init(&tr); -+ -+ if (run->io.string || _in) { -+ r = ioctl(kvm->vcpu_fd[vcpu], KVM_GET_REGS, ®s); -+ if (r == -1) -+ return -errno; -+ } -+ -+ delta = run->io.string_down ? -run->io.size : run->io.size; -+ -+ while (more_io(run, first_time)) { -+ void *value_addr; -+ -+ if (!run->io.string) { -+ if (_in) -+ value_addr = ®s.rax; -+ else -+ value_addr = &run->io.value; -+ } else { -+ r = translate(kvm, vcpu, &tr, run->io.address, -+ &value_addr); -+ if (r) { -+ fprintf(stderr, "failed translating I/O address %llx\n", -+ run->io.address); -+ return r; -+ } -+ } -+ -+ switch (run->io.direction) { -+ case KVM_EXIT_IO_IN: { -+ switch (run->io.size) { -+ case 1: { -+ uint8_t value; -+ r = kvm->callbacks->inb(kvm->opaque, addr, &value); -+ *(uint8_t *)value_addr = value; -+ break; -+ } -+ case 2: { -+ uint16_t value; -+ r = kvm->callbacks->inw(kvm->opaque, addr, &value); -+ *(uint16_t *)value_addr = value; -+ break; -+ } -+ case 4: { -+ uint32_t value; -+ r = kvm->callbacks->inl(kvm->opaque, addr, &value); -+ *(uint32_t *)value_addr = value; -+ break; -+ } -+ default: -+ fprintf(stderr, "bad I/O size %d\n", run->io.size); -+ return -EMSGSIZE; -+ } -+ break; -+ } -+ case KVM_EXIT_IO_OUT: -+ switch (run->io.size) { -+ case 1: -+ r = kvm->callbacks->outb(kvm->opaque, addr, -+ *(uint8_t *)value_addr); -+ break; -+ case 2: -+ r = kvm->callbacks->outw(kvm->opaque, addr, -+ *(uint16_t *)value_addr); -+ break; -+ case 4: -+ r = kvm->callbacks->outl(kvm->opaque, addr, -+ *(uint32_t *)value_addr); -+ break; -+ default: -+ fprintf(stderr, "bad I/O size %d\n", run->io.size); -+ return -EMSGSIZE; -+ } -+ break; -+ default: -+ fprintf(stderr, "bad I/O direction %d\n", run->io.direction); -+ return -EPROTO; -+ } -+ if (run->io.string) { -+ run->io.address += delta; -+ switch (run->io.direction) { -+ case KVM_EXIT_IO_IN: regs.rdi += delta; break; -+ case KVM_EXIT_IO_OUT: regs.rsi += delta; break; -+ } -+ if (run->io.rep) { -+ --regs.rcx; -+ --run->io.count; -+ } -+ } -+ first_time = 0; -+ if (r) { -+ int savedret = r; -+ r = ioctl(kvm->vcpu_fd[vcpu], KVM_SET_REGS, ®s); -+ if (r == -1) -+ return -errno; -+ -+ return savedret; -+ } -+ } -+ -+ if (run->io.string || _in) { -+ r = ioctl(kvm->vcpu_fd[vcpu], KVM_SET_REGS, ®s); -+ if (r == -1) -+ return -errno; -+ -+ } -+ -+ run->emulated = 1; -+ return 0; -+} -+ -+int handle_debug(kvm_context_t kvm, struct kvm_run *run, int vcpu) -+{ -+ return kvm->callbacks->debug(kvm->opaque, vcpu); -+} -+ -+int kvm_get_regs(kvm_context_t kvm, int vcpu, struct kvm_regs *regs) -+{ -+ return ioctl(kvm->vcpu_fd[vcpu], KVM_GET_REGS, regs); -+} -+ -+int kvm_set_regs(kvm_context_t kvm, int vcpu, struct kvm_regs *regs) -+{ -+ return ioctl(kvm->vcpu_fd[vcpu], KVM_SET_REGS, regs); -+} -+ -+int kvm_get_sregs(kvm_context_t kvm, int vcpu, struct kvm_sregs *sregs) -+{ -+ return ioctl(kvm->vcpu_fd[vcpu], KVM_GET_SREGS, sregs); -+} -+ -+int kvm_set_sregs(kvm_context_t kvm, int vcpu, struct kvm_sregs *sregs) -+{ -+ return ioctl(kvm->vcpu_fd[vcpu], KVM_SET_SREGS, sregs); -+} -+ -+/* -+ * Returns available msr list. User must free. -+ */ -+struct kvm_msr_list *kvm_get_msr_list(kvm_context_t kvm) -+{ -+ struct kvm_msr_list sizer, *msrs; -+ int r, e; -+ -+ sizer.nmsrs = 0; -+ r = ioctl(kvm->fd, KVM_GET_MSR_INDEX_LIST, &sizer); -+ if (r == -1 && errno != E2BIG) -+ return 0; -+ msrs = malloc(sizeof *msrs + sizer.nmsrs * sizeof *msrs->indices); -+ if (!msrs) { -+ errno = ENOMEM; -+ return 0; -+ } -+ msrs->nmsrs = sizer.nmsrs; -+ r = ioctl(kvm->fd, KVM_GET_MSR_INDEX_LIST, msrs); -+ if (r == -1) { -+ e = errno; -+ free(msrs); -+ errno = e; -+ return 0; -+ } -+ return msrs; -+} -+ -+int kvm_get_msrs(kvm_context_t kvm, int vcpu, struct kvm_msr_entry *msrs, -+ int n) -+{ -+ struct kvm_msrs *kmsrs = malloc(sizeof *kmsrs + n * sizeof *msrs); -+ int r, e; -+ -+ if (!kmsrs) { -+ errno = ENOMEM; -+ return -1; -+ } -+ kmsrs->nmsrs = n; -+ memcpy(kmsrs->entries, msrs, n * sizeof *msrs); -+ r = ioctl(kvm->vcpu_fd[vcpu], KVM_GET_MSRS, kmsrs); -+ e = errno; -+ memcpy(msrs, kmsrs->entries, n * sizeof *msrs); -+ free(kmsrs); -+ errno = e; -+ return r; -+} -+ -+int kvm_set_msrs(kvm_context_t kvm, int vcpu, struct kvm_msr_entry *msrs, -+ int n) -+{ -+ struct kvm_msrs *kmsrs = malloc(sizeof *kmsrs + n * sizeof *msrs); -+ int r, e; -+ -+ if (!kmsrs) { -+ errno = ENOMEM; -+ return -1; -+ } -+ kmsrs->nmsrs = n; -+ memcpy(kmsrs->entries, msrs, n * sizeof *msrs); -+ r = ioctl(kvm->vcpu_fd[vcpu], KVM_SET_MSRS, kmsrs); -+ e = errno; -+ free(kmsrs); -+ errno = e; -+ return r; -+} -+ -+static void print_seg(FILE *file, const char *name, struct kvm_segment *seg) -+{ -+ fprintf(stderr, -+ "%s %04x (%08llx/%08x p %d dpl %d db %d s %d type %x l %d" -+ " g %d avl %d)\n", -+ name, seg->selector, seg->base, seg->limit, seg->present, -+ seg->dpl, seg->db, seg->s, seg->type, seg->l, seg->g, -+ seg->avl); -+} -+ -+static void print_dt(FILE *file, const char *name, struct kvm_dtable *dt) -+{ -+ fprintf(stderr, "%s %llx/%x\n", name, dt->base, dt->limit); -+} -+ -+void kvm_show_regs(kvm_context_t kvm, int vcpu) -+{ -+ int fd = kvm->vcpu_fd[vcpu]; -+ struct kvm_regs regs; -+ struct kvm_sregs sregs; -+ int r; -+ -+ r = ioctl(fd, KVM_GET_REGS, ®s); -+ if (r == -1) { -+ perror("KVM_GET_REGS"); -+ return; -+ } -+ fprintf(stderr, -+ "rax %016llx rbx %016llx rcx %016llx rdx %016llx\n" -+ "rsi %016llx rdi %016llx rsp %016llx rbp %016llx\n" -+ "r8 %016llx r9 %016llx r10 %016llx r11 %016llx\n" -+ "r12 %016llx r13 %016llx r14 %016llx r15 %016llx\n" -+ "rip %016llx rflags %08llx\n", -+ regs.rax, regs.rbx, regs.rcx, regs.rdx, -+ regs.rsi, regs.rdi, regs.rsp, regs.rbp, -+ regs.r8, regs.r9, regs.r10, regs.r11, -+ regs.r12, regs.r13, regs.r14, regs.r15, -+ regs.rip, regs.rflags); -+ r = ioctl(fd, KVM_GET_SREGS, &sregs); -+ if (r == -1) { -+ perror("KVM_GET_SREGS"); -+ return; -+ } -+ print_seg(stderr, "cs", &sregs.cs); -+ print_seg(stderr, "ds", &sregs.ds); -+ print_seg(stderr, "es", &sregs.es); -+ print_seg(stderr, "ss", &sregs.ss); -+ print_seg(stderr, "fs", &sregs.fs); -+ print_seg(stderr, "gs", &sregs.gs); -+ print_seg(stderr, "tr", &sregs.tr); -+ print_seg(stderr, "ldt", &sregs.ldt); -+ print_dt(stderr, "gdt", &sregs.gdt); -+ print_dt(stderr, "idt", &sregs.idt); -+ fprintf(stderr, "cr0 %llx cr2 %llx cr3 %llx cr4 %llx cr8 %llx" -+ " efer %llx\n", -+ sregs.cr0, sregs.cr2, sregs.cr3, sregs.cr4, sregs.cr8, -+ sregs.efer); -+} -+ -+static int handle_cpuid(kvm_context_t kvm, struct kvm_run *run, int vcpu) -+{ -+ struct kvm_regs regs; -+ uint32_t orig_eax; -+ uint64_t rax, rbx, rcx, rdx; -+ int r; -+ -+ kvm_get_regs(kvm, vcpu, ®s); -+ orig_eax = regs.rax; -+ rax = regs.rax; -+ rbx = regs.rbx; -+ rcx = regs.rcx; -+ rdx = regs.rdx; -+ r = kvm->callbacks->cpuid(kvm->opaque, &rax, &rbx, &rcx, &rdx); -+ regs.rax = rax; -+ regs.rbx = rbx; -+ regs.rcx = rcx; -+ regs.rdx = rdx; -+ if (orig_eax == 1) -+ regs.rdx &= ~(1ull << 12); /* disable mtrr support */ -+ kvm_set_regs(kvm, vcpu, ®s); -+ run->emulated = 1; -+ return r; -+} -+ -+static int handle_mmio(kvm_context_t kvm, struct kvm_run *kvm_run) -+{ -+ unsigned long addr = kvm_run->mmio.phys_addr; -+ void *data = kvm_run->mmio.data; -+ int r = -1; -+ -+ if (kvm_run->mmio.is_write) { -+ switch (kvm_run->mmio.len) { -+ case 1: -+ r = kvm->callbacks->writeb(kvm->opaque, addr, *(uint8_t *)data); -+ break; -+ case 2: -+ r = kvm->callbacks->writew(kvm->opaque, addr, *(uint16_t *)data); -+ break; -+ case 4: -+ r = kvm->callbacks->writel(kvm->opaque, addr, *(uint32_t *)data); -+ break; -+ case 8: -+ r = kvm->callbacks->writeq(kvm->opaque, addr, *(uint64_t *)data); -+ break; -+ } -+ } else { -+ switch (kvm_run->mmio.len) { -+ case 1: -+ r = kvm->callbacks->readb(kvm->opaque, addr, (uint8_t *)data); -+ break; -+ case 2: -+ r = kvm->callbacks->readw(kvm->opaque, addr, (uint16_t *)data); -+ break; -+ case 4: -+ r = kvm->callbacks->readl(kvm->opaque, addr, (uint32_t *)data); -+ break; -+ case 8: -+ r = kvm->callbacks->readq(kvm->opaque, addr, (uint64_t *)data); -+ break; -+ } -+ kvm_run->mmio_completed = 1; -+ } -+ return r; -+} -+ -+static int handle_io_window(kvm_context_t kvm, struct kvm_run *kvm_run) -+{ -+ return kvm->callbacks->io_window(kvm->opaque); -+} -+ -+static int handle_halt(kvm_context_t kvm, struct kvm_run *kvm_run, int vcpu) -+{ -+ return kvm->callbacks->halt(kvm->opaque, vcpu); -+} -+ -+static int handle_shutdown(kvm_context_t kvm, struct kvm_run *kvm_run, -+ int vcpu) -+{ -+ return kvm->callbacks->shutdown(kvm->opaque, vcpu); -+} -+ -+int try_push_interrupts(kvm_context_t kvm) -+{ -+ return kvm->callbacks->try_push_interrupts(kvm->opaque); -+} -+ -+static void post_kvm_run(kvm_context_t kvm, struct kvm_run *kvm_run) -+{ -+ kvm->callbacks->post_kvm_run(kvm->opaque, kvm_run); -+} -+ -+static void pre_kvm_run(kvm_context_t kvm, struct kvm_run *kvm_run) -+{ -+ kvm->callbacks->pre_kvm_run(kvm->opaque, kvm_run); -+} -+ -+int kvm_run(kvm_context_t kvm, int vcpu) -+{ -+ int r; -+ int fd = kvm->vcpu_fd[vcpu]; -+ struct kvm_run kvm_run = { -+ .emulated = 0, -+ .mmio_completed = 0, -+ }; -+ -+again: -+ kvm_run.request_interrupt_window = try_push_interrupts(kvm); -+ pre_kvm_run(kvm, &kvm_run); -+ r = ioctl(fd, KVM_RUN, &kvm_run); -+ post_kvm_run(kvm, &kvm_run); -+ -+ kvm_run.emulated = 0; -+ kvm_run.mmio_completed = 0; -+ if (r == -1 && errno != EINTR) { -+ r = -errno; -+ printf("kvm_run: %m\n"); -+ return r; -+ } -+ if (r == -1) { -+ r = handle_io_window(kvm, &kvm_run); -+ goto more; -+ } -+ switch (kvm_run.exit_type) { -+ case KVM_EXIT_TYPE_FAIL_ENTRY: -+ fprintf(stderr, "kvm_run: failed entry, reason %u\n", -+ kvm_run.exit_reason & 0xffff); -+ return -ENOEXEC; -+ break; -+ case KVM_EXIT_TYPE_VM_EXIT: -+ switch (kvm_run.exit_reason) { -+ case KVM_EXIT_UNKNOWN: -+ fprintf(stderr, "unhandled vm exit: 0x%x\n", -+ kvm_run.hw.hardware_exit_reason); -+ kvm_show_regs(kvm, vcpu); -+ abort(); -+ break; -+ case KVM_EXIT_EXCEPTION: -+ fprintf(stderr, "exception %d (%x)\n", -+ kvm_run.ex.exception, -+ kvm_run.ex.error_code); -+ kvm_show_regs(kvm, vcpu); -+ abort(); -+ break; -+ case KVM_EXIT_IO: -+ r = handle_io(kvm, &kvm_run, vcpu); -+ break; -+ case KVM_EXIT_CPUID: -+ r = handle_cpuid(kvm, &kvm_run, vcpu); -+ break; -+ case KVM_EXIT_DEBUG: -+ r = handle_debug(kvm, &kvm_run, vcpu); -+ break; -+ case KVM_EXIT_MMIO: -+ r = handle_mmio(kvm, &kvm_run); -+ break; -+ case KVM_EXIT_HLT: -+ r = handle_halt(kvm, &kvm_run, vcpu); -+ break; -+ case KVM_EXIT_IRQ_WINDOW_OPEN: -+ break; -+ case KVM_EXIT_SHUTDOWN: -+ r = handle_shutdown(kvm, &kvm_run, vcpu); -+ break; -+ default: -+ fprintf(stderr, "unhandled vm exit: 0x%x\n", kvm_run.exit_reason); -+ kvm_show_regs(kvm, vcpu); -+ abort(); -+ break; -+ } -+ } -+more: -+ if (!r) -+ goto again; -+ return r; -+} -+ -+int kvm_inject_irq(kvm_context_t kvm, int vcpu, unsigned irq) -+{ -+ struct kvm_interrupt intr; -+ -+ intr.irq = irq; -+ return ioctl(kvm->vcpu_fd[vcpu], KVM_INTERRUPT, &intr); -+} -+ -+int kvm_guest_debug(kvm_context_t kvm, int vcpu, struct kvm_debug_guest *dbg) -+{ -+ return ioctl(kvm->vcpu_fd[vcpu], KVM_DEBUG_GUEST, dbg); -+} ---- qemu-0.9.0/kvmctl.h -+++ qemu-0.9.0/kvmctl.h -@@ -0,0 +1,269 @@ -+/** \file kvmctl.h -+ * libkvm API -+ */ -+ -+#ifndef KVMCTL_H -+#define KVMCTL_H -+ -+#define __user /* temporary, until installed via make headers_install */ -+#include "kvm.h" -+#include -+ -+struct kvm_context; -+ -+typedef struct kvm_context *kvm_context_t; -+ -+/*! -+ * \brief KVM callbacks structure -+ * -+ * This structure holds pointers to various functions that KVM will call -+ * when it encounters something that cannot be virtualized, such as -+ * accessing hardware devices via MMIO or regular IO. -+ */ -+struct kvm_callbacks { -+ int (*cpuid)(void *opaque, -+ uint64_t *rax, uint64_t *rbx, uint64_t *rcx, uint64_t *rdx); -+ /// For 8bit IO reads from the guest (Usually when executing 'inb') -+ int (*inb)(void *opaque, uint16_t addr, uint8_t *data); -+ /// For 16bit IO reads from the guest (Usually when executing 'inw') -+ int (*inw)(void *opaque, uint16_t addr, uint16_t *data); -+ /// For 32bit IO reads from the guest (Usually when executing 'inl') -+ int (*inl)(void *opaque, uint16_t addr, uint32_t *data); -+ /// For 8bit IO writes from the guest (Usually when executing 'outb') -+ int (*outb)(void *opaque, uint16_t addr, uint8_t data); -+ /// For 16bit IO writes from the guest (Usually when executing 'outw') -+ int (*outw)(void *opaque, uint16_t addr, uint16_t data); -+ /// For 32bit IO writes from the guest (Usually when executing 'outl') -+ int (*outl)(void *opaque, uint16_t addr, uint32_t data); -+ /// For 8bit memory reads from unmapped memory (For MMIO devices) -+ int (*readb)(void *opaque, uint64_t addr, uint8_t *data); -+ /// For 16bit memory reads from unmapped memory (For MMIO devices) -+ int (*readw)(void *opaque, uint64_t addr, uint16_t *data); -+ /// For 32bit memory reads from unmapped memory (For MMIO devices) -+ int (*readl)(void *opaque, uint64_t addr, uint32_t *data); -+ /// For 64bit memory reads from unmapped memory (For MMIO devices) -+ int (*readq)(void *opaque, uint64_t addr, uint64_t *data); -+ /// For 8bit memory writes to unmapped memory (For MMIO devices) -+ int (*writeb)(void *opaque, uint64_t addr, uint8_t data); -+ /// For 16bit memory writes to unmapped memory (For MMIO devices) -+ int (*writew)(void *opaque, uint64_t addr, uint16_t data); -+ /// For 32bit memory writes to unmapped memory (For MMIO devices) -+ int (*writel)(void *opaque, uint64_t addr, uint32_t data); -+ /// For 64bit memory writes to unmapped memory (For MMIO devices) -+ int (*writeq)(void *opaque, uint64_t addr, uint64_t data); -+ int (*debug)(void *opaque, int vcpu); -+ /*! -+ * \brief Called when the VCPU issues an 'hlt' instruction. -+ * -+ * Typically, you should yeild here to prevent 100% CPU utilization -+ * on the host CPU. -+ */ -+ int (*halt)(void *opaque, int vcpu); -+ int (*shutdown)(void *opaque, int vcpu); -+ int (*io_window)(void *opaque); -+ int (*try_push_interrupts)(void *opaque); -+ void (*post_kvm_run)(void *opaque, struct kvm_run *kvm_run); -+ void (*pre_kvm_run)(void *opaque, struct kvm_run *kvm_run); -+}; -+ -+/*! -+ * \brief Create new KVM context -+ * -+ * This creates a new kvm_context. A KVM context is a small area of data that -+ * holds information about the KVM instance that gets created by this call.\n -+ * This should always be your first call to KVM. -+ * -+ * \param callbacks Pointer to a valid kvm_callbacks structure -+ * \param opaque Not used -+ * \return NULL on failure -+ */ -+kvm_context_t kvm_init(struct kvm_callbacks *callbacks, -+ void *opaque); -+ -+/*! -+ * \brief Cleanup the KVM context -+ * -+ * Should always be called when closing down KVM.\n -+ * Exception: If kvm_init() fails, this function should not be called, as the -+ * context would be invalid -+ * -+ * \param kvm Pointer to the kvm_context that is to be freed -+ */ -+void kvm_finalize(kvm_context_t kvm); -+ -+/*! -+ * \brief Create new virtual machine -+ * -+ * This creates a new virtual machine, maps physical RAM to it, and creates a -+ * virtual CPU for it.\n -+ * \n -+ * Memory gets mapped for addresses 0->0xA0000, 0xC0000->phys_mem_bytes -+ * -+ * \param kvm Pointer to the current kvm_context -+ * \param phys_mem_bytes The amount of physical ram you want the VM to have -+ * \param phys_mem This pointer will be set to point to the memory that -+ * kvm_create allocates for physical RAM -+ * \return 0 on success -+ */ -+int kvm_create(kvm_context_t kvm, -+ unsigned long phys_mem_bytes, -+ void **phys_mem); -+ -+/*! -+ * \brief Start the VCPU -+ * -+ * This starts the VCPU and virtualization is started.\n -+ * \n -+ * This function will not return until any of these conditions are met: -+ * - An IO/MMIO handler does not return "0" -+ * - An exception that neither the guest OS, nor KVM can handle occurs -+ * -+ * \note This function will call the callbacks registered in kvm_init() -+ * to emulate those functions -+ * \note If you at any point want to interrupt the VCPU, kvm_run() will -+ * listen to the EINTR signal. This allows you to simulate external interrupts -+ * and asyncronous IO. -+ * -+ * \param kvm Pointer to the current kvm_context -+ * \param vcpu Which virtual CPU should be started -+ * \return 0 on success, but you really shouldn't expect this function to -+ * return except for when an error has occured, or when you have sent it -+ * an EINTR signal. -+ */ -+int kvm_run(kvm_context_t kvm, int vcpu); -+ -+/*! -+ * \brief Read VCPU registers -+ * -+ * This gets the GP registers from the VCPU and outputs them -+ * into a kvm_regs structure -+ * -+ * \note This function returns a \b copy of the VCPUs registers.\n -+ * If you wish to modify the VCPUs GP registers, you should call kvm_set_regs() -+ * -+ * \param kvm Pointer to the current kvm_context -+ * \param vcpu Which virtual CPU should get dumped -+ * \param regs Pointer to a kvm_regs which will be populated with the VCPUs -+ * registers values -+ * \return 0 on success -+ */ -+int kvm_get_regs(kvm_context_t kvm, int vcpu, struct kvm_regs *regs); -+ -+/*! -+ * \brief Write VCPU registers -+ * -+ * This sets the GP registers on the VCPU from a kvm_regs structure -+ * -+ * \note When this function returns, the regs pointer and the data it points to -+ * can be discarded -+ * \param kvm Pointer to the current kvm_context -+ * \param vcpu Which virtual CPU should get dumped -+ * \param regs Pointer to a kvm_regs which will be populated with the VCPUs -+ * registers values -+ * \return 0 on success -+ */ -+int kvm_set_regs(kvm_context_t kvm, int vcpu, struct kvm_regs *regs); -+ -+/*! -+ * \brief Read VCPU system registers -+ * -+ * This gets the non-GP registers from the VCPU and outputs them -+ * into a kvm_sregs structure -+ * -+ * \note This function returns a \b copy of the VCPUs registers.\n -+ * If you wish to modify the VCPUs non-GP registers, you should call -+ * kvm_set_sregs() -+ * -+ * \param kvm Pointer to the current kvm_context -+ * \param vcpu Which virtual CPU should get dumped -+ * \param regs Pointer to a kvm_sregs which will be populated with the VCPUs -+ * registers values -+ * \return 0 on success -+ */ -+int kvm_get_sregs(kvm_context_t kvm, int vcpu, struct kvm_sregs *regs); -+ -+/*! -+ * \brief Write VCPU system registers -+ * -+ * This sets the non-GP registers on the VCPU from a kvm_sregs structure -+ * -+ * \note When this function returns, the regs pointer and the data it points to -+ * can be discarded -+ * \param kvm Pointer to the current kvm_context -+ * \param vcpu Which virtual CPU should get dumped -+ * \param regs Pointer to a kvm_sregs which will be populated with the VCPUs -+ * registers values -+ * \return 0 on success -+ */ -+int kvm_set_sregs(kvm_context_t kvm, int vcpu, struct kvm_sregs *regs); -+ -+struct kvm_msr_list *kvm_get_msr_list(kvm_context_t); -+int kvm_get_msrs(kvm_context_t, int vcpu, struct kvm_msr_entry *msrs, int n); -+int kvm_set_msrs(kvm_context_t, int vcpu, struct kvm_msr_entry *msrs, int n); -+ -+/*! -+ * \brief Simulate an external vectored interrupt -+ * -+ * This allows you to simulate an external vectored interrupt. -+ * -+ * \param kvm Pointer to the current kvm_context -+ * \param vcpu Which virtual CPU should get dumped -+ * \param irq Vector number -+ * \return 0 on success -+ */ -+int kvm_inject_irq(kvm_context_t kvm, int vcpu, unsigned irq); -+int kvm_guest_debug(kvm_context_t, int vcpu, struct kvm_debug_guest *dbg); -+ -+/*! -+ * \brief Dump all VCPU information -+ * -+ * This dumps \b all the information that KVM has about a virtual CPU, namely: -+ * - GP Registers -+ * - System registers (selectors, descriptors, etc) -+ * - VMCS Data -+ * - MSRS -+ * - Pending interrupts -+ * -+ * \param kvm Pointer to the current kvm_context -+ * \param vcpu Which virtual CPU should get dumped -+ * \return 0 on success -+ */ -+int kvm_dump_vcpu(kvm_context_t kvm, int vcpu); -+ -+/*! -+ * \brief Dump VCPU registers -+ * -+ * This dumps some of the information that KVM has about a virtual CPU, namely: -+ * - GP Registers -+ * -+ * A much more verbose version of this is available as kvm_dump_vcpu() -+ * -+ * \param kvm Pointer to the current kvm_context -+ * \param vcpu Which virtual CPU should get dumped -+ * \return 0 on success -+ */ -+void kvm_show_regs(kvm_context_t kvm, int vcpu); -+ -+void *kvm_create_phys_mem(kvm_context_t, unsigned long phys_start, -+ unsigned long len, int slot, int log, int writable); -+void kvm_destroy_phys_mem(kvm_context_t, unsigned long phys_start, -+ unsigned long len); -+int kvm_get_dirty_pages(kvm_context_t, int slot, void *buf); -+ -+/*! -+ * \brief Enable dirty-pages-logging for all memory regions -+ * -+ * \param kvm Pointer to the current kvm_context -+ */ -+int kvm_dirty_pages_log_enable_all(kvm_context_t kvm); -+ -+/*! -+ * \brief Disable dirty-page-logging for some memory regions -+ * -+ * Disable dirty-pages-logging for those memory regions that were -+ * created with dirty-page-logging disabled. -+ * -+ * \param kvm Pointer to the current kvm_context -+ */ -+int kvm_dirty_pages_log_reset(kvm_context_t kvm); -+#endif ---- qemu-0.9.0/migration.c -+++ qemu-0.9.0/migration.c -@@ -24,6 +24,9 @@ - - #include "vl.h" - #include "qemu_socket.h" -+#ifdef USE_KVM -+#include "qemu-kvm.h" -+#endif - - #include - -@@ -172,6 +175,10 @@ - int dirty_count = 0; - - for (addr = 0; addr < phys_ram_size; addr += TARGET_PAGE_SIZE) { -+#ifdef USE_KVM -+ if (kvm_allowed && (addr>=0xa0000) && (addr<0xc0000)) /* do not access video-addresses */ -+ continue; -+#endif - if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) - dirty_count++; - } -@@ -186,6 +193,11 @@ - if (migrate_write_buffer(s)) - return; - -+#ifdef USE_KVM -+ if (kvm_allowed && !*s->has_error) -+ *s->has_error = kvm_update_dirty_pages_log(); -+#endif -+ - if (migrate_check_convergence(s) || *s->has_error) { - qemu_del_timer(s->timer); - qemu_free_timer(s->timer); -@@ -195,6 +207,11 @@ - } - - while (s->addr < phys_ram_size) { -+#ifdef USE_KVM -+ if (kvm_allowed && (s->addr>=0xa0000) && (s->addr<0xc0000)) /* do not access video-addresses */ -+ s->addr = 0xc0000; -+#endif -+ - if (cpu_physical_memory_get_dirty(s->addr, MIGRATION_DIRTY_FLAG)) { - uint32_t value = cpu_to_be32(s->addr); - -@@ -254,6 +271,10 @@ - fcntl(s->fd, F_SETFL, O_NONBLOCK); - - for (addr = 0; addr < phys_ram_size; addr += TARGET_PAGE_SIZE) { -+#ifdef USE_KVM -+ if (kvm_allowed && (addr>=0xa0000) && (addr<0xc0000)) /* do not access video-addresses */ -+ continue; -+#endif - if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) - cpu_physical_memory_set_dirty(addr); - } -@@ -723,6 +744,10 @@ - unsigned int sum; - - for (addr = 0; addr < phys_ram_size; addr += TARGET_PAGE_SIZE) { -+#ifdef USE_KVM -+ if (kvm_allowed && (addr>=0xa0000) && (addr<0xc0000)) /* do not access video-addresses */ -+ continue; -+#endif - sum = calc_page_checksum(addr); - qemu_put_be32(f, addr); - qemu_put_be32(f, sum); -@@ -737,6 +762,10 @@ - int num_errors = 0; - - for (addr = 0; addr < phys_ram_size; addr += TARGET_PAGE_SIZE) { -+#ifdef USE_KVM -+ if (kvm_allowed && (addr>=0xa0000) && (addr<0xc0000)) /* do not access video-addresses */ -+ continue; -+#endif - sum = calc_page_checksum(addr); - raddr = qemu_get_be32(f); - rsum = qemu_get_be32(f); ---- qemu-0.9.0/qemu-kvm.c -+++ qemu-0.9.0/qemu-kvm.c -@@ -0,0 +1,793 @@ -+ -+#include "config.h" -+#include "config-host.h" -+ -+#ifdef USE_KVM -+ -+#include "exec.h" -+ -+#include "qemu-kvm.h" -+#include -+#include -+ -+#define MSR_IA32_TSC 0x10 -+ -+extern void perror(const char *s); -+ -+int kvm_allowed = 1; -+kvm_context_t kvm_context; -+static struct kvm_msr_list *kvm_msr_list; -+static int kvm_has_msr_star; -+ -+#define NR_CPU 16 -+static CPUState *saved_env[NR_CPU]; -+ -+static void set_msr_entry(struct kvm_msr_entry *entry, uint32_t index, -+ uint64_t data) -+{ -+ entry->index = index; -+ entry->data = data; -+} -+ -+/* returns 0 on success, non-0 on failure */ -+static int get_msr_entry(struct kvm_msr_entry *entry, CPUState *env) -+{ -+ switch (entry->index) { -+ case MSR_IA32_SYSENTER_CS: -+ env->sysenter_cs = entry->data; -+ break; -+ case MSR_IA32_SYSENTER_ESP: -+ env->sysenter_esp = entry->data; -+ break; -+ case MSR_IA32_SYSENTER_EIP: -+ env->sysenter_eip = entry->data; -+ break; -+ case MSR_STAR: -+ env->star = entry->data; -+ break; -+#ifdef TARGET_X86_64 -+ case MSR_CSTAR: -+ env->cstar = entry->data; -+ break; -+ case MSR_KERNELGSBASE: -+ env->kernelgsbase = entry->data; -+ break; -+ case MSR_FMASK: -+ env->fmask = entry->data; -+ break; -+ case MSR_LSTAR: -+ env->lstar = entry->data; -+ break; -+#endif -+ case MSR_IA32_TSC: -+ env->tsc = entry->data; -+ break; -+ default: -+ printf("Warning unknown msr index 0x%x\n", entry->index); -+ return 1; -+ } -+ return 0; -+} -+ -+#ifdef TARGET_X86_64 -+#define MSR_COUNT 9 -+#else -+#define MSR_COUNT 5 -+#endif -+ -+static void set_v8086_seg(struct kvm_segment *lhs, const SegmentCache *rhs) -+{ -+ lhs->selector = rhs->selector; -+ lhs->base = rhs->base; -+ lhs->limit = rhs->limit; -+ lhs->type = 3; -+ lhs->present = 1; -+ lhs->dpl = 3; -+ lhs->db = 0; -+ lhs->s = 1; -+ lhs->l = 0; -+ lhs->g = 0; -+ lhs->avl = 0; -+ lhs->unusable = 0; -+} -+ -+static void set_seg(struct kvm_segment *lhs, const SegmentCache *rhs) -+{ -+ unsigned flags = rhs->flags; -+ lhs->selector = rhs->selector; -+ lhs->base = rhs->base; -+ lhs->limit = rhs->limit; -+ lhs->type = (flags >> DESC_TYPE_SHIFT) & 15; -+ lhs->present = (flags & DESC_P_MASK) != 0; -+ lhs->dpl = rhs->selector & 3; -+ lhs->db = (flags >> DESC_B_SHIFT) & 1; -+ lhs->s = (flags & DESC_S_MASK) != 0; -+ lhs->l = (flags >> DESC_L_SHIFT) & 1; -+ lhs->g = (flags & DESC_G_MASK) != 0; -+ lhs->avl = (flags & DESC_AVL_MASK) != 0; -+ lhs->unusable = 0; -+} -+ -+static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs) -+{ -+ lhs->selector = rhs->selector; -+ lhs->base = rhs->base; -+ lhs->limit = rhs->limit; -+ lhs->flags = -+ (rhs->type << DESC_TYPE_SHIFT) -+ | (rhs->present * DESC_P_MASK) -+ | (rhs->dpl << DESC_DPL_SHIFT) -+ | (rhs->db << DESC_B_SHIFT) -+ | (rhs->s * DESC_S_MASK) -+ | (rhs->l << DESC_L_SHIFT) -+ | (rhs->g * DESC_G_MASK) -+ | (rhs->avl * DESC_AVL_MASK); -+} -+ -+/* the reset values of qemu are not compatible to SVM -+ * this function is used to fix the segment descriptor values */ -+static void fix_realmode_dataseg(struct kvm_segment *seg) -+{ -+ seg->type = 0x02; -+ seg->present = 1; -+ seg->s = 1; -+} -+ -+static void load_regs(CPUState *env) -+{ -+ struct kvm_regs regs; -+ struct kvm_sregs sregs; -+ struct kvm_msr_entry msrs[MSR_COUNT]; -+ int rc, n; -+ -+ /* hack: save env */ -+ if (!saved_env[0]) -+ saved_env[0] = env; -+ -+ regs.rax = env->regs[R_EAX]; -+ regs.rbx = env->regs[R_EBX]; -+ regs.rcx = env->regs[R_ECX]; -+ regs.rdx = env->regs[R_EDX]; -+ regs.rsi = env->regs[R_ESI]; -+ regs.rdi = env->regs[R_EDI]; -+ regs.rsp = env->regs[R_ESP]; -+ regs.rbp = env->regs[R_EBP]; -+#ifdef TARGET_X86_64 -+ regs.r8 = env->regs[8]; -+ regs.r9 = env->regs[9]; -+ regs.r10 = env->regs[10]; -+ regs.r11 = env->regs[11]; -+ regs.r12 = env->regs[12]; -+ regs.r13 = env->regs[13]; -+ regs.r14 = env->regs[14]; -+ regs.r15 = env->regs[15]; -+#endif -+ -+ regs.rflags = env->eflags; -+ regs.rip = env->eip; -+ -+ kvm_set_regs(kvm_context, 0, ®s); -+ -+ memcpy(sregs.interrupt_bitmap, env->kvm_interrupt_bitmap, sizeof(sregs.interrupt_bitmap)); -+ -+ if ((env->eflags & VM_MASK)) { -+ set_v8086_seg(&sregs.cs, &env->segs[R_CS]); -+ set_v8086_seg(&sregs.ds, &env->segs[R_DS]); -+ set_v8086_seg(&sregs.es, &env->segs[R_ES]); -+ set_v8086_seg(&sregs.fs, &env->segs[R_FS]); -+ set_v8086_seg(&sregs.gs, &env->segs[R_GS]); -+ set_v8086_seg(&sregs.ss, &env->segs[R_SS]); -+ } else { -+ set_seg(&sregs.cs, &env->segs[R_CS]); -+ set_seg(&sregs.ds, &env->segs[R_DS]); -+ set_seg(&sregs.es, &env->segs[R_ES]); -+ set_seg(&sregs.fs, &env->segs[R_FS]); -+ set_seg(&sregs.gs, &env->segs[R_GS]); -+ set_seg(&sregs.ss, &env->segs[R_SS]); -+ -+ if (env->cr[0] & CR0_PE_MASK) { -+ /* force ss cpl to cs cpl */ -+ sregs.ss.selector = (sregs.ss.selector & ~3) | -+ (sregs.cs.selector & 3); -+ sregs.ss.dpl = sregs.ss.selector & 3; -+ } -+ -+ if (!(env->cr[0] & CR0_PG_MASK)) { -+ fix_realmode_dataseg(&sregs.ds); -+ fix_realmode_dataseg(&sregs.es); -+ fix_realmode_dataseg(&sregs.fs); -+ fix_realmode_dataseg(&sregs.gs); -+ fix_realmode_dataseg(&sregs.ss); -+ } -+ } -+ -+ set_seg(&sregs.tr, &env->tr); -+ set_seg(&sregs.ldt, &env->ldt); -+ -+ sregs.idt.limit = env->idt.limit; -+ sregs.idt.base = env->idt.base; -+ sregs.gdt.limit = env->gdt.limit; -+ sregs.gdt.base = env->gdt.base; -+ -+ sregs.cr0 = env->cr[0]; -+ sregs.cr2 = env->cr[2]; -+ sregs.cr3 = env->cr[3]; -+ sregs.cr4 = env->cr[4]; -+ -+ sregs.apic_base = cpu_get_apic_base(env); -+ sregs.efer = env->efer; -+ sregs.cr8 = cpu_get_apic_tpr(env); -+ -+ kvm_set_sregs(kvm_context, 0, &sregs); -+ -+ /* msrs */ -+ n = 0; -+ set_msr_entry(&msrs[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs); -+ set_msr_entry(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp); -+ set_msr_entry(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip); -+ if (kvm_has_msr_star) -+ set_msr_entry(&msrs[n++], MSR_STAR, env->star); -+ set_msr_entry(&msrs[n++], MSR_IA32_TSC, env->tsc); -+#ifdef TARGET_X86_64 -+ set_msr_entry(&msrs[n++], MSR_CSTAR, env->cstar); -+ set_msr_entry(&msrs[n++], MSR_KERNELGSBASE, env->kernelgsbase); -+ set_msr_entry(&msrs[n++], MSR_FMASK, env->fmask); -+ set_msr_entry(&msrs[n++], MSR_LSTAR , env->lstar); -+#endif -+ -+ rc = kvm_set_msrs(kvm_context, 0, msrs, n); -+ if (rc == -1) -+ perror("kvm_set_msrs FAILED"); -+} -+ -+ -+static void save_regs(CPUState *env) -+{ -+ struct kvm_regs regs; -+ struct kvm_sregs sregs; -+ struct kvm_msr_entry msrs[MSR_COUNT]; -+ uint32_t hflags; -+ uint32_t i, n, rc; -+ -+ kvm_get_regs(kvm_context, 0, ®s); -+ -+ env->regs[R_EAX] = regs.rax; -+ env->regs[R_EBX] = regs.rbx; -+ env->regs[R_ECX] = regs.rcx; -+ env->regs[R_EDX] = regs.rdx; -+ env->regs[R_ESI] = regs.rsi; -+ env->regs[R_EDI] = regs.rdi; -+ env->regs[R_ESP] = regs.rsp; -+ env->regs[R_EBP] = regs.rbp; -+#ifdef TARGET_X86_64 -+ env->regs[8] = regs.r8; -+ env->regs[9] = regs.r9; -+ env->regs[10] = regs.r10; -+ env->regs[11] = regs.r11; -+ env->regs[12] = regs.r12; -+ env->regs[13] = regs.r13; -+ env->regs[14] = regs.r14; -+ env->regs[15] = regs.r15; -+#endif -+ -+ env->eflags = regs.rflags; -+ env->eip = regs.rip; -+ -+ kvm_get_sregs(kvm_context, 0, &sregs); -+ -+ memcpy(env->kvm_interrupt_bitmap, sregs.interrupt_bitmap, sizeof(env->kvm_interrupt_bitmap)); -+ -+ get_seg(&env->segs[R_CS], &sregs.cs); -+ get_seg(&env->segs[R_DS], &sregs.ds); -+ get_seg(&env->segs[R_ES], &sregs.es); -+ get_seg(&env->segs[R_FS], &sregs.fs); -+ get_seg(&env->segs[R_GS], &sregs.gs); -+ get_seg(&env->segs[R_SS], &sregs.ss); -+ -+ get_seg(&env->tr, &sregs.tr); -+ get_seg(&env->ldt, &sregs.ldt); -+ -+ env->idt.limit = sregs.idt.limit; -+ env->idt.base = sregs.idt.base; -+ env->gdt.limit = sregs.gdt.limit; -+ env->gdt.base = sregs.gdt.base; -+ -+ env->cr[0] = sregs.cr0; -+ env->cr[2] = sregs.cr2; -+ env->cr[3] = sregs.cr3; -+ env->cr[4] = sregs.cr4; -+ -+ cpu_set_apic_base(env, sregs.apic_base); -+ -+ env->efer = sregs.efer; -+ cpu_set_apic_tpr(env, sregs.cr8); -+ -+#define HFLAG_COPY_MASK ~( \ -+ HF_CPL_MASK | HF_PE_MASK | HF_MP_MASK | HF_EM_MASK | \ -+ HF_TS_MASK | HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK | \ -+ HF_OSFXSR_MASK | HF_LMA_MASK | HF_CS32_MASK | \ -+ HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK) -+ -+ -+ -+ hflags = (env->segs[R_CS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK; -+ hflags |= (env->cr[0] & CR0_PE_MASK) << (HF_PE_SHIFT - CR0_PE_SHIFT); -+ hflags |= (env->cr[0] << (HF_MP_SHIFT - CR0_MP_SHIFT)) & -+ (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK); -+ hflags |= (env->eflags & (HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK)); -+ hflags |= (env->cr[4] & CR4_OSFXSR_MASK) << -+ (HF_OSFXSR_SHIFT - CR4_OSFXSR_SHIFT); -+ -+ if (env->efer & MSR_EFER_LMA) { -+ hflags |= HF_LMA_MASK; -+ } -+ -+ if ((hflags & HF_LMA_MASK) && (env->segs[R_CS].flags & DESC_L_MASK)) { -+ hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK; -+ } else { -+ hflags |= (env->segs[R_CS].flags & DESC_B_MASK) >> -+ (DESC_B_SHIFT - HF_CS32_SHIFT); -+ hflags |= (env->segs[R_SS].flags & DESC_B_MASK) >> -+ (DESC_B_SHIFT - HF_SS32_SHIFT); -+ if (!(env->cr[0] & CR0_PE_MASK) || -+ (env->eflags & VM_MASK) || -+ !(hflags & HF_CS32_MASK)) { -+ hflags |= HF_ADDSEG_MASK; -+ } else { -+ hflags |= ((env->segs[R_DS].base | -+ env->segs[R_ES].base | -+ env->segs[R_SS].base) != 0) << -+ HF_ADDSEG_SHIFT; -+ } -+ } -+ env->hflags = (env->hflags & HFLAG_COPY_MASK) | hflags; -+ CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); -+ DF = 1 - (2 * ((env->eflags >> 10) & 1)); -+ CC_OP = CC_OP_EFLAGS; -+ env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); -+ -+ tlb_flush(env, 1); -+ -+ /* msrs */ -+ n = 0; -+ msrs[n++].index = MSR_IA32_SYSENTER_CS; -+ msrs[n++].index = MSR_IA32_SYSENTER_ESP; -+ msrs[n++].index = MSR_IA32_SYSENTER_EIP; -+ if (kvm_has_msr_star) -+ msrs[n++].index = MSR_STAR; -+ msrs[n++].index = MSR_IA32_TSC; -+#ifdef TARGET_X86_64 -+ msrs[n++].index = MSR_CSTAR; -+ msrs[n++].index = MSR_KERNELGSBASE; -+ msrs[n++].index = MSR_FMASK; -+ msrs[n++].index = MSR_LSTAR; -+#endif -+ rc = kvm_get_msrs(kvm_context, 0, msrs, n); -+ if (rc == -1) { -+ perror("kvm_get_msrs FAILED"); -+ } -+ else { -+ n = rc; /* actual number of MSRs */ -+ for (i=0 ; i -+ -+ -+static int try_push_interrupts(void *opaque) -+{ -+ CPUState **envs = opaque, *env; -+ env = envs[0]; -+ -+ if (env->ready_for_interrupt_injection && -+ (env->interrupt_request & CPU_INTERRUPT_HARD) && -+ (env->eflags & IF_MASK)) { -+ env->interrupt_request &= ~CPU_INTERRUPT_HARD; -+ // for now using cpu 0 -+ kvm_inject_irq(kvm_context, 0, cpu_get_pic_interrupt(env)); -+ } -+ -+ return (env->interrupt_request & CPU_INTERRUPT_HARD) != 0; -+} -+ -+static void post_kvm_run(void *opaque, struct kvm_run *kvm_run) -+{ -+ CPUState **envs = opaque, *env; -+ env = envs[0]; -+ -+ env->eflags = (kvm_run->if_flag) ? env->eflags | IF_MASK:env->eflags & ~IF_MASK; -+ env->ready_for_interrupt_injection = kvm_run->ready_for_interrupt_injection; -+ cpu_set_apic_tpr(env, kvm_run->cr8); -+ cpu_set_apic_base(env, kvm_run->apic_base); -+} -+ -+static void pre_kvm_run(void *opaque, struct kvm_run *kvm_run) -+{ -+ CPUState **envs = opaque, *env; -+ env = envs[0]; -+ -+ kvm_run->cr8 = cpu_get_apic_tpr(env); -+} -+ -+void kvm_load_registers(CPUState *env) -+{ -+ load_regs(env); -+} -+ -+void kvm_save_registers(CPUState *env) -+{ -+ save_regs(env); -+} -+ -+int kvm_cpu_exec(CPUState *env) -+{ -+ int r; -+ int pending = (!env->ready_for_interrupt_injection || -+ ((env->interrupt_request & CPU_INTERRUPT_HARD) && -+ (env->eflags & IF_MASK))); -+ -+ if (!pending && (env->interrupt_request & CPU_INTERRUPT_EXIT)) { -+ env->interrupt_request &= ~CPU_INTERRUPT_EXIT; -+ env->exception_index = EXCP_INTERRUPT; -+ cpu_loop_exit(); -+ } -+ -+ -+ if (!saved_env[0]) -+ saved_env[0] = env; -+ -+ r = kvm_run(kvm_context, 0); -+ if (r < 0) { -+ printf("kvm_run returned %d\n", r); -+ exit(1); -+ } -+ -+ return 0; -+} -+ -+ -+static int kvm_cpuid(void *opaque, uint64_t *rax, uint64_t *rbx, -+ uint64_t *rcx, uint64_t *rdx) -+{ -+ CPUState **envs = opaque; -+ CPUState *saved_env; -+ uint32_t eax = *rax; -+ -+ saved_env = env; -+ env = envs[0]; -+ -+ env->regs[R_EAX] = *rax; -+ env->regs[R_EBX] = *rbx; -+ env->regs[R_ECX] = *rcx; -+ env->regs[R_EDX] = *rdx; -+ helper_cpuid(); -+ *rdx = env->regs[R_EDX]; -+ *rcx = env->regs[R_ECX]; -+ *rbx = env->regs[R_EBX]; -+ *rax = env->regs[R_EAX]; -+ // don't report long mode/syscall/nx if no native support -+ if (eax == 0x80000001) { -+ unsigned long h_eax = eax, h_edx; -+ -+ -+ // push/pop hack to workaround gcc 3 register pressure trouble -+ asm ( -+#ifdef __x86_64__ -+ "push %%rbx; push %%rcx; cpuid; pop %%rcx; pop %%rbx" -+#else -+ "push %%ebx; push %%ecx; cpuid; pop %%ecx; pop %%ebx" -+#endif -+ : "+a"(h_eax), "=d"(h_edx)); -+ -+ // long mode -+ if ((h_edx & 0x20000000) == 0) -+ *rdx &= ~0x20000000ull; -+ // syscall -+ if ((h_edx & 0x00000800) == 0) -+ *rdx &= ~0x00000800ull; -+ // nx -+ if ((h_edx & 0x00100000) == 0) -+ *rdx &= ~0x00100000ull; -+ } -+ env = saved_env; -+ return 0; -+} -+ -+static int kvm_debug(void *opaque, int vcpu) -+{ -+ CPUState **envs = opaque; -+ -+ env = envs[0]; -+ env->exception_index = EXCP_DEBUG; -+ return 1; -+} -+ -+static int kvm_inb(void *opaque, uint16_t addr, uint8_t *data) -+{ -+ *data = cpu_inb(0, addr); -+ return 0; -+} -+ -+static int kvm_inw(void *opaque, uint16_t addr, uint16_t *data) -+{ -+ *data = cpu_inw(0, addr); -+ return 0; -+} -+ -+static int kvm_inl(void *opaque, uint16_t addr, uint32_t *data) -+{ -+ *data = cpu_inl(0, addr); -+ return 0; -+} -+ -+static int kvm_outb(void *opaque, uint16_t addr, uint8_t data) -+{ -+ if (addr == 0xb2 && data == 0) { -+ struct kvm_regs regs; -+ -+ kvm_get_regs(kvm_context, 0, ®s); -+ -+ /* hack around smm entry: kvm doesn't emulate smm at this time */ -+ if (regs.rip == 0x409f4) -+ regs.rip += 0x4b; -+ kvm_set_regs(kvm_context, 0, ®s); -+ -+ return 0; -+ } -+ cpu_outb(0, addr, data); -+ return 0; -+} -+ -+static int kvm_outw(void *opaque, uint16_t addr, uint16_t data) -+{ -+ cpu_outw(0, addr, data); -+ return 0; -+} -+ -+static int kvm_outl(void *opaque, uint16_t addr, uint32_t data) -+{ -+ cpu_outl(0, addr, data); -+ return 0; -+} -+ -+static int kvm_readb(void *opaque, uint64_t addr, uint8_t *data) -+{ -+ *data = ldub_phys(addr); -+ return 0; -+} -+ -+static int kvm_readw(void *opaque, uint64_t addr, uint16_t *data) -+{ -+ *data = lduw_phys(addr); -+ return 0; -+} -+ -+static int kvm_readl(void *opaque, uint64_t addr, uint32_t *data) -+{ -+ *data = ldl_phys(addr); -+ return 0; -+} -+ -+static int kvm_readq(void *opaque, uint64_t addr, uint64_t *data) -+{ -+ *data = ldq_phys(addr); -+ return 0; -+} -+ -+static int kvm_writeb(void *opaque, uint64_t addr, uint8_t data) -+{ -+ stb_phys(addr, data); -+ return 0; -+} -+ -+static int kvm_writew(void *opaque, uint64_t addr, uint16_t data) -+{ -+ stw_phys(addr, data); -+ return 0; -+} -+ -+static int kvm_writel(void *opaque, uint64_t addr, uint32_t data) -+{ -+ stl_phys(addr, data); -+ return 0; -+} -+ -+static int kvm_writeq(void *opaque, uint64_t addr, uint64_t data) -+{ -+ stq_phys(addr, data); -+ return 0; -+} -+ -+static int kvm_io_window(void *opaque) -+{ -+ return 1; -+} -+ -+ -+static int kvm_halt(void *opaque, int vcpu) -+{ -+ CPUState **envs = opaque, *env; -+ -+ env = envs[0]; -+ if (!((env->interrupt_request & CPU_INTERRUPT_HARD) && -+ (env->eflags & IF_MASK))) { -+ env->hflags |= HF_HALTED_MASK; -+ env->exception_index = EXCP_HLT; -+ } -+ -+ return 1; -+} -+ -+static int kvm_shutdown(void *opaque, int vcpu) -+{ -+ qemu_system_reset_request(); -+ return 1; -+} -+ -+static struct kvm_callbacks qemu_kvm_ops = { -+ .cpuid = kvm_cpuid, -+ .debug = kvm_debug, -+ .inb = kvm_inb, -+ .inw = kvm_inw, -+ .inl = kvm_inl, -+ .outb = kvm_outb, -+ .outw = kvm_outw, -+ .outl = kvm_outl, -+ .readb = kvm_readb, -+ .readw = kvm_readw, -+ .readl = kvm_readl, -+ .readq = kvm_readq, -+ .writeb = kvm_writeb, -+ .writew = kvm_writew, -+ .writel = kvm_writel, -+ .writeq = kvm_writeq, -+ .halt = kvm_halt, -+ .shutdown = kvm_shutdown, -+ .io_window = kvm_io_window, -+ .try_push_interrupts = try_push_interrupts, -+ .post_kvm_run = post_kvm_run, -+ .pre_kvm_run = pre_kvm_run, -+}; -+ -+int kvm_qemu_init() -+{ -+ /* Try to initialize kvm */ -+ kvm_context = kvm_init(&qemu_kvm_ops, saved_env); -+ if (!kvm_context) { -+ return -1; -+ } -+ -+ return 0; -+} -+ -+int kvm_qemu_create_context(void) -+{ -+ int i; -+ -+ if (kvm_create(kvm_context, phys_ram_size, (void**)&phys_ram_base) < 0) { -+ kvm_qemu_destroy(); -+ return -1; -+ } -+ kvm_msr_list = kvm_get_msr_list(kvm_context); -+ if (!kvm_msr_list) { -+ kvm_qemu_destroy(); -+ return -1; -+ } -+ for (i = 0; i < kvm_msr_list->nmsrs; ++i) -+ if (kvm_msr_list->indices[i] == MSR_STAR) -+ kvm_has_msr_star = 1; -+ return 0; -+} -+ -+void kvm_qemu_destroy(void) -+{ -+ kvm_finalize(kvm_context); -+} -+ -+int kvm_update_debugger(CPUState *env) -+{ -+ struct kvm_debug_guest dbg; -+ int i; -+ -+ dbg.enabled = 0; -+ if (env->nb_breakpoints || env->singlestep_enabled) { -+ dbg.enabled = 1; -+ for (i = 0; i < 4 && i < env->nb_breakpoints; ++i) { -+ dbg.breakpoints[i].enabled = 1; -+ dbg.breakpoints[i].address = env->breakpoints[i]; -+ } -+ dbg.singlestep = env->singlestep_enabled; -+ } -+ return kvm_guest_debug(kvm_context, 0, &dbg); -+} -+ -+ -+/* -+ * dirty pages logging -+ */ -+/* FIXME: use unsigned long pointer instead of unsigned char */ -+unsigned char *kvm_dirty_bitmap = NULL; -+int kvm_physical_memory_set_dirty_tracking(int enable) -+{ -+ int r = 0; -+ -+ if (!kvm_allowed) -+ return 0; -+ -+ if (enable) { -+ if (!kvm_dirty_bitmap) { -+ unsigned bitmap_size = BITMAP_SIZE(phys_ram_size); -+ kvm_dirty_bitmap = qemu_malloc(bitmap_size); -+ if (kvm_dirty_bitmap == NULL) { -+ perror("Failed to allocate dirty pages bitmap"); -+ r=-1; -+ } -+ else { -+ r = kvm_dirty_pages_log_enable_all(kvm_context); -+ } -+ } -+ } -+ else { -+ if (kvm_dirty_bitmap) { -+ r = kvm_dirty_pages_log_reset(kvm_context); -+ qemu_free(kvm_dirty_bitmap); -+ kvm_dirty_bitmap = NULL; -+ } -+ } -+ return r; -+} -+ -+/* get kvm's dirty pages bitmap and update qemu's */ -+int kvm_get_dirty_pages_log_slot(int slot, -+ unsigned char *bitmap, -+ unsigned int offset, -+ unsigned int len) -+{ -+ int r; -+ unsigned int i, j, n=0; -+ unsigned char c; -+ unsigned page_number, addr, addr1; -+ -+ memset(bitmap, 0, len); -+ r = kvm_get_dirty_pages(kvm_context, slot, bitmap); -+ if (r) -+ return r; -+ -+ /* -+ * bitmap-traveling is faster than memory-traveling (for addr...) -+ * especially when most of the memory is not dirty. -+ */ -+ for (i=0; i0) { -+ j = ffsl(c) - 1; -+ c &= ~(1u<>TARGET_PAGE_BITS), HOST_LONG_BITS) / 8) -+#endif ---- qemu-0.9.0/sdl.c -+++ qemu-0.9.0/sdl.c -@@ -214,6 +214,11 @@ - { - char buf[1024]; - strcpy(buf, "QEMU"); -+#if USE_KVM -+ if (kvm_allowed) { -+ strcat(buf, "/KVM"); -+ } -+#endif - if (!vm_running) { - strcat(buf, " [Stopped]"); - } ---- qemu-0.9.0/target-i386/cpu.h -+++ qemu-0.9.0/target-i386/cpu.h -@@ -161,12 +161,17 @@ - #define HF_MP_MASK (1 << HF_MP_SHIFT) - #define HF_EM_MASK (1 << HF_EM_SHIFT) - #define HF_TS_MASK (1 << HF_TS_SHIFT) -+#define HF_IOPL_MASK (3 << HF_IOPL_SHIFT) - #define HF_LMA_MASK (1 << HF_LMA_SHIFT) - #define HF_CS64_MASK (1 << HF_CS64_SHIFT) - #define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT) -+#define HF_VM_MASK (1 << HF_VM_SHIFT) - #define HF_HALTED_MASK (1 << HF_HALTED_SHIFT) - #define HF_SMM_MASK (1 << HF_SMM_SHIFT) - -+#define CR0_PE_SHIFT 0 -+#define CR0_MP_SHIFT 1 -+ - #define CR0_PE_MASK (1 << 0) - #define CR0_MP_MASK (1 << 1) - #define CR0_EM_MASK (1 << 2) -@@ -185,7 +190,8 @@ - #define CR4_PAE_MASK (1 << 5) - #define CR4_PGE_MASK (1 << 7) - #define CR4_PCE_MASK (1 << 8) --#define CR4_OSFXSR_MASK (1 << 9) -+#define CR4_OSFXSR_SHIFT 9 -+#define CR4_OSFXSR_MASK (1 << CR4_OSFXSR_SHIFT) - #define CR4_OSXMMEXCPT_MASK (1 << 10) - - #define PG_PRESENT_BIT 0 -@@ -496,6 +502,10 @@ - target_ulong kernelgsbase; - #endif - -+#ifdef USE_KVM -+ uint64_t tsc; /* time stamp counter */ -+ uint8_t ready_for_interrupt_injection; -+#endif - uint64_t pat; - - /* temporary data for USE_CODE_COPY mode */ -@@ -534,6 +544,13 @@ - int kqemu_enabled; - int last_io_time; - #endif -+ -+#ifdef USE_KVM -+#define BITS_PER_LONG (8 * sizeof (long)) -+#define NR_IRQ_WORDS (256/ BITS_PER_LONG) -+ unsigned long kvm_interrupt_bitmap[NR_IRQ_WORDS]; -+#endif -+ - /* in order to simplify APIC support, we leave this pointer to the - user */ - struct APICState *apic_state; ---- qemu-0.9.0/target-i386/helper.c -+++ qemu-0.9.0/target-i386/helper.c -@@ -18,7 +18,9 @@ - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - #include "exec.h" -- -+#ifdef USE_KVM -+extern int kvm_allowed; -+#endif - //#define DEBUG_PCALL - - #if 0 -@@ -839,6 +841,13 @@ - uint32_t e1, e2, e3, ss; - target_ulong old_eip, esp, offset; - -+#ifdef USE_KVM -+ if (kvm_allowed) { -+ printf("%s: unexpect\n", __FUNCTION__); -+ exit(-1); -+ } -+#endif -+ - has_error_code = 0; - if (!is_int && !is_hw) { - switch(intno) { -@@ -1122,6 +1131,12 @@ - int dpl, cpl; - uint32_t e2; - -+#ifdef USE_KVM -+ if (kvm_allowed) { -+ printf("%s: unexpect\n", __FUNCTION__); -+ exit(-1); -+ } -+#endif - dt = &env->idt; - ptr = dt->base + (intno * 8); - e2 = ldl_kernel(ptr + 4); -@@ -1147,6 +1162,12 @@ - void do_interrupt(int intno, int is_int, int error_code, - target_ulong next_eip, int is_hw) - { -+#ifdef USE_KVM -+ if (kvm_allowed) { -+ printf("%s: unexpect\n", __FUNCTION__); -+ exit(-1); -+ } -+#endif - if (loglevel & CPU_LOG_INT) { - if ((env->cr[0] & CR0_PE_MASK)) { - static int count; -@@ -1958,6 +1979,12 @@ - cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl, - get_seg_base(e1, e2), limit, e2); - EIP = new_eip; -+#ifdef USE_KVM -+ if (kvm_allowed && (e2 & DESC_L_MASK)) { -+ env->exception_index = -1; -+ cpu_loop_exit(); -+ } -+#endif - } else { - /* jump to call or task gate */ - dpl = (e2 >> DESC_DPL_SHIFT) & 3; ---- qemu-0.9.0/target-i386/helper2.c -+++ qemu-0.9.0/target-i386/helper2.c -@@ -143,6 +143,9 @@ - #ifdef USE_KQEMU - kqemu_init(env); - #endif -+#ifdef USE_KVM -+ env->ready_for_interrupt_injection = 1; -+#endif - return env; - } - ---- qemu-0.9.0/vl.c -+++ qemu-0.9.0/vl.c -@@ -88,6 +88,10 @@ - - #include "exec-all.h" - -+#if USE_KVM -+#include "qemu-kvm.h" -+#endif -+ - #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" - #ifdef __sun__ - #define SMBD_COMMAND "/usr/sfw/sbin/smbd" -@@ -149,6 +153,9 @@ - int graphic_depth = 15; - int full_screen = 0; - int no_quit = 0; -+#ifdef USE_KVM -+CharDriverState *vmchannel_hds[MAX_VMCHANNEL_DEVICES]; -+#endif - CharDriverState *serial_hds[MAX_SERIAL_PORTS]; - CharDriverState *parallel_hds[MAX_PARALLEL_PORTS]; - #ifdef TARGET_I386 -@@ -5407,6 +5414,15 @@ - /* XXX: compute hflags from scratch, except for CPL and IIF */ - env->hflags = hflags; - tlb_flush(env, 1); -+#ifdef USE_KVM -+ if (kvm_allowed) { -+ for (i = 0; i < NR_IRQ_WORDS ; i++) { -+ qemu_get_betls(f, &env->kvm_interrupt_bitmap[i]); -+ } -+ qemu_get_be64s(f, &env->tsc); -+ kvm_load_registers(env); -+ } -+#endif - return 0; - } - -@@ -5555,6 +5571,10 @@ - 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 (kvm_allowed && (i>=0xa0000) && (i<0xc0000)) /* do not access video-addresses */ -+ continue; -+#endif - ret = ram_get_page(f, phys_ram_base + i, TARGET_PAGE_SIZE); - if (ret) - return ret; -@@ -5689,6 +5709,10 @@ - target_ulong addr; - - for (addr = 0; addr < phys_ram_size; addr += TARGET_PAGE_SIZE) { -+#ifdef USE_KVM -+ if (kvm_allowed && (addr>=0xa0000) && (addr<0xc0000)) /* do not access video-addresses */ -+ continue; -+#endif - if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) { - qemu_put_be32(f, addr); - qemu_put_buffer(f, phys_ram_base + addr, TARGET_PAGE_SIZE); -@@ -6237,6 +6261,10 @@ - if (reset_requested) { - reset_requested = 0; - qemu_system_reset(); -+#ifdef USE_KVM -+ if (kvm_allowed) -+ kvm_load_registers(env); -+#endif - ret = EXCP_INTERRUPT; - } - if (powerdown_requested) { -@@ -6354,6 +6382,9 @@ - "\n" - "Debug/Expert options:\n" - "-monitor dev redirect the monitor to char device 'dev'\n" -+#ifdef USE_KVM -+ "-vmchannel di:DI,dev redirect the hypercall device with device id DI, to char device 'dev'\n" -+#endif - "-serial dev redirect the serial port to char device 'dev'\n" - "-parallel dev redirect the parallel port to char device 'dev'\n" - "-pidfile file Write PID to 'file'\n" -@@ -6368,6 +6399,9 @@ - "-kernel-kqemu enable KQEMU full virtualization (default is user mode only)\n" - "-no-kqemu disable KQEMU kernel module usage\n" - #endif -+#ifdef USE_KVM -+ "-no-kvm disable KVM hardware virtualization\n" -+#endif - #ifdef USE_CODE_COPY - "-no-code-copy disable code copy acceleration\n" - #endif -@@ -6448,6 +6482,9 @@ - QEMU_OPTION_g, - QEMU_OPTION_std_vga, - QEMU_OPTION_monitor, -+#ifdef USE_KVM -+ QEMU_OPTION_vmchannel, -+#endif - QEMU_OPTION_serial, - QEMU_OPTION_parallel, - QEMU_OPTION_loadvm, -@@ -6462,6 +6499,7 @@ - QEMU_OPTION_smp, - QEMU_OPTION_vnc, - QEMU_OPTION_no_acpi, -+ QEMU_OPTION_no_kvm, - QEMU_OPTION_no_reboot, - QEMU_OPTION_daemonize, - QEMU_OPTION_option_rom, -@@ -6524,12 +6562,18 @@ - { "no-kqemu", 0, QEMU_OPTION_no_kqemu }, - { "kernel-kqemu", 0, QEMU_OPTION_kernel_kqemu }, - #endif -+#ifdef USE_KVM -+ { "no-kvm", 0, QEMU_OPTION_no_kvm }, -+#endif - #if defined(TARGET_PPC) || defined(TARGET_SPARC) - { "g", 1, QEMU_OPTION_g }, - #endif - { "localtime", 0, QEMU_OPTION_localtime }, - { "std-vga", 0, QEMU_OPTION_std_vga }, - { "monitor", 1, QEMU_OPTION_monitor }, -+#ifdef USE_KVM -+ { "vmchannel", 1, QEMU_OPTION_vmchannel }, -+#endif - { "serial", 1, QEMU_OPTION_serial }, - { "parallel", 1, QEMU_OPTION_parallel }, - { "loadvm", HAS_ARG, QEMU_OPTION_loadvm }, -@@ -6787,6 +6831,10 @@ - const char *r, *optarg; - CharDriverState *monitor_hd; - char monitor_device[128]; -+#ifdef USE_KVM -+ char vmchannel_devices[MAX_VMCHANNEL_DEVICES][128]; -+ int vmchannel_device_index; -+#endif - char serial_devices[MAX_SERIAL_PORTS][128]; - int serial_device_index; - char parallel_devices[MAX_PARALLEL_PORTS][128]; -@@ -6858,6 +6906,12 @@ - translation = BIOS_ATA_TRANSLATION_AUTO; - pstrcpy(monitor_device, sizeof(monitor_device), "vc"); - -+#ifdef USE_KVM -+ for(i = 0; i < MAX_VMCHANNEL_DEVICES; i++) -+ vmchannel_devices[i][0] = '\0'; -+ vmchannel_device_index = 0; -+#endif -+ - pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "vc"); - for(i = 1; i < MAX_SERIAL_PORTS; i++) - serial_devices[i][0] = '\0'; -@@ -7145,6 +7199,17 @@ - case QEMU_OPTION_monitor: - pstrcpy(monitor_device, sizeof(monitor_device), optarg); - break; -+#ifdef USE_KVM -+ case QEMU_OPTION_vmchannel: -+ if (vmchannel_device_index >= MAX_VMCHANNEL_DEVICES) { -+ fprintf(stderr, "qemu: too many vmchannel devices\n"); -+ exit(1); -+ } -+ pstrcpy(vmchannel_devices[vmchannel_device_index], -+ sizeof(vmchannel_devices[0]), optarg); -+ vmchannel_device_index++; -+ break; -+#endif - case QEMU_OPTION_serial: - if (serial_device_index >= MAX_SERIAL_PORTS) { - fprintf(stderr, "qemu: too many serial ports\n"); -@@ -7193,6 +7258,11 @@ - kqemu_allowed = 2; - break; - #endif -+#ifdef USE_KVM -+ case QEMU_OPTION_no_kvm: -+ kvm_allowed = 0; -+ break; -+#endif - case QEMU_OPTION_usb: - usb_enabled = 1; - break; -@@ -7283,6 +7353,15 @@ - } - #endif - -+#if USE_KVM -+ if (kvm_allowed) { -+ if (kvm_qemu_init() < 0) { -+ fprintf(stderr, "Could not initialize KVM, will disable KVM support\n"); -+ kvm_allowed = 0; -+ } -+ } -+#endif -+ - #ifdef USE_KQEMU - if (smp_cpus > 1) - kqemu_allowed = 0; -@@ -7362,11 +7441,28 @@ - phys_ram_size += ret; - } - -+#if USE_KVM -+ /* Initialize kvm */ -+ if (kvm_allowed) { -+ phys_ram_size += KVM_EXTRA_PAGES * 4096; -+ if (kvm_qemu_create_context() < 0) { -+ fprintf(stderr, "Could not create KVM context\n"); -+ exit(1); -+ } -+ } 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_base = qemu_vmalloc(phys_ram_size); - if (!phys_ram_base) { - fprintf(stderr, "Could not allocate physical memory\n"); - exit(1); - } -+#endif - - /* we always create the cdrom drive, even if no disk is there */ - bdrv_init(); -@@ -7445,6 +7541,33 @@ - } - monitor_init(monitor_hd, !nographic); - -+#ifdef USE_KVM -+ for(i = 0; i < MAX_VMCHANNEL_DEVICES; i++) { -+ const char *devname = vmchannel_devices[i]; -+ if (devname[0] != '\0' && strcmp(devname, "none")) { -+ int devid; -+ char *termn; -+ -+ if (strstart(devname, "di:", &devname)) { -+ devid = strtol(devname, &termn, 16); -+ devname = termn + 1; -+ } -+ else { -+ fprintf(stderr, "qemu: could not find vmchannel device id '%s'\n", -+ devname); -+ exit(1); -+ } -+ vmchannel_hds[i] = qemu_chr_open(devname); -+ if (!vmchannel_hds[i]) { -+ fprintf(stderr, "qemu: could not open vmchannel device '%s'\n", -+ devname); -+ exit(1); -+ } -+ vmchannel_init(vmchannel_hds[i], devid, i); -+ } -+ } -+#endif -+ - for(i = 0; i < MAX_SERIAL_PORTS; i++) { - const char *devname = serial_devices[i]; - if (devname[0] != '\0' && strcmp(devname, "none")) { ---- qemu-0.9.0/vl.h -+++ qemu-0.9.0/vl.h -@@ -157,6 +157,7 @@ - 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; -@@ -177,6 +178,10 @@ - #define BIOS_SIZE ((256 + 64) * 1024) - #endif - -+#if USE_KVM -+#define KVM_EXTRA_PAGES 3 -+#endif -+ - /* keyboard/mouse support */ - - #define MOUSE_EVENT_LBUTTON 0x01 -@@ -342,6 +347,10 @@ - CharDriverState *text_console_init(DisplayState *ds); - void console_select(unsigned int index); - -+/* vmchannel devices */ -+ -+#define MAX_VMCHANNEL_DEVICES 4 -+ - /* serial ports */ - - #define MAX_SERIAL_PORTS 4 -@@ -1220,6 +1229,11 @@ - - typedef struct ADBDevice ADBDevice; - -+/* hypercall.c */ -+ -+void pci_hypercall_init(PCIBus *bus); -+void vmchannel_init(CharDriverState *hd, uint32_t deviceid, uint32_t index); -+ - /* buf = NULL means polling */ - typedef int ADBDeviceRequest(ADBDevice *d, uint8_t *buf_out, - const uint8_t *buf, int len); diff --git a/qemu-20081008.tar.bz2 b/qemu-20081008.tar.bz2 deleted file mode 100644 index 97e28168..00000000 --- a/qemu-20081008.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:858780f82c1b357e203cb4a64b3fa6de18b344bc72e320cbbe9e09e1430a40ba -size 2780412 diff --git a/qemu-cvs-ia64.patch b/qemu-cvs-ia64.patch deleted file mode 100644 index 9965809f..00000000 --- a/qemu-cvs-ia64.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- Makefile.target -+++ Makefile.target -@@ -84,6 +84,8 @@ - OP_CFLAGS+=$(call cc-option, -fno-reorder-blocks, "") - OP_CFLAGS+=$(call cc-option, -fno-gcse, "") - OP_CFLAGS+=$(call cc-option, -fno-tree-ch, "") -+OP_CFLAGS+=$(call cc-option, -fno-tree-dominator-opts, "") -+OP_CFLAGS+=$(call cc-option, -fno-tree-vrp, "") - OP_CFLAGS+=$(call cc-option, -fno-optimize-sibling-calls, "") - OP_CFLAGS+=$(call cc-option, -fno-crossjumping, "") - OP_CFLAGS+=$(call cc-option, -fno-align-labels, "") -@@ -141,8 +143,9 @@ - endif - - ifeq ($(ARCH),ia64) --CFLAGS+=-mno-sdata --OP_CFLAGS+=-mno-sdata -+OP_CFLAGS+=$(call cc-option, -mno-sched-ar-data-spec, "") -+CFLAGS+=-G0 -mno-sdata -+OP_CFLAGS+=-G0 -mno-sdata - endif - - ifeq ($(ARCH),arm) diff --git a/qemu-cvs-ipc.patch b/qemu-cvs-ipc.patch index a460aaf5..300ef215 100644 --- a/qemu-cvs-ipc.patch +++ b/qemu-cvs-ipc.patch @@ -1,11 +1,11 @@ Index: qemu/linux-user/syscall.c ================================================================================ ---- qemu/linux-user/syscall.c -+++ qemu/linux-user/syscall.c +--- qemu-0.10.1/linux-user/syscall.c ++++ qemu-0.10.1/linux-user/syscall.c @@ -29,7 +29,7 @@ + #include #include #include - #include -#include +#include #include @@ -21,15 +21,15 @@ Index: qemu/linux-user/syscall.c #include #include #include -@@ -154,6 +157,7 @@ - +@@ -158,6 +161,7 @@ + #define __NR_sys_exit __NR_exit #define __NR_sys_sched_getaffinity __NR_sched_getaffinity +#define __NR_sys_ipc __NR_ipc #define __NR_sys_uname __NR_uname #define __NR_sys_faccessat __NR_faccessat #define __NR_sys_fchmodat __NR_fchmodat -@@ -261,6 +265,10 @@ +@@ -266,6 +270,10 @@ #if defined(TARGET_NR_tkill) && defined(__NR_tkill) _syscall2(int,sys_tkill,int,tid,int,sig) #endif @@ -40,29 +40,7 @@ Index: qemu/linux-user/syscall.c #ifdef __NR_sys_sched_getaffinity _syscall3(int,sys_sched_getaffinity,pid_t,pid,unsigned int,cpusetsize,void*,mask) #endif -@@ -1639,6 +1647,21 @@ - abi_ulong __unused2; - }; - -+struct target_ipc64_perm -+{ -+ int key; -+ unsigned int uid; -+ unsigned int gid; -+ unsigned int cuid; -+ unsigned int cgid; -+ unsigned short mode; -+ unsigned short __pad1; -+ unsigned short seq; -+ unsigned short __pad2; -+ target_ulong __unused1; -+ target_ulong __unused2; -+}; -+ - struct target_semid_ds - { - struct target_ipc_perm sem_perm; -@@ -1651,6 +1674,18 @@ +@@ -1687,6 +1695,18 @@ abi_ulong __unused4; }; @@ -81,7 +59,7 @@ Index: qemu/linux-user/syscall.c static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip, abi_ulong target_addr) { -@@ -1689,6 +1724,43 @@ +@@ -1725,6 +1745,43 @@ return 0; } @@ -125,7 +103,7 @@ Index: qemu/linux-user/syscall.c static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd, abi_ulong target_addr) { -@@ -1719,6 +1791,32 @@ +@@ -1755,6 +1812,32 @@ return 0; } @@ -158,7 +136,7 @@ Index: qemu/linux-user/syscall.c union semun { int val; struct semid_ds *buf; -@@ -1731,6 +1829,10 @@ +@@ -1767,6 +1850,10 @@ unsigned short int *array; }; @@ -169,7 +147,7 @@ Index: qemu/linux-user/syscall.c static inline abi_long target_to_host_semun(int cmd, union semun *host_su, abi_ulong target_addr, -@@ -1743,7 +1845,15 @@ +@@ -1779,7 +1866,15 @@ case IPC_SET: if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1)) return -TARGET_EFAULT; @@ -186,7 +164,7 @@ Index: qemu/linux-user/syscall.c host_su->buf = ds; unlock_user_struct(target_su, target_addr, 0); break; -@@ -1779,7 +1889,14 @@ +@@ -1815,7 +1910,14 @@ case IPC_SET: if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) return -TARGET_EFAULT; @@ -202,7 +180,7 @@ Index: qemu/linux-user/syscall.c unlock_user_struct(target_su, target_addr, 1); break; case GETVAL: -@@ -1807,7 +1924,8 @@ +@@ -1843,7 +1945,8 @@ { union semun arg; struct semid_ds dsarg; @@ -212,7 +190,7 @@ Index: qemu/linux-user/syscall.c abi_long ret = 0; switch( cmd ) { -@@ -1836,13 +1954,23 @@ +@@ -1872,13 +1975,23 @@ ret = get_errno(semctl(first, second, cmd, arg)); host_to_target_semun(cmd,ptr,&arg,&dsarg); break; @@ -237,8 +215,8 @@ Index: qemu/linux-user/syscall.c } return ret; -@@ -1866,6 +1994,41 @@ - abi_ulong __unused5; +@@ -1908,6 +2021,41 @@ + abi_ulong __unused5; }; +struct target_shmid64_ds { @@ -279,7 +257,7 @@ Index: qemu/linux-user/syscall.c static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md, abi_ulong target_addr) { -@@ -2094,11 +2257,59 @@ +@@ -2193,11 +2341,59 @@ case IPCOP_shmctl: switch(second) { case IPC_RMID: @@ -339,3 +317,48 @@ Index: qemu/linux-user/syscall.c goto unimplemented; } break; +--- qemu-0.10.1/linux-user/syscall_defs.h ++++ qemu-0.10.1/linux-user/syscall_defs.h +@@ -2001,3 +2001,18 @@ + #include "socket.h" + + #include "errno_defs.h" ++ ++struct target_ipc64_perm ++{ ++ int key; ++ uint32_t uid; ++ uint32_t gid; ++ uint32_t cuid; ++ uint32_t cgid; ++ unsigned short mode; ++ unsigned short __pad1; ++ unsigned short seq; ++ unsigned short __pad2; ++ abi_ulong __unused1; ++ abi_ulong __unused2; ++}; +--- qemu-0.10.1/linux-user/x86_64/syscall.h ++++ qemu-0.10.1/linux-user/x86_64/syscall.h +@@ -61,21 +61,6 @@ + }; + #endif + +-struct target_ipc64_perm +-{ +- int key; +- uint32_t uid; +- uint32_t gid; +- uint32_t cuid; +- uint32_t cgid; +- unsigned short mode; +- unsigned short __pad1; +- unsigned short seq; +- unsigned short __pad2; +- abi_ulong __unused1; +- abi_ulong __unused2; +-}; +- + struct target_msqid64_ds { + struct target_ipc64_perm msg_perm; + unsigned int msg_stime; /* last msgsnd time */ diff --git a/qemu-cvs-mmap-amd64.patch b/qemu-cvs-mmap-amd64.patch index a0dc6da4..d73d045f 100644 --- a/qemu-cvs-mmap-amd64.patch +++ b/qemu-cvs-mmap-amd64.patch @@ -1,10 +1,10 @@ Index: qemu/linux-user/mmap.c ================================================================================ ---- qemu/linux-user/mmap.c -+++ qemu/linux-user/mmap.c -@@ -27,6 +27,10 @@ - +--- qemu-0.10.1/linux-user/mmap.c ++++ qemu-0.10.1/linux-user/mmap.c +@@ -33,6 +33,10 @@ #include "qemu.h" + #include "qemu-common.h" +#if !defined(MAP_32BIT) +#define MAP_32BIT 0 @@ -13,7 +13,7 @@ Index: qemu/linux-user/mmap.c //#define DEBUG_MMAP #if defined(USE_NPTL) -@@ -211,7 +215,7 @@ +@@ -232,7 +236,7 @@ if (prot1 == 0) { /* no page was there, so we allocate one */ void *p = mmap(host_start, qemu_host_page_size, prot, @@ -22,12 +22,3 @@ Index: qemu/linux-user/mmap.c if (p == MAP_FAILED) return -1; prot1 = prot; -@@ -551,7 +555,7 @@ - - mmap_lock(); - /* XXX: use 5 args syscall */ -- host_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags); -+ host_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags | MAP_32BIT); - if (host_addr == -1) { - new_addr = -1; - } else { diff --git a/qemu-cvs-newpath.patch b/qemu-cvs-newpath.patch index 63689e35..ddf0db51 100644 --- a/qemu-cvs-newpath.patch +++ b/qemu-cvs-newpath.patch @@ -1,7 +1,7 @@ Index: qemu.bkp/linux-user/path.c ================================================================================ ---- qemu/linux-user/path.c -+++ qemu/linux-user/path.c +--- qemu-0.10.1/linux-user/path.c ++++ qemu-0.10.1/linux-user/path.c @@ -1,159 +1,81 @@ /* Code to mangle pathnames into those matching a given prefix. eg. open("/lib/foo.so") => open("/usr/gnemul/i386-linux/lib/foo.so"); @@ -176,7 +176,7 @@ Index: qemu.bkp/linux-user/path.c + /* Only do absolute paths: quick and dirty, but should mostly be OK. Could do relative by tracking cwd. */ -- if (!base || name[0] != '/') +- if (!base || !name || name[0] != '/') - return name; + if (!list_head || result[0] != '/') + goto exit; diff --git a/qemu-cvs-ppcspe.patch b/qemu-cvs-ppcspe.patch deleted file mode 100644 index c9908541..00000000 --- a/qemu-cvs-ppcspe.patch +++ /dev/null @@ -1,33 +0,0 @@ ---- target-ppc/op.c -+++ target-ppc/op.c -@@ -2720,6 +2720,7 @@ - } - #endif /* !defined(CONFIG_USER_ONLY) */ - -+#if defined(TARGET_PPC64) - /* SPE extension */ - void OPPROTO op_splatw_T1_64 (void) - { -@@ -3438,3 +3439,4 @@ - T0 = _do_efdtsteq(T0_64, T1_64); - RETURN(); - } -+#endif ---- target-ppc/translate.c -+++ target-ppc/translate.c -@@ -5853,6 +5853,7 @@ - - #endif /* !defined(TARGET_PPC64) */ - -+#if defined(TARGET_PPC64) - #define GEN_SPE(name0, name1, opc2, opc3, inval, type) \ - GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type) \ - { \ -@@ -6760,6 +6761,7 @@ - GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPEFPU); // - GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPEFPU); // - GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPEFPU); // -+#endif - - /* End opcode list */ - GEN_OPCODE_MARK(end); diff --git a/qemu-cvs-sched_getaffinity.patch b/qemu-cvs-sched_getaffinity.patch index e3c11e84..61cc5833 100644 --- a/qemu-cvs-sched_getaffinity.patch +++ b/qemu-cvs-sched_getaffinity.patch @@ -1,16 +1,16 @@ Index: qemu.bkp/linux-user/syscall.c ================================================================================ ---- qemu/linux-user/syscall.c -+++ qemu/linux-user/syscall.c -@@ -152,6 +152,7 @@ - } +--- qemu-0.10.1/linux-user/syscall.c ++++ qemu-0.10.1/linux-user/syscall.c +@@ -157,6 +157,7 @@ + #define __NR_sys_exit __NR_exit +#define __NR_sys_sched_getaffinity __NR_sched_getaffinity #define __NR_sys_uname __NR_uname #define __NR_sys_faccessat __NR_faccessat #define __NR_sys_fchmodat __NR_fchmodat -@@ -242,6 +243,9 @@ +@@ -265,6 +266,9 @@ #if defined(TARGET_NR_tkill) && defined(__NR_tkill) _syscall2(int,sys_tkill,int,tid,int,sig) #endif @@ -20,7 +20,7 @@ Index: qemu.bkp/linux-user/syscall.c #ifdef __NR_exit_group _syscall1(int,exit_group,int,error_code) #endif -@@ -5857,6 +5861,17 @@ +@@ -6090,6 +6094,17 @@ break; #endif diff --git a/qemu-cvs-svm2.patch b/qemu-cvs-svm2.patch deleted file mode 100644 index 68362e8c..00000000 --- a/qemu-cvs-svm2.patch +++ /dev/null @@ -1,71 +0,0 @@ -Index: qemu/cpu-exec.c -=================================================================== ---- qemu.orig/cpu-exec.c -+++ qemu/cpu-exec.c -@@ -408,7 +408,7 @@ int cpu_exec(CPUState *env1) - !(env->hflags & HF_INHIBIT_IRQ_MASK)) { - int intno; - svm_check_intercept(SVM_EXIT_INTR); -- env->interrupt_request &= ~CPU_INTERRUPT_HARD; -+ env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ); - intno = cpu_get_pic_interrupt(env); - if (loglevel & CPU_LOG_TB_IN_ASM) { - fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); -@@ -427,12 +427,13 @@ int cpu_exec(CPUState *env1) - int intno; - /* FIXME: this should respect TPR */ - env->interrupt_request &= ~CPU_INTERRUPT_VIRQ; -- stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), -- ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK); -+ svm_check_intercept(SVM_EXIT_VINTR); - intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector)); - if (loglevel & CPU_LOG_TB_IN_ASM) - fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno); - do_interrupt(intno, 0, 0, -1, 1); -+ stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), -+ ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK); - #if defined(__sparc__) && !defined(HOST_SOLARIS) - tmp_T0 = 0; - #else -Index: qemu/target-i386/helper.c -=================================================================== ---- qemu.orig/target-i386/helper.c -+++ qemu/target-i386/helper.c -@@ -4120,8 +4122,9 @@ void helper_vmrun(target_ulong addr) - if (loglevel & CPU_LOG_TB_IN_ASM) - fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code); - } -- if (int_ctl & V_IRQ_MASK) -+ if ((int_ctl & V_IRQ_MASK) || (env->intercept & INTERCEPT_VINTR)) { - env->interrupt_request |= CPU_INTERRUPT_VIRQ; -+ } - - cpu_loop_exit(); - } -@@ -4283,6 +4291,13 @@ void vmexit(uint64_t exit_code, uint64_t - ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)), - EIP); - -+ if(env->hflags & HF_INHIBIT_IRQ_MASK) { -+ stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), SVM_INTERRUPT_SHADOW_MASK); -+ env->hflags &= ~HF_INHIBIT_IRQ_MASK; -+ } else { -+ stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0); -+ } -+ - /* Save the VM state in the vmcb */ - SVM_SAVE_SEG(env->vm_vmcb, segs[R_ES], es); - SVM_SAVE_SEG(env->vm_vmcb, segs[R_CS], cs); -Index: qemu/target-i386/translate.c -=================================================================== ---- qemu.orig/target-i386/translate.c -+++ qemu/target-i386/translate.c -@@ -5551,8 +5551,6 @@ static target_ulong disas_insn(DisasCont - gen_op_set_inhibit_irq(); - /* give a chance to handle pending irqs */ - gen_jmp_im(s->pc - s->cs_base); -- if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VINTR)) -- break; - gen_eob(s); - } else { - gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); diff --git a/qemu-svn-i386-nptl.patch b/qemu-svn-i386-nptl.patch new file mode 100644 index 00000000..f403c76b --- /dev/null +++ b/qemu-svn-i386-nptl.patch @@ -0,0 +1,46 @@ +Index: linux-user/syscall.c +================================================================================ +--- configure ++++ configure +@@ -1610,6 +1610,7 @@ + echo "KVM_CFLAGS=$kvm_cflags" >> $config_mak + echo "#define CONFIG_KVM 1" >> $config_h + fi ++ target_nptl="yes" + ;; + x86_64) + echo "TARGET_ARCH=x86_64" >> $config_mak +--- linux-user/syscall.c ++++ linux-user/syscall.c +@@ -3175,8 +3175,14 @@ + flags &= ~CLONE_NPTL_FLAGS2; + + /* TODO: Implement CLONE_CHILD_CLEARTID. */ +- if (nptl_flags & CLONE_SETTLS) ++ if (nptl_flags & CLONE_SETTLS) { ++#if defined(TARGET_I386) && defined(TARGET_ABI32) ++ do_set_thread_area(new_env, newtls); ++ cpu_x86_load_seg(new_env, R_GS, new_env->segs[R_GS].selector); ++#else + cpu_set_tls (new_env, newtls); ++#endif ++ } + + /* Grab a mutex so that thread setup appears atomic. */ + pthread_mutex_lock(&clone_lock); +@@ -3247,8 +3253,14 @@ + if (flags & CLONE_PARENT_SETTID) + put_user_u32(gettid(), parent_tidptr); + ts = (TaskState *)env->opaque; +- if (flags & CLONE_SETTLS) ++ if (flags & CLONE_SETTLS) { ++#if defined(TARGET_I386) && defined(TARGET_ABI32) ++ do_set_thread_area(env, newtls); ++ cpu_x86_load_seg(env, R_GS, env->segs[R_GS].selector); ++#else + cpu_set_tls (env, newtls); ++#endif ++ } + /* TODO: Implement CLONE_CHILD_CLEARTID. */ + #endif + } else { diff --git a/qemu-svn-ncurses.patch b/qemu-svn-ncurses.patch index f2d494b4..8ee00bfc 100644 --- a/qemu-svn-ncurses.patch +++ b/qemu-svn-ncurses.patch @@ -1,15 +1,15 @@ --- configure +++ configure -@@ -799,7 +799,7 @@ +@@ -949,7 +949,7 @@ #include int main(void) { return curses_version(); } EOF -- if $cc $ARCH_CFLAGS -o $TMPE $TMPC -lcurses 2> /dev/null ; then -+ if $cc $ARCH_CFLAGS -o $TMPE $TMPC -lncurses 2> /dev/null ; then +- if $cc $ARCH_CFLAGS -o $TMPE $TMPC -lcurses > /dev/null 2> /dev/null ; then ++ if $cc $ARCH_CFLAGS -o $TMPE $TMPC -lncurses > /dev/null 2> /dev/null ; then curses=yes fi fi # test "$curses" -@@ -1102,7 +1102,7 @@ +@@ -1427,7 +1427,7 @@ if test "$curses" = "yes" ; then echo "#define CONFIG_CURSES 1" >> $config_h echo "CONFIG_CURSES=yes" >> $config_mak diff --git a/qemu-svn-nodyngen.patch b/qemu-svn-nodyngen.patch deleted file mode 100644 index e3d15e32..00000000 --- a/qemu-svn-nodyngen.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- configure -+++ configure -@@ -547,11 +549,8 @@ - mipsel-softmmu \ - mips64-softmmu \ - mips64el-softmmu \ --ppc-softmmu \ --ppcemb-softmmu \ --ppc64-softmmu \ - sh4-softmmu \ - sh4eb-softmmu \ - sparc-softmmu \ - " - fi -@@ -569,11 +566,8 @@ - m68k-linux-user \ - mips-linux-user \ - mipsel-linux-user \ --ppc-linux-user \ --ppc64-linux-user \ --ppc64abi32-linux-user \ - sh4-linux-user \ - sh4eb-linux-user \ - sparc-linux-user \ - sparc64-linux-user \ - sparc32plus-linux-user \ diff --git a/qemu-svn-pcap.patch b/qemu-svn-pcap.patch index 449cf12e..a314a545 100644 --- a/qemu-svn-pcap.patch +++ b/qemu-svn-pcap.patch @@ -2,7 +2,7 @@ Index: Makefile.target ================================================================================ --- Makefile.target +++ Makefile.target -@@ -644,6 +644,9 @@ +@@ -690,6 +690,9 @@ ifdef CONFIG_SLIRP CPPFLAGS+=-I$(SRC_PATH)/slirp endif @@ -14,7 +14,7 @@ Index: Makefile.target # specific flags are needed for non soft mmu emulator --- configure +++ configure -@@ -92,6 +92,7 @@ +@@ -160,6 +160,7 @@ gdbstub="yes" slirp="yes" vde="yes" @@ -22,7 +22,7 @@ Index: Makefile.target fmod_lib="" fmod_inc="" oss_lib="" -@@ -296,6 +297,8 @@ +@@ -392,6 +393,8 @@ ;; --disable-vde) vde="no" ;; @@ -31,7 +31,7 @@ Index: Makefile.target --disable-kqemu) kqemu="no" ;; --disable-brlapi) brlapi="no" -@@ -1204,6 +1207,10 @@ +@@ -1353,6 +1356,10 @@ echo "#define CONFIG_VDE 1" >> $config_h echo "VDE_LIBS=-lvdeplug" >> $config_mak fi @@ -42,25 +42,14 @@ Index: Makefile.target for card in $audio_card_list; do def=CONFIG_`echo $card | tr '[:lower:]' '[:upper:]'` echo "$def=yes" >> $config_mak ---- vl.c -+++ vl.c -@@ -106,6 +106,10 @@ - - #include "qemu_socket.h" - -+#if defined(CONFIG_PCAP) -+#include -+#endif -+ - #if defined(CONFIG_SLIRP) - #include "libslirp.h" - #endif -@@ -4305,6 +4309,104 @@ +--- net.c ++++ net.c +@@ -689,6 +689,104 @@ #endif /* CONFIG_SLIRP */ +#if defined(CONFIG_PCAP) -+ ++#include +typedef struct PCAPState { + VLANClientState *vc; + pcap_t *handle; @@ -87,7 +76,7 @@ Index: Makefile.target + pcap_dispatch(s->handle, 1, (pcap_handler)&pcap_callback, (u_char *)s->vc); +} + -+static int net_pcap_init(VLANState *vlan, char *ifname) ++static int net_pcap_init(VLANState *vlan, const char *model, const char *name, char *ifname) +{ + PCAPState *s; + char errbuf[PCAP_ERRBUF_SIZE]; @@ -136,7 +125,7 @@ Index: Makefile.target + } +#endif /* BIOCIMMEDIATE */ + -+ s->vc = qemu_new_vlan_client(vlan, pcap_receive, NULL, s); ++ s->vc = qemu_new_vlan_client(vlan, model, name, pcap_receive, NULL, s); + snprintf(s->vc->info_str, sizeof(s->vc->info_str), "pcap redirector"); + if ((fd = pcap_get_selectable_fd(s->handle)) < 0) { + fprintf(stderr, "qemu: pcap_get_selectable_fd failed\n"); @@ -160,30 +149,35 @@ Index: Makefile.target #if !defined(_WIN32) typedef struct TAPState { -@@ -5235,6 +5337,15 @@ - ret = net_slirp_init(vlan); - } else - #endif +@@ -1656,7 +1754,17 @@ + } + vlan->nb_host_devs++; + ret = net_slirp_init(vlan, device, name); +- } else if (!strcmp(device, "channel")) { ++ } else +#ifdef CONFIG_PCAP + if (!strcmp(device, "pcap")) { + char ifname[64]; + if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) -+ ret = net_pcap_init(vlan, NULL); ++ ret = net_pcap_init(vlan, device, name, NULL); + else -+ ret = net_pcap_init(vlan, ifname); ++ ret = net_pcap_init(vlan, device, name, ifname); + } else +#endif - #ifdef _WIN32 - if (!strcmp(device, "tap")) { - char ifname[64]; -@@ -8108,6 +8219,10 @@ - " connect the user mode network stack to VLAN 'n' and send\n" - " hostname 'host' to DHCP clients\n" ++ if (!strcmp(device, "channel")) { + long port; + char name[20], *devname; + struct VMChannel *vmc; +--- vl.c ++++ vl.c +@@ -3990,6 +3994,10 @@ + " use '[down]script=no' to disable script execution;\n" + " use 'fd=h' to connect to an already opened TAP interface\n" #endif +#ifdef CONFIG_PCAP + "-net pcap[,vlan=n][,ifname=name]\n" + " connect the host network interface using PCAP to VLAN 'n'\n" +#endif - #ifdef _WIN32 - "-net tap[,vlan=n],ifname=name\n" - " connect the host TAP network interface to VLAN 'n'\n" + "-net socket[,vlan=n][,name=str][,fd=h][,listen=[host]:port][,connect=host:port]\n" + " connect the vlan 'n' to another VLAN using a socket connection\n" + "-net socket[,vlan=n][,name=str][,fd=h][,mcast=maddr:port]\n" diff --git a/qemu-svn-s390.patch b/qemu-svn-s390.patch new file mode 100644 index 00000000..61ee9caf --- /dev/null +++ b/qemu-svn-s390.patch @@ -0,0 +1,1481 @@ +Index: s390x.ld +=================================================================== +--- s390x.ld (revision 0) ++++ s390x.ld (revision 0) +@@ -0,0 +1,194 @@ ++/* Default linker script, for normal executables */ ++OUTPUT_FORMAT("elf64-s390", "elf64-s390", ++ "elf64-s390") ++OUTPUT_ARCH(s390:64-bit) ++ENTRY(_start) ++SEARCH_DIR("/usr/s390x-suse-linux/lib64"); SEARCH_DIR("/usr/local/lib64"); SEARCH_DIR("/lib64"); SEARCH_DIR("/usr/lib64"); SEARCH_DIR("/usr/s390x-suse-linux/lib"); SEARCH_DIR("/usr/lib64"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib"); ++SECTIONS ++{ ++ /* Read-only sections, merged into text segment: */ ++ PROVIDE (__executable_start = 0x60000000); . = 0x60000000 + SIZEOF_HEADERS; ++ .interp : { *(.interp) } ++ .note.gnu.build-id : { *(.note.gnu.build-id) } ++ .hash : { *(.hash) } ++ .gnu.hash : { *(.gnu.hash) } ++ .dynsym : { *(.dynsym) } ++ .dynstr : { *(.dynstr) } ++ .gnu.version : { *(.gnu.version) } ++ .gnu.version_d : { *(.gnu.version_d) } ++ .gnu.version_r : { *(.gnu.version_r) } ++ .rel.init : { *(.rel.init) } ++ .rela.init : { *(.rela.init) } ++ .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } ++ .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } ++ .rel.fini : { *(.rel.fini) } ++ .rela.fini : { *(.rela.fini) } ++ .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } ++ .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } ++ .rel.data.rel.ro : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) } ++ .rela.data.rel.ro : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) } ++ .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } ++ .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } ++ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } ++ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } ++ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } ++ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } ++ .rel.ctors : { *(.rel.ctors) } ++ .rela.ctors : { *(.rela.ctors) } ++ .rel.dtors : { *(.rel.dtors) } ++ .rela.dtors : { *(.rela.dtors) } ++ .rel.got : { *(.rel.got) } ++ .rela.got : { *(.rela.got) } ++ .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } ++ .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } ++ .rel.plt : { *(.rel.plt) } ++ .rela.plt : { *(.rela.plt) } ++ .init : ++ { ++ KEEP (*(.init)) ++ } =0x07070707 ++ .plt : { *(.plt) } ++ .text : ++ { ++ *(.text .stub .text.* .gnu.linkonce.t.*) ++ /* .gnu.warning sections are handled specially by elf32.em. */ ++ *(.gnu.warning) ++ } =0x07070707 ++ .fini : ++ { ++ KEEP (*(.fini)) ++ } =0x07070707 ++ PROVIDE (__etext = .); ++ PROVIDE (_etext = .); ++ PROVIDE (etext = .); ++ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } ++ .rodata1 : { *(.rodata1) } ++ .eh_frame_hdr : { *(.eh_frame_hdr) } ++ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } ++ .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } ++ /* Adjust the address for the data segment. We want to adjust up to ++ the same address within the page on the next page up. */ ++ . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); ++ /* Exception handling */ ++ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } ++ .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } ++ /* Thread Local Storage sections */ ++ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } ++ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } ++ .preinit_array : ++ { ++ PROVIDE_HIDDEN (__preinit_array_start = .); ++ KEEP (*(.preinit_array)) ++ PROVIDE_HIDDEN (__preinit_array_end = .); ++ } ++ .init_array : ++ { ++ PROVIDE_HIDDEN (__init_array_start = .); ++ KEEP (*(SORT(.init_array.*))) ++ KEEP (*(.init_array)) ++ PROVIDE_HIDDEN (__init_array_end = .); ++ } ++ .fini_array : ++ { ++ PROVIDE_HIDDEN (__fini_array_start = .); ++ KEEP (*(.fini_array)) ++ KEEP (*(SORT(.fini_array.*))) ++ PROVIDE_HIDDEN (__fini_array_end = .); ++ } ++ .ctors : ++ { ++ /* gcc uses crtbegin.o to find the start of ++ the constructors, so we make sure it is ++ first. Because this is a wildcard, it ++ doesn't matter if the user does not ++ actually link against crtbegin.o; the ++ linker won't look for a file to match a ++ wildcard. The wildcard also means that it ++ doesn't matter which directory crtbegin.o ++ is in. */ ++ KEEP (*crtbegin.o(.ctors)) ++ KEEP (*crtbegin?.o(.ctors)) ++ /* We don't want to include the .ctor section from ++ the crtend.o file until after the sorted ctors. ++ The .ctor section from the crtend file contains the ++ end of ctors marker and it must be last */ ++ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) ++ KEEP (*(SORT(.ctors.*))) ++ KEEP (*(.ctors)) ++ } ++ .dtors : ++ { ++ KEEP (*crtbegin.o(.dtors)) ++ KEEP (*crtbegin?.o(.dtors)) ++ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) ++ KEEP (*(SORT(.dtors.*))) ++ KEEP (*(.dtors)) ++ } ++ .jcr : { KEEP (*(.jcr)) } ++ .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } ++ .dynamic : { *(.dynamic) } ++ . = DATA_SEGMENT_RELRO_END (0, .); ++ .got : { *(.got.plt) *(.got) } ++ .data : ++ { ++ *(.data .data.* .gnu.linkonce.d.*) ++ SORT(CONSTRUCTORS) ++ } ++ .data1 : { *(.data1) } ++ _edata = .; PROVIDE (edata = .); ++ __bss_start = .; ++ .bss : ++ { ++ *(.dynbss) ++ *(.bss .bss.* .gnu.linkonce.b.*) ++ *(COMMON) ++ /* Align here to ensure that the .bss section occupies space up to ++ _end. Align after .bss to ensure correct alignment even if the ++ .bss section disappears because there are no input sections. ++ FIXME: Why do we need it? When there is no .bss section, we don't ++ pad the .data section. */ ++ . = ALIGN(. != 0 ? 64 / 8 : 1); ++ } ++ . = ALIGN(64 / 8); ++ . = ALIGN(64 / 8); ++ _end = .; PROVIDE (end = .); ++ . = DATA_SEGMENT_END (.); ++ /* Stabs debugging sections. */ ++ .stab 0 : { *(.stab) } ++ .stabstr 0 : { *(.stabstr) } ++ .stab.excl 0 : { *(.stab.excl) } ++ .stab.exclstr 0 : { *(.stab.exclstr) } ++ .stab.index 0 : { *(.stab.index) } ++ .stab.indexstr 0 : { *(.stab.indexstr) } ++ .comment 0 : { *(.comment) } ++ /* DWARF debug sections. ++ Symbols in the DWARF debugging sections are relative to the beginning ++ of the section so we begin them at 0. */ ++ /* DWARF 1 */ ++ .debug 0 : { *(.debug) } ++ .line 0 : { *(.line) } ++ /* GNU DWARF 1 extensions */ ++ .debug_srcinfo 0 : { *(.debug_srcinfo) } ++ .debug_sfnames 0 : { *(.debug_sfnames) } ++ /* DWARF 1.1 and DWARF 2 */ ++ .debug_aranges 0 : { *(.debug_aranges) } ++ .debug_pubnames 0 : { *(.debug_pubnames) } ++ /* DWARF 2 */ ++ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } ++ .debug_abbrev 0 : { *(.debug_abbrev) } ++ .debug_line 0 : { *(.debug_line) } ++ .debug_frame 0 : { *(.debug_frame) } ++ .debug_str 0 : { *(.debug_str) } ++ .debug_loc 0 : { *(.debug_loc) } ++ .debug_macinfo 0 : { *(.debug_macinfo) } ++ /* SGI/MIPS DWARF 2 extensions */ ++ .debug_weaknames 0 : { *(.debug_weaknames) } ++ .debug_funcnames 0 : { *(.debug_funcnames) } ++ .debug_typenames 0 : { *(.debug_typenames) } ++ .debug_varnames 0 : { *(.debug_varnames) } ++ /* DWARF 3 */ ++ .debug_pubtypes 0 : { *(.debug_pubtypes) } ++ .debug_ranges 0 : { *(.debug_ranges) } ++ .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } ++ /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) } ++} +Index: dyngen-exec.h +=================================================================== +--- dyngen-exec.h (revision 6883) ++++ dyngen-exec.h (working copy) +@@ -162,7 +162,7 @@ + + /* The return address may point to the start of the next instruction. + Subtracting one gets us the call instruction itself. */ +-#if defined(__s390__) ++#if defined(__s390__) && !defined(__s390x__) + # define GETPC() ((void*)(((unsigned long)__builtin_return_address(0) & 0x7fffffffUL) - 1)) + #elif defined(__arm__) + /* Thumb return addresses have the low bit set, so we need to subtract two. +Index: Makefile.target +=================================================================== +--- Makefile.target (revision 6883) ++++ Makefile.target (working copy) +@@ -145,6 +145,9 @@ + ifeq ($(ARCH),sparc64) + CPPFLAGS+=-I$(SRC_PATH)/tcg/sparc + endif ++ifeq ($(ARCH),s390x) ++CPPFLAGS+=-I$(SRC_PATH)/tcg/s390 ++endif + ifdef CONFIG_SOFTFLOAT + LIBOBJS+=fpu/softfloat.o + else +@@ -271,6 +274,9 @@ + ifeq ($(ARCH),s390) + LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld + endif ++ifeq ($(ARCH),s390x) ++LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld ++endif + + ifeq ($(ARCH),sparc) + # -static is used to avoid g1/g3 usage by the dynamic linker +@@ -436,6 +442,9 @@ + ifeq ($(ARCH),s390) + LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld + endif ++ifeq ($(ARCH),s390x) ++LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld ++endif + + ifeq ($(ARCH),sparc) + # -static is used to avoid g1/g3 usage by the dynamic linker +Index: s390-dis.c +=================================================================== +--- s390-dis.c (revision 6883) ++++ s390-dis.c (working copy) +@@ -195,10 +195,10 @@ + // switch (info->mach) + // { + // case bfd_mach_s390_31: +- current_arch_mask = 1 << S390_OPCODE_ESA; ++// current_arch_mask = 1 << S390_OPCODE_ESA; + // break; + // case bfd_mach_s390_64: +-// current_arch_mask = 1 << S390_OPCODE_ZARCH; ++ current_arch_mask = 1 << S390_OPCODE_ZARCH; + // break; + // default: + // abort (); +Index: linux-user/syscall.c +=================================================================== +--- linux-user/syscall.c (revision 6883) ++++ linux-user/syscall.c (working copy) +@@ -184,7 +184,7 @@ + #define __NR_sys_inotify_add_watch __NR_inotify_add_watch + #define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch + +-#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) ++#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) || defined(__s390x__) + #define __NR__llseek __NR_lseek + #endif + +Index: tcg/s390/tcg-target.c +=================================================================== +--- tcg/s390/tcg-target.c (revision 0) ++++ tcg/s390/tcg-target.c (revision 0) +@@ -0,0 +1,1082 @@ ++/* ++ * Tiny Code Generator for QEMU ++ * ++ * Copyright (c) 2009 Ulrich Hecht ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#ifndef NDEBUG ++static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { ++ "%r0", ++ "%r1", ++ "%r2", ++ "%r3", ++ "%r4", ++ "%r5", ++ "%r6", ++ "%r7", ++ "%r8", ++ "%r9", ++ "%r10", ++ "%r11", ++ "%r12", ++ "%r13", ++ "%r14", ++ "%r15" ++}; ++#endif ++ ++static const int tcg_target_reg_alloc_order[] = { ++ TCG_REG_R6, ++ TCG_REG_R7, ++ TCG_REG_R8, ++ TCG_REG_R9, ++ TCG_REG_R10, ++ TCG_REG_R11, ++ TCG_REG_R12, ++ TCG_REG_R13, ++ TCG_REG_R14, ++ TCG_REG_R15, ++ TCG_REG_R0, ++ TCG_REG_R1, ++ TCG_REG_R2, ++ TCG_REG_R3, ++ TCG_REG_R4, ++ TCG_REG_R5, ++}; ++ ++static const int tcg_target_call_iarg_regs[4] = { ++ TCG_REG_R2, TCG_REG_R3, TCG_REG_R4, TCG_REG_R5 ++}; ++static const int tcg_target_call_oarg_regs[2] = { ++ TCG_REG_R2, TCG_REG_R3 ++}; ++ ++static void patch_reloc(uint8_t *code_ptr, int type, ++ tcg_target_long value, tcg_target_long addend) ++{ ++ switch (type) { ++ case R_390_PC32DBL: ++ //fprintf(stderr,"patching %p to 0x%lx (0x%lx)\n", code_ptr, value, (value - ((tcg_target_long)code_ptr + addend)) >> 1); ++ *(uint32_t*)code_ptr = (value - ((tcg_target_long)code_ptr + addend)) >> 1; ++ break; ++ default: ++ tcg_abort(); ++ break; ++ } ++} ++ ++/* maximum number of register used for input function arguments */ ++static inline int tcg_target_get_call_iarg_regs_count(int flags) ++{ ++ return 4; ++} ++ ++/* parse target specific constraints */ ++static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) ++{ ++ const char *ct_str; ++ ++ ct->ct |= TCG_CT_REG; ++ tcg_regset_set32(ct->u.regs, 0, 0xffff); ++ ct_str = *pct_str; ++ switch(ct_str[0]) { ++ case 'L': /* qemu_ld constraint */ ++ tcg_regset_reset_reg (ct->u.regs, TCG_REG_R2); ++#ifdef CONFIG_SOFTMMU ++ tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3); ++#endif ++ break; ++ case 'S': /* qemu_st constraint */ ++ tcg_regset_reset_reg (ct->u.regs, TCG_REG_R2); ++#ifdef CONFIG_SOFTMMU ++ tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3); ++ tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4); ++#endif ++ break; ++ case 'R': /* not R0 */ ++ tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0); ++ break; ++ default: ++ break; ++ } ++ ct_str++; ++ *pct_str = ct_str; ++ ++ return 0; ++} ++ ++/* Test if a constant matches the constraint. */ ++/* No idea what to do here, just eat everything. */ ++static inline int tcg_target_const_match(tcg_target_long val, ++ const TCGArgConstraint *arg_ct) ++{ ++ int ct; ++ //fprintf(stderr,"tcg_target_const_match %ld ct %d\n",val,arg_ct->ct); ++ ct = arg_ct->ct; ++ if (ct & TCG_CT_CONST) ++ return 1; ++ else ++ return 0; ++} ++ ++#ifdef CONFIG_SOFTMMU ++ ++#include "../../softmmu_defs.h" ++ ++static void *qemu_ld_helpers[4] = { ++ __ldb_mmu, ++ __ldw_mmu, ++ __ldl_mmu, ++ __ldq_mmu, ++}; ++ ++static void *qemu_st_helpers[4] = { ++ __stb_mmu, ++ __stw_mmu, ++ __stl_mmu, ++ __stq_mmu, ++}; ++#endif ++ ++static uint8_t *tb_ret_addr; ++ ++/* signed/unsigned is handled by using COMPARE and COMPARE LOGICAL, ++ respectively */ ++static const uint8_t tcg_cond_to_s390_cond[10] = { ++ [TCG_COND_EQ] = 8, ++ [TCG_COND_LT] = 4, ++ [TCG_COND_LTU] = 4, ++ [TCG_COND_LE] = 8 | 4, ++ [TCG_COND_LEU] = 8 | 4, ++ [TCG_COND_GT] = 2, ++ [TCG_COND_GTU] = 2, ++ [TCG_COND_GE] = 8 | 2, ++ [TCG_COND_GEU] = 8 | 2, ++ [TCG_COND_NE] = 4 | 2 | 1, ++}; ++ ++/* emit load/store (and then some) instructions (E3 prefix) */ ++static inline void tcg_out_e3(TCGContext* s, int op, int r1, int r2, int disp) ++{ ++ tcg_out16(s, 0xe300 | (r1 << 4)); ++ tcg_out32(s, op | (r2 << 28) | ((disp & 0xfff) << 16) | ((disp >> 12) << 8)); ++} ++#define E3_LG 0x04 ++#define E3_LRVG 0x0f ++#define E3_LGF 0x14 ++#define E3_LGH 0x15 ++#define E3_LLGF 0x16 ++#define E3_LRV 0x1e ++#define E3_LRVH 0x1f ++#define E3_CG 0x20 ++#define E3_STG 0x24 ++#define E3_STRVG 0x2f ++#define E3_STRV 0x3e ++#define E3_STRVH 0x3f ++#define E3_STHY 0x70 ++#define E3_STCY 0x72 ++#define E3_LGB 0x77 ++#define E3_LLGC 0x90 ++#define E3_LLGH 0x91 ++ ++/* emit 64-bit register/register insns (B9 prefix) */ ++static inline void tcg_out_b9(TCGContext* s, int op, int r1, int r2) ++{ ++ tcg_out32(s, 0xb9000000 | (op << 16) | (r1 << 4) | r2); ++} ++#define B9_LGR 0x04 ++#define B9_AGR 0x08 ++#define B9_SGR 0x09 ++#define B9_MSGR 0x0c ++#define B9_LGFR 0x14 ++#define B9_LLGFR 0x16 ++#define B9_CGR 0x20 ++#define B9_CLGR 0x21 ++#define B9_NGR 0x80 ++#define B9_OGR 0x81 ++#define B9_XGR 0x82 ++ ++/* emit (mostly) 32-bit register/register insns */ ++static inline void tcg_out_rr(TCGContext* s, int op, int r1, int r2) ++{ ++ tcg_out16(s, (op << 8) | (r1 << 4) | r2); ++} ++#define RR_BASR 0x0d ++#define RR_NR 0x14 ++#define RR_CLR 0x15 ++#define RR_OR 0x16 ++#define RR_XR 0x17 ++#define RR_LR 0x18 ++#define RR_CR 0x19 ++#define RR_AR 0x1a ++#define RR_SR 0x1b ++ ++/* emit 64-bit shifts (EB prefix) */ ++static inline void tcg_out_sh64(TCGContext* s, int op, int r0, int r1, int r2, int imm) ++{ ++ tcg_out16(s, 0xeb00 | (r0 << 4) | r1); ++ tcg_out32(s, op | (r2 << 28) | ((imm & 0xfff) << 16) | ((imm >> 12) << 8)); ++} ++#define SH64_REG_NONE 0 /* use immediate only (not R0!) */ ++#define SH64_SRAG 0x0a ++#define SH64_SRLG 0x0c ++#define SH64_SLLG 0x0d ++ ++/* emit 32-bit shifts */ ++static inline void tcg_out_sh32(TCGContext* s, int op, int r0, int r1, int imm) ++{ ++ tcg_out32(s, 0x80000000 | (op << 24) | (r0 << 20) | (r1 << 12) | imm); ++} ++#define SH32_REG_NONE 0 /* use immediate only (not R0!) */ ++#define SH32_SRL 0x8 ++#define SH32_SLL 0x9 ++#define SH32_SRA 0xa ++ ++/* branch to relative address (long) */ ++static inline void tcg_out_brasl(TCGContext* s, int r, tcg_target_long raddr) ++{ ++ tcg_out16(s, 0xc005 | (r << 4)); ++ tcg_out32(s, raddr >> 1); ++} ++ ++/* store 8/16/32 bits */ ++static inline void tcg_out_store(TCGContext* s, int op, int r0, int r1, int off) ++{ ++ tcg_out32(s, (op << 24) | (r0 << 20) | (r1 << 12) | off); ++} ++#define ST_STH 0x40 ++#define ST_STC 0x42 ++#define ST_ST 0x50 ++ ++/* load a register with an immediate value */ ++static inline void tcg_out_movi(TCGContext *s, TCGType type, ++ int ret, tcg_target_long arg) ++{ ++ //fprintf(stderr,"tcg_out_movi ret 0x%x arg 0x%lx\n",ret,arg); ++ if(arg >= -0x8000 && arg < 0x8000) { /* signed immediate load */ ++ /* lghi %rret, arg */ ++ tcg_out32(s, 0xa7090000 | (ret << 20) | (arg & 0xffff)); ++ } ++ else if (!(arg & 0xffffffffffff0000UL)) { ++ /* llill %rret, arg */ ++ tcg_out32(s, 0xa50f0000 | (ret << 20) | arg); ++ } ++ else if (!(arg & 0xffffffff00000000UL)) { ++ /* llill %rret, arg */ ++ tcg_out32(s, 0xa50f0000 | (ret << 20) | (arg & 0xffff)); ++ /* iilh %rret, arg */ ++ tcg_out32(s, 0xa5020000 | (ret << 20) | (arg >> 16)); ++ } ++ else { ++ /* branch over constant and store its address in R13 */ ++ tcg_out_brasl(s, TCG_REG_R13, 14); ++ /* 64-bit constant */ ++ tcg_out32(s,arg >> 32); ++ tcg_out32(s,arg); ++ /* load constant to ret */ ++ tcg_out_e3(s, E3_LG, ret, TCG_REG_R13, 0); ++ } ++} ++ ++/* load data without address translation or endianness conversion */ ++static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg, ++ int arg1, tcg_target_long arg2) ++{ ++ int op; ++ //fprintf(stderr,"tcg_out_ld type %d arg %d arg1 %d arg2 %ld\n",type,arg,arg1,arg2); ++ ++ if (type == TCG_TYPE_I32) op = E3_LLGF; /* 32-bit zero-extended */ ++ else op = E3_LG; /* 64-bit */ ++ ++ if(arg2 < -0x80000 || arg2 > 0x7ffff) { ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, arg2); /* load the displacement */ ++ tcg_out_b9(s, B9_AGR, TCG_REG_R13, arg1); /* add the address */ ++ tcg_out_e3(s, op, arg, TCG_REG_R13, 0); /* load the data */ ++ } ++ else { ++ tcg_out_e3(s, op, arg, arg1, arg2); /* load the data */ ++ } ++} ++ ++/* load data with address translation (if applicable) and endianness conversion */ ++static void tcg_out_qemu_ld(TCGContext* s, const TCGArg* args, int opc) ++{ ++ int addr_reg, data_reg, mem_index, s_bits; ++#if defined(CONFIG_SOFTMMU) ++ uint16_t *label1_ptr, *label2_ptr; ++#endif ++ ++ data_reg = *args++; ++ addr_reg = *args++; ++ mem_index = *args; ++ ++ s_bits = opc & 3; ++ ++ int arg0 = TCG_REG_R2; ++#ifdef CONFIG_SOFTMMU ++ int arg1 = TCG_REG_R3; ++#endif ++ ++ /* fprintf(stderr,"tcg_out_qemu_ld opc %d data_reg %d addr_reg %d mem_index %d s_bits %d\n", ++ opc, data_reg, addr_reg, mem_index, s_bits); */ ++ ++#ifdef CONFIG_SOFTMMU ++ tcg_out_b9(s, B9_LGR, arg1, addr_reg); ++ tcg_out_b9(s, B9_LGR, arg0, addr_reg); ++ ++ tcg_out_sh64(s, SH64_SRLG, arg1, addr_reg, SH64_REG_NONE, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); ++ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, TARGET_PAGE_MASK | ((1 << s_bits) - 1)); ++ tcg_out_b9(s, B9_NGR, arg0, TCG_REG_R13); ++ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS); ++ tcg_out_b9(s, B9_NGR, arg1, TCG_REG_R13); ++ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, offsetof(CPUState, tlb_table[mem_index][0].addr_read)); ++ tcg_out_b9(s, B9_AGR, arg1, TCG_REG_R13); ++ ++ tcg_out_b9(s, B9_AGR, arg1, TCG_AREG0); ++ ++ tcg_out_e3(s, E3_CG, arg0, arg1, 0); ++ ++ label1_ptr = (uint16_t*)s->code_ptr; ++ tcg_out32(s, 0xa7840000); /* je label1 (offset will be patched in later) */ ++ ++ /* call load helper */ ++ tcg_out_b9(s, B9_LGR, arg0, addr_reg); ++ tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index); ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, (tcg_target_ulong)qemu_ld_helpers[s_bits]); ++ tcg_out_rr(s, RR_BASR, TCG_REG_R14, TCG_REG_R13); ++ ++ /* sign extension */ ++ switch(opc) { ++ case 0 | 4: ++ tcg_out_sh64(s, SH64_SLLG, data_reg, arg0, SH64_REG_NONE, 56); ++ tcg_out_sh64(s, SH64_SRAG, data_reg, data_reg, SH64_REG_NONE, 56); ++ break; ++ case 1 | 4: ++ tcg_out_sh64(s, SH64_SLLG, data_reg, arg0, SH64_REG_NONE, 48); ++ tcg_out_sh64(s, SH64_SRAG, data_reg, data_reg, SH64_REG_NONE, 48); ++ break; ++ case 2 | 4: ++ tcg_out_b9(s, B9_LGFR, data_reg, arg0); ++ break; ++ case 0: case 1: case 2: case 3: default: ++ /* unsigned -> just copy */ ++ tcg_out_b9(s, B9_LGR, data_reg, arg0); ++ break; ++ } ++ ++ /* jump to label2 (end) */ ++ label2_ptr = (uint16_t*)s->code_ptr; ++ tcg_out32(s, 0xa7d50000); /* bras %r13, label2 */ ++ ++ /* this is label1, patch branch */ ++ *(label1_ptr + 1) = ((unsigned long)s->code_ptr - (unsigned long)label1_ptr) >> 1; ++ ++ tcg_out_e3(s, E3_LG, arg1, arg1, offsetof(CPUTLBEntry, addend) - offsetof(CPUTLBEntry, addr_read)); ++ ++#if TARGET_LONG_BITS == 32 ++ /* zero upper 32 bits */ ++ tcg_out_b9(s, B9_LLGFR, arg0, addr_reg); ++#else ++ /* just copy */ ++ tcg_out_b9(s, B9_LGR, arg0, addr_reg); ++#endif ++ tcg_out_b9(s, B9_AGR, arg0, arg1); ++ ++#else /* CONFIG_SOFTMMU */ ++ /* user mode, no address translation required */ ++ arg0 = addr_reg; ++#endif ++ ++ switch(opc) { ++ case 0: /* unsigned byte */ ++ tcg_out_e3(s, E3_LLGC, data_reg, arg0, 0); ++ break; ++ case 0 | 4: /* signed byte */ ++ tcg_out_e3(s, E3_LGB, data_reg, arg0, 0); ++ break; ++ case 1: /* unsigned short */ ++#ifdef TARGET_WORDS_BIGENDIAN ++ tcg_out_e3(s, E3_LLGH, data_reg, arg0, 0); ++#else ++ /* swapped unsigned halfword load with upper bits zeroed */ ++ tcg_out_e3(s, E3_LRVH, data_reg, arg0, 0); ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, 0xffffL); ++ tcg_out_b9(s, B9_NGR, data_reg, 13); ++#endif ++ break; ++ case 1 | 4: /* signed short */ ++#ifdef TARGET_WORDS_BIGENDIAN ++ tcg_out_e3(s, E3_LGH, data_reg, arg0, 0); ++#else ++ /* swapped sign-extended halfword load */ ++ tcg_out_e3(s, E3_LRVH, data_reg, arg0, 0); ++ tcg_out_sh64(s, SH64_SLLG, data_reg, data_reg, SH64_REG_NONE, 48); ++ tcg_out_sh64(s, SH64_SRAG, data_reg, data_reg, SH64_REG_NONE, 48); ++#endif ++ break; ++ case 2: /* unsigned int */ ++#ifdef TARGET_WORDS_BIGENDIAN ++ tcg_out_e3(s, E3_LLGF, data_reg, arg0, 0); ++#else ++ /* swapped unsigned int load with upper bits zeroed */ ++ tcg_out_e3(s, E3_LRV, data_reg, arg0, 0); ++ tcg_out_b9(s, B9_LLGFR, data_reg, data_reg); ++#endif ++ break; ++ case 2 | 4: /* signed int */ ++#ifdef TARGET_WORDS_BIGENDIAN ++ tcg_out_e3(s, E3_LGF, data_reg, arg0, 0); ++#else ++ /* swapped sign-extended int load */ ++ tcg_out_e3(s, E3_LRV, data_reg, arg0, 0); ++ tcg_out_b9(s, B9_LGFR, data_reg, data_reg); ++#endif ++ break; ++ case 3: /* long (64 bit) */ ++#ifdef TARGET_WORDS_BIGENDIAN ++ tcg_out_e3(s, E3_LG, data_reg, arg0, 0); ++#else ++ tcg_out_e3(s, E3_LRVG, data_reg, arg0, 0); ++#endif ++ break; ++ default: ++ tcg_abort(); ++ } ++ ++#ifdef CONFIG_SOFTMMU ++ /* this is label2, patch branch */ ++ *(label2_ptr + 1) = ((unsigned long)s->code_ptr - (unsigned long)label2_ptr) >> 1; ++#endif ++} ++ ++static void tcg_out_qemu_st(TCGContext* s, const TCGArg* args, int opc) ++{ ++ int addr_reg, data_reg, mem_index, s_bits; ++#if defined(CONFIG_SOFTMMU) ++ uint16_t *label1_ptr, *label2_ptr; ++#endif ++ ++ data_reg = *args++; ++ addr_reg = *args++; ++ mem_index = *args; ++ ++ s_bits = opc; ++ ++ int arg0 = TCG_REG_R2; ++#ifdef CONFIG_SOFTMMU ++ int arg1 = TCG_REG_R3; ++ int arg2 = TCG_REG_R4; ++#endif ++ ++ /* fprintf(stderr,"tcg_out_qemu_st opc %d data_reg %d addr_reg %d mem_index %d s_bits %d\n", ++ opc, data_reg, addr_reg, mem_index, s_bits); */ ++ ++#ifdef CONFIG_SOFTMMU ++ tcg_out_b9(s, B9_LGR, arg1, addr_reg); ++ tcg_out_b9(s, B9_LGR, arg0, addr_reg); ++ ++ tcg_out_sh64(s, SH64_SRLG, arg1, addr_reg, SH64_REG_NONE, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); ++ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, TARGET_PAGE_MASK | ((1 << s_bits) - 1)); ++ tcg_out_b9(s, B9_NGR, arg0, TCG_REG_R13); ++ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS); ++ tcg_out_b9(s, B9_NGR, arg1, TCG_REG_R13); ++ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, offsetof(CPUState, tlb_table[mem_index][0].addr_write)); ++ tcg_out_b9(s, B9_AGR, arg1, TCG_REG_R13); ++ ++ tcg_out_b9(s, B9_AGR, arg1, TCG_AREG0); ++ ++ tcg_out_e3(s, E3_CG, arg0, arg1, 0); ++ ++ tcg_out_b9(s, B9_LGR, arg0, addr_reg); ++ ++ /* jump to label1 */ ++ label1_ptr = (uint16_t*)s->code_ptr; ++ tcg_out32(s, 0xa7840000); /* je label1 */ ++ ++ /* call store helper */ ++ tcg_out_b9(s, B9_LGR, arg1, data_reg); ++ tcg_out_movi(s, TCG_TYPE_I32, arg2, mem_index); ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, (tcg_target_ulong)qemu_st_helpers[s_bits]); ++ tcg_out_rr(s, RR_BASR, TCG_REG_R14, TCG_REG_R13); ++ ++ /* jump to label2 (end) */ ++ label2_ptr = (uint16_t*)s->code_ptr; ++ tcg_out32(s, 0xa7d50000); /* bras %r13, label2 */ ++ ++ /* this is label1, patch branch */ ++ *(label1_ptr + 1) = ((unsigned long)s->code_ptr - (unsigned long)label1_ptr) >> 1; ++ ++ tcg_out_e3(s, E3_LG, arg1, arg1, offsetof(CPUTLBEntry, addend) - offsetof(CPUTLBEntry, addr_write)); ++ ++#if TARGET_LONG_BITS == 32 ++ /* zero upper 32 bits */ ++ tcg_out_b9(s, B9_LLGFR, arg0, addr_reg); ++#else ++ /* just copy */ ++ tcg_out_b9(s, B9_LGR, arg0, addr_reg); ++#endif ++ tcg_out_b9(s, B9_AGR, arg0, arg1); ++ ++#else /* CONFIG_SOFTMMU */ ++ /* user mode, no address translation required */ ++ arg0 = addr_reg; ++#endif ++ ++ switch(opc) { ++ case 0: ++ tcg_out_store(s, ST_STC, data_reg, arg0, 0); ++ break; ++ case 1: ++#ifdef TARGET_WORDS_BIGENDIAN ++ tcg_out_store(s, ST_STH, data_reg, arg0, 0); ++#else ++ tcg_out_e3(s, E3_STRVH, data_reg, arg0, 0); ++#endif ++ break; ++ case 2: ++#ifdef TARGET_WORDS_BIGENDIAN ++ tcg_out_store(s, ST_ST, data_reg, arg0, 0); ++#else ++ tcg_out_e3(s, E3_STRV, data_reg, arg0, 0); ++#endif ++ break; ++ case 3: ++#ifdef TARGET_WORDS_BIGENDIAN ++ tcg_out_e3(s, E3_STG, data_reg, arg0, 0); ++#else ++ tcg_out_e3(s, E3_STRVG, data_reg, arg0, 0); ++#endif ++ break; ++ default: ++ tcg_abort(); ++ } ++ ++#ifdef CONFIG_SOFTMMU ++ /* this is label2, patch branch */ ++ *(label2_ptr + 1) = ((unsigned long)s->code_ptr - (unsigned long)label2_ptr) >> 1; ++#endif ++} ++ ++static inline void tcg_out_st(TCGContext *s, TCGType type, int arg, ++ int arg1, tcg_target_long arg2) ++{ ++ //fprintf(stderr,"tcg_out_st arg 0x%x arg1 0x%x arg2 0x%lx\n",arg,arg1,arg2); ++ if (type == TCG_TYPE_I32) { ++ if(((long)arg2) < -0x800 || ((long)arg2) > 0x7ff) { ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, arg2); ++ tcg_out_b9(s, B9_AGR, 13, arg1); ++ tcg_out_store(s, ST_ST, arg, TCG_REG_R13, 0); ++ } ++ else tcg_out_store(s, ST_ST, arg, arg1, arg2); ++ } ++ else { ++ if(((long)arg2) < -0x80000 || ((long)arg2) > 0x7ffff) tcg_abort(); ++ tcg_out_e3(s, E3_STG, arg, arg1, arg2); ++ } ++} ++ ++static inline void tcg_out_op(TCGContext *s, int opc, ++ const TCGArg *args, const int *const_args) ++{ ++ TCGLabel* l; ++ int op; ++ int op2; ++ //fprintf(stderr,"0x%x\n", INDEX_op_qemu_ld32s); ++ switch (opc) { ++ case INDEX_op_exit_tb: ++ //fprintf(stderr,"op 0x%x exit_tb 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, args[0]); /* return value */ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, (unsigned long)tb_ret_addr); ++ tcg_out16(s,0x7fd); /* br %r13 */ ++ break; ++ case INDEX_op_goto_tb: ++ //fprintf(stderr,"op 0x%x goto_tb 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if(s->tb_jmp_offset) { ++ tcg_abort(); ++ } ++ else { ++ tcg_target_long off = ((tcg_target_long)(s->tb_next + args[0]) - (tcg_target_long)s->code_ptr) >> 1; ++ if (off > -0x80000000L && off < 0x7fffffffL) { /* load address relative to PC */ ++ /* larl %r13, off */ ++ tcg_out16(s,0xc0d0); tcg_out32(s,off); ++ } ++ else { /* too far for larl */ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, (tcg_target_long)(s->tb_next + args[0])); ++ } ++ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R13, TCG_REG_R13, 0); /* load address stored at s->tb_next + args[0] */ ++ tcg_out_rr(s, RR_BASR, TCG_REG_R13, TCG_REG_R13); /* and go there */ ++ } ++ s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; ++ break; ++ case INDEX_op_call: ++ //fprintf(stderr,"op 0x%x call 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if(const_args[0]) { ++ tcg_target_long off = (args[0] - (tcg_target_long)s->code_ptr + 4) >> 1; /* FIXME: + 4? Where did that come from? */ ++ if (off > -0x80000000 && off < 0x7fffffff) { /* relative call */ ++ tcg_out_brasl(s, TCG_REG_R14, off << 1); ++ tcg_abort(); // untested ++ } ++ else { /* too far for a relative call, load full address */ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, args[0]); ++ tcg_out_rr(s, RR_BASR, TCG_REG_R14, TCG_REG_R13); ++ } ++ } ++ else { /* call function in register args[0] */ ++ tcg_out_rr(s, RR_BASR, TCG_REG_R14, args[0]); ++ } ++ break; ++ case INDEX_op_jmp: ++ fprintf(stderr,"op 0x%x jmp 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ tcg_abort(); ++ break; ++ case INDEX_op_ld8u_i32: ++ case INDEX_op_ld8u_i64: ++ //fprintf(stderr,"op 0x%x ld8u_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if ((long)args[2] > -0x80000 && (long)args[2] < 0x7ffff) { ++ tcg_out_e3(s, E3_LLGC, args[0], args[1], args[2]); ++ } ++ else { /* displacement too large, have to calculate address manually */ ++ tcg_abort(); ++ } ++ break; ++ case INDEX_op_ld8s_i32: ++ fprintf(stderr,"op 0x%x ld8s_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ tcg_abort(); ++ break; ++ case INDEX_op_ld16u_i32: ++ fprintf(stderr,"op 0x%x ld16u_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if ((long)args[2] > -0x80000 && (long)args[2] < 0x7ffff) { ++ tcg_out_e3(s, E3_LLGH, args[0], args[1], args[2]); ++ } ++ else { /* displacement too large, have to calculate address manually */ ++ tcg_abort(); ++ } ++ break; ++ case INDEX_op_ld16s_i32: ++ fprintf(stderr,"op 0x%x ld16s_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ tcg_abort(); ++ break; ++ case INDEX_op_ld_i32: ++ case INDEX_op_ld32u_i64: ++ tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]); ++ break; ++ case INDEX_op_ld32s_i64: ++ if(args[2] < -0x80000 || args[2] > 0x7ffff) { ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, args[2]); /* load the displacement */ ++ tcg_out_b9(s, B9_AGR, TCG_REG_R13, args[1]); /* add the address */ ++ tcg_out_e3(s, E3_LGF, args[0], TCG_REG_R13, 0); /* load the data (sign-extended) */ ++ } ++ else { ++ tcg_out_e3(s, E3_LGF, args[0], args[1], args[2]); /* load the data (sign-extended) */ ++ } ++ break; ++ case INDEX_op_ld_i64: ++ tcg_out_ld(s, TCG_TYPE_I64, args[0], args[1], args[2]); ++ break; ++ case INDEX_op_st8_i32: ++ case INDEX_op_st8_i64: ++ //fprintf(stderr,"op 0x%x st8_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if(((long)args[2]) >= -0x800 && ((long)args[2]) < 0x800) ++ tcg_out_store(s, ST_STC, args[0], args[1], args[2]); ++ else if(((long)args[2]) >= -0x80000 && ((long)args[2]) < 0x80000) { ++ tcg_out_e3(s, E3_STCY, args[0], args[1], args[2]); /* FIXME: requires long displacement facility */ ++ tcg_abort(); // untested ++ } ++ else tcg_abort(); ++ break; ++ case INDEX_op_st16_i32: ++ case INDEX_op_st16_i64: ++ //fprintf(stderr,"op 0x%x st16_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if(((long)args[2]) >= -0x800 && ((long)args[2]) < 0x800) ++ tcg_out_store(s, ST_STH, args[0], args[1], args[2]); ++ else if(((long)args[2]) >= -0x80000 && ((long)args[2]) < 0x80000) { ++ tcg_out_e3(s, E3_STHY, args[0], args[1], args[2]); /* FIXME: requires long displacement facility */ ++ tcg_abort(); // untested ++ } ++ else tcg_abort(); ++ break; ++ case INDEX_op_st_i32: ++ case INDEX_op_st32_i64: ++ tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]); ++ break; ++ case INDEX_op_st_i64: ++ tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]); ++ break; ++ case INDEX_op_mov_i32: ++ fprintf(stderr,"op 0x%x mov_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ tcg_abort(); ++ break; ++ case INDEX_op_movi_i32: ++ fprintf(stderr,"op 0x%x movi_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ tcg_abort(); ++ break; ++ case INDEX_op_add_i32: ++ if(args[0] == args[1]) { ++ tcg_out_rr(s, RR_AR, args[1], args[2]); ++ } ++ else if(args[0] == args[2]) { ++ tcg_out_rr(s, RR_AR, args[0], args[1]); ++ } ++ else { ++ tcg_out_rr(s, RR_LR, args[0], args[1]); ++ tcg_out_rr(s, RR_AR, args[0], args[2]); ++ } ++ break; ++ case INDEX_op_sub_i32: ++ //fprintf(stderr,"op 0x%x sub_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if(args[0] == args[1]) { ++ tcg_out_rr(s, RR_SR, args[1], args[2]); /* sr %ra0/1, %ra2 */ ++ } ++ else if(args[0] == args[2]) { ++ tcg_out_rr(s, RR_LR, TCG_REG_R13, args[2]); /* lr %r13, %raa0/2 */ ++ tcg_out_rr(s, RR_LR, args[0], args[1]); /* lr %ra0/2, %ra1 */ ++ tcg_out_rr(s, RR_SR, args[0], TCG_REG_R13); /* sr %ra0/2, %r13 */ ++ } ++ else { ++ tcg_out_rr(s, RR_LR, args[0], args[1]); /* lr %ra0, %ra1 */ ++ tcg_out_rr(s, RR_SR, args[0], args[2]); /* sr %ra0, %ra2 */ ++ } ++ break; ++ ++ case INDEX_op_sub_i64: ++ //fprintf(stderr,"op 0x%x sub_i64 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if(args[0] == args[1]) { ++ tcg_out_b9(s, B9_SGR, args[1], args[2]); /* sgr %ra0/1, %ra2 */ ++ } ++ else if(args[0] == args[2]) { ++ tcg_out_b9(s, B9_LGR, TCG_REG_R13, args[2]); /* lgr %r13, %raa0/2 */ ++ tcg_out_b9(s, B9_LGR, args[0], args[1]); /* lgr %ra0/2, %ra1 */ ++ tcg_out_b9(s, B9_SGR, args[0], TCG_REG_R13); /* sgr %ra0/2, %r13 */ ++ } ++ else { ++ tcg_out_b9(s, B9_LGR, args[0], args[1]); /* lgr %ra0, %ra1 */ ++ tcg_out_b9(s, B9_SGR, args[0], args[2]); /* sgr %ra0, %ra2 */ ++ } ++ break; ++ case INDEX_op_add_i64: ++ //fprintf(stderr,"op 0x%x add_i64 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if(args[0] == args[1]) { ++ tcg_out_b9(s, B9_AGR, args[1], args[2]); ++ } ++ else if(args[0] == args[2]) { ++ tcg_out_b9(s, B9_AGR, args[0], args[1]); ++ } ++ else { ++ tcg_out_b9(s, B9_LGR, args[0], args[1]); ++ tcg_out_b9(s, B9_AGR, args[0], args[2]); ++ } ++ break; ++ ++ case INDEX_op_and_i32: ++ op = RR_NR; ++do_logic_i32: ++ if(args[0] == args[1]) ++ tcg_out_rr(s, op, args[1], args[2]); /* xr %ra0/1, %ra2 */ ++ else if(args[0] == args[2]) ++ tcg_out_rr(s, op, args[0], args[1]); /* xr %ra0/2, %ra1 */ ++ else { ++ tcg_out_rr(s, RR_LR, args[0], args[1]); /* lr %ra0, %ra1 */ ++ tcg_out_rr(s, op, args[0], args[2]); /* xr %ra0, %ra2 */ ++ } ++ break; ++ case INDEX_op_or_i32: op = RR_OR; goto do_logic_i32; ++ case INDEX_op_xor_i32: op = RR_XR; goto do_logic_i32; ++ ++ case INDEX_op_and_i64: ++ //fprintf(stderr,"op 0x%x and_i64 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ op = B9_NGR; ++do_logic_i64: ++ if (args[0] == args[1]) ++ tcg_out_b9(s, op, args[0], args[2]); ++ else if (args[0] == args[2]) ++ tcg_out_b9(s, op, args[0], args[1]); ++ else { ++ tcg_out_b9(s, B9_LGR, args[0], args[1]); ++ tcg_out_b9(s, op, args[0], args[2]); ++ } ++ break; ++ case INDEX_op_or_i64: op = B9_OGR; goto do_logic_i64; ++ case INDEX_op_xor_i64: op = B9_XGR; goto do_logic_i64; ++ ++ case INDEX_op_neg_i32: ++ //fprintf(stderr,"op 0x%x neg_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ /* FIXME: optimize args[0] != args[1] case */ ++ tcg_out_rr(s, RR_LR, 13, args[1]); ++ tcg_out32(s, 0xa7090000 | (args[0] << 20)); /* lghi %ra0, 0 */ ++ tcg_out_rr(s, RR_SR, args[0], 13); ++ break; ++ case INDEX_op_neg_i64: ++ //fprintf(stderr,"op 0x%x neg_i64 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ /* FIXME: optimize args[0] != args[1] case */ ++ tcg_out_b9(s, B9_LGR, 13, args[1]); ++ tcg_out32(s, 0xa7090000 | (args[0] << 20)); /* lghi %ra0, 0 */ ++ tcg_out_b9(s, B9_SGR, args[0], 13); ++ break; ++ ++ case INDEX_op_mul_i32: ++ //fprintf(stderr,"op 0x%x mul_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if (args[0] == args[1]) ++ tcg_out32(s, 0xb2520000 | (args[0] << 4) | args[2]); /* msr %ra0/1, %ra2 */ ++ else if (args[0] == args[2]) ++ tcg_out32(s, 0xb2520000 | (args[0] << 4) | args[1]); /* msr %ra0/2, %ra1 */ ++ else tcg_abort(); ++ break; ++ case INDEX_op_mul_i64: ++ //fprintf(stderr,"op 0x%x mul_i64 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if(args[0] == args[1]) { ++ tcg_out_b9(s, B9_MSGR, args[0], args[2]); ++ } ++ else if(args[0] == args[2]) { ++ tcg_out_b9(s, B9_MSGR, args[0], args[1]); ++ } ++ else tcg_abort(); ++ break; ++ ++ case INDEX_op_shl_i32: ++ op = SH32_SLL; op2 = SH64_SLLG; ++do_shift32: ++ if(const_args[2]) { ++ if(args[0] == args[1]) ++ tcg_out_sh32(s, op, args[0], SH32_REG_NONE, args[2]); ++ else { ++ tcg_out_rr(s, RR_LR, args[0], args[1]); ++ tcg_out_sh32(s, op, args[0], SH32_REG_NONE, args[2]); ++ } ++ } ++ else { ++ if(args[0] == args[1]) ++ tcg_out_sh32(s, op, args[0], args[2], 0); ++ else ++ tcg_out_sh64(s, op2, args[0], args[1], args[2], 0); ++ } ++ break; ++ case INDEX_op_shr_i32: op = SH32_SRL; op2 = SH64_SRLG; goto do_shift32; ++ case INDEX_op_sar_i32: op = SH32_SRA; op2 = SH64_SRAG; goto do_shift32; ++ ++ case INDEX_op_shl_i64: ++ op = SH64_SLLG; ++do_shift64: ++ if(const_args[2]) { ++ tcg_out_sh64(s, op, args[0], args[1], SH64_REG_NONE, args[2]); ++ } ++ else { ++ tcg_out_sh64(s, op, args[0], args[1], args[2], 0); ++ } ++ break; ++ case INDEX_op_shr_i64: op = SH64_SRLG; goto do_shift64; ++ case INDEX_op_sar_i64: op = SH64_SRAG; goto do_shift64; ++ ++ case INDEX_op_br: ++ //fprintf(stderr,"op 0x%x br 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ l = &s->labels[args[0]]; ++ if (l->has_value) { ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, l->u.value); ++ } ++ else { ++ /* larl %r13, ... */ ++ tcg_out16(s, 0xc0d0); ++ tcg_out_reloc(s, s->code_ptr, R_390_PC32DBL, args[0], -2); ++ s->code_ptr += 4; ++ } ++ tcg_out_rr(s, RR_BASR, TCG_REG_R13, TCG_REG_R13); ++ break; ++ case INDEX_op_brcond_i64: ++ //fprintf(stderr,"op 0x%x brcond_i64 0x%lx 0x%lx (c %d) 0x%lx\n",opc,args[0],args[1],const_args[1],args[2]); ++ if (args[2] > TCG_COND_GT) { /* unsigned */ ++ tcg_out_b9(s, B9_CLGR, args[0], args[1]); /* clgr %ra0, %ra1 */ ++ } ++ else { /* signed */ ++ tcg_out_b9(s, B9_CGR, args[0], args[1]); /* cgr %ra0, %ra1 */ ++ } ++ goto do_brcond; ++ case INDEX_op_brcond_i32: ++ //fprintf(stderr,"op 0x%x brcond_i32 0x%lx 0x%lx (c %d) 0x%lx\n",opc,args[0],args[1],const_args[1],args[2]); ++ if (args[2] > TCG_COND_GT) { /* unsigned */ ++ tcg_out_rr(s, RR_CLR, args[0], args[1]); /* clr %ra0, %ra1 */ ++ } ++ else { /* signed */ ++ tcg_out_rr(s, RR_CR, args[0], args[1]); /* cr %ra0, %ra1 */ ++ } ++do_brcond: ++ l = &s->labels[args[3]]; ++ if(l->has_value) { ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, l->u.value); ++ } ++ else { ++ /* larl %r13, ... */ ++ tcg_out16(s, 0xc0d0); ++ tcg_out_reloc(s, s->code_ptr, R_390_PC32DBL, args[3], -2); ++ s->code_ptr += 4; ++ } ++ tcg_out16(s, 0x070d | (tcg_cond_to_s390_cond[args[2]] << 4)); /* bcr cond,%r13 */ ++ break; ++ ++ case INDEX_op_qemu_ld8u: tcg_out_qemu_ld(s, args, 0); break; ++ case INDEX_op_qemu_ld8s: tcg_out_qemu_ld(s, args, 0 | 4); break; ++ case INDEX_op_qemu_ld16u: tcg_out_qemu_ld(s, args, 1); break; ++ case INDEX_op_qemu_ld16s: tcg_out_qemu_ld(s, args, 1 | 4); break; ++ case INDEX_op_qemu_ld32u: tcg_out_qemu_ld(s, args, 2); break; ++ case INDEX_op_qemu_ld32s: tcg_out_qemu_ld(s, args, 2 | 4); break; ++ case INDEX_op_qemu_ld64: tcg_out_qemu_ld(s, args, 3); break; ++ case INDEX_op_qemu_st8: tcg_out_qemu_st(s, args, 0); break; ++ case INDEX_op_qemu_st16: tcg_out_qemu_st(s, args, 1); break; ++ case INDEX_op_qemu_st32: tcg_out_qemu_st(s, args, 2); break; ++ case INDEX_op_qemu_st64: tcg_out_qemu_st(s, args, 3); break; ++ ++ default: ++ fprintf(stderr,"unimplemented opc 0x%x\n",opc); ++ tcg_abort(); ++ } ++} ++ ++static const TCGTargetOpDef s390_op_defs[] = { ++ { INDEX_op_exit_tb, { } }, ++ { INDEX_op_goto_tb, { } }, ++ { INDEX_op_call, { "ri" } }, ++ { INDEX_op_jmp, { "ri" } }, ++ { INDEX_op_br, { } }, ++ ++ { INDEX_op_mov_i32, { "r", "r" } }, ++ { INDEX_op_movi_i32, { "r" } }, ++ ++ { INDEX_op_ld8u_i32, { "r", "r" } }, ++ { INDEX_op_ld8s_i32, { "r", "r" } }, ++ { INDEX_op_ld16u_i32, { "r", "r" } }, ++ { INDEX_op_ld16s_i32, { "r", "r" } }, ++ { INDEX_op_ld_i32, { "r", "r" } }, ++ { INDEX_op_st8_i32, { "r", "r" } }, ++ { INDEX_op_st16_i32, { "r", "r" } }, ++ { INDEX_op_st_i32, { "r", "r" } }, ++ ++ { INDEX_op_add_i32, { "r", "r", "r" } }, ++ { INDEX_op_sub_i32, { "r", "r", "r" } }, ++ { INDEX_op_mul_i32, { "r", "r", "r" } }, ++ ++ { INDEX_op_and_i32, { "r", "r", "r" } }, ++ { INDEX_op_or_i32, { "r", "r", "r" } }, ++ { INDEX_op_xor_i32, { "r", "r", "r" } }, ++ { INDEX_op_neg_i32, { "r", "r" } }, ++ ++ { INDEX_op_shl_i32, { "r", "r", "Ri" } }, ++ { INDEX_op_shr_i32, { "r", "r", "Ri" } }, ++ { INDEX_op_sar_i32, { "r", "r", "Ri" } }, ++ ++ { INDEX_op_brcond_i32, { "r", "r" } }, ++ ++ { INDEX_op_qemu_ld8u, { "r", "L" } }, ++ { INDEX_op_qemu_ld8s, { "r", "L" } }, ++ { INDEX_op_qemu_ld16u, { "r", "L" } }, ++ { INDEX_op_qemu_ld16s, { "r", "L" } }, ++ { INDEX_op_qemu_ld32u, { "r", "L" } }, ++ { INDEX_op_qemu_ld32s, { "r", "L" } }, ++ ++ { INDEX_op_qemu_st8, { "S", "S" } }, ++ { INDEX_op_qemu_st16, { "S", "S" } }, ++ { INDEX_op_qemu_st32, { "S", "S" } }, ++ ++#if defined(__s390x__) ++ { INDEX_op_mov_i64, { "r", "r" } }, ++ { INDEX_op_movi_i64, { "r" } }, ++ ++ { INDEX_op_ld8u_i64, { "r", "r" } }, ++ { INDEX_op_ld8s_i64, { "r", "r" } }, ++ { INDEX_op_ld16u_i64, { "r", "r" } }, ++ { INDEX_op_ld16s_i64, { "r", "r" } }, ++ { INDEX_op_ld32u_i64, { "r", "r" } }, ++ { INDEX_op_ld32s_i64, { "r", "r" } }, ++ { INDEX_op_ld_i64, { "r", "r" } }, ++ ++ { INDEX_op_st8_i64, { "r", "r" } }, ++ { INDEX_op_st16_i64, { "r", "r" } }, ++ { INDEX_op_st32_i64, { "r", "r" } }, ++ { INDEX_op_st_i64, { "r", "r" } }, ++ ++ { INDEX_op_qemu_ld64, { "L", "L" } }, ++ { INDEX_op_qemu_st64, { "S", "S" } }, ++ ++ { INDEX_op_add_i64, { "r", "r", "r" } }, ++ { INDEX_op_mul_i64, { "r", "r", "r" } }, ++ { INDEX_op_sub_i64, { "r", "r", "r" } }, ++ ++ { INDEX_op_and_i64, { "r", "r", "r" } }, ++ { INDEX_op_or_i64, { "r", "r", "r" } }, ++ { INDEX_op_xor_i64, { "r", "r", "r" } }, ++ { INDEX_op_neg_i64, { "r", "r" } }, ++ ++ { INDEX_op_shl_i64, { "r", "r", "Ri" } }, ++ { INDEX_op_shr_i64, { "r", "r", "Ri" } }, ++ { INDEX_op_sar_i64, { "r", "r", "Ri" } }, ++ ++ { INDEX_op_brcond_i64, { "r", "r" } }, ++#endif ++ ++ { -1 }, ++}; ++ ++void tcg_target_init(TCGContext *s) ++{ ++ /* fail safe */ ++ if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry)) ++ tcg_abort(); ++ ++ tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff); ++ tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff); ++ tcg_regset_set32(tcg_target_call_clobber_regs, 0, ++ (1 << TCG_REG_R0) | ++ (1 << TCG_REG_R1) | ++ (1 << TCG_REG_R2) | ++ (1 << TCG_REG_R3) | ++ (1 << TCG_REG_R4) | ++ (1 << TCG_REG_R5) | ++ (1 << TCG_REG_R14)); /* link register */ ++ ++ tcg_regset_clear(s->reserved_regs); ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13); /* frequently used as a temporary */ ++ ++ tcg_add_target_add_op_defs(s390_op_defs); ++} ++ ++void tcg_target_qemu_prologue(TCGContext *s) ++{ ++ tcg_out16(s,0xeb6f);tcg_out32(s,0xf0300024); /* stmg %r6,%r15,48(%r15) (save registers) */ ++ tcg_out32(s, 0xa7fbff60); /* aghi %r15,-160 (stack frame) */ ++ tcg_out16(s,0x7f2); /* br %r2 (go to TB) */ ++ tb_ret_addr = s->code_ptr; ++ tcg_out16(s,0xeb6f);tcg_out32(s, 0xf0d00004); /* lmg %r6,%r15,208(%r15) (restore registers) */ ++ tcg_out16(s,0x7fe); /* br %r14 (return) */ ++} ++ ++ ++static inline void tcg_out_mov(TCGContext *s, int ret, int arg) ++{ ++ tcg_out_b9(s, B9_LGR, ret, arg); ++} ++ ++static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) ++{ ++ tcg_abort(); ++} +Index: tcg/s390/tcg-target.h +=================================================================== +--- tcg/s390/tcg-target.h (revision 0) ++++ tcg/s390/tcg-target.h (revision 0) +@@ -0,0 +1,76 @@ ++/* ++ * Tiny Code Generator for QEMU ++ * ++ * Copyright (c) 2009 Ulrich Hecht ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++#define TCG_TARGET_S390 1 ++ ++#define TCG_TARGET_REG_BITS 64 ++#define TCG_TARGET_WORDS_BIGENDIAN ++#undef TCG_TARGET_HAS_div_i32 ++#undef TCG_TARGET_HAS_div_i64 ++#undef TCG_TARGET_HAS_bswap_i32 ++#define TCG_TARGET_HAS_neg_i32 ++#define TCG_TARGET_HAS_neg_i64 ++#undef TCG_TARGET_STACK_GROWSUP ++ ++enum { ++ TCG_REG_R0 = 0, ++ TCG_REG_R1, ++ TCG_REG_R2, ++ TCG_REG_R3, ++ TCG_REG_R4, ++ TCG_REG_R5, ++ TCG_REG_R6, ++ TCG_REG_R7, ++ TCG_REG_R8, ++ TCG_REG_R9, ++ TCG_REG_R10, ++ TCG_REG_R11, ++ TCG_REG_R12, ++ TCG_REG_R13, ++ TCG_REG_R14, ++ TCG_REG_R15 ++}; ++#define TCG_TARGET_NB_REGS 16 ++ ++/* used for function call generation */ ++#define TCG_REG_CALL_STACK TCG_REG_R15 ++#define TCG_TARGET_STACK_ALIGN 8 ++#define TCG_TARGET_CALL_STACK_OFFSET 0 ++ ++enum { ++ /* Note: must be synced with dyngen-exec.h */ ++ TCG_AREG0 = TCG_REG_R10, ++ TCG_AREG1 = TCG_REG_R7, ++ TCG_AREG2 = TCG_REG_R8, ++ TCG_AREG3 = TCG_REG_R9, ++}; ++ ++static inline void flush_icache_range(unsigned long start, unsigned long stop) ++{ ++#if QEMU_GNUC_PREREQ(4, 1) ++ void __clear_cache(char *beg, char *end); ++ __clear_cache((char *) start, (char *) stop); ++#else ++#error not implemented ++#endif ++} +Index: configure +=================================================================== +--- configure (revision 6883) ++++ configure (working copy) +@@ -139,9 +139,12 @@ + ppc64) + cpu="ppc64" + ;; +- s390*) ++ s390) + cpu="s390" + ;; ++ s390x) ++ cpu="s390x" ++ ;; + sparc|sun4[cdmuv]) + cpu="sparc" + ;; +@@ -727,6 +730,7 @@ + if test "$cpu" = "x86_64" \ + -o "$cpu" = "alpha" \ + -o "$cpu" = "ia64" \ ++ -o "$cpu" = "s390x" \ + -o "$cpu" = "sparc64" \ + -o "$cpu" = "ppc64"; then + hostlongbits="64" +@@ -1311,6 +1315,10 @@ + echo "ARCH=s390" >> $config_mak + echo "#define HOST_S390 1" >> $config_h + ;; ++ s390x) ++ echo "ARCH=s390x" >> $config_mak ++ echo "#define HOST_S390X 1" >> $config_h ++ ;; + sparc) + echo "ARCH=sparc" >> $config_mak + echo "#define HOST_SPARC 1" >> $config_h diff --git a/qemu.changes b/qemu.changes index 0836ee6d..9bf0bf21 100644 --- a/qemu.changes +++ b/qemu.changes @@ -1,3 +1,63 @@ +------------------------------------------------------------------- +Fri Mar 27 12:20:21 CET 2009 - crrodriguez@suse.de + +- BuildRequire zlib-devel-static + +------------------------------------------------------------------- +Tue Mar 24 15:33:47 CET 2009 - uli@suse.de + +- update -> release (0.10.1) + - fixes bnc #435135 (CVE-2008-4539, SWAMP #22179), #362956 + (CVE-2008-1945, CVE-2008-0928), #461565 (CVE-2008-2382) + - Kernel Virtual Machine acceleration support + - GDB XML register description support + - Intel e1000 emulation + - HPET emulation + - VirtIO paravirtual device support + - Marvell 88w8618 / MusicPal emulation + - Nokia N-series tablet emulation / OMAP2 processor emulation + - PCI hotplug support + - Curses display support + - qemu-nbd utility to mount supported block formats + - Altivec support in PPC emulation and new firmware (OpenBIOS) + - Multiple VNC clients are now supported + - TLS encryption is now supported in VNC + - MIPS Magnum R4000 machine (Hervé Poussineau) + - Braille support (Samuel Thibault) + - Freecom MusicPal system emulation (Jan Kiszka) + - OMAP242x and Nokia N800, N810 machines (Andrzej Zaborowski) + - EsounD audio driver (Frederick Reeve) + - Gravis Ultrasound GF1 sound card (Tibor "TS" Schütz) + - Many, many, bug fixes and new features + - virtio-net: allow masking of notifications on empty queue (Alex + Williamson) + - e1000: fix rx descriptor low threshold logic (Alex Willaimson) + - x86 tcg: add NULL checks to lsl instruction (Jan Kiszka) + - kvm vga: fix screen corruption with -std-vga and Windows (Avi Kivity) + - kvm vga: fix screen corruption with Ubuntu installations (Glauber Costa) + - virtio-net: check right return size on sg list (Alex Williamson) + - Make qemu_announce_self handle holes (live migration after hotplug) + (Marcelo Tosatti) + - Revert r6804-r6808 (qcow2 allocation info). This series of changes + added a high cost to startup for large qcow2 images (Anthony Liguori) + - qemu-img: fix help message (Aurelien Jarno) + - Fix build for non-default installs of SDL (Anthony Liguori) + - Fix race condition in env->interrupt_request. When using TCG and a + dynticks host timer, this condition could cause TCG to get stuck in an + infinite loop (Aurelien Jarno) + - Fix reading encrypted hard disk passwords during early startup (Jan + Kiszka) + - Fix encrypted disk reporting in 'info block' (Jan Kiszka) + - Fix console size with tiny displays (MusicPal) (Jan Kiszka) + - Improve error handling in bdrv_open2 (Jan Kiszka) + - Avoid leaking data in mux'ed character devices (Jan Kiszka) + - Fix initial character device reset (no banner in monitor) (Jan Kiszka) + - Fix cpuid KVM crash on i386 host (Lubomir Rintel) + - Fix SLES10sp2 installation by adding ISTAT1 register to LSI SCSI + emulation (Ryan Harper) +- s390x TCG backend +- i386-linux-user NPTL support + ------------------------------------------------------------------- Wed Oct 8 17:03:34 CEST 2008 - uli@suse.de diff --git a/qemu.spec b/qemu.spec index 2acd5dea..9223fcfc 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,7 +1,7 @@ # -# spec file for package qemu (Version 0.9.2svn20081008) +# spec file for package qemu (Version 0.10.1) # -# Copyright (c) 2008 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,23 +19,19 @@ Name: qemu -BuildRequires: SDL-devel bison e2fsprogs-devel libgnutls-devel libpcap-devel ncurses-devel +BuildRequires: SDL-devel bison e2fsprogs-devel libgnutls-devel libpcap-devel ncurses-devel zlib-devel-static Url: http://fabrice.bellard.free.fr/qemu/ License: BSD 3-Clause; GPL v2 or later; LGPL v2.1 or later; X11/MIT Group: System/Emulators/PC Summary: Universal CPU emulator -Version: 0.9.2svn20081008 +Version: 0.10.1 Release: 1 -Source: %name-20081008.tar.bz2 +Source: %name-%version.tar.bz2 Patch1: qemu-0.9.0.cvs-binfmt.patch Patch6: qemu-0.7.0-amd64.patch Patch8: qemu-cvs-pthread.patch -Patch14: qemu-0.7.1-jobsignals.patch #Patch19: qemu-0.9.0-nousbdevfs.patch Patch34: qemu-0.9.0-migration.patch -Patch37: qemu-0.9.0-kvm.patch -Patch38: qemu-0.9.0-kvm-bios.patch -Patch39: qemu-0.9.0-kvm-kqemu-window-caption.patch Patch50: qemu-cvs-newpath.patch Patch53: qemu-cvs-sched_getaffinity.patch Patch56: qemu-cvs-ipc.patch @@ -49,21 +45,17 @@ Patch63: qemu-cvs-gettimeofday.patch Patch64: qemu-cvs-nofadvise64.patch Patch65: qemu-cvs-flash.patch Patch66: qemu-cvs-mmap-amd64.patch -#Patch67: qemu-cvs-noppcemb.patch -Patch69: qemu-cvs-ia64.patch -Patch82: qemu-cvs-svm2.patch -Patch83: qemu-cvs-ppcspe.patch Patch85: qemu-img-vmdk-scsi.patch Patch86: qemu-svn-ncurses.patch -Patch87: qemu-svn-nodyngen.patch Patch88: qemu-svn-pcap.patch Patch90: qemu-nonvoid_return.patch #Patch91: qemu-svn-dirent.patch -Source200: kvm_bios.bin +Patch92: qemu-svn-s390.patch +Patch93: qemu-svn-i386-nptl.patch # this is to make lint happy Source300: rpmlintrc BuildRoot: %{_tmppath}/%{name}-%{version}-build -ExclusiveArch: %ix86 ppc sparc x86_64 ia64 s390 ppc64 +ExclusiveArch: %ix86 ppc sparc %arm x86_64 s390x ppc64 %description QEMU is an extremely well-performing CPU emulator that allows you to @@ -79,12 +71,11 @@ Authors: Fabrice Bellard %prep -%setup -q -n %name +%setup -q ln -s fpu/*.h . %patch1 -p1 %patch6 %patch8 -p1 -%patch14 #%patch19 %patch50 -p1 %patch53 -p1 @@ -99,18 +90,15 @@ ln -s fpu/*.h . %patch64 -p1 %patch65 -p1 %patch66 -p1 -#%patch67 -p1 -%patch69 -%patch83 %patch85 -p1 %patch86 -%patch87 %patch88 %patch90 #%patch91 +%patch92 +%patch93 %build -cp -p %SOURCE200 pc-bios/ # build QEMU mkdir -p dynamic # build qemu-system without kqemu support @@ -118,20 +106,19 @@ mkdir -p dynamic --interp-prefix=/usr/share/qemu/qemu-i386 \ --audio-card-list="ac97 adlib cs4231a gus" \ --audio-drv-list="alsa sdl" --enable-mixemu \ - --disable-gcc-check \ --extra-cflags="$QEMU_OPT_FLAGS" --enable-system --disable-linux-user -make %{?jobs:-j%{jobs}} -mv */qemu */qemu-* dynamic || true +make %{?jobs:-j%{jobs}} V=1 +make qemu-img V=1 +mv */qemu */qemu-* qemu-img dynamic || true make clean # build userland emus ./configure --prefix=/usr \ --interp-prefix=/usr/share/qemu/qemu-i386 \ --enable-linux-user \ --disable-system \ - --static --disable-gcc-check \ + --static \ --extra-cflags="$QEMU_OPT_FLAGS" -make %{?jobs:-j%{jobs}} -make qemu-img +make %{?jobs:-j%{jobs}} V=1 %install install -d -m 755 $RPM_BUILD_ROOT/usr/bin @@ -146,7 +133,7 @@ install -d -m 755 $RPM_BUILD_ROOT/usr/share/qemu install -m 644 pc-bios/*.bin pc-bios/video.x pc-bios/openbios-sparc* $RPM_BUILD_ROOT/usr/share/qemu install -d -m 755 $RPM_BUILD_ROOT/usr/sbin install -m 755 qemu-binfmt-conf.sh $RPM_BUILD_ROOT/usr/sbin -install -m 755 qemu-img $RPM_BUILD_ROOT/usr/bin +install -m 755 dynamic/qemu-img $RPM_BUILD_ROOT/usr/bin install -d -m 755 $RPM_BUILD_ROOT/usr/share/qemu/keymaps install -m 644 keymaps/[a-z]* $RPM_BUILD_ROOT/usr/share/qemu/keymaps %ifnarch %ix86 x86_64 @@ -174,6 +161,60 @@ rm -rf ${RPM_BUILD_ROOT} %endif %changelog +* Fri Mar 27 2009 crrodriguez@suse.de +- BuildRequire zlib-devel-static +* Tue Mar 24 2009 uli@suse.de +- update -> release (0.10.1) + - fixes bnc #435135 (CVE-2008-4539, SWAMP #22179), #362956 + (CVE-2008-1945, CVE-2008-0928), #461565 (CVE-2008-2382) + - Kernel Virtual Machine acceleration support + - GDB XML register description support + - Intel e1000 emulation + - HPET emulation + - VirtIO paravirtual device support + - Marvell 88w8618 / MusicPal emulation + - Nokia N-series tablet emulation / OMAP2 processor emulation + - PCI hotplug support + - Curses display support + - qemu-nbd utility to mount supported block formats + - Altivec support in PPC emulation and new firmware (OpenBIOS) + - Multiple VNC clients are now supported + - TLS encryption is now supported in VNC + - MIPS Magnum R4000 machine (Hervé Poussineau) + - Braille support (Samuel Thibault) + - Freecom MusicPal system emulation (Jan Kiszka) + - OMAP242x and Nokia N800, N810 machines (Andrzej Zaborowski) + - EsounD audio driver (Frederick Reeve) + - Gravis Ultrasound GF1 sound card (Tibor "TS" Schütz) + - Many, many, bug fixes and new features + - virtio-net: allow masking of notifications on empty queue (Alex + Williamson) + - e1000: fix rx descriptor low threshold logic (Alex Willaimson) + - x86 tcg: add NULL checks to lsl instruction (Jan Kiszka) + - kvm vga: fix screen corruption with -std-vga and Windows (Avi Kivity) + - kvm vga: fix screen corruption with Ubuntu installations (Glauber Costa) + - virtio-net: check right return size on sg list (Alex Williamson) + - Make qemu_announce_self handle holes (live migration after hotplug) + (Marcelo Tosatti) + - Revert r6804-r6808 (qcow2 allocation info). This series of changes + added a high cost to startup for large qcow2 images (Anthony Liguori) + - qemu-img: fix help message (Aurelien Jarno) + - Fix build for non-default installs of SDL (Anthony Liguori) + - Fix race condition in env->interrupt_request. When using TCG and a + dynticks host timer, this condition could cause TCG to get stuck in an + infinite loop (Aurelien Jarno) + - Fix reading encrypted hard disk passwords during early startup (Jan + Kiszka) + - Fix encrypted disk reporting in 'info block' (Jan Kiszka) + - Fix console size with tiny displays (MusicPal) (Jan Kiszka) + - Improve error handling in bdrv_open2 (Jan Kiszka) + - Avoid leaking data in mux'ed character devices (Jan Kiszka) + - Fix initial character device reset (no banner in monitor) (Jan Kiszka) + - Fix cpuid KVM crash on i386 host (Lubomir Rintel) + - Fix SLES10sp2 installation by adding ISTAT1 register to LSI SCSI + emulation (Ryan Harper) +- s390x TCG backend +- i386-linux-user NPTL support * Wed Oct 08 2008 uli@suse.de - update -> current SVN - fixes PPC hosts @@ -258,7 +299,7 @@ rm -rf ${RPM_BUILD_ROOT} - disable only SNDRV_SB_CSP_IOCTL_LOAD_CODE for _IOC_SIZEBITS < 14 * Thu Aug 09 2007 olh@suse.de - disable some alsa SB ioctl declarations -* Tue Aug 07 2007 olh@suse.de +* Mon Aug 06 2007 olh@suse.de - remove inclusion of linux/compiler.h * Mon Jul 30 2007 uli@suse.de - fixed for S/390 @@ -287,7 +328,7 @@ rm -rf ${RPM_BUILD_ROOT} * Thu Jun 14 2007 agraf@suse.de - made wine work (set FS register to 0 on init) - suppressed robust_list warnings -* Thu Jun 14 2007 agraf@suse.de +* Wed Jun 13 2007 agraf@suse.de - made flash player 9 work on ppc - fixed FUTEX_WAKE_OP on machines where endianness differs - made mmap on x86_64 use the MAP_32BIT flag @@ -315,7 +356,7 @@ rm -rf ${RPM_BUILD_ROOT} - applied strace patch for debugging (by Stuart R. Anderson) * Wed Apr 04 2007 agraf@suse.de - fixed initrd loading on x86 -* Fri Mar 30 2007 ro@suse.de +* Thu Mar 29 2007 ro@suse.de - added bison to BuildRequires * Tue Feb 20 2007 uli@suse.de - added better fix by Robert Schiele (bug #241950) @@ -368,9 +409,9 @@ rm -rf ${RPM_BUILD_ROOT} * Wed Mar 08 2006 uli@suse.de - split giant patch - added NWFPE glue code fix -* Wed Mar 08 2006 schwab@suse.de -- More fixes for ia64 port. * Tue Mar 07 2006 schwab@suse.de +- More fixes for ia64 port. +* Mon Mar 06 2006 schwab@suse.de - Remove obsolete hunk from ia64 patch. * Wed Jan 25 2006 mls@suse.de - converted neededforbuild to BuildRequires @@ -386,7 +427,7 @@ rm -rf ${RPM_BUILD_ROOT} - updated linker scripts for new binutils release * Sat Sep 17 2005 dmueller@suse.de - update to 0.7.2 -* Tue Aug 16 2005 schwab@suse.de +* Mon Aug 15 2005 schwab@suse.de - Don't package /emul/ia32-linux on ia64. * Mon Aug 15 2005 schwab@suse.de - Fix compilation on ia64.