Merge branch 'upstream-1.7' into tizen_qemu_1.7
authorSeokYeon Hwang <syeon.hwang@samsung.com>
Wed, 11 Dec 2013 01:38:35 +0000 (10:38 +0900)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Wed, 11 Dec 2013 05:12:09 +0000 (14:12 +0900)
Signed-off-by: SeokYeon Hwang <syeon.hwang@samsung.com>
Conflicts:
VERSION
block/cow.c
block/raw-win32.c
block/stream.c
block/vmdk.c
blockdev.c
exec.c
hw/i386/pc_piix.c
hw/scsi/scsi-bus.c
include/qom/cpu.h
include/sysemu/kvm.h
qemu-img.c
tcg/tcg.c
tcg/tcg.h
vl.c

Change-Id: Ib8de93ad2c05150934e17e63d7f8e90ffdfccc62

57 files changed:
1  2 
.gitignore
Makefile
Makefile.target
arch_init.c
audio/audio.c
block.c
block/raw-win32.c
blockdev.c
configure
cpu-exec.c
cpus.c
default-configs/arm-softmmu.mak
exec.c
hw/Makefile.objs
hw/acpi/piix4.c
hw/arm/Makefile.objs
hw/display/vga.c
hw/i386/pc.c
hw/i386/pc_piix.c
hw/i386/pc_sysfw.c
hw/intc/apic_common.c
hw/pci/pci-hotplug-old.c
hw/pci/pci.c
hw/usb/dev-storage.c
hw/vigs/vigs_device.c
hw/virtio/virtio-pci.c
include/exec/cpu-defs.h
include/hw/i386/pc.h
include/qemu-common.h
include/sysemu/arch_init.h
include/sysemu/kvm.h
include/sysemu/sysemu.h
main-loop.c
qapi-schema.json
qemu-char.c
qemu-options.hx
qom/object.c
target-i386/translate.c
tcg/i386/tcg-target.c
tcg/tcg.c
tcg/tcg.h
tizen/src/ecs/ecs.c
tizen/src/hw/maru_board.c
tizen/src/hw/maru_brill_codec.c
tizen/src/hw/maru_brill_codec.h
tizen/src/hw/maru_camera_common_pci.c
tizen/src/hw/maru_vga.c
tizen/src/hw/maru_vga_template.h
tizen/src/maru_sdl.c
tizen/src/mloop_event.c
ui/input.c
ui/sdl.c
util/oslib-posix.c
util/oslib-win32.c
util/qemu-sockets.c
vl.c
xen-all.c

diff --combined .gitignore
@@@ -1,3 -1,3 +1,4 @@@
++config.status
  config-devices.*
  config-all-devices.*
  config-all-disas.*
@@@ -44,8 -44,11 +45,11 @@@ qemu-g
  qemu-bridge-helper
  qemu-monitor.texi
  vscclient
- QMP/qmp-commands.txt
+ qmp-commands.txt
+ test-bitops
  test-coroutine
+ test-int128
+ test-opts-visitor
  test-qmp-input-visitor
  test-qmp-output-visitor
  test-string-input-visitor
@@@ -79,6 -82,7 +83,7 @@@ fsdev/virtfs-proxy-helper.po
  *.la
  *.pc
  .libs
+ .sdk
  *.swp
  *.orig
  .pc
@@@ -106,19 -110,3 +111,19 @@@ cscope.
  tags
  TAGS
  *~
 +tizen/emulator
 +tizen/src/build_info.h
 +tizen/src/skin/client/src/about.properties
 +tizen/src/skin/client/bin
 +tizen/src/skin/client/build
 +tizen/src/skin/client/emulator-skin.jar
 +tizen/src/skin/client/lib
 +tizen/src/skin/client/native_src/*.so
 +tizen/src/skin/client/native_src/*.dynlib
 +tizen/src/check-cam
 +fsdev/virtfs-proxy-helper
 +.cproject
 +.project
 +tizen/src/check-hax
 +tizen/src/check-cam
 +
diff --combined Makefile
+++ b/Makefile
@@@ -28,7 -28,14 +28,14 @@@ CONFIG_ALL=
  include $(SRC_PATH)/rules.mak
  config-host.mak: $(SRC_PATH)/configure
        @echo $@ is out-of-date, running configure
-       @sed -n "/.*Configured with/s/[^:]*: //p" $@ | sh
+       @# TODO: The next lines include code which supports a smooth
+       @# transition from old configurations without config.status.
+       @# This code can be removed after QEMU 1.7.
+       @if test -x config.status; then \
+           ./config.status; \
+         else \
+           sed -n "/.*Configured with/s/[^:]*: //p" $@ | sh; \
+       fi
  else
  config-host.mak:
  ifneq ($(filter-out %clean,$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail))
@@@ -65,7 -72,7 +72,7 @@@ LIBS+=-lz $(LIBS_TOOLS
  HELPERS-$(CONFIG_LINUX) = qemu-bridge-helper$(EXESUF)
  
  ifdef BUILD_DOCS
- DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 QMP/qmp-commands.txt
+ DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 qmp-commands.txt
  ifdef CONFIG_VIRTFS
  DOCS+=fsdev/virtfs-proxy-helper.1
  endif
@@@ -168,7 -175,9 +175,9 @@@ recurse-all: $(SUBDIR_RULES) $(ROMSUBDI
  bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
  
  $(BUILD_DIR)/version.o: $(SRC_PATH)/version.rc $(BUILD_DIR)/config-host.h | $(BUILD_DIR)/version.lo
+       $(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<,"  RC    version.o")
  $(BUILD_DIR)/version.lo: $(SRC_PATH)/version.rc $(BUILD_DIR)/config-host.h
+       $(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<,"  RC    version.lo")
  
  Makefile: $(version-obj-y) $(version-lobj-y)
  
@@@ -233,8 -242,9 +242,9 @@@ clean
        rm -f qemu-options.def
        find . -name '*.[oda]' -type f -exec rm -f {} +
        find . -name '*.l[oa]' -type f -exec rm -f {} +
-       rm -f $(TOOLS) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
-       rm -Rf .libs
+       rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
+       rm -f fsdev/*.pod
+       rm -rf .libs */.libs
        rm -f qemu-img-cmds.h
        @# May not be present in GENERATED_HEADERS
        rm -f trace/generated-tracers-dtrace.dtrace*
        rm -f $(foreach f,$(GENERATED_SOURCES),$(f) $(f)-timestamp)
        rm -rf qapi-generated
        rm -rf qga/qapi-generated
-       $(MAKE) -C tests/tcg clean
        for d in $(ALL_SUBDIRS); do \
        if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
        rm -f $$d/qemu-options.def; \
@@@ -259,6 -268,7 +268,7 @@@ qemu-%.tar.bz2
  distclean: clean
        rm -f config-host.mak config-host.h* config-host.ld $(DOCS) qemu-options.texi qemu-img-cmds.texi qemu-monitor.texi
        rm -f config-all-devices.mak config-all-disas.mak
+       rm -f po/*.mo
        rm -f roms/seabios/config.mak roms/vgabios/config.mak
        rm -f qemu-doc.info qemu-doc.aux qemu-doc.cp qemu-doc.cps qemu-doc.dvi
        rm -f qemu-doc.fn qemu-doc.fns qemu-doc.info qemu-doc.ky qemu-doc.kys
        for d in $(TARGET_DIRS); do \
        rm -rf $$d || exit 1 ; \
          done
+       rm -Rf .sdk
        if test -f pixman/config.log; then make -C pixman distclean; fi
        if test -f dtc/version_gen.h; then make $(DTC_MAKE_ARGS) clean; fi
  
  KEYMAPS=da     en-gb  et  fr     fr-ch  is  lt  modifiers  no  pt-br  sv \
  ar      de     en-us  fi  fr-be  hr     it  lv  nl         pl  ru     th \
  common  de-ch  es     fo  fr-ca  hu     ja  mk  nl-be      pt  sl     tr \
- bepo
+ bepo    cz
  
  ifdef INSTALL_BLOBS
  BLOBS=bios.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \
  vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \
  acpi-dsdt.aml q35-acpi-dsdt.aml \
- ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \
+ ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin \
  pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
  pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
  efi-e1000.rom efi-eepro100.rom efi-ne2k_pci.rom \
@@@ -301,7 -312,7 +312,7 @@@ endi
  install-doc: $(DOCS)
        $(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)"
        $(INSTALL_DATA) qemu-doc.html  qemu-tech.html "$(DESTDIR)$(qemu_docdir)"
-       $(INSTALL_DATA) QMP/qmp-commands.txt "$(DESTDIR)$(qemu_docdir)"
+       $(INSTALL_DATA) qmp-commands.txt "$(DESTDIR)$(qemu_docdir)"
  ifdef CONFIG_POSIX
        $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
        $(INSTALL_DATA) qemu.1 "$(DESTDIR)$(mandir)/man1"
@@@ -315,6 -326,7 +326,6 @@@ ifdef CONFIG_VIRTF
        $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
        $(INSTALL_DATA) fsdev/virtfs-proxy-helper.1 "$(DESTDIR)$(mandir)/man1"
  endif
 -
  install-datadir:
        $(INSTALL_DIR) "$(DESTDIR)$(qemu_datadir)"
  
@@@ -394,7 -406,7 +405,7 @@@ qemu-options.texi: $(SRC_PATH)/qemu-opt
  qemu-monitor.texi: $(SRC_PATH)/hmp-commands.hx
        $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"  GEN   $@")
  
QMP/qmp-commands.txt: $(SRC_PATH)/qmp-commands.hx
+ qmp-commands.txt: $(SRC_PATH)/qmp-commands.hx
        $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -q < $< > $@,"  GEN   $@")
  
  qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx
diff --combined Makefile.target
@@@ -65,15 -65,11 +65,11 @@@ els
  stap:
  endif
  
 -all: $(PROGS) stap
 +all: $(PROGS) stap check-gl
  
  # Dummy command so that make thinks it has done something
        @true
  
- CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
- CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
- CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
  #########################################################
  # cpu emulator library
  obj-y = exec.o translate-all.o cpu-exec.o
@@@ -83,8 -79,8 +79,8 @@@ obj-$(CONFIG_TCG_INTERPRETER) += disas/
  obj-y += fpu/softfloat.o
  obj-y += target-$(TARGET_BASE_ARCH)/
  obj-y += disas.o
- obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o
- obj-$(CONFIG_NO_KVM) += kvm-stub.o
+ obj-$(call notempty,$(TARGET_XML_FILES)) += gdbstub-xml.o
+ obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
  
  #########################################################
  # Linux user emulator target
@@@ -125,18 -121,8 +121,18 @@@ LIBS+=$(libs_softmmu
  
  # xen support
  obj-$(CONFIG_XEN) += xen-all.o xen-mapcache.o
- obj-$(CONFIG_NO_XEN) += xen-stub.o
+ obj-$(call lnot,$(CONFIG_XEN)) += xen-stub.o
  
 +# HAX support
 +ifdef CONFIG_WIN32
 +obj-$(CONFIG_HAX) += target-i386/hax-all.o target-i386/hax-windows.o
 +obj-$(CONFIG_NO_HAX) += hax-stub.o
 +endif
 +ifdef CONFIG_DARWIN
 +obj-$(CONFIG_HAX) += target-i386/hax-all.o target-i386/hax-darwin.o
 +obj-$(CONFIG_NO_HAX) += hax-stub.o
 +endif
 +
  # Hardware support
  ifeq ($(TARGET_NAME), sparc64)
  obj-y += hw/sparc64/
@@@ -155,12 -141,6 +151,12 @@@ endif # CONFIG_SOFTMM
  
  nested-vars += obj-y
  
 +# Makefile for TIZEN-maru
 +ifdef CONFIG_MARU
 +include $(SRC_PATH)/tizen/src/Makefile.tizen
 +endif
 +##
 +
  # This resolves all nested paths, so it must come last
  include $(SRC_PATH)/Makefile.objs
  
@@@ -182,32 -162,6 +178,32 @@@ $(QEMU_PROG): $(all-obj-y) ../libqemuut
        $(call LINK,$^)
  endif
  
 +CHECK_GL_OBJS = check_gl.o gloffscreen_test.o gloffscreen_common.o 
 +CHECK_GL_LDFLAGS =
 +CHECK_GL_TARGET =
 +ifdef CONFIG_LINUX
 +CHECK_GL_OBJS += gloffscreen_xcomposite.o
 +#CHECK_GL_LDFLAGS += -lGL -lXcomposite -lXext -lglib-2.0
 +# Fix linking error on Ubuntu 13.04
 +CHECK_GL_LDFLAGS += -lGL -lXcomposite -lX11 -lXext -lglib-2.0
 +CHECK_GL_TARGET = check-gl
 +endif
 +ifdef CONFIG_WIN32
 +CHECK_GL_OBJS += gloffscreen_wgl.o
 +CHECK_GL_LDFLAGS += -fstack-protector `pkg-config --libs glib-2.0` -lopengl32 -lglu32 -lgdi32
 +CHECK_GL_TARGET = check-gl.exe
 +endif
 +ifdef CONFIG_DARWIN
 +CHECK_GL_OBJS += gloffscreen_agl.o
 +CHECK_GL_LDFLAGS += -mmacosx-version-min=10.4 `pkg-config --cflags --libs glib-2.0` -framework GLUT -framework OpenGL -framework AGL
 +CHECK_GL_TARGET = check-gl
 +endif
 +
 +check-gl: check_gl.o
 +      gcc -o $(CHECK_GL_TARGET) $(CHECK_GL_OBJS) $(CHECK_GL_LDFLAGS)
 +check_gl.o: check_gl.c
 +      gcc -c ../tizen/src/check_gl.c
 +
  gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh
        $(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES),"  GEN   $(TARGET_DIR)$@")
  
diff --combined arch_init.c
@@@ -150,10 -150,9 +150,9 @@@ int qemu_read_default_config_files(boo
      return 0;
  }
  
- static inline bool is_zero_page(uint8_t *p)
+ static inline bool is_zero_range(uint8_t *p, uint64_t size)
  {
-     return buffer_find_nonzero_offset(p, TARGET_PAGE_SIZE) ==
-         TARGET_PAGE_SIZE;
+     return buffer_find_nonzero_offset(p, size) == size;
  }
  
  /* struct contains XBZRLE cache and a static page
@@@ -342,7 -341,8 +341,8 @@@ ram_addr_t migration_bitmap_find_and_re
  {
      unsigned long base = mr->ram_addr >> TARGET_PAGE_BITS;
      unsigned long nr = base + (start >> TARGET_PAGE_BITS);
-     unsigned long size = base + (int128_get64(mr->size) >> TARGET_PAGE_BITS);
+     uint64_t mr_size = TARGET_PAGE_ALIGN(memory_region_size(mr));
+     unsigned long size = base + (mr_size >> TARGET_PAGE_BITS);
  
      unsigned long next;
  
@@@ -392,7 -392,7 +392,7 @@@ static void migration_bitmap_sync(void
      }
  
      if (!start_time) {
-         start_time = qemu_get_clock_ms(rt_clock);
+         start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
      }
  
      trace_migration_bitmap_sync_start();
      trace_migration_bitmap_sync_end(migration_dirty_pages
                                      - num_dirty_pages_init);
      num_dirty_pages_period += migration_dirty_pages - num_dirty_pages_init;
-     end_time = qemu_get_clock_ms(rt_clock);
+     end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
  
      /* more than 1 second = 1000 millisecons */
      if (end_time > start_time + 1000) {
@@@ -496,7 -496,7 +496,7 @@@ static int ram_save_block(QEMUFile *f, 
                          acct_info.dup_pages++;
                      }
                  }
-             } else if (is_zero_page(p)) {
+             } else if (is_zero_range(p, TARGET_PAGE_SIZE)) {
                  acct_info.dup_pages++;
                  bytes_sent = save_block_hdr(f, block, offset, cont,
                                              RAM_SAVE_FLAG_COMPRESS);
@@@ -672,7 -672,7 +672,7 @@@ static int ram_save_iterate(QEMUFile *f
  
      ram_control_before_iterate(f, RAM_CONTROL_ROUND);
  
-     t0 = qemu_get_clock_ns(rt_clock);
+     t0 = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
      i = 0;
      while ((ret = qemu_file_rate_limit(f)) == 0) {
          int bytes_sent;
             iterations
          */
          if ((i & 63) == 0) {
-             uint64_t t1 = (qemu_get_clock_ns(rt_clock) - t0) / 1000000;
+             uint64_t t1 = (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - t0) / 1000000;
              if (t1 > MAX_WAIT) {
                  DPRINTF("big wait: %" PRIu64 " milliseconds, %d iterations\n",
                          t1, i);
       */
      ram_control_after_iterate(f, RAM_CONTROL_ROUND);
  
+     bytes_transferred += total_sent;
+     /*
+      * Do not count these 8 bytes into total_sent, so that we can
+      * return 0 if no page had been dirtied.
+      */
+     qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
+     bytes_transferred += 8;
+     ret = qemu_file_get_error(f);
      if (ret < 0) {
-         bytes_transferred += total_sent;
          return ret;
      }
  
-     qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
-     total_sent += 8;
-     bytes_transferred += total_sent;
      return total_sent;
  }
  
@@@ -843,15 -848,8 +848,8 @@@ static inline void *host_from_stream_of
   */
  void ram_handle_compressed(void *host, uint8_t ch, uint64_t size)
  {
-     if (ch != 0 || !is_zero_page(host)) {
+     if (ch != 0 || !is_zero_range(host, size)) {
          memset(host, ch, size);
- #ifndef _WIN32
-         if (ch == 0 &&
-             (!kvm_enabled() || kvm_has_sync_mmu()) &&
-             getpagesize() <= TARGET_PAGE_SIZE) {
-             qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
-         }
- #endif
      }
  }
  
@@@ -1112,9 -1110,6 +1110,6 @@@ int qemu_uuid_parse(const char *str, ui
      if (ret != 16) {
          return -1;
      }
- #ifdef TARGET_I386
-     smbios_add_field(1, offsetof(struct smbios_type_1, uuid), uuid, 16);
- #endif
      return 0;
  }
  
@@@ -1125,20 -1120,18 +1120,18 @@@ void do_acpitable_option(const QemuOpt
  
      acpi_table_add(opts, &err);
      if (err) {
-         fprintf(stderr, "Wrong acpi table provided: %s\n",
-                 error_get_pretty(err));
+         error_report("Wrong acpi table provided: %s",
+                      error_get_pretty(err));
          error_free(err);
          exit(1);
      }
  #endif
  }
  
- void do_smbios_option(const char *optarg)
+ void do_smbios_option(QemuOpts *opts)
  {
  #ifdef TARGET_I386
-     if (smbios_entry_add(optarg) < 0) {
-         exit(1);
-     }
+     smbios_entry_add(opts);
  #endif
  }
  
@@@ -1195,15 -1188,14 +1188,14 @@@ static void mig_sleep_cpu(void *opq
     much time in the VM. The migration thread will try to catchup.
     Workload will experience a performance drop.
  */
- static void mig_throttle_cpu_down(CPUState *cpu, void *data)
- {
-     async_run_on_cpu(cpu, mig_sleep_cpu, NULL);
- }
  static void mig_throttle_guest_down(void)
  {
+     CPUState *cpu;
      qemu_mutex_lock_iothread();
-     qemu_for_each_cpu(mig_throttle_cpu_down, NULL);
+     CPU_FOREACH(cpu) {
+         async_run_on_cpu(cpu, mig_sleep_cpu, NULL);
+     }
      qemu_mutex_unlock_iothread();
  }
  
@@@ -1217,11 -1209,11 +1209,11 @@@ static void check_guest_throttling(void
      }
  
      if (!t0)  {
-         t0 = qemu_get_clock_ns(rt_clock);
+         t0 = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
          return;
      }
  
-     t1 = qemu_get_clock_ns(rt_clock);
+     t1 = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
  
      /* If it has been more than 40 ms since the last time the guest
       * was throttled then do it again.
          t0 = t1;
      }
  }
 +
 +int hax_available(void)
 +{
 +#ifdef CONFIG_HAX
 +    return 1;
 +#else
 +    return 0;
 +#endif
 +}
diff --combined audio/audio.c
  #define SW_NAME(sw) (sw)->name ? (sw)->name : "unknown"
  
  
 +#ifdef CONFIG_MARU
 +#include "../tizen/src/debug_ch.h"
 +MULTI_DEBUG_CHANNEL(tizen, qemu_audio);
 +#endif
 +
  /* Order of CONFIG_AUDIO_DRIVERS is import.
     The 1st one is the one used by default, that is the reason
      that we generate the list.
@@@ -344,15 -339,11 +344,15 @@@ void AUD_vlog (const char *cap, const c
          monitor_vprintf(default_mon, fmt, ap);
      }
      else {
 +#ifdef CONFIG_MARU
 +        TRACE(fmt, ap);
 +#else
          if (cap) {
              fprintf (stderr, "%s: ", cap);
          }
  
          vfprintf (stderr, fmt, ap);
 +#endif
      }
  }
  
@@@ -1133,10 -1124,11 +1133,11 @@@ static int audio_is_timer_needed (void
  static void audio_reset_timer (AudioState *s)
  {
      if (audio_is_timer_needed ()) {
-         qemu_mod_timer (s->ts, qemu_get_clock_ns (vm_clock) + 1);
+         timer_mod (s->ts,
+             qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + conf.period.ticks);
      }
      else {
-         qemu_del_timer (s->ts);
+         timer_del (s->ts);
      }
  }
  
@@@ -1843,7 -1835,7 +1844,7 @@@ static void audio_init (void
      QLIST_INIT (&s->cap_head);
      atexit (audio_atexit);
  
-     s->ts = qemu_new_timer_ns (vm_clock, audio_timer, s);
+     s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s);
      if (!s->ts) {
          hw_error("Could not create audio timer\n");
      }
          }
      }
  
 +#ifdef CONFIG_MARU
 +// Try to avoid certain wave out locking action in recent Windows...
 +// If wave out is locked (because nothing is wired to output jack, ...),
 +// QEMU can find voice out device, but open will failed. And it will cause guest audio lock-up.
 +// So, we test whether opening is success or not.
 +// It can not prevent lock-up caused by runtime voice out lock.
 +// To prevent it, QEMU audio backend structure must be changed.
 +// We should do it, but now we used simple fix temporarily.
 +    HWVoiceOut* hw = audio_calloc(AUDIO_FUNC, 1, s->drv->voice_size_out);
 +    if (!hw) {
 +        dolog ("Can not allocate voice `%s' size %d\n",
 +               s->drv->name, s->drv->voice_size_out);
 +    }
 +    if(s->drv->pcm_ops->init_out(hw, &conf.fixed_out.settings)) {
 +        INFO("Host audio out [%s] is malfunction. Change to noaudio driver\n",
 +                s->drv->name);
 +        done = 0;
 +    }
 +    else {
 +        INFO("Host audio out [%s] is normal.\n", s->drv->name);
 +        s->drv->pcm_ops->fini_out(hw);
 +    }
 +    g_free(hw);
 +#endif
 +
      if (!done) {
          done = !audio_driver_init (s, &no_audio_driver);
          if (!done) {
diff --combined block.c
+++ b/block.c
@@@ -86,13 -86,6 +86,6 @@@ static void coroutine_fn bdrv_co_do_rw(
  static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
      int64_t sector_num, int nb_sectors);
  
- static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors,
-         bool is_write, double elapsed_time, uint64_t *wait);
- static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write,
-         double elapsed_time, uint64_t *wait);
- static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors,
-         bool is_write, int64_t *wait);
  static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
      QTAILQ_HEAD_INITIALIZER(bdrv_states);
  
@@@ -123,70 -116,101 +116,101 @@@ int is_windows_drive(const char *filena
  #endif
  
  /* throttling disk I/O limits */
- void bdrv_io_limits_disable(BlockDriverState *bs)
+ void bdrv_set_io_limits(BlockDriverState *bs,
+                         ThrottleConfig *cfg)
  {
-     bs->io_limits_enabled = false;
+     int i;
  
-     do {} while (qemu_co_enter_next(&bs->throttled_reqs));
+     throttle_config(&bs->throttle_state, cfg);
  
-     if (bs->block_timer) {
-         qemu_del_timer(bs->block_timer);
-         qemu_free_timer(bs->block_timer);
-         bs->block_timer = NULL;
+     for (i = 0; i < 2; i++) {
+         qemu_co_enter_next(&bs->throttled_reqs[i]);
      }
+ }
  
-     bs->slice_start = 0;
-     bs->slice_end   = 0;
+ /* this function drain all the throttled IOs */
+ static bool bdrv_start_throttled_reqs(BlockDriverState *bs)
+ {
+     bool drained = false;
+     bool enabled = bs->io_limits_enabled;
+     int i;
+     bs->io_limits_enabled = false;
+     for (i = 0; i < 2; i++) {
+         while (qemu_co_enter_next(&bs->throttled_reqs[i])) {
+             drained = true;
+         }
+     }
+     bs->io_limits_enabled = enabled;
+     return drained;
  }
  
static void bdrv_block_timer(void *opaque)
void bdrv_io_limits_disable(BlockDriverState *bs)
  {
-     BlockDriverState *bs = opaque;
+     bs->io_limits_enabled = false;
  
-     qemu_co_enter_next(&bs->throttled_reqs);
+     bdrv_start_throttled_reqs(bs);
+     throttle_destroy(&bs->throttle_state);
  }
  
void bdrv_io_limits_enable(BlockDriverState *bs)
static void bdrv_throttle_read_timer_cb(void *opaque)
  {
-     qemu_co_queue_init(&bs->throttled_reqs);
-     bs->block_timer = qemu_new_timer_ns(vm_clock, bdrv_block_timer, bs);
-     bs->io_limits_enabled = true;
+     BlockDriverState *bs = opaque;
+     qemu_co_enter_next(&bs->throttled_reqs[0]);
+ }
+ static void bdrv_throttle_write_timer_cb(void *opaque)
+ {
+     BlockDriverState *bs = opaque;
+     qemu_co_enter_next(&bs->throttled_reqs[1]);
  }
  
- bool bdrv_io_limits_enabled(BlockDriverState *bs)
+ /* should be called before bdrv_set_io_limits if a limit is set */
+ void bdrv_io_limits_enable(BlockDriverState *bs)
  {
-     BlockIOLimit *io_limits = &bs->io_limits;
-     return io_limits->bps[BLOCK_IO_LIMIT_READ]
-          || io_limits->bps[BLOCK_IO_LIMIT_WRITE]
-          || io_limits->bps[BLOCK_IO_LIMIT_TOTAL]
-          || io_limits->iops[BLOCK_IO_LIMIT_READ]
-          || io_limits->iops[BLOCK_IO_LIMIT_WRITE]
-          || io_limits->iops[BLOCK_IO_LIMIT_TOTAL];
+     assert(!bs->io_limits_enabled);
+     throttle_init(&bs->throttle_state,
+                   QEMU_CLOCK_VIRTUAL,
+                   bdrv_throttle_read_timer_cb,
+                   bdrv_throttle_write_timer_cb,
+                   bs);
+     bs->io_limits_enabled = true;
  }
  
+ /* This function makes an IO wait if needed
+  *
+  * @nb_sectors: the number of sectors of the IO
+  * @is_write:   is the IO a write
+  */
  static void bdrv_io_limits_intercept(BlockDriverState *bs,
-                                      bool is_write, int nb_sectors)
+                                      int nb_sectors,
+                                      bool is_write)
  {
-     int64_t wait_time = -1;
+     /* does this io must wait */
+     bool must_wait = throttle_schedule_timer(&bs->throttle_state, is_write);
  
-     if (!qemu_co_queue_empty(&bs->throttled_reqs)) {
-         qemu_co_queue_wait(&bs->throttled_reqs);
+     /* if must wait or any request of this type throttled queue the IO */
+     if (must_wait ||
+         !qemu_co_queue_empty(&bs->throttled_reqs[is_write])) {
+         qemu_co_queue_wait(&bs->throttled_reqs[is_write]);
      }
  
-     /* In fact, we hope to keep each request's timing, in FIFO mode. The next
-      * throttled requests will not be dequeued until the current request is
-      * allowed to be serviced. So if the current request still exceeds the
-      * limits, it will be inserted to the head. All requests followed it will
-      * be still in throttled_reqs queue.
-      */
+     /* the IO will be executed, do the accounting */
+     throttle_account(&bs->throttle_state,
+                      is_write,
+                      nb_sectors * BDRV_SECTOR_SIZE);
  
-     while (bdrv_exceed_io_limits(bs, nb_sectors, is_write, &wait_time)) {
-         qemu_mod_timer(bs->block_timer,
-                        wait_time + qemu_get_clock_ns(vm_clock));
-         qemu_co_queue_wait_insert_head(&bs->throttled_reqs);
+     /* if the next request must wait -> do nothing */
+     if (throttle_schedule_timer(&bs->throttle_state, is_write)) {
+         return;
      }
  
-     qemu_co_queue_next(&bs->throttled_reqs);
+     /* else queue next request for execution */
+     qemu_co_queue_next(&bs->throttled_reqs[is_write]);
  }
  
  /* check if the path starts with "<protocol>:" */
@@@ -306,6 -330,9 +330,9 @@@ BlockDriverState *bdrv_new(const char *
      bdrv_iostatus_disable(bs);
      notifier_list_init(&bs->close_notifiers);
      notifier_with_return_list_init(&bs->before_write_notifiers);
+     qemu_co_queue_init(&bs->throttled_reqs[0]);
+     qemu_co_queue_init(&bs->throttled_reqs[1]);
+     bs->refcnt = 1;
  
      return bs;
  }
@@@ -367,18 -394,26 +394,26 @@@ typedef struct CreateCo 
      char *filename;
      QEMUOptionParameter *options;
      int ret;
+     Error *err;
  } CreateCo;
  
  static void coroutine_fn bdrv_create_co_entry(void *opaque)
  {
+     Error *local_err = NULL;
+     int ret;
      CreateCo *cco = opaque;
      assert(cco->drv);
  
-     cco->ret = cco->drv->bdrv_create(cco->filename, cco->options);
+     ret = cco->drv->bdrv_create(cco->filename, cco->options, &local_err);
+     if (error_is_set(&local_err)) {
+         error_propagate(&cco->err, local_err);
+     }
+     cco->ret = ret;
  }
  
  int bdrv_create(BlockDriver *drv, const char* filename,
-     QEMUOptionParameter *options)
+     QEMUOptionParameter *options, Error **errp)
  {
      int ret;
  
          .filename = g_strdup(filename),
          .options = options,
          .ret = NOT_DONE,
+         .err = NULL,
      };
  
      if (!drv->bdrv_create) {
+         error_setg(errp, "Driver '%s' does not support image creation", drv->format_name);
          ret = -ENOTSUP;
          goto out;
      }
      }
  
      ret = cco.ret;
+     if (ret < 0) {
+         if (error_is_set(&cco.err)) {
+             error_propagate(errp, cco.err);
+         } else {
+             error_setg_errno(errp, -ret, "Could not create image");
+         }
+     }
  
  out:
      g_free(cco.filename);
      return ret;
  }
  
- int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
+ int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
+                      Error **errp)
  {
      BlockDriver *drv;
+     Error *local_err = NULL;
+     int ret;
  
      drv = bdrv_find_protocol(filename, true);
      if (drv == NULL) {
+         error_setg(errp, "Could not find protocol for file '%s'", filename);
          return -ENOENT;
      }
  
-     return bdrv_create(drv, filename, options);
+     ret = bdrv_create(drv, filename, options, &local_err);
+     if (error_is_set(&local_err)) {
+         error_propagate(errp, local_err);
+     }
+     return ret;
  }
  
  /*
@@@ -525,7 -577,7 +577,7 @@@ BlockDriver *bdrv_find_protocol(const c
  }
  
  static int find_image_format(BlockDriverState *bs, const char *filename,
-                              BlockDriver **pdrv)
+                              BlockDriver **pdrv, Error **errp)
  {
      int score, score_max;
      BlockDriver *drv1, *drv;
      if (bs->sg || !bdrv_is_inserted(bs) || bdrv_getlength(bs) == 0) {
          drv = bdrv_find_format("raw");
          if (!drv) {
+             error_setg(errp, "Could not find raw image format");
              ret = -ENOENT;
          }
          *pdrv = drv;
  
      ret = bdrv_pread(bs, 0, buf, sizeof(buf));
      if (ret < 0) {
+         error_setg_errno(errp, -ret, "Could not read image for determining its "
+                          "format");
          *pdrv = NULL;
          return ret;
      }
          }
      }
      if (!drv) {
+         error_setg(errp, "Could not determine image format: No compatible "
+                    "driver found");
          ret = -ENOENT;
      }
      *pdrv = drv;
@@@ -583,7 -640,7 +640,7 @@@ static int refresh_total_sectors(BlockD
          if (length < 0) {
              return length;
          }
-         hint = length >> BDRV_SECTOR_BITS;
+         hint = DIV_ROUND_UP(length, BDRV_SECTOR_SIZE);
      }
  
      bs->total_sectors = hint;
@@@ -679,10 -736,11 +736,11 @@@ static int bdrv_open_flags(BlockDriverS
   * Removes all processed options from *options.
   */
  static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
-     QDict *options, int flags, BlockDriver *drv)
+     QDict *options, int flags, BlockDriver *drv, Error **errp)
  {
      int ret, open_flags;
      const char *filename;
+     Error *local_err = NULL;
  
      assert(drv != NULL);
      assert(bs->file == NULL);
  
      bs->open_flags = flags;
      bs->buffer_alignment = 512;
+     bs->zero_beyond_eof = true;
      open_flags = bdrv_open_flags(bs, flags);
      bs->read_only = !(open_flags & BDRV_O_RDWR);
  
      if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, bs->read_only)) {
+         error_setg(errp,
+                    !bs->read_only && bdrv_is_whitelisted(drv, true)
+                         ? "Driver '%s' can only be used for read-only devices"
+                         : "Driver '%s' is not whitelisted",
+                    drv->format_name);
          return -ENOTSUP;
      }
  
      assert(bs->copy_on_read == 0); /* bdrv_new() and bdrv_close() make it so */
-     if (!bs->read_only && (flags & BDRV_O_COPY_ON_READ)) {
-         bdrv_enable_copy_on_read(bs);
+     if (flags & BDRV_O_COPY_ON_READ) {
+         if (!bs->read_only) {
+             bdrv_enable_copy_on_read(bs);
+         } else {
+             error_setg(errp, "Can't use copy-on-read on read-only device");
+             return -EINVAL;
+         }
      }
  
      if (filename != NULL) {
      /* Open the image, either directly or using a protocol */
      if (drv->bdrv_file_open) {
          assert(file == NULL);
-         assert(drv->bdrv_parse_filename || filename != NULL);
-         ret = drv->bdrv_file_open(bs, options, open_flags);
+         assert(!drv->bdrv_needs_filename || filename != NULL);
+         ret = drv->bdrv_file_open(bs, options, open_flags, &local_err);
      } else {
          if (file == NULL) {
-             qerror_report(ERROR_CLASS_GENERIC_ERROR, "Can't use '%s' as a "
-                           "block driver for the protocol level",
-                           drv->format_name);
+             error_setg(errp, "Can't use '%s' as a block driver for the "
+                        "protocol level", drv->format_name);
              ret = -EINVAL;
              goto free_and_fail;
          }
-         assert(file != NULL);
          bs->file = file;
-         ret = drv->bdrv_open(bs, options, open_flags);
+         ret = drv->bdrv_open(bs, options, open_flags, &local_err);
      }
  
      if (ret < 0) {
+         if (error_is_set(&local_err)) {
+             error_propagate(errp, local_err);
+         } else if (bs->filename[0]) {
+             error_setg_errno(errp, -ret, "Could not open '%s'", bs->filename);
+         } else {
+             error_setg_errno(errp, -ret, "Could not open image");
+         }
          goto free_and_fail;
      }
  
      ret = refresh_total_sectors(bs, bs->total_sectors);
      if (ret < 0) {
+         error_setg_errno(errp, -ret, "Could not refresh total sector count");
          goto free_and_fail;
      }
  
  #ifndef _WIN32
      if (bs->is_temporary) {
-         assert(filename != NULL);
-         unlink(filename);
+         assert(bs->filename[0] != '\0');
+         unlink(bs->filename);
      }
  #endif
      return 0;
@@@ -781,12 -856,13 +856,13 @@@ free_and_fail
   * dictionary, it needs to use QINCREF() before calling bdrv_file_open.
   */
  int bdrv_file_open(BlockDriverState **pbs, const char *filename,
-                    QDict *options, int flags)
+                    QDict *options, int flags, Error **errp)
  {
      BlockDriverState *bs;
      BlockDriver *drv;
      const char *drvname;
      bool allow_protocol_prefix = false;
+     Error *local_err = NULL;
      int ret;
  
      /* NULL means an empty set of options */
          qdict_put(options, "filename", qstring_from_str(filename));
          allow_protocol_prefix = true;
      } else {
-         qerror_report(ERROR_CLASS_GENERIC_ERROR, "Can't specify 'file' and "
-                       "'filename' options at the same time");
+         error_setg(errp, "Can't specify 'file' and 'filename' options at the "
+                    "same time");
          ret = -EINVAL;
          goto fail;
      }
      /* Find the right block driver */
      drvname = qdict_get_try_str(options, "driver");
      if (drvname) {
-         drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR));
+         drv = bdrv_find_format(drvname);
+         if (!drv) {
+             error_setg(errp, "Unknown driver '%s'", drvname);
+         }
          qdict_del(options, "driver");
      } else if (filename) {
          drv = bdrv_find_protocol(filename, allow_protocol_prefix);
          if (!drv) {
-             qerror_report(ERROR_CLASS_GENERIC_ERROR, "Unknown protocol");
+             error_setg(errp, "Unknown protocol");
          }
      } else {
-         qerror_report(ERROR_CLASS_GENERIC_ERROR,
-                       "Must specify either driver or file");
+         error_setg(errp, "Must specify either driver or file");
          drv = NULL;
      }
  
      if (!drv) {
+         /* errp has been set already */
          ret = -ENOENT;
          goto fail;
      }
  
      /* Parse the filename and open it */
      if (drv->bdrv_parse_filename && filename) {
-         Error *local_err = NULL;
          drv->bdrv_parse_filename(filename, options, &local_err);
          if (error_is_set(&local_err)) {
-             qerror_report_err(local_err);
-             error_free(local_err);
+             error_propagate(errp, local_err);
              ret = -EINVAL;
              goto fail;
          }
          qdict_del(options, "filename");
-     } else if (!drv->bdrv_parse_filename && !filename) {
-         qerror_report(ERROR_CLASS_GENERIC_ERROR,
-                       "The '%s' block driver requires a file name",
-                       drv->format_name);
+     } else if (drv->bdrv_needs_filename && !filename) {
+         error_setg(errp, "The '%s' block driver requires a file name",
+                    drv->format_name);
          ret = -EINVAL;
          goto fail;
      }
  
-     ret = bdrv_open_common(bs, NULL, options, flags, drv);
+     ret = bdrv_open_common(bs, NULL, options, flags, drv, &local_err);
      if (ret < 0) {
+         error_propagate(errp, local_err);
          goto fail;
      }
  
      /* Check if any unknown options were used */
      if (qdict_size(options) != 0) {
          const QDictEntry *entry = qdict_first(options);
-         qerror_report(ERROR_CLASS_GENERIC_ERROR, "Block protocol '%s' doesn't "
-                       "support the option '%s'",
-                       drv->format_name, entry->key);
+         error_setg(errp, "Block protocol '%s' doesn't support the option '%s'",
+                    drv->format_name, entry->key);
          ret = -EINVAL;
          goto fail;
      }
@@@ -876,7 -952,7 +952,7 @@@ fail
      if (!bs->drv) {
          QDECREF(bs->options);
      }
-     bdrv_delete(bs);
+     bdrv_unref(bs);
      return ret;
  }
  
   * function (even on failure), so if the caller intends to reuse the dictionary,
   * it needs to use QINCREF() before calling bdrv_file_open.
   */
- int bdrv_open_backing_file(BlockDriverState *bs, QDict *options)
+ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
  {
      char backing_filename[PATH_MAX];
      int back_flags, ret;
      BlockDriver *back_drv = NULL;
+     Error *local_err = NULL;
  
      if (bs->backing_hd != NULL) {
          QDECREF(options);
      } else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) {
          QDECREF(options);
          return 0;
+     } else {
+         bdrv_get_full_backing_filename(bs, backing_filename,
+                                        sizeof(backing_filename));
      }
  
      bs->backing_hd = bdrv_new("");
-     bdrv_get_full_backing_filename(bs, backing_filename,
-                                    sizeof(backing_filename));
  
      if (bs->backing_format[0] != '\0') {
          back_drv = bdrv_find_format(bs->backing_format);
      }
  
      /* backing files always opened read-only */
-     back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT);
+     back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT |
+                                     BDRV_O_COPY_ON_READ);
  
      ret = bdrv_open(bs->backing_hd,
                      *backing_filename ? backing_filename : NULL, options,
-                     back_flags, back_drv);
+                     back_flags, back_drv, &local_err);
      if (ret < 0) {
-         bdrv_delete(bs->backing_hd);
+         bdrv_unref(bs->backing_hd);
          bs->backing_hd = NULL;
          bs->open_flags |= BDRV_O_NO_BACKING;
+         error_setg(errp, "Could not open backing file: %s",
+                    error_get_pretty(local_err));
+         error_free(local_err);
          return ret;
      }
+     pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+             bs->backing_hd->file->filename);
      return 0;
  }
  
- static void extract_subqdict(QDict *src, QDict **dst, const char *start)
- {
-     const QDictEntry *entry, *next;
-     const char *p;
-     *dst = qdict_new();
-     entry = qdict_first(src);
-     while (entry != NULL) {
-         next = qdict_next(src, entry);
-         if (strstart(entry->key, start, &p)) {
-             qobject_incref(entry->value);
-             qdict_put_obj(*dst, p, entry->value);
-             qdict_del(src, entry->key);
-         }
-         entry = next;
-     }
- }
  /*
   * Opens a disk image (raw, qcow2, vmdk, ...)
   *
   * dictionary, it needs to use QINCREF() before calling bdrv_open.
   */
  int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
-               int flags, BlockDriver *drv)
+               int flags, BlockDriver *drv, Error **errp)
  {
      int ret;
      /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
      BlockDriverState *file = NULL;
      QDict *file_options = NULL;
      const char *drvname;
+     Error *local_err = NULL;
  
      /* NULL means an empty set of options */
      if (options == NULL) {
          char backing_filename[PATH_MAX];
  
          if (qdict_size(options) != 0) {
-             error_report("Can't use snapshot=on with driver-specific options");
+             error_setg(errp, "Can't use snapshot=on with driver-specific options");
              ret = -EINVAL;
              goto fail;
          }
  
          /* if there is a backing file, use it */
          bs1 = bdrv_new("");
-         ret = bdrv_open(bs1, filename, NULL, 0, drv);
+         ret = bdrv_open(bs1, filename, NULL, 0, drv, &local_err);
          if (ret < 0) {
-             bdrv_delete(bs1);
+             bdrv_unref(bs1);
              goto fail;
          }
          total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK;
  
-         bdrv_delete(bs1);
+         bdrv_unref(bs1);
  
          ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
          if (ret < 0) {
+             error_setg_errno(errp, -ret, "Could not get temporary filename");
              goto fail;
          }
  
                       "%s", filename);
          } else if (!realpath(filename, backing_filename)) {
              ret = -errno;
+             error_setg_errno(errp, errno, "Could not resolve path '%s'", filename);
              goto fail;
          }
  
                  drv->format_name);
          }
  
-         ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options);
+         ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options, &local_err);
          free_option_parameters(create_options);
          if (ret < 0) {
+             error_setg_errno(errp, -ret, "Could not create temporary overlay "
+                              "'%s': %s", tmp_filename,
+                              error_get_pretty(local_err));
+             error_free(local_err);
+             local_err = NULL;
              goto fail;
          }
  
          flags |= BDRV_O_ALLOW_RDWR;
      }
  
-     extract_subqdict(options, &file_options, "file.");
+     qdict_extract_subqdict(options, &file_options, "file.");
  
      ret = bdrv_file_open(&file, filename, file_options,
-                          bdrv_open_flags(bs, flags | BDRV_O_UNMAP));
+                          bdrv_open_flags(bs, flags | BDRV_O_UNMAP), &local_err);
      if (ret < 0) {
          goto fail;
      }
      /* Find the right image format driver */
      drvname = qdict_get_try_str(options, "driver");
      if (drvname) {
-         drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR));
+         drv = bdrv_find_format(drvname);
          qdict_del(options, "driver");
+         if (!drv) {
+             error_setg(errp, "Invalid driver: '%s'", drvname);
+             ret = -EINVAL;
+             goto unlink_and_fail;
+         }
      }
  
      if (!drv) {
-         ret = find_image_format(file, filename, &drv);
+         ret = find_image_format(file, filename, &drv, &local_err);
      }
  
      if (!drv) {
      }
  
      /* Open the image */
-     ret = bdrv_open_common(bs, file, options, flags, drv);
+     ret = bdrv_open_common(bs, file, options, flags, drv, &local_err);
      if (ret < 0) {
          goto unlink_and_fail;
      }
  
      if (bs->file != file) {
-         bdrv_delete(file);
+         bdrv_unref(file);
          file = NULL;
      }
  
      if ((flags & BDRV_O_NO_BACKING) == 0) {
          QDict *backing_options;
  
-         extract_subqdict(options, &backing_options, "backing.");
-         ret = bdrv_open_backing_file(bs, backing_options);
+         qdict_extract_subqdict(options, &backing_options, "backing.");
+         ret = bdrv_open_backing_file(bs, backing_options, &local_err);
          if (ret < 0) {
              goto close_and_fail;
          }
      /* Check if any unknown options were used */
      if (qdict_size(options) != 0) {
          const QDictEntry *entry = qdict_first(options);
-         qerror_report(ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by "
-             "device '%s' doesn't support the option '%s'",
-             drv->format_name, bs->device_name, entry->key);
+         error_setg(errp, "Block format '%s' used by device '%s' doesn't "
+                    "support the option '%s'", drv->format_name, bs->device_name,
+                    entry->key);
  
          ret = -EINVAL;
          goto close_and_fail;
          bdrv_dev_change_media_cb(bs, true);
      }
  
-     /* throttling disk I/O limits */
-     if (bs->io_limits_enabled) {
-         bdrv_io_limits_enable(bs);
-     }
      return 0;
  
  unlink_and_fail:
      if (file != NULL) {
-         bdrv_delete(file);
+         bdrv_unref(file);
      }
      if (bs->is_temporary) {
          unlink(filename);
@@@ -1130,11 -1203,17 +1203,17 @@@ fail
      QDECREF(bs->options);
      QDECREF(options);
      bs->options = NULL;
+     if (error_is_set(&local_err)) {
+         error_propagate(errp, local_err);
+     }
      return ret;
  
  close_and_fail:
      bdrv_close(bs);
      QDECREF(options);
+     if (error_is_set(&local_err)) {
+         error_propagate(errp, local_err);
+     }
      return ret;
  }
  
@@@ -1382,7 -1461,7 +1461,7 @@@ void bdrv_close(BlockDriverState *bs
  
      if (bs->drv) {
          if (bs->backing_hd) {
-             bdrv_delete(bs->backing_hd);
+             bdrv_unref(bs->backing_hd);
              bs->backing_hd = NULL;
          }
          bs->drv->bdrv_close(bs);
          bs->valid_key = 0;
          bs->sg = 0;
          bs->growable = 0;
+         bs->zero_beyond_eof = false;
          QDECREF(bs->options);
          bs->options = NULL;
  
          if (bs->file != NULL) {
-             bdrv_delete(bs->file);
+             bdrv_unref(bs->file);
              bs->file = NULL;
          }
      }
@@@ -1428,6 -1508,38 +1508,38 @@@ void bdrv_close_all(void
      }
  }
  
+ /* Check if any requests are in-flight (including throttled requests) */
+ static bool bdrv_requests_pending(BlockDriverState *bs)
+ {
+     if (!QLIST_EMPTY(&bs->tracked_requests)) {
+         return true;
+     }
+     if (!qemu_co_queue_empty(&bs->throttled_reqs[0])) {
+         return true;
+     }
+     if (!qemu_co_queue_empty(&bs->throttled_reqs[1])) {
+         return true;
+     }
+     if (bs->file && bdrv_requests_pending(bs->file)) {
+         return true;
+     }
+     if (bs->backing_hd && bdrv_requests_pending(bs->backing_hd)) {
+         return true;
+     }
+     return false;
+ }
+ static bool bdrv_requests_pending_all(void)
+ {
+     BlockDriverState *bs;
+     QTAILQ_FOREACH(bs, &bdrv_states, list) {
+         if (bdrv_requests_pending(bs)) {
+             return true;
+         }
+     }
+     return false;
+ }
  /*
   * Wait for pending requests to complete across all BlockDriverStates
   *
   */
  void bdrv_drain_all(void)
  {
+     /* Always run first iteration so any pending completion BHs run */
+     bool busy = true;
      BlockDriverState *bs;
-     bool busy;
-     do {
-         busy = qemu_aio_wait();
  
+     while (busy) {
          /* FIXME: We do not have timer support here, so this is effectively
           * a busy wait.
           */
          QTAILQ_FOREACH(bs, &bdrv_states, list) {
-             while (qemu_co_enter_next(&bs->throttled_reqs)) {
+             if (bdrv_start_throttled_reqs(bs)) {
                  busy = true;
              }
          }
-     } while (busy);
  
-     /* If requests are still pending there is a bug somewhere */
-     QTAILQ_FOREACH(bs, &bdrv_states, list) {
-         assert(QLIST_EMPTY(&bs->tracked_requests));
-         assert(qemu_co_queue_empty(&bs->throttled_reqs));
+         busy = bdrv_requests_pending_all();
+         busy |= aio_poll(qemu_get_aio_context(), busy);
      }
  }
  
@@@ -1497,13 -1605,12 +1605,12 @@@ static void bdrv_move_feature_fields(Bl
  
      bs_dest->enable_write_cache = bs_src->enable_write_cache;
  
-     /* i/o timing parameters */
-     bs_dest->slice_start        = bs_src->slice_start;
-     bs_dest->slice_end          = bs_src->slice_end;
-     bs_dest->slice_submitted    = bs_src->slice_submitted;
-     bs_dest->io_limits          = bs_src->io_limits;
-     bs_dest->throttled_reqs     = bs_src->throttled_reqs;
-     bs_dest->block_timer        = bs_src->block_timer;
+     /* i/o throttled req */
+     memcpy(&bs_dest->throttle_state,
+            &bs_src->throttle_state,
+            sizeof(ThrottleState));
+     bs_dest->throttled_reqs[0]  = bs_src->throttled_reqs[0];
+     bs_dest->throttled_reqs[1]  = bs_src->throttled_reqs[1];
      bs_dest->io_limits_enabled  = bs_src->io_limits_enabled;
  
      /* r/w error */
      /* dirty bitmap */
      bs_dest->dirty_bitmap       = bs_src->dirty_bitmap;
  
+     /* reference count */
+     bs_dest->refcnt             = bs_src->refcnt;
      /* job */
      bs_dest->in_use             = bs_src->in_use;
      bs_dest->job                = bs_src->job;
@@@ -1550,7 -1660,7 +1660,7 @@@ void bdrv_swap(BlockDriverState *bs_new
      assert(bs_new->dev == NULL);
      assert(bs_new->in_use == 0);
      assert(bs_new->io_limits_enabled == false);
-     assert(bs_new->block_timer == NULL);
+     assert(!throttle_have_timer(&bs_new->throttle_state));
  
      tmp = *bs_new;
      *bs_new = *bs_old;
      assert(bs_new->job == NULL);
      assert(bs_new->in_use == 0);
      assert(bs_new->io_limits_enabled == false);
-     assert(bs_new->block_timer == NULL);
+     assert(!throttle_have_timer(&bs_new->throttle_state));
  
      bdrv_rebind(bs_new);
      bdrv_rebind(bs_old);
@@@ -1600,14 -1710,15 +1710,17 @@@ void bdrv_append(BlockDriverState *bs_n
              bs_new->drv ? bs_new->drv->format_name : "");
  }
  
- void bdrv_delete(BlockDriverState *bs)
static void bdrv_delete(BlockDriverState *bs)
  {
      assert(!bs->dev);
      assert(!bs->job);
      assert(!bs->in_use);
+     assert(!bs->refcnt);
+     bdrv_close(bs);
  
 +    bdrv_close(bs);
 +
      /* remove from list, if necessary */
      bdrv_make_anon(bs);
  
@@@ -2123,7 -2234,7 +2236,7 @@@ int bdrv_drop_intermediate(BlockDriverS
      QSIMPLEQ_FOREACH_SAFE(intermediate_state, &states_to_delete, entry, next) {
          /* so that bdrv_close() does not recursively close the chain */
          intermediate_state->bs->backing_hd = NULL;
-         bdrv_delete(intermediate_state->bs);
+         bdrv_unref(intermediate_state->bs);
      }
      ret = 0;
  
@@@ -2515,11 -2626,6 +2628,6 @@@ static int coroutine_fn bdrv_co_do_read
          return -EIO;
      }
  
-     /* throttling disk read I/O */
-     if (bs->io_limits_enabled) {
-         bdrv_io_limits_intercept(bs, false, nb_sectors);
-     }
      if (bs->copy_on_read) {
          flags |= BDRV_REQ_COPY_ON_READ;
      }
          wait_for_overlapping_requests(bs, sector_num, nb_sectors);
      }
  
+     /* throttling disk I/O */
+     if (bs->io_limits_enabled) {
+         bdrv_io_limits_intercept(bs, nb_sectors, false);
+     }
      tracked_request_begin(&req, bs, sector_num, nb_sectors, false);
  
      if (flags & BDRV_REQ_COPY_ON_READ) {
          int pnum;
  
-         ret = bdrv_co_is_allocated(bs, sector_num, nb_sectors, &pnum);
+         ret = bdrv_is_allocated(bs, sector_num, nb_sectors, &pnum);
          if (ret < 0) {
              goto out;
          }
          }
      }
  
-     ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
+     if (!(bs->zero_beyond_eof && bs->growable)) {
+         ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
+     } else {
+         /* Read zeros after EOF of growable BDSes */
+         int64_t len, total_sectors, max_nb_sectors;
+         len = bdrv_getlength(bs);
+         if (len < 0) {
+             ret = len;
+             goto out;
+         }
+         total_sectors = DIV_ROUND_UP(len, BDRV_SECTOR_SIZE);
+         max_nb_sectors = MAX(0, total_sectors - sector_num);
+         if (max_nb_sectors > 0) {
+             ret = drv->bdrv_co_readv(bs, sector_num,
+                                      MIN(nb_sectors, max_nb_sectors), qiov);
+         } else {
+             ret = 0;
+         }
+         /* Reading beyond end of file is supposed to produce zeroes */
+         if (ret == 0 && total_sectors < sector_num + nb_sectors) {
+             uint64_t offset = MAX(0, total_sectors - sector_num);
+             uint64_t bytes = (sector_num + nb_sectors - offset) *
+                               BDRV_SECTOR_SIZE;
+             qemu_iovec_memset(qiov, offset * BDRV_SECTOR_SIZE, 0, bytes);
+         }
+     }
  
  out:
      tracked_request_end(&req);
@@@ -2628,15 -2767,15 +2769,15 @@@ static int coroutine_fn bdrv_co_do_writ
          return -EIO;
      }
  
-     /* throttling disk write I/O */
-     if (bs->io_limits_enabled) {
-         bdrv_io_limits_intercept(bs, true, nb_sectors);
-     }
      if (bs->copy_on_read_in_flight) {
          wait_for_overlapping_requests(bs, sector_num, nb_sectors);
      }
  
+     /* throttling disk I/O */
+     if (bs->io_limits_enabled) {
+         bdrv_io_limits_intercept(bs, nb_sectors, true);
+     }
      tracked_request_begin(&req, bs, sector_num, nb_sectors, true);
  
      ret = notifier_with_return_list_notify(&bs->before_write_notifiers, &req);
      if (bs->wr_highest_sector < sector_num + nb_sectors - 1) {
          bs->wr_highest_sector = sector_num + nb_sectors - 1;
      }
+     if (bs->growable && ret >= 0) {
+         bs->total_sectors = MAX(bs->total_sectors, sector_num + nb_sectors);
+     }
  
      tracked_request_end(&req);
  
@@@ -2734,9 -2876,10 +2878,10 @@@ int64_t bdrv_getlength(BlockDriverStat
      if (!drv)
          return -ENOMEDIUM;
  
-     if (bs->growable || bdrv_dev_has_removable_media(bs)) {
-         if (drv->bdrv_getlength) {
-             return drv->bdrv_getlength(bs);
+     if (drv->has_variable_length) {
+         int ret = refresh_total_sectors(bs, bs->total_sectors);
+         if (ret < 0) {
+             return ret;
          }
      }
      return bs->total_sectors * BDRV_SECTOR_SIZE;
@@@ -2754,14 -2897,6 +2899,6 @@@ void bdrv_get_geometry(BlockDriverStat
      *nb_sectors_ptr = length;
  }
  
- /* throttling disk io limits */
- void bdrv_set_io_limits(BlockDriverState *bs,
-                         BlockIOLimit *io_limits)
- {
-     bs->io_limits = *io_limits;
-     bs->io_limits_enabled = bdrv_io_limits_enabled(bs);
- }
  void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error,
                         BlockdevOnError on_write_error)
  {
@@@ -2954,6 -3089,11 +3091,11 @@@ int bdrv_has_zero_init(BlockDriverStat
  {
      assert(bs->drv);
  
+     /* If BS is a copy on write image, it is initialized to
+        the contents of the base image, which may not be zeroes.  */
+     if (bs->backing_hd) {
+         return 0;
+     }
      if (bs->drv->bdrv_has_zero_init) {
          return bs->drv->bdrv_has_zero_init(bs);
      }
      return 0;
  }
  
- typedef struct BdrvCoIsAllocatedData {
+ typedef struct BdrvCoGetBlockStatusData {
      BlockDriverState *bs;
      BlockDriverState *base;
      int64_t sector_num;
      int nb_sectors;
      int *pnum;
-     int ret;
+     int64_t ret;
      bool done;
- } BdrvCoIsAllocatedData;
+ } BdrvCoGetBlockStatusData;
  
  /*
   * Returns true iff the specified sector is present in the disk image. Drivers
   * 'nb_sectors' is the max value 'pnum' should be set to.  If nb_sectors goes
   * beyond the end of the disk image it will be clamped.
   */
- int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t sector_num,
-                                       int nb_sectors, int *pnum)
+ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
+                                                      int64_t sector_num,
+                                                      int nb_sectors, int *pnum)
  {
+     int64_t length;
      int64_t n;
+     int64_t ret, ret2;
  
-     if (sector_num >= bs->total_sectors) {
+     length = bdrv_getlength(bs);
+     if (length < 0) {
+         return length;
+     }
+     if (sector_num >= (length >> BDRV_SECTOR_BITS)) {
          *pnum = 0;
          return 0;
      }
          nb_sectors = n;
      }
  
-     if (!bs->drv->bdrv_co_is_allocated) {
+     if (!bs->drv->bdrv_co_get_block_status) {
          *pnum = nb_sectors;
-         return 1;
+         ret = BDRV_BLOCK_DATA;
+         if (bs->drv->protocol_name) {
+             ret |= BDRV_BLOCK_OFFSET_VALID | (sector_num * BDRV_SECTOR_SIZE);
+         }
+         return ret;
      }
  
-     return bs->drv->bdrv_co_is_allocated(bs, sector_num, nb_sectors, pnum);
+     ret = bs->drv->bdrv_co_get_block_status(bs, sector_num, nb_sectors, pnum);
+     if (ret < 0) {
+         *pnum = 0;
+         return ret;
+     }
+     if (ret & BDRV_BLOCK_RAW) {
+         assert(ret & BDRV_BLOCK_OFFSET_VALID);
+         return bdrv_get_block_status(bs->file, ret >> BDRV_SECTOR_BITS,
+                                      *pnum, pnum);
+     }
+     if (!(ret & BDRV_BLOCK_DATA)) {
+         if (bdrv_has_zero_init(bs)) {
+             ret |= BDRV_BLOCK_ZERO;
+         } else if (bs->backing_hd) {
+             BlockDriverState *bs2 = bs->backing_hd;
+             int64_t length2 = bdrv_getlength(bs2);
+             if (length2 >= 0 && sector_num >= (length2 >> BDRV_SECTOR_BITS)) {
+                 ret |= BDRV_BLOCK_ZERO;
+             }
+         }
+     }
+     if (bs->file &&
+         (ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO) &&
+         (ret & BDRV_BLOCK_OFFSET_VALID)) {
+         ret2 = bdrv_co_get_block_status(bs->file, ret >> BDRV_SECTOR_BITS,
+                                         *pnum, pnum);
+         if (ret2 >= 0) {
+             /* Ignore errors.  This is just providing extra information, it
+              * is useful but not necessary.
+              */
+             ret |= (ret2 & BDRV_BLOCK_ZERO);
+         }
+     }
+     return ret;
  }
  
- /* Coroutine wrapper for bdrv_is_allocated() */
- static void coroutine_fn bdrv_is_allocated_co_entry(void *opaque)
+ /* Coroutine wrapper for bdrv_get_block_status() */
+ static void coroutine_fn bdrv_get_block_status_co_entry(void *opaque)
  {
-     BdrvCoIsAllocatedData *data = opaque;
+     BdrvCoGetBlockStatusData *data = opaque;
      BlockDriverState *bs = data->bs;
  
-     data->ret = bdrv_co_is_allocated(bs, data->sector_num, data->nb_sectors,
-                                      data->pnum);
+     data->ret = bdrv_co_get_block_status(bs, data->sector_num, data->nb_sectors,
+                                          data->pnum);
      data->done = true;
  }
  
  /*
-  * Synchronous wrapper around bdrv_co_is_allocated().
+  * Synchronous wrapper around bdrv_co_get_block_status().
   *
-  * See bdrv_co_is_allocated() for details.
+  * See bdrv_co_get_block_status() for details.
   */
- int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
-                       int *pnum)
+ int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num,
+                               int nb_sectors, int *pnum)
  {
      Coroutine *co;
-     BdrvCoIsAllocatedData data = {
+     BdrvCoGetBlockStatusData data = {
          .bs = bs,
          .sector_num = sector_num,
          .nb_sectors = nb_sectors,
          .done = false,
      };
  
-     co = qemu_coroutine_create(bdrv_is_allocated_co_entry);
-     qemu_coroutine_enter(co, &data);
-     while (!data.done) {
-         qemu_aio_wait();
+     if (qemu_in_coroutine()) {
+         /* Fast-path if already in coroutine context */
+         bdrv_get_block_status_co_entry(&data);
+     } else {
+         co = qemu_coroutine_create(bdrv_get_block_status_co_entry);
+         qemu_coroutine_enter(co, &data);
+         while (!data.done) {
+             qemu_aio_wait();
+         }
      }
      return data.ret;
  }
  
+ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num,
+                                    int nb_sectors, int *pnum)
+ {
+     int64_t ret = bdrv_get_block_status(bs, sector_num, nb_sectors, pnum);
+     if (ret < 0) {
+         return ret;
+     }
+     return
+         (ret & BDRV_BLOCK_DATA) ||
+         ((ret & BDRV_BLOCK_ZERO) && !bdrv_has_zero_init(bs));
+ }
  /*
   * Given an image chain: ... -> [BASE] -> [INTER1] -> [INTER2] -> [TOP]
   *
   *  allocated/unallocated state.
   *
   */
- int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top,
-                                             BlockDriverState *base,
-                                             int64_t sector_num,
-                                             int nb_sectors, int *pnum)
+ int bdrv_is_allocated_above(BlockDriverState *top,
+                             BlockDriverState *base,
+                             int64_t sector_num,
+                             int nb_sectors, int *pnum)
  {
      BlockDriverState *intermediate;
      int ret, n = nb_sectors;
      intermediate = top;
      while (intermediate && intermediate != base) {
          int pnum_inter;
-         ret = bdrv_co_is_allocated(intermediate, sector_num, nb_sectors,
-                                    &pnum_inter);
+         ret = bdrv_is_allocated(intermediate, sector_num, nb_sectors,
+                                 &pnum_inter);
          if (ret < 0) {
              return ret;
          } else if (ret) {
      return 0;
  }
  
- /* Coroutine wrapper for bdrv_is_allocated_above() */
- static void coroutine_fn bdrv_is_allocated_above_co_entry(void *opaque)
- {
-     BdrvCoIsAllocatedData *data = opaque;
-     BlockDriverState *top = data->bs;
-     BlockDriverState *base = data->base;
-     data->ret = bdrv_co_is_allocated_above(top, base, data->sector_num,
-                                            data->nb_sectors, data->pnum);
-     data->done = true;
- }
- /*
-  * Synchronous wrapper around bdrv_co_is_allocated_above().
-  *
-  * See bdrv_co_is_allocated_above() for details.
-  */
- int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
-                             int64_t sector_num, int nb_sectors, int *pnum)
- {
-     Coroutine *co;
-     BdrvCoIsAllocatedData data = {
-         .bs = top,
-         .base = base,
-         .sector_num = sector_num,
-         .nb_sectors = nb_sectors,
-         .pnum = pnum,
-         .done = false,
-     };
-     co = qemu_coroutine_create(bdrv_is_allocated_above_co_entry);
-     qemu_coroutine_enter(co, &data);
-     while (!data.done) {
-         qemu_aio_wait();
-     }
-     return data.ret;
- }
  const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
  {
      if (bs->backing_hd && bs->backing_hd->encrypted)
@@@ -3178,6 -3346,15 +3348,15 @@@ int bdrv_get_info(BlockDriverState *bs
      return drv->bdrv_get_info(bs, bdi);
  }
  
+ ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs)
+ {
+     BlockDriver *drv = bs->drv;
+     if (drv && drv->bdrv_get_specific_info) {
+         return drv->bdrv_get_specific_info(bs);
+     }
+     return NULL;
+ }
  int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
                        int64_t pos, int size)
  {
@@@ -3571,169 -3748,6 +3750,6 @@@ void bdrv_aio_cancel(BlockDriverAIOCB *
      acb->aiocb_info->cancel(acb);
  }
  
- /* block I/O throttling */
- static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors,
-                  bool is_write, double elapsed_time, uint64_t *wait)
- {
-     uint64_t bps_limit = 0;
-     uint64_t extension;
-     double   bytes_limit, bytes_base, bytes_res;
-     double   slice_time, wait_time;
-     if (bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL]) {
-         bps_limit = bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL];
-     } else if (bs->io_limits.bps[is_write]) {
-         bps_limit = bs->io_limits.bps[is_write];
-     } else {
-         if (wait) {
-             *wait = 0;
-         }
-         return false;
-     }
-     slice_time = bs->slice_end - bs->slice_start;
-     slice_time /= (NANOSECONDS_PER_SECOND);
-     bytes_limit = bps_limit * slice_time;
-     bytes_base  = bs->slice_submitted.bytes[is_write];
-     if (bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL]) {
-         bytes_base += bs->slice_submitted.bytes[!is_write];
-     }
-     /* bytes_base: the bytes of data which have been read/written; and
-      *             it is obtained from the history statistic info.
-      * bytes_res: the remaining bytes of data which need to be read/written.
-      * (bytes_base + bytes_res) / bps_limit: used to calcuate
-      *             the total time for completing reading/writting all data.
-      */
-     bytes_res   = (unsigned) nb_sectors * BDRV_SECTOR_SIZE;
-     if (bytes_base + bytes_res <= bytes_limit) {
-         if (wait) {
-             *wait = 0;
-         }
-         return false;
-     }
-     /* Calc approx time to dispatch */
-     wait_time = (bytes_base + bytes_res) / bps_limit - elapsed_time;
-     /* When the I/O rate at runtime exceeds the limits,
-      * bs->slice_end need to be extended in order that the current statistic
-      * info can be kept until the timer fire, so it is increased and tuned
-      * based on the result of experiment.
-      */
-     extension = wait_time * NANOSECONDS_PER_SECOND;
-     extension = DIV_ROUND_UP(extension, BLOCK_IO_SLICE_TIME) *
-                 BLOCK_IO_SLICE_TIME;
-     bs->slice_end += extension;
-     if (wait) {
-         *wait = wait_time * NANOSECONDS_PER_SECOND;
-     }
-     return true;
- }
- static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write,
-                              double elapsed_time, uint64_t *wait)
- {
-     uint64_t iops_limit = 0;
-     double   ios_limit, ios_base;
-     double   slice_time, wait_time;
-     if (bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL]) {
-         iops_limit = bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL];
-     } else if (bs->io_limits.iops[is_write]) {
-         iops_limit = bs->io_limits.iops[is_write];
-     } else {
-         if (wait) {
-             *wait = 0;
-         }
-         return false;
-     }
-     slice_time = bs->slice_end - bs->slice_start;
-     slice_time /= (NANOSECONDS_PER_SECOND);
-     ios_limit  = iops_limit * slice_time;
-     ios_base   = bs->slice_submitted.ios[is_write];
-     if (bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL]) {
-         ios_base += bs->slice_submitted.ios[!is_write];
-     }
-     if (ios_base + 1 <= ios_limit) {
-         if (wait) {
-             *wait = 0;
-         }
-         return false;
-     }
-     /* Calc approx time to dispatch, in seconds */
-     wait_time = (ios_base + 1) / iops_limit;
-     if (wait_time > elapsed_time) {
-         wait_time = wait_time - elapsed_time;
-     } else {
-         wait_time = 0;
-     }
-     /* Exceeded current slice, extend it by another slice time */
-     bs->slice_end += BLOCK_IO_SLICE_TIME;
-     if (wait) {
-         *wait = wait_time * NANOSECONDS_PER_SECOND;
-     }
-     return true;
- }
- static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors,
-                            bool is_write, int64_t *wait)
- {
-     int64_t  now, max_wait;
-     uint64_t bps_wait = 0, iops_wait = 0;
-     double   elapsed_time;
-     int      bps_ret, iops_ret;
-     now = qemu_get_clock_ns(vm_clock);
-     if (now > bs->slice_end) {
-         bs->slice_start = now;
-         bs->slice_end   = now + BLOCK_IO_SLICE_TIME;
-         memset(&bs->slice_submitted, 0, sizeof(bs->slice_submitted));
-     }
-     elapsed_time  = now - bs->slice_start;
-     elapsed_time  /= (NANOSECONDS_PER_SECOND);
-     bps_ret  = bdrv_exceed_bps_limits(bs, nb_sectors,
-                                       is_write, elapsed_time, &bps_wait);
-     iops_ret = bdrv_exceed_iops_limits(bs, is_write,
-                                       elapsed_time, &iops_wait);
-     if (bps_ret || iops_ret) {
-         max_wait = bps_wait > iops_wait ? bps_wait : iops_wait;
-         if (wait) {
-             *wait = max_wait;
-         }
-         now = qemu_get_clock_ns(vm_clock);
-         if (bs->slice_end < now + max_wait) {
-             bs->slice_end = now + max_wait;
-         }
-         return true;
-     }
-     if (wait) {
-         *wait = 0;
-     }
-     bs->slice_submitted.bytes[is_write] += (int64_t)nb_sectors *
-                                            BDRV_SECTOR_SIZE;
-     bs->slice_submitted.ios[is_write]++;
-     return false;
- }
  /**************************************************************/
  /* async block device emulation */
  
@@@ -4394,6 -4408,23 +4410,23 @@@ int64_t bdrv_get_dirty_count(BlockDrive
      }
  }
  
+ /* Get a reference to bs */
+ void bdrv_ref(BlockDriverState *bs)
+ {
+     bs->refcnt++;
+ }
+ /* Release a previously grabbed reference to bs.
+  * If after releasing, reference count is zero, the BlockDriverState is
+  * deleted. */
+ void bdrv_unref(BlockDriverState *bs)
+ {
+     assert(bs->refcnt > 0);
+     if (--bs->refcnt == 0) {
+         bdrv_delete(bs);
+     }
+ }
  void bdrv_set_in_use(BlockDriverState *bs, int in_use)
  {
      assert(bs->in_use != in_use);
@@@ -4476,6 -4507,7 +4509,7 @@@ void bdrv_img_create(const char *filena
      BlockDriverState *bs = NULL;
      BlockDriver *drv, *proto_drv;
      BlockDriver *backing_drv = NULL;
+     Error *local_err = NULL;
      int ret = 0;
  
      /* Find driver and parse its options */
              bs = bdrv_new("");
  
              ret = bdrv_open(bs, backing_file->value.s, NULL, back_flags,
-                             backing_drv);
+                             backing_drv, &local_err);
              if (ret < 0) {
-                 error_setg_errno(errp, -ret, "Could not open '%s'",
-                                  backing_file->value.s);
+                 error_setg_errno(errp, -ret, "Could not open '%s': %s",
+                                  backing_file->value.s,
+                                  error_get_pretty(local_err));
+                 error_free(local_err);
+                 local_err = NULL;
                  goto out;
              }
              bdrv_get_geometry(bs, &size);
          print_option_parameters(param);
          puts("");
      }
-     ret = bdrv_create(drv, filename, param);
-     if (ret < 0) {
-         if (ret == -ENOTSUP) {
-             error_setg(errp,"Formatting or formatting option not supported for "
-                             "file format '%s'", fmt);
-         } else if (ret == -EFBIG) {
-             const char *cluster_size_hint = "";
-             if (get_option_parameter(create_options, BLOCK_OPT_CLUSTER_SIZE)) {
-                 cluster_size_hint = " (try using a larger cluster size)";
-             }
-             error_setg(errp, "The image size is too large for file format '%s'%s",
-                        fmt, cluster_size_hint);
-         } else {
-             error_setg(errp, "%s: error while creating %s: %s", filename, fmt,
-                        strerror(-ret));
+     ret = bdrv_create(drv, filename, param, &local_err);
+     if (ret == -EFBIG) {
+         /* This is generally a better message than whatever the driver would
+          * deliver (especially because of the cluster_size_hint), since that
+          * is most probably not much different from "image too large". */
+         const char *cluster_size_hint = "";
+         if (get_option_parameter(create_options, BLOCK_OPT_CLUSTER_SIZE)) {
+             cluster_size_hint = " (try using a larger cluster size)";
          }
+         error_setg(errp, "The image size is too large for file format '%s'"
+                    "%s", fmt, cluster_size_hint);
+         error_free(local_err);
+         local_err = NULL;
      }
  
  out:
      free_option_parameters(param);
  
      if (bs) {
-         bdrv_delete(bs);
+         bdrv_unref(bs);
+     }
+     if (error_is_set(&local_err)) {
+         error_propagate(errp, local_err);
      }
  }
  
@@@ -4622,3 -4657,30 +4659,30 @@@ void bdrv_add_before_write_notifier(Blo
  {
      notifier_with_return_list_add(&bs->before_write_notifiers, notifier);
  }
+ int bdrv_amend_options(BlockDriverState *bs, QEMUOptionParameter *options)
+ {
+     if (bs->drv->bdrv_amend_options == NULL) {
+         return -ENOTSUP;
+     }
+     return bs->drv->bdrv_amend_options(bs, options);
+ }
+ ExtSnapshotPerm bdrv_check_ext_snapshot(BlockDriverState *bs)
+ {
+     if (bs->drv->bdrv_check_ext_snapshot) {
+         return bs->drv->bdrv_check_ext_snapshot(bs);
+     }
+     if (bs->file && bs->file->drv && bs->file->drv->bdrv_check_ext_snapshot) {
+         return bs->file->drv->bdrv_check_ext_snapshot(bs);
+     }
+     /* external snapshots are allowed by default */
+     return EXT_SNAPSHOT_ALLOWED;
+ }
+ ExtSnapshotPerm bdrv_check_ext_snapshot_forbidden(BlockDriverState *bs)
+ {
+     return EXT_SNAPSHOT_FORBIDDEN;
+ }
diff --combined block/raw-win32.c
@@@ -31,9 -31,6 +31,9 @@@
  #include "qemu/iov.h"
  #include <windows.h>
  #include <winioctl.h>
 +#ifdef CONFIG_MARU
 +#include <errno.h>
 +#endif
  
  #define FTYPE_FILE 0
  #define FTYPE_CD     1
@@@ -88,6 -85,7 +88,7 @@@ static size_t handle_aiocb_rw(RawWin32A
              ret_count = 0;
          }
          if (ret_count != len) {
+             offset += ret_count;
              break;
          }
          offset += len;
@@@ -204,7 -202,6 +205,7 @@@ static int set_sparse(int fd
                                 NULL, 0, NULL, 0, &returned, NULL);
  }
  
 +#ifndef CONFIG_MARU
  static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped)
  {
      assert(access_flags != NULL);
          *overlapped |= FILE_FLAG_NO_BUFFERING;
      }
  }
 +#endif
  
  static QemuOptsList raw_runtime_opts = {
      .name = "raw",
      },
  };
  
- static int raw_open(BlockDriverState *bs, QDict *options, int flags)
+ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
+                     Error **errp)
  {
      BDRVRawState *s = bs->opaque;
 -    int access_flags;
 -    DWORD overlapped;
      QemuOpts *opts;
      Error *local_err = NULL;
      const char *filename;
      int ret;
 +#ifndef CONFIG_MARU
 +    DWORD overlapped;
 +    int access_flags;
 +#else
 +    int open_flags;
 +#endif
  
      s->type = FTYPE_FILE;
  
      opts = qemu_opts_create_nofail(&raw_runtime_opts);
      qemu_opts_absorb_qdict(opts, options, &local_err);
      if (error_is_set(&local_err)) {
-         qerror_report_err(local_err);
-         error_free(local_err);
+         error_propagate(errp, local_err);
          ret = -EINVAL;
          goto fail;
      }
  
      filename = qemu_opt_get(opts, "filename");
  
 +#ifndef CONFIG_MARU
      raw_parse_flags(flags, &access_flags, &overlapped);
  
      if ((flags & BDRV_O_NATIVE_AIO) && aio == NULL) {
          aio = win32_aio_init();
          if (aio == NULL) {
+             error_setg(errp, "Could not initialize AIO");
              ret = -EINVAL;
              goto fail;
          }
      s->hfile = CreateFile(filename, access_flags,
                            FILE_SHARE_READ, NULL,
                            OPEN_EXISTING, overlapped, NULL);
 -    if (s->hfile == INVALID_HANDLE_VALUE) {
 +      if (s->hfile == INVALID_HANDLE_VALUE) {
          int err = GetLastError();
  
          if (err == ERROR_ACCESS_DENIED) {
          }
          goto fail;
      }
 +#else
 +    open_flags = O_BINARY & ~O_ACCMODE;
 +    if (flags & BDRV_O_RDWR) {
 +        open_flags |= O_RDWR;
 +    } else {
 +        open_flags |= O_RDONLY;
 +    }
 +
 +    /* Use O_DSYNC for write-through caching, no flags for write-back caching,
 +     * and O_DIRECT for no caching. */
 +    /*
 +       if ((flags & BDRV_O_NOCACHE)) {
 +       open_flags |= O_DIRECT;
 +       }
 +       if (!(flags & BDRV_O_CACHE_WB)) {
 +       open_flags |= O_DSYNC;
 +       }
 +     */
 +
 +    if ((flags & BDRV_O_NATIVE_AIO) && aio == NULL) {
 +        aio = win32_aio_init();
 +        if (aio == NULL) {
 +            ret = -EINVAL;
 +            goto fail;
 +        }
 +    }
 +
 +    ret = qemu_open(filename, open_flags, 0644);
 +    if (ret < 0) {
 +        error_report("raw_open failed(%d) \n", ret);
 +        return -errno;
 +    }
 +    s->hfile = (HANDLE)_get_osfhandle(ret);
 +#endif
  
      if (flags & BDRV_O_NATIVE_AIO) {
          ret = win32_aio_attach(aio, s->hfile);
          if (ret < 0) {
              CloseHandle(s->hfile);
+             error_setg_errno(errp, -ret, "Could not enable AIO");
              goto fail;
          }
          s->aio = aio;
@@@ -464,7 -423,8 +467,8 @@@ static int64_t raw_get_allocated_file_s
      return st.st_size;
  }
  
- static int raw_create(const char *filename, QEMUOptionParameter *options)
+ static int raw_create(const char *filename, QEMUOptionParameter *options,
+                       Error **errp)
  {
      int fd;
      int64_t total_size = 0;
  
      fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
                     0644);
-     if (fd < 0)
+     if (fd < 0) {
+         error_setg_errno(errp, errno, "Could not create file");
          return -EIO;
+     }
      set_sparse(fd);
      ftruncate(fd, total_size * 512);
      qemu_close(fd);
@@@ -500,6 -462,7 +506,7 @@@ static BlockDriver bdrv_file = 
      .format_name      = "file",
      .protocol_name    = "file",
      .instance_size    = sizeof(BDRVRawState),
+     .bdrv_needs_filename = true,
      .bdrv_file_open   = raw_open,
      .bdrv_close               = raw_close,
      .bdrv_create      = raw_create,
@@@ -575,16 -538,13 +582,18 @@@ static int hdev_probe_device(const cha
      return 0;
  }
  
- static int hdev_open(BlockDriverState *bs, QDict *options, int flags)
+ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
+                      Error **errp)
  {
      BDRVRawState *s = bs->opaque;
 +#ifndef CONFIG_MARU
      int access_flags, create_flags;
+     int ret = 0;
      DWORD overlapped;
 +#else
 +    int open_flags;
 +#endif
 +    int ret = 0;
      char device_name[64];
  
      Error *local_err = NULL;
      QemuOpts *opts = qemu_opts_create_nofail(&raw_runtime_opts);
      qemu_opts_absorb_qdict(opts, options, &local_err);
      if (error_is_set(&local_err)) {
-         qerror_report_err(local_err);
-         error_free(local_err);
+         error_propagate(errp, local_err);
          ret = -EINVAL;
          goto done;
      }
  
      if (strstart(filename, "/dev/cdrom", NULL)) {
          if (find_cdrom(device_name, sizeof(device_name)) < 0) {
+             error_setg(errp, "Could not open CD-ROM drive");
              ret = -ENOENT;
              goto done;
          }
      }
      s->type = find_device_type(bs, filename);
  
 +#ifndef CONFIG_MARU
      raw_parse_flags(flags, &access_flags, &overlapped);
  
      create_flags = OPEN_EXISTING;
      s->hfile = CreateFile(filename, access_flags,
                            FILE_SHARE_READ, NULL,
                            create_flags, overlapped, NULL);
 -    if (s->hfile == INVALID_HANDLE_VALUE) {
 +      if (s->hfile == INVALID_HANDLE_VALUE) {
          int err = GetLastError();
  
          if (err == ERROR_ACCESS_DENIED) {
              ret = -EACCES;
          } else {
-             ret = -1;
+             ret = -EINVAL;
          }
+         error_setg_errno(errp, -ret, "Could not open device");
          goto done;
      }
 +#else
 +      /*
 +    s->hfile = CreateFile(g_win32_locale_filename_from_utf8(filename),
 +                          access_flags,
 +                          FILE_SHARE_READ, NULL,
 +                          create_flags, overlapped, NULL);
 +      */
 +    open_flags = (O_BINARY & ~O_ACCMODE);
 +    if (flags & BDRV_O_RDWR) {
 +        open_flags |= O_RDWR;
 +    } else {
 +        open_flags |= O_RDONLY;
 +    }
 +
 +    /* Use O_DSYNC for write-through caching, no flags for write-back caching,
 +     * and O_DIRECT for no caching. */
 +    /*
 +       if ((flags & BDRV_O_NOCACHE)) {
 +       open_flags |= O_DIRECT;
 +       }
 +       if (!(flags & BDRV_O_CACHE_WB)) {
 +       open_flags |= O_DSYNC;
 +       }
 +     */
 +
 +    ret = qemu_open(filename, open_flags, 0644);
 +    if (ret < 0) {
 +        error_report("raw_open failed(%d) \n", ret);
 +        return -errno;
 +    }
 +    s->hfile = (HANDLE)_get_osfhandle(ret);
 +#endif
 +    return 0;
  
  done:
      qemu_opts_del(opts);
@@@ -679,6 -606,7 +689,7 @@@ static BlockDriver bdrv_host_device = 
      .format_name      = "host_device",
      .protocol_name    = "host_device",
      .instance_size    = sizeof(BDRVRawState),
+     .bdrv_needs_filename = true,
      .bdrv_probe_device        = hdev_probe_device,
      .bdrv_file_open   = hdev_open,
      .bdrv_close               = raw_close,
      .bdrv_aio_writev    = raw_aio_writev,
      .bdrv_aio_flush     = raw_aio_flush,
  
-     .bdrv_getlength   = raw_getlength,
+     .bdrv_getlength      = raw_getlength,
+     .has_variable_length = true,
      .bdrv_get_allocated_file_size
                          = raw_get_allocated_file_size,
  };
diff --combined blockdev.c
@@@ -38,6 -38,8 +38,8 @@@
  #include "qemu/option.h"
  #include "qemu/config-file.h"
  #include "qapi/qmp/types.h"
+ #include "qapi-visit.h"
+ #include "qapi/qmp-output-visitor.h"
  #include "sysemu/sysemu.h"
  #include "block/block_int.h"
  #include "qmp-commands.h"
@@@ -45,8 -47,6 +47,6 @@@
  #include "sysemu/arch_init.h"
  
  static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
- extern QemuOptsList qemu_common_drive_opts;
- extern QemuOptsList qemu_old_drive_opts;
  
  static const char *const if_name[IF_COUNT] = {
      [IF_NONE] = "none",
@@@ -90,6 -90,10 +90,10 @@@ void blockdev_mark_auto_del(BlockDriver
  {
      DriveInfo *dinfo = drive_get_by_blockdev(bs);
  
+     if (dinfo && !dinfo->enable_auto_del) {
+         return;
+     }
      if (bs->job) {
          block_job_cancel(bs->job);
      }
@@@ -212,8 -216,11 +216,11 @@@ static void bdrv_format_print(void *opa
  
  static void drive_uninit(DriveInfo *dinfo)
  {
-     qemu_opts_del(dinfo->opts);
-     bdrv_delete(dinfo->bdrv);
+     if (dinfo->opts) {
+         qemu_opts_del(dinfo->opts);
+     }
+     bdrv_unref(dinfo->bdrv);
      g_free(dinfo->id);
      QTAILQ_REMOVE(&drives, dinfo, next);
      g_free(dinfo->serial);
@@@ -235,36 -242,36 +242,36 @@@ void drive_get_ref(DriveInfo *dinfo
  
  typedef struct {
      QEMUBH *bh;
-     DriveInfo *dinfo;
- } DrivePutRefBH;
+     BlockDriverState *bs;
+ } BDRVPutRefBH;
  
- static void drive_put_ref_bh(void *opaque)
+ static void bdrv_put_ref_bh(void *opaque)
  {
-     DrivePutRefBH *s = opaque;
+     BDRVPutRefBH *s = opaque;
  
-     drive_put_ref(s->dinfo);
+     bdrv_unref(s->bs);
      qemu_bh_delete(s->bh);
      g_free(s);
  }
  
  /*
-  * Release a drive reference in a BH
+  * Release a BDS reference in a BH
   *
-  * It is not possible to use drive_put_ref() from a callback function when the
-  * callers still need the drive.  In such cases we schedule a BH to release the
-  * reference.
+  * It is not safe to use bdrv_unref() from a callback function when the callers
+  * still need the BlockDriverState.  In such cases we schedule a BH to release
+  * the reference.
   */
- static void drive_put_ref_bh_schedule(DriveInfo *dinfo)
+ static void bdrv_put_ref_bh_schedule(BlockDriverState *bs)
  {
-     DrivePutRefBH *s;
+     BDRVPutRefBH *s;
  
-     s = g_new(DrivePutRefBH, 1);
-     s->bh = qemu_bh_new(drive_put_ref_bh, s);
-     s->dinfo = dinfo;
+     s = g_new(BDRVPutRefBH, 1);
+     s->bh = qemu_bh_new(bdrv_put_ref_bh, s);
+     s->bs = bs;
      qemu_bh_schedule(s->bh);
  }
  
- static int parse_block_error_action(const char *buf, bool is_read)
+ static int parse_block_error_action(const char *buf, bool is_read, Error **errp)
  {
      if (!strcmp(buf, "ignore")) {
          return BLOCKDEV_ON_ERROR_IGNORE;
      } else if (!strcmp(buf, "report")) {
          return BLOCKDEV_ON_ERROR_REPORT;
      } else {
-         error_report("'%s' invalid %s error action",
-                      buf, is_read ? "read" : "write");
+         error_setg(errp, "'%s' invalid %s error action",
+                    buf, is_read ? "read" : "write");
          return -1;
      }
  }
  
- static bool do_check_io_limits(BlockIOLimit *io_limits, Error **errp)
 +#ifdef CONFIG_MARU
 +extern int start_simple_client(char* msg);
 +extern char* maru_convert_path(char* msg, const char *path);
 +#endif
 +
+ static bool check_throttle_config(ThrottleConfig *cfg, Error **errp)
  {
-     bool bps_flag;
-     bool iops_flag;
-     assert(io_limits);
-     bps_flag  = (io_limits->bps[BLOCK_IO_LIMIT_TOTAL] != 0)
-                  && ((io_limits->bps[BLOCK_IO_LIMIT_READ] != 0)
-                  || (io_limits->bps[BLOCK_IO_LIMIT_WRITE] != 0));
-     iops_flag = (io_limits->iops[BLOCK_IO_LIMIT_TOTAL] != 0)
-                  && ((io_limits->iops[BLOCK_IO_LIMIT_READ] != 0)
-                  || (io_limits->iops[BLOCK_IO_LIMIT_WRITE] != 0));
-     if (bps_flag || iops_flag) {
-         error_setg(errp, "bps(iops) and bps_rd/bps_wr(iops_rd/iops_wr) "
-                          "cannot be used at the same time");
+     if (throttle_conflicting(cfg)) {
+         error_setg(errp, "bps/iops/max total values and read/write values"
+                          " cannot be used at the same time");
          return false;
      }
  
-     if (io_limits->bps[BLOCK_IO_LIMIT_TOTAL] < 0 ||
-         io_limits->bps[BLOCK_IO_LIMIT_WRITE] < 0 ||
-         io_limits->bps[BLOCK_IO_LIMIT_READ] < 0 ||
-         io_limits->iops[BLOCK_IO_LIMIT_TOTAL] < 0 ||
-         io_limits->iops[BLOCK_IO_LIMIT_WRITE] < 0 ||
-         io_limits->iops[BLOCK_IO_LIMIT_READ] < 0) {
-         error_setg(errp, "bps and iops values must be 0 or greater");
+     if (!throttle_is_valid(cfg)) {
+         error_setg(errp, "bps/iops/maxs values must be 0 or greater");
          return false;
      }
  
      return true;
  }
  
- static DriveInfo *blockdev_init(QemuOpts *all_opts,
-                                 BlockInterfaceType block_default_type)
+ typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType;
+ /* Takes the ownership of bs_opts */
+ static DriveInfo *blockdev_init(QDict *bs_opts,
+                                 BlockInterfaceType type,
+                                 Error **errp)
  {
      const char *buf;
      const char *file = NULL;
      const char *serial;
-     const char *mediastr = "";
-     BlockInterfaceType type;
-     enum { MEDIA_DISK, MEDIA_CDROM } media;
-     int bus_id, unit_id;
-     int cyls, heads, secs, translation;
-     int max_devs;
-     int index;
      int ro = 0;
      int bdrv_flags = 0;
      int on_read_error, on_write_error;
-     const char *devaddr;
      DriveInfo *dinfo;
-     BlockIOLimit io_limits;
+     ThrottleConfig cfg;
      int snapshot = 0;
      bool copy_on_read;
      int ret;
      Error *error = NULL;
      QemuOpts *opts;
-     QDict *bs_opts;
      const char *id;
      bool has_driver_specific_opts;
      BlockDriver *drv = NULL;
  
-     translation = BIOS_ATA_TRANSLATION_AUTO;
-     media = MEDIA_DISK;
-     /* Check common options by copying from all_opts to opts, all other options
-      * are stored in bs_opts. */
-     id = qemu_opts_id(all_opts);
+     /* Check common options by copying from bs_opts to opts, all other options
+      * stay in bs_opts for processing by bdrv_open(). */
+     id = qdict_get_try_str(bs_opts, "id");
      opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error);
      if (error_is_set(&error)) {
-         qerror_report_err(error);
-         error_free(error);
+         error_propagate(errp, error);
          return NULL;
      }
  
-     bs_opts = qdict_new();
-     qemu_opts_to_qdict(all_opts, bs_opts);
      qemu_opts_absorb_qdict(opts, bs_opts, &error);
      if (error_is_set(&error)) {
-         qerror_report_err(error);
-         error_free(error);
-         return NULL;
+         error_propagate(errp, error);
+         goto early_err;
      }
  
      if (id) {
      has_driver_specific_opts = !!qdict_size(bs_opts);
  
      /* extract parameters */
-     bus_id  = qemu_opt_get_number(opts, "bus", 0);
-     unit_id = qemu_opt_get_number(opts, "unit", -1);
-     index   = qemu_opt_get_number(opts, "index", -1);
-     cyls  = qemu_opt_get_number(opts, "cyls", 0);
-     heads = qemu_opt_get_number(opts, "heads", 0);
-     secs  = qemu_opt_get_number(opts, "secs", 0);
      snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
      ro = qemu_opt_get_bool(opts, "read-only", 0);
      copy_on_read = qemu_opt_get_bool(opts, "copy-on-read", false);
      file = qemu_opt_get(opts, "file");
      serial = qemu_opt_get(opts, "serial");
  
-     if ((buf = qemu_opt_get(opts, "if")) != NULL) {
-         for (type = 0; type < IF_COUNT && strcmp(buf, if_name[type]); type++)
-             ;
-         if (type == IF_COUNT) {
-             error_report("unsupported bus type '%s'", buf);
-             return NULL;
-       }
-     } else {
-         type = block_default_type;
-     }
-     max_devs = if_max_devs[type];
-     if (cyls || heads || secs) {
-         if (cyls < 1) {
-             error_report("invalid physical cyls number");
-           return NULL;
-       }
-         if (heads < 1) {
-             error_report("invalid physical heads number");
-           return NULL;
-       }
-         if (secs < 1) {
-             error_report("invalid physical secs number");
-           return NULL;
-       }
-     }
-     if ((buf = qemu_opt_get(opts, "trans")) != NULL) {
-         if (!cyls) {
-             error_report("'%s' trans must be used with cyls, heads and secs",
-                          buf);
-             return NULL;
-         }
-         if (!strcmp(buf, "none"))
-             translation = BIOS_ATA_TRANSLATION_NONE;
-         else if (!strcmp(buf, "lba"))
-             translation = BIOS_ATA_TRANSLATION_LBA;
-         else if (!strcmp(buf, "auto"))
-             translation = BIOS_ATA_TRANSLATION_AUTO;
-       else {
-             error_report("'%s' invalid translation type", buf);
-           return NULL;
-       }
-     }
-     if ((buf = qemu_opt_get(opts, "media")) != NULL) {
-         if (!strcmp(buf, "disk")) {
-           media = MEDIA_DISK;
-       } else if (!strcmp(buf, "cdrom")) {
-             if (cyls || secs || heads) {
-                 error_report("CHS can't be set with media=%s", buf);
-               return NULL;
-             }
-           media = MEDIA_CDROM;
-       } else {
-           error_report("'%s' invalid media", buf);
-           return NULL;
-       }
-     }
      if ((buf = qemu_opt_get(opts, "discard")) != NULL) {
          if (bdrv_parse_discard_flags(buf, &bdrv_flags) != 0) {
-             error_report("invalid discard option");
-             return NULL;
+             error_setg(errp, "invalid discard option");
+             goto early_err;
          }
      }
  
          } else if (!strcmp(buf, "threads")) {
              /* this is the default */
          } else {
-            error_report("invalid aio option");
-            return NULL;
+            error_setg(errp, "invalid aio option");
+            goto early_err;
          }
      }
  #endif
              error_printf("Supported formats:");
              bdrv_iterate_format(bdrv_format_print, NULL);
              error_printf("\n");
-             return NULL;
+             goto early_err;
          }
  
-         drv = bdrv_find_whitelisted_format(buf, ro);
+         drv = bdrv_find_format(buf);
          if (!drv) {
-             error_report("'%s' invalid format", buf);
-             return NULL;
+             error_setg(errp, "'%s' invalid format", buf);
+             goto early_err;
          }
      }
  
      /* disk I/O throttling */
-     io_limits.bps[BLOCK_IO_LIMIT_TOTAL]  =
+     memset(&cfg, 0, sizeof(cfg));
+     cfg.buckets[THROTTLE_BPS_TOTAL].avg =
          qemu_opt_get_number(opts, "throttling.bps-total", 0);
-     io_limits.bps[BLOCK_IO_LIMIT_READ]   =
+     cfg.buckets[THROTTLE_BPS_READ].avg  =
          qemu_opt_get_number(opts, "throttling.bps-read", 0);
-     io_limits.bps[BLOCK_IO_LIMIT_WRITE]  =
+     cfg.buckets[THROTTLE_BPS_WRITE].avg =
          qemu_opt_get_number(opts, "throttling.bps-write", 0);
-     io_limits.iops[BLOCK_IO_LIMIT_TOTAL] =
+     cfg.buckets[THROTTLE_OPS_TOTAL].avg =
          qemu_opt_get_number(opts, "throttling.iops-total", 0);
-     io_limits.iops[BLOCK_IO_LIMIT_READ]  =
+     cfg.buckets[THROTTLE_OPS_READ].avg =
          qemu_opt_get_number(opts, "throttling.iops-read", 0);
-     io_limits.iops[BLOCK_IO_LIMIT_WRITE] =
+     cfg.buckets[THROTTLE_OPS_WRITE].avg =
          qemu_opt_get_number(opts, "throttling.iops-write", 0);
  
-     if (!do_check_io_limits(&io_limits, &error)) {
-         error_report("%s", error_get_pretty(error));
-         error_free(error);
-         return NULL;
-     }
+     cfg.buckets[THROTTLE_BPS_TOTAL].max =
+         qemu_opt_get_number(opts, "throttling.bps-total-max", 0);
+     cfg.buckets[THROTTLE_BPS_READ].max  =
+         qemu_opt_get_number(opts, "throttling.bps-read-max", 0);
+     cfg.buckets[THROTTLE_BPS_WRITE].max =
+         qemu_opt_get_number(opts, "throttling.bps-write-max", 0);
+     cfg.buckets[THROTTLE_OPS_TOTAL].max =
+         qemu_opt_get_number(opts, "throttling.iops-total-max", 0);
+     cfg.buckets[THROTTLE_OPS_READ].max =
+         qemu_opt_get_number(opts, "throttling.iops-read-max", 0);
+     cfg.buckets[THROTTLE_OPS_WRITE].max =
+         qemu_opt_get_number(opts, "throttling.iops-write-max", 0);
  
-     if (qemu_opt_get(opts, "boot") != NULL) {
-         fprintf(stderr, "qemu-kvm: boot=on|off is deprecated and will be "
-                 "ignored. Future versions will reject this parameter. Please "
-                 "update your scripts.\n");
+     cfg.op_size = qemu_opt_get_number(opts, "throttling.iops-size", 0);
+     if (!check_throttle_config(&cfg, &error)) {
+         error_propagate(errp, error);
+         goto early_err;
      }
  
      on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;
      if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
          if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
-             error_report("werror is not supported by this bus type");
-             return NULL;
+             error_setg(errp, "werror is not supported by this bus type");
+             goto early_err;
          }
  
-         on_write_error = parse_block_error_action(buf, 0);
-         if (on_write_error < 0) {
-             return NULL;
+         on_write_error = parse_block_error_action(buf, 0, &error);
+         if (error_is_set(&error)) {
+             error_propagate(errp, error);
+             goto early_err;
          }
      }
  
      if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
          if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI && type != IF_NONE) {
              error_report("rerror is not supported by this bus type");
-             return NULL;
+             goto early_err;
          }
  
-         on_read_error = parse_block_error_action(buf, 1);
-         if (on_read_error < 0) {
-             return NULL;
-         }
-     }
-     if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) {
-         if (type != IF_VIRTIO) {
-             error_report("addr is not supported by this bus type");
-             return NULL;
+         on_read_error = parse_block_error_action(buf, 1, &error);
+         if (error_is_set(&error)) {
+             error_propagate(errp, error);
+             goto early_err;
          }
      }
  
-     /* compute bus and unit according index */
-     if (index != -1) {
-         if (bus_id != 0 || unit_id != -1) {
-             error_report("index cannot be used with bus and unit");
-             return NULL;
-         }
-         bus_id = drive_index_to_bus_id(type, index);
-         unit_id = drive_index_to_unit_id(type, index);
-     }
-     /* if user doesn't specify a unit_id,
-      * try to find the first free
-      */
-     if (unit_id == -1) {
-        unit_id = 0;
-        while (drive_get(type, bus_id, unit_id) != NULL) {
-            unit_id++;
-            if (max_devs && unit_id >= max_devs) {
-                unit_id -= max_devs;
-                bus_id++;
-            }
-        }
-     }
-     /* check unit id */
-     if (max_devs && unit_id >= max_devs) {
-         error_report("unit %d too big (max is %d)",
-                      unit_id, max_devs - 1);
-         return NULL;
-     }
-     /*
-      * catch multiple definitions
-      */
-     if (drive_get(type, bus_id, unit_id) != NULL) {
-         error_report("drive with bus=%d, unit=%d (index=%d) exists",
-                      bus_id, unit_id, index);
-         return NULL;
-     }
      /* init */
      dinfo = g_malloc0(sizeof(*dinfo));
-     if ((buf = qemu_opts_id(opts)) != NULL) {
-         dinfo->id = g_strdup(buf);
-     } else {
-         /* no id supplied -> create one */
-         dinfo->id = g_malloc0(32);
-         if (type == IF_IDE || type == IF_SCSI)
-             mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
-         if (max_devs)
-             snprintf(dinfo->id, 32, "%s%i%s%i",
-                      if_name[type], bus_id, mediastr, unit_id);
-         else
-             snprintf(dinfo->id, 32, "%s%s%i",
-                      if_name[type], mediastr, unit_id);
-     }
+     dinfo->id = g_strdup(qemu_opts_id(opts));
      dinfo->bdrv = bdrv_new(dinfo->id);
      dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
      dinfo->bdrv->read_only = ro;
-     dinfo->devaddr = devaddr;
      dinfo->type = type;
-     dinfo->bus = bus_id;
-     dinfo->unit = unit_id;
-     dinfo->cyls = cyls;
-     dinfo->heads = heads;
-     dinfo->secs = secs;
-     dinfo->trans = translation;
-     dinfo->opts = all_opts;
      dinfo->refcount = 1;
      if (serial != NULL) {
          dinfo->serial = g_strdup(serial);
      bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
  
      /* disk I/O throttling */
-     bdrv_set_io_limits(dinfo->bdrv, &io_limits);
-     switch(type) {
-     case IF_IDE:
-     case IF_SCSI:
-     case IF_XEN:
-     case IF_NONE:
-         dinfo->media_cd = media == MEDIA_CDROM;
-         break;
-     case IF_SD:
-     case IF_FLOPPY:
-     case IF_PFLASH:
-     case IF_MTD:
-         break;
-     case IF_VIRTIO:
-     {
-         /* add virtio block device */
-         QemuOpts *devopts;
-         devopts = qemu_opts_create_nofail(qemu_find_opts("device"));
-         if (arch_type == QEMU_ARCH_S390X) {
-             qemu_opt_set(devopts, "driver", "virtio-blk-s390");
-         } else {
-             qemu_opt_set(devopts, "driver", "virtio-blk-pci");
-         }
-         qemu_opt_set(devopts, "drive", dinfo->id);
-         if (devaddr)
-             qemu_opt_set(devopts, "addr", devaddr);
-         break;
-     }
-     default:
-         abort();
+     if (throttle_enabled(&cfg)) {
+         bdrv_io_limits_enable(dinfo->bdrv);
+         bdrv_set_io_limits(dinfo->bdrv, &cfg);
      }
      if (!file || !*file) {
          if (has_driver_specific_opts) {
              file = NULL;
          } else {
+             QDECREF(bs_opts);
+             qemu_opts_del(opts);
              return dinfo;
          }
      }
          bdrv_flags |= BDRV_O_INCOMING;
      }
  
-     if (media == MEDIA_CDROM) {
-         /* CDROM is fine for any interface, don't check.  */
-         ro = 1;
-     } else if (ro == 1) {
-         if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY &&
-             type != IF_NONE && type != IF_PFLASH) {
-             error_report("read-only not supported by this bus type");
-             goto err;
-         }
-     }
      bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
  
-     if (ro && copy_on_read) {
-         error_report("warning: disabling copy_on_read on read-only drive");
-     }
      QINCREF(bs_opts);
-     ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, drv);
+     ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, drv, &error);
  
      if (ret < 0) {
-         if (ret == -EMEDIUMTYPE) {
-             error_report("could not open disk image %s: not in %s format",
-                          file ?: dinfo->id, drv ? drv->format_name :
-                          qdict_get_str(bs_opts, "driver"));
-         } else {
-             error_report("could not open disk image %s: %s",
-                          file ?: dinfo->id, strerror(-ret));
-         }
 +#ifdef CONFIG_MARU
 +        const char _msg[] = "Failed to load disk file from the following path. Check if the file is corrupted or missing.\n\n";
 +          char* err_msg = NULL;
 +        err_msg = maru_convert_path((char*)_msg, file);
 +        start_simple_client(err_msg);
 +        if (err_msg) {
 +            g_free(err_msg);
 +        }
 +#endif
 +
+         error_setg(errp, "could not open disk image %s: %s",
+                    file ?: dinfo->id, error_get_pretty(error));
+         error_free(error);
          goto err;
      }
  
      return dinfo;
  
  err:
-     qemu_opts_del(opts);
-     QDECREF(bs_opts);
-     bdrv_delete(dinfo->bdrv);
+     bdrv_unref(dinfo->bdrv);
      g_free(dinfo->id);
      QTAILQ_REMOVE(&drives, dinfo, next);
      g_free(dinfo);
+ early_err:
+     QDECREF(bs_opts);
+     qemu_opts_del(opts);
      return NULL;
  }
  
@@@ -762,30 -551,86 +566,86 @@@ static void qemu_opt_rename(QemuOpts *o
      }
  }
  
+ QemuOptsList qemu_legacy_drive_opts = {
+     .name = "drive",
+     .head = QTAILQ_HEAD_INITIALIZER(qemu_legacy_drive_opts.head),
+     .desc = {
+         {
+             .name = "bus",
+             .type = QEMU_OPT_NUMBER,
+             .help = "bus number",
+         },{
+             .name = "unit",
+             .type = QEMU_OPT_NUMBER,
+             .help = "unit number (i.e. lun for scsi)",
+         },{
+             .name = "index",
+             .type = QEMU_OPT_NUMBER,
+             .help = "index number",
+         },{
+             .name = "media",
+             .type = QEMU_OPT_STRING,
+             .help = "media type (disk, cdrom)",
+         },{
+             .name = "if",
+             .type = QEMU_OPT_STRING,
+             .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
+         },{
+             .name = "cyls",
+             .type = QEMU_OPT_NUMBER,
+             .help = "number of cylinders (ide disk geometry)",
+         },{
+             .name = "heads",
+             .type = QEMU_OPT_NUMBER,
+             .help = "number of heads (ide disk geometry)",
+         },{
+             .name = "secs",
+             .type = QEMU_OPT_NUMBER,
+             .help = "number of sectors (ide disk geometry)",
+         },{
+             .name = "trans",
+             .type = QEMU_OPT_STRING,
+             .help = "chs translation (auto, lba, none)",
+         },{
+             .name = "boot",
+             .type = QEMU_OPT_BOOL,
+             .help = "(deprecated, ignored)",
+         },{
+             .name = "addr",
+             .type = QEMU_OPT_STRING,
+             .help = "pci address (virtio only)",
+         },
+         /* Options that are passed on, but have special semantics with -drive */
+         {
+             .name = "read-only",
+             .type = QEMU_OPT_BOOL,
+             .help = "open drive file as read-only",
+         },{
+             .name = "copy-on-read",
+             .type = QEMU_OPT_BOOL,
+             .help = "copy read data from backing file into image file",
+         },
+         { /* end of list */ }
+     },
+ };
  DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
  {
      const char *value;
-     /*
-      * Check that only old options are used by copying into a QemuOpts with
-      * stricter checks. Going through a QDict seems to be the easiest way to
-      * achieve this...
-      */
-     QemuOpts* check_opts;
-     QDict *qdict;
+     DriveInfo *dinfo = NULL;
+     QDict *bs_opts;
+     QemuOpts *legacy_opts;
+     DriveMediaType media = MEDIA_DISK;
+     BlockInterfaceType type;
+     int cyls, heads, secs, translation;
+     int max_devs, bus_id, unit_id, index;
+     const char *devaddr;
+     bool read_only = false;
+     bool copy_on_read;
      Error *local_err = NULL;
  
-     qdict = qemu_opts_to_qdict(all_opts, NULL);
-     check_opts = qemu_opts_from_qdict(&qemu_old_drive_opts, qdict, &local_err);
-     QDECREF(qdict);
-     if (error_is_set(&local_err)) {
-         qerror_report_err(local_err);
-         error_free(local_err);
-         return NULL;
-     }
-     qemu_opts_del(check_opts);
      /* Change legacy command line options into QMP ones */
      qemu_opt_rename(all_opts, "iops", "throttling.iops-total");
      qemu_opt_rename(all_opts, "iops_rd", "throttling.iops-read");
      qemu_opt_rename(all_opts, "bps_rd", "throttling.bps-read");
      qemu_opt_rename(all_opts, "bps_wr", "throttling.bps-write");
  
+     qemu_opt_rename(all_opts, "iops_max", "throttling.iops-total-max");
+     qemu_opt_rename(all_opts, "iops_rd_max", "throttling.iops-read-max");
+     qemu_opt_rename(all_opts, "iops_wr_max", "throttling.iops-write-max");
+     qemu_opt_rename(all_opts, "bps_max", "throttling.bps-total-max");
+     qemu_opt_rename(all_opts, "bps_rd_max", "throttling.bps-read-max");
+     qemu_opt_rename(all_opts, "bps_wr_max", "throttling.bps-write-max");
+     qemu_opt_rename(all_opts,
+                     "iops_size", "throttling.iops-size");
      qemu_opt_rename(all_opts, "readonly", "read-only");
  
      value = qemu_opt_get(all_opts, "cache");
          qemu_opt_unset(all_opts, "cache");
      }
  
-     return blockdev_init(all_opts, block_default_type);
+     /* Get a QDict for processing the options */
+     bs_opts = qdict_new();
+     qemu_opts_to_qdict(all_opts, bs_opts);
+     legacy_opts = qemu_opts_create_nofail(&qemu_legacy_drive_opts);
+     qemu_opts_absorb_qdict(legacy_opts, bs_opts, &local_err);
+     if (error_is_set(&local_err)) {
+         qerror_report_err(local_err);
+         error_free(local_err);
+         goto fail;
+     }
+     /* Deprecated option boot=[on|off] */
+     if (qemu_opt_get(legacy_opts, "boot") != NULL) {
+         fprintf(stderr, "qemu-kvm: boot=on|off is deprecated and will be "
+                 "ignored. Future versions will reject this parameter. Please "
+                 "update your scripts.\n");
+     }
+     /* Media type */
+     value = qemu_opt_get(legacy_opts, "media");
+     if (value) {
+         if (!strcmp(value, "disk")) {
+             media = MEDIA_DISK;
+         } else if (!strcmp(value, "cdrom")) {
+             media = MEDIA_CDROM;
+             read_only = true;
+         } else {
+             error_report("'%s' invalid media", value);
+             goto fail;
+         }
+     }
+     /* copy-on-read is disabled with a warning for read-only devices */
+     read_only |= qemu_opt_get_bool(legacy_opts, "read-only", false);
+     copy_on_read = qemu_opt_get_bool(legacy_opts, "copy-on-read", false);
+     if (read_only && copy_on_read) {
+         error_report("warning: disabling copy-on-read on read-only drive");
+         copy_on_read = false;
+     }
+     qdict_put(bs_opts, "read-only",
+               qstring_from_str(read_only ? "on" : "off"));
+     qdict_put(bs_opts, "copy-on-read",
+               qstring_from_str(copy_on_read ? "on" :"off"));
+     /* Controller type */
+     value = qemu_opt_get(legacy_opts, "if");
+     if (value) {
+         for (type = 0;
+              type < IF_COUNT && strcmp(value, if_name[type]);
+              type++) {
+         }
+         if (type == IF_COUNT) {
+             error_report("unsupported bus type '%s'", value);
+             goto fail;
+         }
+     } else {
+         type = block_default_type;
+     }
+     /* Geometry */
+     cyls  = qemu_opt_get_number(legacy_opts, "cyls", 0);
+     heads = qemu_opt_get_number(legacy_opts, "heads", 0);
+     secs  = qemu_opt_get_number(legacy_opts, "secs", 0);
+     if (cyls || heads || secs) {
+         if (cyls < 1) {
+             error_report("invalid physical cyls number");
+             goto fail;
+         }
+         if (heads < 1) {
+             error_report("invalid physical heads number");
+             goto fail;
+         }
+         if (secs < 1) {
+             error_report("invalid physical secs number");
+             goto fail;
+         }
+     }
+     translation = BIOS_ATA_TRANSLATION_AUTO;
+     value = qemu_opt_get(legacy_opts, "trans");
+     if (value != NULL) {
+         if (!cyls) {
+             error_report("'%s' trans must be used with cyls, heads and secs",
+                          value);
+             goto fail;
+         }
+         if (!strcmp(value, "none")) {
+             translation = BIOS_ATA_TRANSLATION_NONE;
+         } else if (!strcmp(value, "lba")) {
+             translation = BIOS_ATA_TRANSLATION_LBA;
+         } else if (!strcmp(value, "auto")) {
+             translation = BIOS_ATA_TRANSLATION_AUTO;
+         } else {
+             error_report("'%s' invalid translation type", value);
+             goto fail;
+         }
+     }
+     if (media == MEDIA_CDROM) {
+         if (cyls || secs || heads) {
+             error_report("CHS can't be set with media=cdrom");
+             goto fail;
+         }
+     }
+     /* Device address specified by bus/unit or index.
+      * If none was specified, try to find the first free one. */
+     bus_id  = qemu_opt_get_number(legacy_opts, "bus", 0);
+     unit_id = qemu_opt_get_number(legacy_opts, "unit", -1);
+     index   = qemu_opt_get_number(legacy_opts, "index", -1);
+     max_devs = if_max_devs[type];
+     if (index != -1) {
+         if (bus_id != 0 || unit_id != -1) {
+             error_report("index cannot be used with bus and unit");
+             goto fail;
+         }
+         bus_id = drive_index_to_bus_id(type, index);
+         unit_id = drive_index_to_unit_id(type, index);
+     }
+     if (unit_id == -1) {
+        unit_id = 0;
+        while (drive_get(type, bus_id, unit_id) != NULL) {
+            unit_id++;
+            if (max_devs && unit_id >= max_devs) {
+                unit_id -= max_devs;
+                bus_id++;
+            }
+        }
+     }
+     if (max_devs && unit_id >= max_devs) {
+         error_report("unit %d too big (max is %d)", unit_id, max_devs - 1);
+         goto fail;
+     }
+     if (drive_get(type, bus_id, unit_id) != NULL) {
+         error_report("drive with bus=%d, unit=%d (index=%d) exists",
+                      bus_id, unit_id, index);
+         goto fail;
+     }
+     /* no id supplied -> create one */
+     if (qemu_opts_id(all_opts) == NULL) {
+         char *new_id;
+         const char *mediastr = "";
+         if (type == IF_IDE || type == IF_SCSI) {
+             mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
+         }
+         if (max_devs) {
+             new_id = g_strdup_printf("%s%i%s%i", if_name[type], bus_id,
+                                      mediastr, unit_id);
+         } else {
+             new_id = g_strdup_printf("%s%s%i", if_name[type],
+                                      mediastr, unit_id);
+         }
+         qdict_put(bs_opts, "id", qstring_from_str(new_id));
+         g_free(new_id);
+     }
+     /* Add virtio block device */
+     devaddr = qemu_opt_get(legacy_opts, "addr");
+     if (devaddr && type != IF_VIRTIO) {
+         error_report("addr is not supported by this bus type");
+         goto fail;
+     }
+     if (type == IF_VIRTIO) {
+         QemuOpts *devopts;
+         devopts = qemu_opts_create_nofail(qemu_find_opts("device"));
+         if (arch_type == QEMU_ARCH_S390X) {
+             qemu_opt_set(devopts, "driver", "virtio-blk-s390");
+         } else {
+             qemu_opt_set(devopts, "driver", "virtio-blk-pci");
+         }
+         qemu_opt_set(devopts, "drive", qdict_get_str(bs_opts, "id"));
+         if (devaddr) {
+             qemu_opt_set(devopts, "addr", devaddr);
+         }
+     }
+     /* Actual block device init: Functionality shared with blockdev-add */
+     dinfo = blockdev_init(bs_opts, type, &local_err);
+     if (dinfo == NULL) {
+         if (error_is_set(&local_err)) {
+             qerror_report_err(local_err);
+             error_free(local_err);
+         }
+         goto fail;
+     } else {
+         assert(!error_is_set(&local_err));
+     }
+     /* Set legacy DriveInfo fields */
+     dinfo->enable_auto_del = true;
+     dinfo->opts = all_opts;
+     dinfo->cyls = cyls;
+     dinfo->heads = heads;
+     dinfo->secs = secs;
+     dinfo->trans = translation;
+     dinfo->bus = bus_id;
+     dinfo->unit = unit_id;
+     dinfo->devaddr = devaddr;
+     switch(type) {
+     case IF_IDE:
+     case IF_SCSI:
+     case IF_XEN:
+     case IF_NONE:
+         dinfo->media_cd = media == MEDIA_CDROM;
+         break;
+     default:
+         break;
+     }
+ fail:
+     qemu_opts_del(legacy_opts);
+     return dinfo;
  }
  
  void do_commit(Monitor *mon, const QDict *qdict)
@@@ -876,6 -957,80 +972,80 @@@ void qmp_blockdev_snapshot_sync(const c
                         &snapshot, errp);
  }
  
+ void qmp_blockdev_snapshot_internal_sync(const char *device,
+                                          const char *name,
+                                          Error **errp)
+ {
+     BlockdevSnapshotInternal snapshot = {
+         .device = (char *) device,
+         .name = (char *) name
+     };
+     blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC,
+                        &snapshot, errp);
+ }
+ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
+                                                          bool has_id,
+                                                          const char *id,
+                                                          bool has_name,
+                                                          const char *name,
+                                                          Error **errp)
+ {
+     BlockDriverState *bs = bdrv_find(device);
+     QEMUSnapshotInfo sn;
+     Error *local_err = NULL;
+     SnapshotInfo *info = NULL;
+     int ret;
+     if (!bs) {
+         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+         return NULL;
+     }
+     if (!has_id) {
+         id = NULL;
+     }
+     if (!has_name) {
+         name = NULL;
+     }
+     if (!id && !name) {
+         error_setg(errp, "Name or id must be provided");
+         return NULL;
+     }
+     ret = bdrv_snapshot_find_by_id_and_name(bs, id, name, &sn, &local_err);
+     if (error_is_set(&local_err)) {
+         error_propagate(errp, local_err);
+         return NULL;
+     }
+     if (!ret) {
+         error_setg(errp,
+                    "Snapshot with id '%s' and name '%s' does not exist on "
+                    "device '%s'",
+                    STR_OR_NULL(id), STR_OR_NULL(name), device);
+         return NULL;
+     }
+     bdrv_snapshot_delete(bs, id, name, &local_err);
+     if (error_is_set(&local_err)) {
+         error_propagate(errp, local_err);
+         return NULL;
+     }
+     info = g_malloc0(sizeof(SnapshotInfo));
+     info->id = g_strdup(sn.id_str);
+     info->name = g_strdup(sn.name);
+     info->date_nsec = sn.date_nsec;
+     info->date_sec = sn.date_sec;
+     info->vm_state_size = sn.vm_state_size;
+     info->vm_clock_nsec = sn.vm_clock_nsec % 1000000000;
+     info->vm_clock_sec = sn.vm_clock_nsec / 1000000000;
+     return info;
+ }
  
  /* New and old BlockDriverState structs for group snapshots */
  
@@@ -907,6 -1062,117 +1077,117 @@@ struct BlkTransactionState 
      QSIMPLEQ_ENTRY(BlkTransactionState) entry;
  };
  
+ /* internal snapshot private data */
+ typedef struct InternalSnapshotState {
+     BlkTransactionState common;
+     BlockDriverState *bs;
+     QEMUSnapshotInfo sn;
+ } InternalSnapshotState;
+ static void internal_snapshot_prepare(BlkTransactionState *common,
+                                       Error **errp)
+ {
+     const char *device;
+     const char *name;
+     BlockDriverState *bs;
+     QEMUSnapshotInfo old_sn, *sn;
+     bool ret;
+     qemu_timeval tv;
+     BlockdevSnapshotInternal *internal;
+     InternalSnapshotState *state;
+     int ret1;
+     g_assert(common->action->kind ==
+              TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC);
+     internal = common->action->blockdev_snapshot_internal_sync;
+     state = DO_UPCAST(InternalSnapshotState, common, common);
+     /* 1. parse input */
+     device = internal->device;
+     name = internal->name;
+     /* 2. check for validation */
+     bs = bdrv_find(device);
+     if (!bs) {
+         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+         return;
+     }
+     if (!bdrv_is_inserted(bs)) {
+         error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
+         return;
+     }
+     if (bdrv_is_read_only(bs)) {
+         error_set(errp, QERR_DEVICE_IS_READ_ONLY, device);
+         return;
+     }
+     if (!bdrv_can_snapshot(bs)) {
+         error_set(errp, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+                   bs->drv->format_name, device, "internal snapshot");
+         return;
+     }
+     if (!strlen(name)) {
+         error_setg(errp, "Name is empty");
+         return;
+     }
+     /* check whether a snapshot with name exist */
+     ret = bdrv_snapshot_find_by_id_and_name(bs, NULL, name, &old_sn, errp);
+     if (error_is_set(errp)) {
+         return;
+     } else if (ret) {
+         error_setg(errp,
+                    "Snapshot with name '%s' already exists on device '%s'",
+                    name, device);
+         return;
+     }
+     /* 3. take the snapshot */
+     sn = &state->sn;
+     pstrcpy(sn->name, sizeof(sn->name), name);
+     qemu_gettimeofday(&tv);
+     sn->date_sec = tv.tv_sec;
+     sn->date_nsec = tv.tv_usec * 1000;
+     sn->vm_clock_nsec = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+     ret1 = bdrv_snapshot_create(bs, sn);
+     if (ret1 < 0) {
+         error_setg_errno(errp, -ret1,
+                          "Failed to create snapshot '%s' on device '%s'",
+                          name, device);
+         return;
+     }
+     /* 4. succeed, mark a snapshot is created */
+     state->bs = bs;
+ }
+ static void internal_snapshot_abort(BlkTransactionState *common)
+ {
+     InternalSnapshotState *state =
+                              DO_UPCAST(InternalSnapshotState, common, common);
+     BlockDriverState *bs = state->bs;
+     QEMUSnapshotInfo *sn = &state->sn;
+     Error *local_error = NULL;
+     if (!bs) {
+         return;
+     }
+     if (bdrv_snapshot_delete(bs, sn->id_str, sn->name, &local_error) < 0) {
+         error_report("Failed to delete snapshot with id '%s' and name '%s' on "
+                      "device '%s' in abort: %s",
+                      sn->id_str,
+                      sn->name,
+                      bdrv_get_device_name(bs),
+                      error_get_pretty(local_error));
+         error_free(local_error);
+     }
+ }
  /* external snapshot private data */
  typedef struct ExternalSnapshotState {
      BlkTransactionState common;
@@@ -970,6 -1236,11 +1251,11 @@@ static void external_snapshot_prepare(B
          }
      }
  
+     if (bdrv_check_ext_snapshot(state->old_bs) != EXT_SNAPSHOT_ALLOWED) {
+         error_set(errp, QERR_FEATURE_DISABLED, "snapshot");
+         return;
+     }
      flags = state->old_bs->open_flags;
  
      /* create new image w/backing file */
      /* TODO Inherit bs->options or only take explicit options with an
       * extended QMP command? */
      ret = bdrv_open(state->new_bs, new_image_file, NULL,
-                     flags | BDRV_O_NO_BACKING, drv);
+                     flags | BDRV_O_NO_BACKING, drv, &local_err);
      if (ret != 0) {
-         error_setg_file_open(errp, -ret, new_image_file);
+         error_propagate(errp, local_err);
      }
  }
  
@@@ -1014,7 -1285,7 +1300,7 @@@ static void external_snapshot_abort(Blk
      ExternalSnapshotState *state =
                               DO_UPCAST(ExternalSnapshotState, common, common);
      if (state->new_bs) {
-         bdrv_delete(state->new_bs);
+         bdrv_unref(state->new_bs);
      }
  }
  
@@@ -1090,6 -1361,11 +1376,11 @@@ static const BdrvActionOps actions[] = 
          .prepare = abort_prepare,
          .commit = abort_commit,
      },
+     [TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC] = {
+         .instance_size = sizeof(InternalSnapshotState),
+         .prepare  = internal_snapshot_prepare,
+         .abort = internal_snapshot_abort,
+     },
  };
  
  /*
@@@ -1120,6 -1396,8 +1411,8 @@@ void qmp_transaction(TransactionActionL
          assert(dev_info->kind < ARRAY_SIZE(actions));
  
          ops = &actions[dev_info->kind];
+         assert(ops->instance_size > 0);
          state = g_malloc0(ops->instance_size);
          state->ops = ops;
          state->action = dev_info;
@@@ -1221,11 -1499,12 +1514,12 @@@ static void qmp_bdrv_open_encrypted(Blo
                                      int bdrv_flags, BlockDriver *drv,
                                      const char *password, Error **errp)
  {
+     Error *local_err = NULL;
      int ret;
  
-     ret = bdrv_open(bs, filename, NULL, bdrv_flags, drv);
+     ret = bdrv_open(bs, filename, NULL, bdrv_flags, drv, &local_err);
      if (ret < 0) {
-         error_setg_file_open(errp, -ret, filename);
+         error_propagate(errp, local_err);
          return;
      }
  
@@@ -1279,10 -1558,26 +1573,26 @@@ void qmp_change_blockdev(const char *de
  
  /* throttling disk I/O limits */
  void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
-                                int64_t bps_wr, int64_t iops, int64_t iops_rd,
-                                int64_t iops_wr, Error **errp)
+                                int64_t bps_wr,
+                                int64_t iops,
+                                int64_t iops_rd,
+                                int64_t iops_wr,
+                                bool has_bps_max,
+                                int64_t bps_max,
+                                bool has_bps_rd_max,
+                                int64_t bps_rd_max,
+                                bool has_bps_wr_max,
+                                int64_t bps_wr_max,
+                                bool has_iops_max,
+                                int64_t iops_max,
+                                bool has_iops_rd_max,
+                                int64_t iops_rd_max,
+                                bool has_iops_wr_max,
+                                int64_t iops_wr_max,
+                                bool has_iops_size,
+                                int64_t iops_size, Error **errp)
  {
-     BlockIOLimit io_limits;
+     ThrottleConfig cfg;
      BlockDriverState *bs;
  
      bs = bdrv_find(device);
          return;
      }
  
-     io_limits.bps[BLOCK_IO_LIMIT_TOTAL] = bps;
-     io_limits.bps[BLOCK_IO_LIMIT_READ]  = bps_rd;
-     io_limits.bps[BLOCK_IO_LIMIT_WRITE] = bps_wr;
-     io_limits.iops[BLOCK_IO_LIMIT_TOTAL]= iops;
-     io_limits.iops[BLOCK_IO_LIMIT_READ] = iops_rd;
-     io_limits.iops[BLOCK_IO_LIMIT_WRITE]= iops_wr;
+     memset(&cfg, 0, sizeof(cfg));
+     cfg.buckets[THROTTLE_BPS_TOTAL].avg = bps;
+     cfg.buckets[THROTTLE_BPS_READ].avg  = bps_rd;
+     cfg.buckets[THROTTLE_BPS_WRITE].avg = bps_wr;
  
-     if (!do_check_io_limits(&io_limits, errp)) {
-         return;
+     cfg.buckets[THROTTLE_OPS_TOTAL].avg = iops;
+     cfg.buckets[THROTTLE_OPS_READ].avg  = iops_rd;
+     cfg.buckets[THROTTLE_OPS_WRITE].avg = iops_wr;
+     if (has_bps_max) {
+         cfg.buckets[THROTTLE_BPS_TOTAL].max = bps_max;
+     }
+     if (has_bps_rd_max) {
+         cfg.buckets[THROTTLE_BPS_READ].max = bps_rd_max;
+     }
+     if (has_bps_wr_max) {
+         cfg.buckets[THROTTLE_BPS_WRITE].max = bps_wr_max;
+     }
+     if (has_iops_max) {
+         cfg.buckets[THROTTLE_OPS_TOTAL].max = iops_max;
+     }
+     if (has_iops_rd_max) {
+         cfg.buckets[THROTTLE_OPS_READ].max = iops_rd_max;
+     }
+     if (has_iops_wr_max) {
+         cfg.buckets[THROTTLE_OPS_WRITE].max = iops_wr_max;
+     }
+     if (has_iops_size) {
+         cfg.op_size = iops_size;
      }
  
-     bs->io_limits = io_limits;
+     if (!check_throttle_config(&cfg, errp)) {
+         return;
+     }
  
-     if (!bs->io_limits_enabled && bdrv_io_limits_enabled(bs)) {
+     if (!bs->io_limits_enabled && throttle_enabled(&cfg)) {
          bdrv_io_limits_enable(bs);
-     } else if (bs->io_limits_enabled && !bdrv_io_limits_enabled(bs)) {
+     } else if (bs->io_limits_enabled && !throttle_enabled(&cfg)) {
          bdrv_io_limits_disable(bs);
-     } else {
-         if (bs->block_timer) {
-             qemu_mod_timer(bs->block_timer, qemu_get_clock_ns(vm_clock));
-         }
+     }
+     if (bs->io_limits_enabled) {
+         bdrv_set_io_limits(bs, &cfg);
      }
  }
  
@@@ -1415,7 -1733,7 +1748,7 @@@ static void block_job_cb(void *opaque, 
      }
      qobject_decref(obj);
  
-     drive_put_ref_bh_schedule(drive_get_by_blockdev(bs));
+     bdrv_put_ref_bh_schedule(bs);
  }
  
  void qmp_block_stream(const char *device, bool has_base,
          return;
      }
  
-     /* Grab a reference so hotplug does not delete the BlockDriverState from
-      * underneath us.
-      */
-     drive_get_ref(drive_get_by_blockdev(bs));
      trace_qmp_block_stream(bs, bs->job);
  }
  
@@@ -1513,10 -1826,6 +1841,6 @@@ void qmp_block_commit(const char *devic
          error_propagate(errp, local_err);
          return;
      }
-     /* Grab a reference so hotplug does not delete the BlockDriverState from
-      * underneath us.
-      */
-     drive_get_ref(drive_get_by_blockdev(bs));
  }
  
  void qmp_drive_backup(const char *device, const char *target,
      }
  
      target_bs = bdrv_new("");
-     ret = bdrv_open(target_bs, target, NULL, flags, drv);
+     ret = bdrv_open(target_bs, target, NULL, flags, drv, &local_err);
      if (ret < 0) {
-         bdrv_delete(target_bs);
-         error_setg_file_open(errp, -ret, target);
+         bdrv_unref(target_bs);
+         error_propagate(errp, local_err);
          return;
      }
  
      backup_start(bs, target_bs, speed, sync, on_source_error, on_target_error,
                   block_job_cb, bs, &local_err);
      if (local_err != NULL) {
-         bdrv_delete(target_bs);
+         bdrv_unref(target_bs);
          error_propagate(errp, local_err);
          return;
      }
-     /* Grab a reference so hotplug does not delete the BlockDriverState from
-      * underneath us.
-      */
-     drive_get_ref(drive_get_by_blockdev(bs));
  }
  
  #define DEFAULT_MIRROR_BUF_SIZE   (10 << 20)
@@@ -1717,6 -2021,9 +2036,9 @@@ void qmp_drive_mirror(const char *devic
      if (!source && sync == MIRROR_SYNC_MODE_TOP) {
          sync = MIRROR_SYNC_MODE_FULL;
      }
+     if (sync == MIRROR_SYNC_MODE_NONE) {
+         source = bs;
+     }
  
      size = bdrv_getlength(bs);
      if (size < 0) {
          return;
      }
  
-     if (sync == MIRROR_SYNC_MODE_FULL && mode != NEW_IMAGE_MODE_EXISTING) {
+     if ((sync == MIRROR_SYNC_MODE_FULL || !source)
+         && mode != NEW_IMAGE_MODE_EXISTING)
+     {
          /* create new image w/o backing file */
          assert(format && drv);
          bdrv_img_create(target, format,
      } else {
          switch (mode) {
          case NEW_IMAGE_MODE_EXISTING:
-             ret = 0;
              break;
          case NEW_IMAGE_MODE_ABSOLUTE_PATHS:
              /* create new image with backing file */
       * file.
       */
      target_bs = bdrv_new("");
-     ret = bdrv_open(target_bs, target, NULL, flags | BDRV_O_NO_BACKING, drv);
+     ret = bdrv_open(target_bs, target, NULL, flags | BDRV_O_NO_BACKING, drv,
+                     &local_err);
      if (ret < 0) {
-         bdrv_delete(target_bs);
-         error_setg_file_open(errp, -ret, target);
+         bdrv_unref(target_bs);
+         error_propagate(errp, local_err);
          return;
      }
  
                   on_source_error, on_target_error,
                   block_job_cb, bs, &local_err);
      if (local_err != NULL) {
-         bdrv_delete(target_bs);
+         bdrv_unref(target_bs);
          error_propagate(errp, local_err);
          return;
      }
-     /* Grab a reference so hotplug does not delete the BlockDriverState from
-      * underneath us.
-      */
-     drive_get_ref(drive_get_by_blockdev(bs));
  }
  
  static BlockJob *find_block_job(const char *device)
@@@ -1861,6 -2165,54 +2180,54 @@@ void qmp_block_job_complete(const char 
      block_job_complete(job, errp);
  }
  
+ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
+ {
+     QmpOutputVisitor *ov = qmp_output_visitor_new();
+     QObject *obj;
+     QDict *qdict;
+     Error *local_err = NULL;
+     /* Require an ID in the top level */
+     if (!options->has_id) {
+         error_setg(errp, "Block device needs an ID");
+         goto fail;
+     }
+     /* TODO Sort it out in raw-posix and drive_init: Reject aio=native with
+      * cache.direct=false instead of silently switching to aio=threads, except
+      * if called from drive_init.
+      *
+      * For now, simply forbidding the combination for all drivers will do. */
+     if (options->has_aio && options->aio == BLOCKDEV_AIO_OPTIONS_NATIVE) {
+         bool direct = options->cache->has_direct && options->cache->direct;
+         if (!options->has_cache && !direct) {
+             error_setg(errp, "aio=native requires cache.direct=true");
+             goto fail;
+         }
+     }
+     visit_type_BlockdevOptions(qmp_output_get_visitor(ov),
+                                &options, NULL, &local_err);
+     if (error_is_set(&local_err)) {
+         error_propagate(errp, local_err);
+         goto fail;
+     }
+     obj = qmp_output_get_qobject(ov);
+     qdict = qobject_to_qdict(obj);
+     qdict_flatten(qdict);
+     blockdev_init(qdict, IF_NONE, &local_err);
+     if (error_is_set(&local_err)) {
+         error_propagate(errp, local_err);
+         goto fail;
+     }
+ fail:
+     qmp_output_visitor_cleanup(ov);
+ }
  static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs)
  {
      BlockJobInfoList **prev = opaque;
@@@ -1888,42 -2240,6 +2255,6 @@@ QemuOptsList qemu_common_drive_opts = 
      .head = QTAILQ_HEAD_INITIALIZER(qemu_common_drive_opts.head),
      .desc = {
          {
-             .name = "bus",
-             .type = QEMU_OPT_NUMBER,
-             .help = "bus number",
-         },{
-             .name = "unit",
-             .type = QEMU_OPT_NUMBER,
-             .help = "unit number (i.e. lun for scsi)",
-         },{
-             .name = "if",
-             .type = QEMU_OPT_STRING,
-             .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
-         },{
-             .name = "index",
-             .type = QEMU_OPT_NUMBER,
-             .help = "index number",
-         },{
-             .name = "cyls",
-             .type = QEMU_OPT_NUMBER,
-             .help = "number of cylinders (ide disk geometry)",
-         },{
-             .name = "heads",
-             .type = QEMU_OPT_NUMBER,
-             .help = "number of heads (ide disk geometry)",
-         },{
-             .name = "secs",
-             .type = QEMU_OPT_NUMBER,
-             .help = "number of sectors (ide disk geometry)",
-         },{
-             .name = "trans",
-             .type = QEMU_OPT_STRING,
-             .help = "chs translation (auto, lba. none)",
-         },{
-             .name = "media",
-             .type = QEMU_OPT_STRING,
-             .help = "media type (disk, cdrom)",
-         },{
              .name = "snapshot",
              .type = QEMU_OPT_BOOL,
              .help = "enable/disable snapshot mode",
              .type = QEMU_OPT_STRING,
              .help = "write error action",
          },{
-             .name = "addr",
-             .type = QEMU_OPT_STRING,
-             .help = "pci address (virtio only)",
-         },{
              .name = "read-only",
              .type = QEMU_OPT_BOOL,
              .help = "open drive file as read-only",
              .type = QEMU_OPT_NUMBER,
              .help = "limit write bytes per second",
          },{
-             .name = "copy-on-read",
-             .type = QEMU_OPT_BOOL,
-             .help = "copy read data from backing file into image file",
-         },{
-             .name = "boot",
-             .type = QEMU_OPT_BOOL,
-             .help = "(deprecated, ignored)",
-         },
-         { /* end of list */ }
-     },
- };
- QemuOptsList qemu_old_drive_opts = {
-     .name = "drive",
-     .head = QTAILQ_HEAD_INITIALIZER(qemu_old_drive_opts.head),
-     .desc = {
-         {
-             .name = "bus",
-             .type = QEMU_OPT_NUMBER,
-             .help = "bus number",
-         },{
-             .name = "unit",
-             .type = QEMU_OPT_NUMBER,
-             .help = "unit number (i.e. lun for scsi)",
-         },{
-             .name = "if",
-             .type = QEMU_OPT_STRING,
-             .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
-         },{
-             .name = "index",
-             .type = QEMU_OPT_NUMBER,
-             .help = "index number",
-         },{
-             .name = "cyls",
-             .type = QEMU_OPT_NUMBER,
-             .help = "number of cylinders (ide disk geometry)",
-         },{
-             .name = "heads",
-             .type = QEMU_OPT_NUMBER,
-             .help = "number of heads (ide disk geometry)",
-         },{
-             .name = "secs",
+             .name = "throttling.iops-total-max",
              .type = QEMU_OPT_NUMBER,
-             .help = "number of sectors (ide disk geometry)",
-         },{
-             .name = "trans",
-             .type = QEMU_OPT_STRING,
-             .help = "chs translation (auto, lba. none)",
-         },{
-             .name = "media",
-             .type = QEMU_OPT_STRING,
-             .help = "media type (disk, cdrom)",
-         },{
-             .name = "snapshot",
-             .type = QEMU_OPT_BOOL,
-             .help = "enable/disable snapshot mode",
-         },{
-             .name = "file",
-             .type = QEMU_OPT_STRING,
-             .help = "disk image",
-         },{
-             .name = "discard",
-             .type = QEMU_OPT_STRING,
-             .help = "discard operation (ignore/off, unmap/on)",
-         },{
-             .name = "cache",
-             .type = QEMU_OPT_STRING,
-             .help = "host cache usage (none, writeback, writethrough, "
-                     "directsync, unsafe)",
-         },{
-             .name = "aio",
-             .type = QEMU_OPT_STRING,
-             .help = "host AIO implementation (threads, native)",
-         },{
-             .name = "format",
-             .type = QEMU_OPT_STRING,
-             .help = "disk format (raw, qcow2, ...)",
-         },{
-             .name = "serial",
-             .type = QEMU_OPT_STRING,
-             .help = "disk serial number",
-         },{
-             .name = "rerror",
-             .type = QEMU_OPT_STRING,
-             .help = "read error action",
-         },{
-             .name = "werror",
-             .type = QEMU_OPT_STRING,
-             .help = "write error action",
-         },{
-             .name = "addr",
-             .type = QEMU_OPT_STRING,
-             .help = "pci address (virtio only)",
-         },{
-             .name = "readonly",
-             .type = QEMU_OPT_BOOL,
-             .help = "open drive file as read-only",
+             .help = "I/O operations burst",
          },{
-             .name = "iops",
+             .name = "throttling.iops-read-max",
              .type = QEMU_OPT_NUMBER,
-             .help = "limit total I/O operations per second",
+             .help = "I/O operations read burst",
          },{
-             .name = "iops_rd",
+             .name = "throttling.iops-write-max",
              .type = QEMU_OPT_NUMBER,
-             .help = "limit read operations per second",
+             .help = "I/O operations write burst",
          },{
-             .name = "iops_wr",
+             .name = "throttling.bps-total-max",
              .type = QEMU_OPT_NUMBER,
-             .help = "limit write operations per second",
+             .help = "total bytes burst",
          },{
-             .name = "bps",
+             .name = "throttling.bps-read-max",
              .type = QEMU_OPT_NUMBER,
-             .help = "limit total bytes per second",
+             .help = "total bytes read burst",
          },{
-             .name = "bps_rd",
+             .name = "throttling.bps-write-max",
              .type = QEMU_OPT_NUMBER,
-             .help = "limit read bytes per second",
+             .help = "total bytes write burst",
          },{
-             .name = "bps_wr",
+             .name = "throttling.iops-size",
              .type = QEMU_OPT_NUMBER,
-             .help = "limit write bytes per second",
+             .help = "when limiting by iops max size of an I/O in bytes",
          },{
              .name = "copy-on-read",
              .type = QEMU_OPT_BOOL,
              .help = "copy read data from backing file into image file",
-         },{
-             .name = "boot",
-             .type = QEMU_OPT_BOOL,
-             .help = "(deprecated, ignored)",
          },
          { /* end of list */ }
      },
diff --combined configure
+++ b/configure
@@@ -27,6 -27,19 +27,19 @@@ printf " '%s'" "$0" "$@" >> config.lo
  echo >> config.log
  echo "#" >> config.log
  
+ # Save the configure command line for later reuse.
+ cat <<EOD >config.status
+ #!/bin/sh
+ # Generated by configure.
+ # Run this file to recreate the current configuration.
+ # Compiler output produced by configure, useful for debugging
+ # configure, is in config.log if it exists.
+ EOD
+ printf "exec" >>config.status
+ printf " '%s'" "$0" "$@" >>config.status
+ echo >>config.status
+ chmod +x config.status
  error_exit() {
      echo
      echo "ERROR: $1"
@@@ -119,6 -132,7 +132,7 @@@ path_of() 
  # default parameters
  source_path=`dirname "$0"`
  cpu=""
+ iasl="iasl"
  interp_prefix="/usr/gnemul/qemu-%M"
  static="no"
  cross_prefix=""
@@@ -179,7 -193,6 +193,7 @@@ xfs="
  vhost_net="no"
  vhost_scsi="no"
  kvm="no"
 +hax="no"
  rdma=""
  gprof="no"
  debug_tcg="no"
@@@ -216,7 -229,6 +230,6 @@@ linux_user="no
  bsd_user="no"
  guest_base="yes"
  uname_release=""
- mixemu="no"
  aix="no"
  blobs="yes"
  pkgversion=""
@@@ -230,25 -242,17 +243,28 @@@ rbd="
  smartcard_nss=""
  libusb=""
  usb_redir=""
 +opengl=""
 +efence="no"
 +yagl="no"
 +yagl_stats="no"
  glx=""
 +vigs="no"
  zlib="yes"
  guest_agent=""
+ guest_agent_with_vss="no"
+ vss_win32_sdk=""
+ win_sdk="no"
  want_tools="yes"
  libiscsi=""
  coroutine=""
  coroutine_pool=""
  seccomp=""
 +gl="yes"
 +
 +# for TIZEN-maru 
 +maru="no"
 +shm="no"
 +#
  glusterfs=""
  glusterfs_discard="no"
  virtio_blk_data_plane=""
@@@ -256,6 -260,7 +272,7 @@@ gtk="
  gtkabi="2.0"
  tpm="no"
  libssh2=""
+ vhdx=""
  
  # parse CC options first
  for opt do
    ;;
    --cc=*) CC="$optarg"
    ;;
+   --cxx=*) CXX="$optarg"
+   ;;
    --source-path=*) source_path="$optarg"
    ;;
    --cpu=*) cpu="$optarg"
@@@ -295,6 -302,12 +314,12 @@@ els
    cc="${CC-${cross_prefix}gcc}"
  fi
  
+ if test -z "${CXX}${cross_prefix}"; then
+   cxx="c++"
+ else
+   cxx="${CXX-${cross_prefix}g++}"
+ fi
  ar="${AR-${cross_prefix}ar}"
  as="${AS-${cross_prefix}as}"
  cpp="${CPP-$cc -E}"
@@@ -310,6 -323,9 +335,9 @@@ query_pkg_config() 
  pkg_config=query_pkg_config
  sdl_config="${SDL_CONFIG-${cross_prefix}sdl-config}"
  
+ # If the user hasn't specified ARFLAGS, default to 'rv', just as make does.
+ ARFLAGS="${ARFLAGS-rv}"
  # default flags for all hosts
  QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS"
  QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS"
@@@ -375,7 -391,11 +403,11 @@@ if test ! -z "$cpu" ; the
  elif check_define __i386__ ; then
    cpu="i386"
  elif check_define __x86_64__ ; then
-   cpu="x86_64"
+   if check_define __ILP32__ ; then
+     cpu="x32"
+   else
+     cpu="x86_64"
+   fi
  elif check_define __sparc__ ; then
    if check_define __arch64__ ; then
      cpu="sparc64"
@@@ -412,7 -432,7 +444,7 @@@ ARCH
  # Normalise host CPU name and set ARCH.
  # Note that this case should only have supported host CPUs, not guests.
  case "$cpu" in
-   ia64|ppc|ppc64|s390|s390x|sparc64)
+   ia64|ppc|ppc64|s390|s390x|sparc64|x32)
      cpu="$cpu"
    ;;
    i386|i486|i586|i686|i86pc|BePC)
    aarch64)
      cpu="aarch64"
    ;;
-   hppa|parisc|parisc64)
-     cpu="hppa"
-   ;;
    mips*)
      cpu="mips"
    ;;
@@@ -559,26 -576,18 +588,22 @@@ Haiku
    audio_possible_drivers="oss alsa sdl esd pa"
    linux="yes"
    linux_user="yes"
-   usb="linux"
    kvm="yes"
    vhost_net="yes"
    vhost_scsi="yes"
-   if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
+   if [ "$cpu" = "i386" -o "$cpu" = "x86_64" -o "$cpu" = "x32" ] ; then
      audio_possible_drivers="$audio_possible_drivers fmod"
    fi
 +
 +# fix linking error on Ubuntu 13.04
 +#  libs_qga="-lrt $libs_qga"
 +#  QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers $QEMU_INCLUDES"
    QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers -I$(pwd)/linux-headers $QEMU_INCLUDES"
  ;;
  esac
  
  if [ "$bsd" = "yes" ] ; then
    if [ "$darwin" != "yes" ] ; then
-     if [ "$targetos" != "FreeBSD" ]; then
-       usb="bsd"
-     fi
      bsd_user="yes"
    fi
  fi
@@@ -639,6 -648,10 +664,10 @@@ for opt d
    ;;
    --host-cc=*) host_cc="$optarg"
    ;;
+   --cxx=*)
+   ;;
+   --iasl=*) iasl="$optarg"
+   ;;
    --objcc=*) objcc="$optarg"
    ;;
    --make=*) make="$optarg"
    ;;
    --enable-kvm) kvm="yes"
    ;;
 +  --disable-gl) gl="no"
 +  ;;
 +  --enable-gl) gl="yes"
 +  ;;
 +  --disable-hax) hax="no"
 +  ;;
 +  --enable-hax) hax="yes"
 +  ;;
    --disable-tcg-interpreter) tcg_interpreter="no"
    ;;
    --enable-tcg-interpreter) tcg_interpreter="yes"
    ;;
    --enable-fdt) fdt="yes"
    ;;
-   --enable-mixemu) mixemu="yes"
-   ;;
    --disable-linux-aio) linux_aio="no"
    ;;
    --enable-linux-aio) linux_aio="yes"
    ;;
    --enable-vhost-net) vhost_net="yes"
    ;;
 +  --enable-efence) efence="yes"
 +  ;;
 +  --disable-efence) efence="no"
 +  ;;
 +  --enable-yagl) yagl="yes"
 +  ;;
 +  --disable-yagl) yagl="no"
 +  ;;
 +  --enable-yagl-stats) yagl_stats="yes"
 +  ;;
 +  --disable-yagl-stats) yagl_stats="no"
 +  ;;
 +  --enable-opengl) opengl="yes"
 +  ;;
 +  --enable-vigs) vigs="yes"
 +  ;;
 +  --disable-vigs) vigs="no"
 +  ;;
 +  --disable-opengl) opengl="no"
 +  ;;
    --disable-vhost-scsi) vhost_scsi="no"
    ;;
    --enable-vhost-scsi) vhost_scsi="yes"
    ;;
    --disable-guest-agent) guest_agent="no"
    ;;
+   --with-vss-sdk) vss_win32_sdk=""
+   ;;
+   --with-vss-sdk=*) vss_win32_sdk="$optarg"
+   ;;
+   --without-vss-sdk) vss_win32_sdk="no"
+   ;;
+   --with-win-sdk) win_sdk=""
+   ;;
+   --with-win-sdk=*) win_sdk="$optarg"
+   ;;
+   --without-win-sdk) win_sdk="no"
+   ;;
    --enable-tools) want_tools="yes"
    ;;
    --disable-tools) want_tools="no"
    ;;
    --disable-seccomp) seccomp="no"
    ;;
 +# for TIZEN-maru
 +  --enable-maru) maru="yes"
 +  ;;
 +  --enable-shm) shm="yes"
 +  ;;
 +#
    --disable-glusterfs) glusterfs="no"
    ;;
    --enable-glusterfs) glusterfs="yes"
    ;;
    --enable-libssh2) libssh2="yes"
    ;;
+   --enable-vhdx) vhdx="yes"
+   ;;
+   --disable-vhdx) vhdx="no"
+   ;;
    *) echo "ERROR: unknown option $opt"; show_help="yes"
    ;;
    esac
  done
  
  case "$cpu" in
+     ppc)
+            CPU_CFLAGS="-m32"
+            LDFLAGS="-m32 $LDFLAGS"
+            ;;
+     ppc64)
+            CPU_CFLAGS="-m64"
+            LDFLAGS="-m64 $LDFLAGS"
+            ;;
      sparc)
             LDFLAGS="-m32 $LDFLAGS"
             CPU_CFLAGS="-m32 -mcpu=ultrasparc"
             LDFLAGS="-m64 $LDFLAGS"
             cc_i386='$(CC) -m32'
             ;;
+     x32)
+            CPU_CFLAGS="-mx32"
+            LDFLAGS="-mx32 $LDFLAGS"
+            cc_i386='$(CC) -m32'
+            ;;
      # No special flags required for other host CPUs
  esac
  
@@@ -1076,8 -1082,10 +1132,10 @@@ echo "Advanced options (experts only):
  echo "  --source-path=PATH       path of source code [$source_path]"
  echo "  --cross-prefix=PREFIX    use PREFIX for compile tools [$cross_prefix]"
  echo "  --cc=CC                  use C compiler CC [$cc]"
+ echo "  --iasl=IASL              use ACPI compiler IASL [$iasl]"
  echo "  --host-cc=CC             use C compiler CC [$host_cc] for code run at"
  echo "                           build time"
+ echo "  --cxx=CXX                use C++ compiler CXX [$cxx]"
  echo "  --objcc=OBJCC            use Objective-C compiler OBJCC [$objcc]"
  echo "  --extra-cflags=CFLAGS    append extra C compiler flags QEMU_CFLAGS"
  echo "  --extra-ldflags=LDFLAGS  append extra linker flags LDFLAGS"
@@@ -1122,7 -1130,6 +1180,6 @@@ echo "                           (affec
  echo "  --block-drv-ro-whitelist=L"
  echo "                           set block driver read-only whitelist"
  echo "                           (affects only QEMU, not qemu-img)"
- echo "  --enable-mixemu          enable mixer emulation"
  echo "  --disable-xen            disable xen backend driver support"
  echo "  --enable-xen             enable xen backend driver support"
  echo "  --disable-xen-pci-passthrough"
@@@ -1150,12 -1157,6 +1207,12 @@@ echo "  --enable-bluez           enabl
  echo "  --disable-slirp          disable SLIRP userspace network connectivity"
  echo "  --disable-kvm            disable KVM acceleration support"
  echo "  --enable-kvm             enable KVM acceleration support"
 +
 +echo "  --disable-hax            disable HAX acceleration support"
 +echo "  --enable-hax             enable HAX acceleration support"
 +
 +echo "  --disable-gl             disable GL acceleration support"
 +echo "  --enable-gl              enable GL acceleration support"
  echo "  --disable-rdma           disable RDMA-based migration support"
  echo "  --enable-rdma            enable RDMA-based migration support"
  echo "  --enable-tcg-interpreter enable TCG with bytecode interpreter (TCI)"
@@@ -1201,16 -1202,6 +1258,16 @@@ echo "  --enable-spice           enabl
  echo "  --enable-rbd             enable building the rados block device (rbd)"
  echo "  --disable-libiscsi       disable iscsi support"
  echo "  --enable-libiscsi        enable iscsi support"
 +echo "  --enable-efence          enable Electic Fence"
 +echo "  --disable-efence         disable Electic Fence"
 +echo "  --enable-yagl            enable YaGL device"
 +echo "  --disable-yagl           disable YaGL device"
 +echo "  --enable-yagl-stats      enable YaGL stats"
 +echo "  --disable-yagl-stats     disable YaGL stats"
 +echo "  --enable-vigs            enable VIGS device"
 +echo "  --disable-vigs           disable VIGS device"
 +echo "  --disable-smartcard      disable smartcard support"
 +echo "  --enable-smartcard       enable smartcard support"
  echo "  --disable-smartcard-nss  disable smartcard nss support"
  echo "  --enable-smartcard-nss   enable smartcard nss support"
  echo "  --disable-libusb         disable libusb (for usb passthrough)"
@@@ -1219,6 -1210,8 +1276,8 @@@ echo "  --disable-usb-redir      disabl
  echo "  --enable-usb-redir       enable usb network redirection support"
  echo "  --disable-guest-agent    disable building of the QEMU Guest Agent"
  echo "  --enable-guest-agent     enable building of the QEMU Guest Agent"
+ echo "  --with-vss-sdk=SDK-path  enable Windows VSS support in QEMU Guest Agent"
+ echo "  --with-win-sdk=SDK-path  path to Windows Platform SDK (to build VSS .tlb)"
  echo "  --disable-seccomp        disable seccomp support"
  echo "  --enable-seccomp         enables seccomp support"
  echo "  --with-coroutine=BACKEND coroutine backend. Supported options:"
@@@ -1232,11 -1225,9 +1291,13 @@@ echo "  --gcov=GCOV              use sp
  echo "  --enable-tpm             enable TPM support"
  echo "  --disable-libssh2        disable ssh block device support"
  echo "  --enable-libssh2         enable ssh block device support"
+ echo "  --disable-vhdx           disables support for the Microsoft VHDX image format"
+ echo "  --enable-vhdx            enable support for the Microsoft VHDX image format"
  echo ""
 +# for TIZEN-maru
 +echo "TIZEN-maru options:"
 +echo "  --enable-maru            enable maru board"
 +echo "  --enable-shm             enable shared memory for framebuffer"
  echo "NOTE: The object files are built at the place where configure is launched"
  exit 1
  fi
@@@ -1281,6 -1272,7 +1342,7 @@@ gcc_flags="-Wformat-security -Wformat-y
  gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
  gcc_flags="-Wendif-labels $gcc_flags"
  gcc_flags="-Wno-initializer-overrides $gcc_flags"
+ gcc_flags="-Wno-string-plus-int $gcc_flags"
  # Note that we do not add -Werror to gcc_flags here, because that would
  # enable it for all configure tests. If a configure test failed due
  # to -Werror this would just silently disable some features,
  
  if test "$pie" = ""; then
    case "$cpu-$targetos" in
-     i386-Linux|x86_64-Linux|i386-OpenBSD|x86_64-OpenBSD)
+     i386-Linux|x86_64-Linux|x32-Linux|i386-OpenBSD|x86_64-OpenBSD)
        ;;
      *)
        pie="no"
  
  # Note that if the Python conditional here evaluates True we will exit
  # with status 1 which is a shell 'false' value.
- if ! "$python" -c 'import sys; sys.exit(sys.version_info < (2,4) or sys.version_info >= (3,))'; then
+ if ! $python -c 'import sys; sys.exit(sys.version_info < (2,4) or sys.version_info >= (3,))'; then
    error_exit "Cannot use '$python', Python 2.4 or later is required." \
        "Note that Python 3 or later is not yet supported." \
        "Use --python=/path/to/python to specify a supported Python."
  fi
  
+ # The -B switch was added in Python 2.6.
+ # If it is supplied, compiled files are not written.
+ # Use it for Python versions which support it.
+ if $python -B -c 'import sys; sys.exit(0)' 2>/dev/null; then
+   python="$python -B"
+ fi
  if test -z "${target_list+xxx}" ; then
      target_list="$default_target_list"
  else
@@@ -1464,39 -1463,27 +1533,27 @@@ feature_not_found() 
        "configure was not able to find it"
  }
  
- if test -z "$cross_prefix" ; then
  # ---
  # big/little endian test
  cat > $TMPC << EOF
- #include <inttypes.h>
- int main(void) {
-         volatile uint32_t i=0x01234567;
-         return (*((uint8_t*)(&i))) == 0x67;
+ short big_endian[] = { 0x4269, 0x4765, 0x4e64, 0x4961, 0x4e00, 0, };
+ short little_endian[] = { 0x694c, 0x7454, 0x654c, 0x6e45, 0x6944, 0x6e41, 0, };
+ extern int foo(short *, short *);
+ int main(int argc, char *argv[]) {
+     return foo(big_endian, little_endian);
  }
  EOF
  
- if compile_prog "" "" ; then
- $TMPE && bigendian="yes"
- else
- echo big/little test failed
- fi
- else
- # if cross compiling, cannot launch a program, so make a static guess
- case "$cpu" in
-   arm)
-     # ARM can be either way; ask the compiler which one we are
-     if check_define __ARMEB__; then
-       bigendian=yes
+ if compile_object ; then
+     if grep -q BiGeNdIaN $TMPO ; then
+         bigendian="yes"
+     elif grep -q LiTtLeEnDiAn $TMPO ; then
+         bigendian="no"
+     else
+         echo big/little test failed
      fi
-   ;;
-   hppa|m68k|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64)
-     bigendian=yes
-   ;;
- esac
+ else
+     echo big/little test failed
  fi
  
  ##########################################
@@@ -1546,7 -1533,7 +1603,7 @@@ libs_softmmu="$libs_softmmu -lz
  # libseccomp check
  
  if test "$seccomp" != "no" ; then
-     if $pkg_config --atleast-version=2.1.0 libseccomp --modversion >/dev/null 2>&1; then
+     if $pkg_config --atleast-version=2.1.0 libseccomp; then
          libs_softmmu="$libs_softmmu `$pkg_config --libs libseccomp`"
          QEMU_CFLAGS="$QEMU_CFLAGS `$pkg_config --cflags libseccomp`"
        seccomp="yes"
@@@ -1780,10 -1767,10 +1837,10 @@@ if test "$gtk" != "no"; the
          fi
          gtk="no"
      else
-       gtk_cflags=`$pkg_config --cflags $gtkpackage 2>/dev/null`
-       gtk_libs=`$pkg_config --libs $gtkpackage 2>/dev/null`
-       vte_cflags=`$pkg_config --cflags $vtepackage 2>/dev/null`
-       vte_libs=`$pkg_config --libs $vtepackage 2>/dev/null`
+       gtk_cflags=`$pkg_config --cflags $gtkpackage`
+       gtk_libs=`$pkg_config --libs $gtkpackage`
+       vte_cflags=`$pkg_config --cflags $vtepackage`
+       vte_libs=`$pkg_config --libs $vtepackage`
        libs_softmmu="$gtk_libs $vte_libs $libs_softmmu"
        gtk="yes"
      fi
@@@ -1798,7 -1785,7 +1855,7 @@@ if test "`basename $sdl_config`" != sdl
    sdl_config=sdl-config
  fi
  
- if $pkg_config sdl --modversion >/dev/null 2>&1; then
+ if $pkg_config sdl --exists; then
    sdlconfig="$pkg_config sdl"
    _sdlversion=`$sdlconfig --modversion 2>/dev/null | sed 's/[^0-9]//g'`
  elif has ${sdl_config}; then
@@@ -1984,9 -1971,9 +2041,9 @@@ int main(void) 
      return png_ptr != 0;
  }
  EOF
-   if $pkg_config libpng --modversion >/dev/null 2>&1; then
-     vnc_png_cflags=`$pkg_config libpng --cflags 2> /dev/null`
-     vnc_png_libs=`$pkg_config libpng --libs 2> /dev/null`
+   if $pkg_config libpng --exists; then
+     vnc_png_cflags=`$pkg_config libpng --cflags`
+     vnc_png_libs=`$pkg_config libpng --libs`
    else
      vnc_png_cflags=""
      vnc_png_libs="-lpng"
    fi
  fi
  
+ if test "$vhdx" = "yes" ; then
+     if test "$uuid" = "no" ; then
+         error_exit "uuid required for VHDX support"
+     fi
+ elif test "$vhdx" != "no" ; then
+     if test "$uuid" = "yes" ; then
+         vhdx=yes
+     else
+         vhdx=no
+     fi
+ fi
  ##########################################
  # xfsctl() probe, used for raw-posix
  if test "$xfs" != "no" ; then
  ##########################################
  # curl probe
  if test "$curl" != "no" ; then
-   if $pkg_config libcurl --modversion >/dev/null 2>&1; then
+   if $pkg_config libcurl --exists; then
      curlconfig="$pkg_config libcurl"
    else
      curlconfig=curl-config
@@@ -2315,10 -2314,9 +2384,9 @@@ if test "$mingw32" = yes; the
  else
      glib_req_ver=2.12
  fi
- if $pkg_config --atleast-version=$glib_req_ver gthread-2.0 > /dev/null 2>&1
- then
-     glib_cflags=`$pkg_config --cflags gthread-2.0 2>/dev/null`
-     glib_libs=`$pkg_config --libs gthread-2.0 2>/dev/null`
+ if $pkg_config --atleast-version=$glib_req_ver gthread-2.0; then
+     glib_cflags=`$pkg_config --cflags gthread-2.0`
+     glib_libs=`$pkg_config --libs gthread-2.0`
      LIBS="$glib_libs $LIBS"
      libs_qga="$glib_libs $libs_qga"
  else
@@@ -2347,8 -2345,8 +2415,8 @@@ if test "$pixman" = "none"; the
    pixman_cflags=
    pixman_libs=
  elif test "$pixman" = "system"; then
-   pixman_cflags=`$pkg_config --cflags pixman-1 2>/dev/null`
-   pixman_libs=`$pkg_config --libs pixman-1 2>/dev/null`
+   pixman_cflags=`$pkg_config --cflags pixman-1`
+   pixman_libs=`$pkg_config --libs pixman-1`
  else
    if test ! -d ${source_path}/pixman/pixman; then
      error_exit "pixman not present. Your options:" \
  # libssh2 probe
  min_libssh2_version=1.2.8
  if test "$libssh2" != "no" ; then
-   if $pkg_config --atleast-version=$min_libssh2_version libssh2 >/dev/null 2>&1
-   then
+   if $pkg_config --atleast-version=$min_libssh2_version libssh2; then
      libssh2_cflags=`$pkg_config libssh2 --cflags`
      libssh2_libs=`$pkg_config libssh2 --libs`
      libssh2=yes
  fdt_required=no
  for target in $target_list; do
    case $target in
-     arm*-softmmu|ppc*-softmmu|microblaze*-softmmu)
+     aarch64*-softmmu|arm*-softmmu|ppc*-softmmu|microblaze*-softmmu)
        fdt_required=yes
      ;;
    esac
  ##########################################
  # glusterfs probe
  if test "$glusterfs" != "no" ; then
-   if $pkg_config --atleast-version=3 glusterfs-api >/dev/null 2>&1; then
+   if $pkg_config --atleast-version=3 glusterfs-api; then
      glusterfs="yes"
-     glusterfs_cflags=`$pkg_config --cflags glusterfs-api 2>/dev/null`
-     glusterfs_libs=`$pkg_config --libs glusterfs-api 2>/dev/null`
+     glusterfs_cflags=`$pkg_config --cflags glusterfs-api`
+     glusterfs_libs=`$pkg_config --libs glusterfs-api`
      CFLAGS="$CFLAGS $glusterfs_cflags"
      libs_tools="$glusterfs_libs $libs_tools"
      libs_softmmu="$glusterfs_libs $libs_softmmu"
-     if $pkg_config --atleast-version=5 glusterfs-api >/dev/null 2>&1; then
+     if $pkg_config --atleast-version=5 glusterfs-api; then
        glusterfs_discard="yes"
      fi
    else
@@@ -2895,6 -2892,37 +2962,37 @@@ if compile_prog "" "" ; the
    dup3=yes
  fi
  
+ # check for ppoll support
+ ppoll=no
+ cat > $TMPC << EOF
+ #include <poll.h>
+ int main(void)
+ {
+     struct pollfd pfd = { .fd = 0, .events = 0, .revents = 0 };
+     ppoll(&pfd, 1, 0, 0);
+     return 0;
+ }
+ EOF
+ if compile_prog "" "" ; then
+   ppoll=yes
+ fi
+ # check for prctl(PR_SET_TIMERSLACK , ... ) support
+ prctl_pr_set_timerslack=no
+ cat > $TMPC << EOF
+ #include <sys/prctl.h>
+ int main(void)
+ {
+     prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0);
+     return 0;
+ }
+ EOF
+ if compile_prog "" "" ; then
+   prctl_pr_set_timerslack=yes
+ fi
  # check for epoll support
  epoll=no
  cat > $TMPC << EOF
@@@ -3005,10 -3033,10 +3103,10 @@@ if test "$libiscsi" != "no" ; the
  #include <iscsi/iscsi.h>
  int main(void) { iscsi_unmap_sync(NULL,0,0,0,NULL,0); return 0; }
  EOF
-   if $pkg_config --atleast-version=1.7.0 libiscsi --modversion >/dev/null 2>&1; then
+   if $pkg_config --atleast-version=1.7.0 libiscsi; then
      libiscsi="yes"
-     libiscsi_cflags=$($pkg_config --cflags libiscsi 2>/dev/null)
-     libiscsi_libs=$($pkg_config --libs libiscsi 2>/dev/null)
+     libiscsi_cflags=$($pkg_config --cflags libiscsi)
+     libiscsi_libs=$($pkg_config --libs libiscsi)
      CFLAGS="$CFLAGS $libiscsi_cflags"
      LIBS="$LIBS $libiscsi_libs"
    elif compile_prog "" "-liscsi" ; then
@@@ -3075,8 -3103,8 +3173,8 @@@ int main(void) { spice_server_new(); re
  EOF
    spice_cflags=$($pkg_config --cflags spice-protocol spice-server 2>/dev/null)
    spice_libs=$($pkg_config --libs spice-protocol spice-server 2>/dev/null)
-   if $pkg_config --atleast-version=0.12.0 spice-server >/dev/null 2>&1 && \
-      $pkg_config --atleast-version=0.12.3 spice-protocol > /dev/null 2>&1 && \
+   if $pkg_config --atleast-version=0.12.0 spice-server && \
+      $pkg_config --atleast-version=0.12.3 spice-protocol && \
       compile_prog "$spice_cflags" "$spice_libs" ; then
      spice="yes"
      libs_softmmu="$libs_softmmu $spice_libs"
@@@ -3111,7 -3139,7 +3209,7 @@@ EO
          test_cflags="-Werror $test_cflags"
      fi
      if test -n "$libtool" &&
-             $pkg_config --atleast-version=3.12.8 nss >/dev/null 2>&1 && \
+        $pkg_config --atleast-version=3.12.8 nss && \
        compile_prog "$test_cflags" "$libcacard_libs"; then
          smartcard_nss="yes"
          QEMU_CFLAGS="$QEMU_CFLAGS $libcacard_cflags"
  
  # check for libusb
  if test "$libusb" != "no" ; then
-     if $pkg_config --atleast-version=1.0.13 libusb-1.0 >/dev/null 2>&1 ; then
+     if $pkg_config --atleast-version=1.0.13 libusb-1.0; then
          libusb="yes"
-       usb="libusb"
-         libusb_cflags=$($pkg_config --cflags libusb-1.0 2>/dev/null)
-         libusb_libs=$($pkg_config --libs libusb-1.0 2>/dev/null)
+         libusb_cflags=$($pkg_config --cflags libusb-1.0)
+         libusb_libs=$($pkg_config --libs libusb-1.0)
          QEMU_CFLAGS="$QEMU_CFLAGS $libusb_cflags"
          libs_softmmu="$libs_softmmu $libusb_libs"
      else
  
  # check for usbredirparser for usb network redirection support
  if test "$usb_redir" != "no" ; then
-     if $pkg_config --atleast-version=0.6 libusbredirparser-0.5 >/dev/null 2>&1 ; then
+     if $pkg_config --atleast-version=0.6 libusbredirparser-0.5; then
          usb_redir="yes"
-         usb_redir_cflags=$($pkg_config --cflags libusbredirparser-0.5 2>/dev/null)
-         usb_redir_libs=$($pkg_config --libs libusbredirparser-0.5 2>/dev/null)
+         usb_redir_cflags=$($pkg_config --cflags libusbredirparser-0.5)
+         usb_redir_libs=$($pkg_config --libs libusbredirparser-0.5)
          QEMU_CFLAGS="$QEMU_CFLAGS $usb_redir_cflags"
          libs_softmmu="$libs_softmmu $usb_redir_libs"
      else
  fi
  
  ##########################################
+ # check if we have VSS SDK headers for win
+ if test "$mingw32" = "yes" -a "$guest_agent" != "no" -a "$vss_win32_sdk" != "no" ; then
+   case "$vss_win32_sdk" in
+     "")   vss_win32_include="-I$source_path" ;;
+     *\ *) # The SDK is installed in "Program Files" by default, but we cannot
+           # handle path with spaces. So we symlink the headers into ".sdk/vss".
+           vss_win32_include="-I$source_path/.sdk/vss"
+         symlink "$vss_win32_sdk/inc" "$source_path/.sdk/vss/inc"
+         ;;
+     *)    vss_win32_include="-I$vss_win32_sdk"
+   esac
+   cat > $TMPC << EOF
+ #define __MIDL_user_allocate_free_DEFINED__
+ #include <inc/win2003/vss.h>
+ int main(void) { return VSS_CTX_BACKUP; }
+ EOF
+   if compile_prog "$vss_win32_include" "" ; then
+     guest_agent_with_vss="yes"
+     QEMU_CFLAGS="$QEMU_CFLAGS $vss_win32_include"
+     libs_qga="-lole32 -loleaut32 -lshlwapi -luuid -lstdc++ -Wl,--enable-stdcall-fixup $libs_qga"
+   else
+     if test "$vss_win32_sdk" != "" ; then
+       echo "ERROR: Please download and install Microsoft VSS SDK:"
+       echo "ERROR:   http://www.microsoft.com/en-us/download/details.aspx?id=23490"
+       echo "ERROR: On POSIX-systems, you can extract the SDK headers by:"
+       echo "ERROR:   scripts/extract-vsssdk-headers setup.exe"
+       echo "ERROR: The headers are extracted in the directory \`inc'."
+       feature_not_found "VSS support"
+     fi
+     guest_agent_with_vss="no"
+   fi
+ fi
+ ##########################################
+ # lookup Windows platform SDK (if not specified)
+ # The SDK is needed only to build .tlb (type library) file of guest agent
+ # VSS provider from the source. It is usually unnecessary because the
+ # pre-compiled .tlb file is included.
+ if test "$mingw32" = "yes" -a "$guest_agent" != "no" -a "$guest_agent_with_vss" = "yes" ; then
+   if test -z "$win_sdk"; then
+     programfiles="$PROGRAMFILES"
+     test -n "$PROGRAMW6432" && programfiles="$PROGRAMW6432"
+     if test -n "$programfiles"; then
+       win_sdk=$(ls -d "$programfiles/Microsoft SDKs/Windows/v"* | tail -1) 2>/dev/null
+     else
+       feature_not_found "Windows SDK"
+     fi
+   elif test "$win_sdk" = "no"; then
+     win_sdk=""
+   fi
+ fi
+ ##########################################
  
  ##########################################
  # check if we have fdatasync
@@@ -3468,7 -3550,7 +3620,7 @@@ if test "$gcov" = "yes" ; the
    CFLAGS="-fprofile-arcs -ftest-coverage -g $CFLAGS"
    LDFLAGS="-fprofile-arcs -ftest-coverage $LDFLAGS"
  elif test "$debug" = "no" ; then
-   CFLAGS="-O2 -D_FORTIFY_SOURCE=2 $CFLAGS"
+   CFLAGS="-O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $CFLAGS"
  fi
  
  
@@@ -3534,8 -3616,11 +3686,11 @@@ if test "$softmmu" = yes ; the
    fi
  fi
  if [ "$guest_agent" != "no" ]; then
-   if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
+   if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" -o "$mingw32" = "yes" ] ; then
        tools="qemu-ga\$(EXESUF) $tools"
+       if [ "$mingw32" = "yes" -a "$guest_agent_with_vss" = "yes" ]; then
+         tools="qga/vss-win32/qga-vss.dll qga/vss-win32/qga-vss.tlb $tools"
+       fi
        guest_agent=yes
    elif [ "$guest_agent" != yes ]; then
        guest_agent=no
  if test "$pie" = "no" ; then
    textseg_addr=
    case "$cpu" in
-     arm | hppa | i386 | m68k | ppc | ppc64 | s390* | sparc | sparc64 | x86_64)
+     arm | hppa | i386 | m68k | ppc | ppc64 | s390* | sparc | sparc64 | x86_64 | x32)
        textseg_addr=0x60000000
        ;;
      mips)
@@@ -3606,11 -3691,14 +3761,14 @@@ echo "Manual directory  `eval echo $man
  echo "ELF interp prefix $interp_prefix"
  else
  echo "local state directory   queried at runtime"
+ echo "Windows SDK       $win_sdk"
  fi
  echo "Source path       $source_path"
  echo "C compiler        $cc"
  echo "Host C compiler   $host_cc"
+ echo "C++ compiler      $cxx"
  echo "Objective-C compiler $objcc"
+ echo "ARFLAGS           $ARFLAGS"
  echo "CFLAGS            $CFLAGS"
  echo "QEMU_CFLAGS       $QEMU_CFLAGS"
  echo "LDFLAGS           $LDFLAGS"
@@@ -3642,7 -3730,6 +3800,6 @@@ echo "mingw32 support   $mingw32
  echo "Audio drivers     $audio_drv_list"
  echo "Block whitelist (rw) $block_drv_rw_whitelist"
  echo "Block whitelist (ro) $block_drv_ro_whitelist"
- echo "Mixer emulation   $mixemu"
  echo "VirtFS support    $virtfs"
  echo "VNC support       $vnc"
  if test "$vnc" = "yes" ; then
@@@ -3668,8 -3755,6 +3825,8 @@@ echo "Linux AIO support $linux_aio
  echo "ATTR/XATTR support $attr"
  echo "Install blobs     $blobs"
  echo "KVM support       $kvm"
 +echo "HAX support       $hax"
 +echo "GL support        $gl"
  echo "RDMA support      $rdma"
  echo "TCG interpreter   $tcg_interpreter"
  echo "fdt support       $fdt"
@@@ -3690,14 -3775,10 +3847,15 @@@ echo "xfsctl support    $xfs
  echo "nss used          $smartcard_nss"
  echo "libusb            $libusb"
  echo "usb net redir     $usb_redir"
 +echo "OpenGL support    $opengl"
 +echo "EFence support    $efence"
 +echo "YaGL support      $yagl"
 +echo "YaGL stats        $yagl_stats"
  echo "GLX support       $glx"
 +echo "VIGS support      $vigs"
  echo "libiscsi support  $libiscsi"
  echo "build guest agent $guest_agent"
+ echo "QGA VSS support   $guest_agent_with_vss"
  echo "seccomp support   $seccomp"
  echo "coroutine backend $coroutine"
  echo "coroutine pool    $coroutine_pool"
@@@ -3709,12 -3790,8 +3867,13 @@@ echo "TPM support       $tpm
  echo "libssh2 support   $libssh2"
  echo "TPM passthrough   $tpm_passthrough"
  echo "QOM debugging     $qom_cast_debug"
+ echo "vhdx              $vhdx"
  
 +# for TIZEN-maru
 +echo "TIZEN-maru support $maru"
 +echo "TIZEN-maru shared framebuffer support $shm"
 +#
 +
  if test "$sdl_too_old" = "yes"; then
  echo "-> Your SDL version is too old - please upgrade to have SDL support"
  fi
@@@ -3724,8 -3801,6 +3883,6 @@@ config_host_mak="config-host.mak
  echo "# Automatically generated by configure - do not modify" >config-all-disas.mak
  
  echo "# Automatically generated by configure - do not modify" > $config_host_mak
- printf "# Configured with:" >> $config_host_mak
- printf " '%s'" "$0" "$@" >> $config_host_mak
  echo >> $config_host_mak
  
  echo all: >> $config_host_mak
@@@ -3750,14 -3825,6 +3907,6 @@@ echo "libs_softmmu=$libs_softmmu" >> $c
  
  echo "ARCH=$ARCH" >> $config_host_mak
  
- case "$cpu" in
-   arm|i386|x86_64|ppc|aarch64)
-     # The TCG interpreter currently does not support ld/st optimization.
-     if test "$tcg_interpreter" = "no" ; then
-         echo "CONFIG_QEMU_LDST_OPTIMIZATION=y" >> $config_host_mak
-     fi
-   ;;
- esac
  if test "$debug_tcg" = "yes" ; then
    echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
  fi
@@@ -3778,6 -3845,10 +3927,10 @@@ if test "$mingw32" = "yes" ; the
    version_micro=0
    echo "CONFIG_FILEVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> $config_host_mak
    echo "CONFIG_PRODUCTVERSION=$version_major,$version_minor,$version_subminor,$version_micro" >> $config_host_mak
+   if test "$guest_agent_with_vss" = "yes" ; then
+     echo "CONFIG_QGA_VSS=y" >> $config_host_mak
+     echo "WIN_SDK=\"$win_sdk\"" >> $config_host_mak
+   fi
  else
    echo "CONFIG_POSIX=y" >> $config_host_mak
  fi
@@@ -3836,9 -3907,6 +3989,6 @@@ if test "$audio_win_int" = "yes" ; the
  fi
  echo "CONFIG_BDRV_RW_WHITELIST=$block_drv_rw_whitelist" >> $config_host_mak
  echo "CONFIG_BDRV_RO_WHITELIST=$block_drv_ro_whitelist" >> $config_host_mak
- if test "$mixemu" = "yes" ; then
-   echo "CONFIG_MIXEMU=y" >> $config_host_mak
- fi
  if test "$vnc" = "yes" ; then
    echo "CONFIG_VNC=y" >> $config_host_mak
  fi
  if test "$dup3" = "yes" ; then
    echo "CONFIG_DUP3=y" >> $config_host_mak
  fi
+ if test "$ppoll" = "yes" ; then
+   echo "CONFIG_PPOLL=y" >> $config_host_mak
+ fi
+ if test "$prctl_pr_set_timerslack" = "yes" ; then
+   echo "CONFIG_PRCTL_PR_SET_TIMERSLACK=y" >> $config_host_mak
+ fi
  if test "$epoll" = "yes" ; then
    echo "CONFIG_EPOLL=y" >> $config_host_mak
  fi
@@@ -4010,35 -4084,6 +4166,35 @@@ if test "$spice" = "yes" ; the
    echo "CONFIG_SPICE=y" >> $config_host_mak
  fi
  
 +if test "$efence" = "yes" ; then
 +  echo "CONFIG_EFENCE=y" >> $config_host_mak
 +fi
 +
 +if test "$yagl" = "yes" ; then
 +  echo "CONFIG_YAGL=y" >> $config_host_mak
 +  if test "$linux" = "yes" ; then
 +    echo -n;
 +  elif test "$mingw32" = "yes" ; then
 +    echo -n;
 +  elif test "$darwin" = "yes" ; then
 +    echo -n;  else
 +    echo "ERROR: YaGL is not available on $targetos"
 +    exit 1
 +  fi
 +fi
 +
 +if test "$yagl_stats" = "yes" ; then
 +  echo "CONFIG_YAGL_STATS=y" >> $config_host_mak
 +fi
 +
 +if test "$vigs" = "yes" ; then
 +  echo "CONFIG_VIGS=y" >> $config_host_mak
 +fi
 +
 +if test "$smartcard" = "yes" ; then
 +  echo "CONFIG_SMARTCARD=y" >> $config_host_mak
 +fi
 +
  if test "$smartcard_nss" = "yes" ; then
    echo "CONFIG_SMARTCARD_NSS=y" >> $config_host_mak
    echo "libcacard_libs=$libcacard_libs" >> $config_host_mak
@@@ -4138,36 -4183,17 +4294,27 @@@ if test "$virtio_blk_data_plane" = "yes
    echo 'CONFIG_VIRTIO_BLK_DATA_PLANE=$(CONFIG_VIRTIO)' >> $config_host_mak
  fi
  
+ if test "$vhdx" = "yes" ; then
+   echo "CONFIG_VHDX=y" >> $config_host_mak
+ fi
  # USB host support
- case "$usb" in
- linux)
-   echo "HOST_USB=linux legacy" >> $config_host_mak
- ;;
- bsd)
-   echo "HOST_USB=bsd" >> $config_host_mak
- ;;
- libusb)
-   if test "$linux" = "yes"; then
-     echo "HOST_USB=libusb linux legacy" >> $config_host_mak
-   else
-     echo "HOST_USB=libusb legacy" >> $config_host_mak
-   fi
- ;;
- *)
+ if test "$libusb" = "yes"; then
+   echo "HOST_USB=libusb legacy" >> $config_host_mak
+ else
    echo "HOST_USB=stub" >> $config_host_mak
- ;;
- esac
+ fi
  
 +# for TIZEN-maru
 +if test "$maru" = "yes" ; then
 +  echo "CONFIG_MARU=y" >> $config_host_mak
 +fi
 +if test "$shm" = "yes" ; then
 +  echo "CONFIG_USE_SHM=y" >> $config_host_mak
 +fi
 +if test "$gl" = "yes" ; then
 +  echo "CONFIG_GL_BACKEND=y" >> $config_host_mak
 +fi
  # TPM passthrough support?
  if test "$tpm" = "yes"; then
    echo 'CONFIG_TPM=$(CONFIG_SOFTMMU)' >> $config_host_mak
@@@ -4213,15 -4239,6 +4360,15 @@@ echo "CONFIG_TRACE_FILE=$trace_file" >
  if test "$trace_default" = "yes"; then
    echo "CONFIG_TRACE_DEFAULT=y" >> $config_host_mak
  fi
 +if test "$hax" = "yes" ; then
 +  if test "$mingw32" = "yes" ; then
 +    echo "CONFIG_HAX_BACKEND=y" >> $config_host_mak
 +  elif test "$darwin" = "yes" ; then
 +    echo "CONFIG_HAX_BACKEND=y" >> $config_host_mak
 +  else
 +    hax="no"
 +  fi
 +fi
  
  if test "$rdma" = "yes" ; then
    echo "CONFIG_RDMA=y" >> $config_host_mak
@@@ -4233,7 -4250,7 +4380,7 @@@ elif test "$ARCH" = "sparc64" ; the
    QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/sparc $QEMU_INCLUDES"
  elif test "$ARCH" = "s390x" ; then
    QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/s390 $QEMU_INCLUDES"
- elif test "$ARCH" = "x86_64" ; then
+ elif test "$ARCH" = "x86_64" -o "$ARCH" = "x32" ; then
    QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/i386 $QEMU_INCLUDES"
  else
    QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/\$(ARCH) $QEMU_INCLUDES"
  fi
  echo "PYTHON=$python" >> $config_host_mak
  echo "CC=$cc" >> $config_host_mak
+ if $iasl -h > /dev/null 2>&1; then
+   echo "IASL=$iasl" >> $config_host_mak
+ fi
  echo "CC_I386=$cc_i386" >> $config_host_mak
  echo "HOST_CC=$host_cc" >> $config_host_mak
+ echo "CXX=$cxx" >> $config_host_mak
  echo "OBJCC=$objcc" >> $config_host_mak
  echo "AR=$ar" >> $config_host_mak
+ echo "ARFLAGS=$ARFLAGS" >> $config_host_mak
  echo "AS=$as" >> $config_host_mak
  echo "CPP=$cpp" >> $config_host_mak
  echo "OBJCOPY=$objcopy" >> $config_host_mak
  if test "$linux" = "yes" ; then
    mkdir -p linux-headers
    case "$cpu" in
-   i386|x86_64)
+   i386|x86_64|x32)
      linux_arch=x86
      ;;
    ppcemb|ppc|ppc64)
@@@ -4381,6 -4403,11 +4533,11 @@@ case "$target_name" i
      bflt="yes"
      gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
    ;;
+   aarch64)
+     TARGET_BASE_ARCH=arm
+     bflt="yes"
+     gdb_xml_files="aarch64-core.xml"
+   ;;
    cris)
    ;;
    lm32)
@@@ -4507,41 -4534,6 +4664,41 @@@ case "$target_name" i
        fi
      fi
  esac
 +case "$target_name" in
 +  i386|x86_64)
 +    echo "CONFIG_HAVE_GET_MEMORY_MAPPING=y" >> $config_target_mak
 +esac
 +if test "$hax" = "yes" ; then
 +  if test "$target_softmmu" = "yes" ; then
 +    case "$target_name" in
 +    i386|x86_64)
 +      echo "CONFIG_HAX=y" >> $config_target_mak
 +    ;;
 +    *)
 +      echo "CONFIG_NO_HAX=y" >> $config_target_mak
 +    ;;
 +    esac
 +  else
 +    echo "CONFIG_NO_HAX=y" >> $config_target_mak
 +  fi
 +fi
 +if test "$gl" = "yes" ; then
 +  case "$target_name" in
 +  i386|x86_64|arm)
 +    echo "CONFIG_GL=y" >> $config_target_mak
 +    if test "$mingw32" = "yes" ; then
 +      echo "LIBS+=-lopengl32 -lglu32" >> $config_target_mak
 +    elif test "$darwin" = "yes" ; then
 +      echo "LIBS+=-framework OpenGL -framework AGL " >> $config_target_mak
 +    else
 +      echo "LIBS+=-lGLU -ldl" >> $config_target_mak
 +    fi
 +  ;;
 +  *)
 +    echo "CONFIG_NO_GL=y" >> $config_target_mak
 +  ;;
 +  esac
 +fi
  if test "$target_bigendian" = "yes" ; then
    echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak
  fi
  cflags=""
  ldflags=""
  
 +if test "$tcg_interpreter" = "yes"; then
 +  includes="-I\$(SRC_PATH)/tcg/tci $includes"
 +elif test "$ARCH" = "sparc64" ; then
 +  includes="-I\$(SRC_PATH)/tcg/sparc $includes"
 +elif test "$ARCH" = "s390x" ; then
 +  includes="-I\$(SRC_PATH)/tcg/s390 $includes"
 +elif test "$ARCH" = "x86_64" ; then
 +  includes="-I\$(SRC_PATH)/tcg/i386 $includes"
 +else
 +  includes="-I\$(SRC_PATH)/tcg/\$(ARCH) $includes"
 +fi
 +includes="-I\$(SRC_PATH)/tcg $includes"
 +
 +if test "$linux" = "yes" ; then
 +  includes="-I\$(SRC_PATH)/linux-headers $includes"
 +fi
 +
 +if test "$target_user_only" = "yes" ; then
 +    libdis_config_mak=libdis-user/config.mak
 +else
 +    libdis_config_mak=libdis/config.mak
 +fi
 +
 +if test "$efence" = "yes" ; then
 +  echo "CONFIG_BUILD_WITH_EFENCE=y" >> $config_target_mak
 +  echo "LIBS+=-lefence" >> $config_target_mak
 +fi
 +
 +if test "$yagl" = "yes" ; then
 +  echo "CONFIG_BUILD_YAGL=y" >> $config_target_mak
 +fi
 +
 +if test "$vigs" = "yes" ; then
 +  echo "CONFIG_BUILD_VIGS=y" >> $config_target_mak
 +fi
 +
  for i in $ARCH $TARGET_BASE_ARCH ; do
    case "$i" in
    alpha)
      echo "CONFIG_HPPA_DIS=y"  >> $config_target_mak
      echo "CONFIG_HPPA_DIS=y"  >> config-all-disas.mak
    ;;
-   i386|x86_64)
+   i386|x86_64|x32)
      echo "CONFIG_I386_DIS=y"  >> $config_target_mak
      echo "CONFIG_I386_DIS=y"  >> config-all-disas.mak
    ;;
@@@ -4698,20 -4654,6 +4855,20 @@@ alpha
  ;;
  esac
  
 +if test "$target_softmmu" = "yes" ; then
 +  case "$TARGET_BASE_ARCH" in
 +  arm)
 +    cflags="-DHAS_AUDIO -DHAS_AUDIO_CHOICE $cflags"
 +  ;;
 +  lm32)
 +    cflags="-DHAS_AUDIO $cflags"
 +  ;;
 +  i386|mips|ppc)
 +    cflags="-DHAS_AUDIO -DHAS_AUDIO_CHOICE $cflags"
 +  ;;
 +  esac
 +fi
 +
  if test "$gprof" = "yes" ; then
    echo "TARGET_GPROF=yes" >> $config_target_mak
    if test "$target_linux_user" = "yes" ; then
@@@ -4746,7 -4688,8 +4903,8 @@@ if [ "$dtc_internal" = "yes" ]; the
  fi
  
  # build tree in object directory in case the source is not in the current directory
- DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-schema tests/tcg/xtensa"
+ DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-schema tests/tcg/xtensa tests/qemu-iotests"
+ DIRS="$DIRS fsdev"
  DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw"
  DIRS="$DIRS roms/seabios roms/vgabios"
  DIRS="$DIRS qapi-generated"
@@@ -4786,7 -4729,7 +4944,7 @@@ for rom in seabios vgabios ; d
      echo "BCC=bcc" >> $config_mak
      echo "CPP=$cpp" >> $config_mak
      echo "OBJCOPY=objcopy" >> $config_mak
-     echo "IASL=iasl" >> $config_mak
+     echo "IASL=$iasl" >> $config_mak
      echo "LD=$ld" >> $config_mak
  done
  
diff --combined cpu-exec.c
@@@ -22,7 -22,6 +22,7 @@@
  #include "tcg.h"
  #include "qemu/atomic.h"
  #include "sysemu/qtest.h"
 +#include "sysemu/hax.h"
  
  bool qemu_cpu_has_work(CPUState *cpu)
  {
@@@ -54,7 -53,7 +54,7 @@@ void cpu_resume_from_signal(CPUArchStat
  static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr)
  {
      CPUArchState *env = cpu->env_ptr;
-     tcg_target_ulong next_tb = tcg_qemu_tb_exec(env, tb_ptr);
+     uintptr_t next_tb = tcg_qemu_tb_exec(env, tb_ptr);
      if ((next_tb & TB_EXIT_MASK) > TB_EXIT_IDX1) {
          /* We didn't start executing this TB (eg because the instruction
           * counter hit zero); we must restore the guest PC to the address
@@@ -200,25 -199,6 +200,25 @@@ static void cpu_handle_debug_exception(
  
  volatile sig_atomic_t exit_request;
  
 +/*
 + * QEMU emulate can happens because of MMIO or emulation mode, i.e. non-PG mode,
 + * when it's because of MMIO, the MMIO, the interrupt should not be emulated,
 + * because MMIO is emulated for only one instruction now and then back to
 + * HAX kernel
 + */
 +static int need_handle_intr_request(CPUState *cpu)
 +{
 +#ifdef CONFIG_HAX
 +    CPUArchState *env = cpu->env_ptr;
 +    if (!hax_enabled() || hax_vcpu_emulation_mode(env))
 +        return cpu->interrupt_request;
 +    return 0;
 +#else
 +    return cpu->interrupt_request;
 +#endif
 +}
 +
 +
  int cpu_exec(CPUArchState *env)
  {
      CPUState *cpu = ENV_GET_CPU(env);
      int ret, interrupt_request;
      TranslationBlock *tb;
      uint8_t *tc_ptr;
-     tcg_target_ulong next_tb;
+     uintptr_t next_tb;
  
      if (cpu->halted) {
          if (!cpu_has_work(cpu)) {
                  }
              }
  
 +#ifdef CONFIG_HAX
 +            if (hax_enabled() && !hax_vcpu_exec(env))
 +                longjmp(env->jmp_env, 1);
 +#endif
 +
              next_tb = 0; /* force lookup of first TB */
              for(;;) {
 -                interrupt_request = cpu->interrupt_request;
 +                interrupt_request = need_handle_intr_request(cpu);
                  if (unlikely(interrupt_request)) {
                      if (unlikely(cpu->singlestep_enabled & SSTEP_NOIRQ)) {
                          /* Mask out external interrupts for this step. */
                              cpu_loop_exit(env);
                      } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
                              do_cpu_sipi(x86_env_get_cpu(env));
 +
                      } else if (env->hflags2 & HF2_GIF_MASK) {
                          if ((interrupt_request & CPU_INTERRUPT_SMI) &&
                              !(env->hflags & HF_SMM_MASK)) {
                              cpu_svm_check_intercept_param(env, SVM_EXIT_SMI,
                                                            0);
                              cpu->interrupt_request &= ~CPU_INTERRUPT_SMI;
 +#ifdef CONFIG_HAX
 +                            if (hax_enabled())
 +                                env->hax_vcpu->resync = 1;
 +#endif
                              do_smm_enter(x86_env_get_cpu(env));
                              next_tb = 0;
                          } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
                      }
                  }
                  cpu->current_tb = NULL;
 +#ifdef CONFIG_HAX
 +                if (hax_enabled() && hax_stop_emulation(env))
 +                    cpu_loop_exit(env);
 +#endif
                  /* reset soft MMU for next block (it can currently
                     only be set by a memory fault) */
              } /* for(;;) */
               * local variables as longjmp is marked 'noreturn'. */
              cpu = current_cpu;
              env = cpu->env_ptr;
+ #if !(defined(CONFIG_USER_ONLY) && \
+       (defined(TARGET_M68K) || defined(TARGET_PPC) || defined(TARGET_S390X)))
+             cc = CPU_GET_CLASS(cpu);
+ #endif
          }
      } /* for(;;) */
  
diff --combined cpus.c
--- 1/cpus.c
--- 2/cpus.c
+++ b/cpus.c
@@@ -30,7 -30,6 +30,7 @@@
  #include "exec/gdbstub.h"
  #include "sysemu/dma.h"
  #include "sysemu/kvm.h"
 +#include "sysemu/hax.h"
  #include "qmp-commands.h"
  
  #include "qemu/thread.h"
@@@ -38,6 -37,7 +38,7 @@@
  #include "sysemu/qtest.h"
  #include "qemu/main-loop.h"
  #include "qemu/bitmap.h"
+ #include "qemu/seqlock.h"
  
  #ifndef _WIN32
  #include "qemu/compatfd.h"
  
  static CPUState *next_cpu;
  
+ bool cpu_is_stopped(CPUState *cpu)
+ {
+     return cpu->stopped || !runstate_is_running();
+ }
  static bool cpu_thread_is_idle(CPUState *cpu)
  {
      if (cpu->stop || cpu->queued_work_first) {
          return false;
      }
-     if (cpu->stopped || !runstate_is_running()) {
+     if (cpu_is_stopped(cpu)) {
          return true;
      }
      if (!cpu->halted || qemu_cpu_has_work(cpu) ||
 -        kvm_halt_in_kernel()) {
 +        kvm_halt_in_kernel() || hax_enabled()) {
          return false;
      }
      return true;
@@@ -82,7 -87,7 +88,7 @@@ static bool all_cpu_threads_idle(void
  {
      CPUState *cpu;
  
-     for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
+     CPU_FOREACH(cpu) {
          if (!cpu_thread_is_idle(cpu)) {
              return false;
          }
  /***********************************************************/
  /* guest cycle counter */
  
+ /* Protected by TimersState seqlock */
+ /* Compensate for varying guest execution speed.  */
+ static int64_t qemu_icount_bias;
+ static int64_t vm_clock_warp_start;
  /* Conversion factor from emulated instructions to virtual clock ticks.  */
  static int icount_time_shift;
  /* Arbitrarily pick 1MIPS as the minimum allowable speed.  */
  #define MAX_ICOUNT_SHIFT 10
- /* Compensate for varying guest execution speed.  */
- static int64_t qemu_icount_bias;
+ /* Only written by TCG thread */
+ static int64_t qemu_icount;
  static QEMUTimer *icount_rt_timer;
  static QEMUTimer *icount_vm_timer;
  static QEMUTimer *icount_warp_timer;
- static int64_t vm_clock_warp_start;
- static int64_t qemu_icount;
  
  typedef struct TimersState {
+     /* Protected by BQL.  */
      int64_t cpu_ticks_prev;
      int64_t cpu_ticks_offset;
+     /* cpu_clock_offset can be read out of BQL, so protect it with
+      * this lock.
+      */
+     QemuSeqLock vm_clock_seqlock;
      int64_t cpu_clock_offset;
      int32_t cpu_ticks_enabled;
      int64_t dummy;
  static TimersState timers_state;
  
  /* Return the virtual CPU time, based on the instruction counter.  */
int64_t cpu_get_icount(void)
static int64_t cpu_get_icount_locked(void)
  {
      int64_t icount;
      CPUState *cpu = current_cpu;
      return qemu_icount_bias + (icount << icount_time_shift);
  }
  
+ int64_t cpu_get_icount(void)
+ {
+     int64_t icount;
+     unsigned start;
+     do {
+         start = seqlock_read_begin(&timers_state.vm_clock_seqlock);
+         icount = cpu_get_icount_locked();
+     } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start));
+     return icount;
+ }
  /* return the host CPU cycle counter and handle stop/restart */
+ /* Caller must hold the BQL */
  int64_t cpu_get_ticks(void)
  {
+     int64_t ticks;
      if (use_icount) {
          return cpu_get_icount();
      }
-     if (!timers_state.cpu_ticks_enabled) {
-         return timers_state.cpu_ticks_offset;
-     } else {
-         int64_t ticks;
-         ticks = cpu_get_real_ticks();
-         if (timers_state.cpu_ticks_prev > ticks) {
-             /* Note: non increasing ticks may happen if the host uses
-                software suspend */
-             timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
-         }
-         timers_state.cpu_ticks_prev = ticks;
-         return ticks + timers_state.cpu_ticks_offset;
+     ticks = timers_state.cpu_ticks_offset;
+     if (timers_state.cpu_ticks_enabled) {
+         ticks += cpu_get_real_ticks();
+     }
+     if (timers_state.cpu_ticks_prev > ticks) {
+         /* Note: non increasing ticks may happen if the host uses
+            software suspend */
+         timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
+         ticks = timers_state.cpu_ticks_prev;
      }
+     timers_state.cpu_ticks_prev = ticks;
+     return ticks;
+ }
+ static int64_t cpu_get_clock_locked(void)
+ {
+     int64_t ticks;
+     ticks = timers_state.cpu_clock_offset;
+     if (timers_state.cpu_ticks_enabled) {
+         ticks += get_clock();
+     }
+     return ticks;
  }
  
  /* return the host CPU monotonic timer and handle stop/restart */
  int64_t cpu_get_clock(void)
  {
      int64_t ti;
-     if (!timers_state.cpu_ticks_enabled) {
-         return timers_state.cpu_clock_offset;
-     } else {
-         ti = get_clock();
-         return ti + timers_state.cpu_clock_offset;
-     }
+     unsigned start;
+     do {
+         start = seqlock_read_begin(&timers_state.vm_clock_seqlock);
+         ti = cpu_get_clock_locked();
+     } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start));
+     return ti;
  }
  
- /* enable cpu_get_ticks() */
+ /* enable cpu_get_ticks()
+  * Caller must hold BQL which server as mutex for vm_clock_seqlock.
+  */
  void cpu_enable_ticks(void)
  {
+     /* Here, the really thing protected by seqlock is cpu_clock_offset. */
+     seqlock_write_lock(&timers_state.vm_clock_seqlock);
      if (!timers_state.cpu_ticks_enabled) {
          timers_state.cpu_ticks_offset -= cpu_get_real_ticks();
          timers_state.cpu_clock_offset -= get_clock();
          timers_state.cpu_ticks_enabled = 1;
      }
+     seqlock_write_unlock(&timers_state.vm_clock_seqlock);
  }
  
  /* disable cpu_get_ticks() : the clock is stopped. You must not call
-    cpu_get_ticks() after that.  */
+  * cpu_get_ticks() after that.
+  * Caller must hold BQL which server as mutex for vm_clock_seqlock.
+  */
  void cpu_disable_ticks(void)
  {
+     /* Here, the really thing protected by seqlock is cpu_clock_offset. */
+     seqlock_write_lock(&timers_state.vm_clock_seqlock);
      if (timers_state.cpu_ticks_enabled) {
-         timers_state.cpu_ticks_offset = cpu_get_ticks();
-         timers_state.cpu_clock_offset = cpu_get_clock();
+         timers_state.cpu_ticks_offset += cpu_get_real_ticks();
+         timers_state.cpu_clock_offset = cpu_get_clock_locked();
          timers_state.cpu_ticks_enabled = 0;
      }
+     seqlock_write_unlock(&timers_state.vm_clock_seqlock);
  }
  
  /* Correlation between real and virtual time is always going to be
@@@ -197,13 -255,19 +256,19 @@@ static void icount_adjust(void
      int64_t cur_time;
      int64_t cur_icount;
      int64_t delta;
+     /* Protected by TimersState mutex.  */
      static int64_t last_delta;
      /* If the VM is not running, then do nothing.  */
      if (!runstate_is_running()) {
          return;
      }
-     cur_time = cpu_get_clock();
-     cur_icount = qemu_get_clock_ns(vm_clock);
+     seqlock_write_lock(&timers_state.vm_clock_seqlock);
+     cur_time = cpu_get_clock_locked();
+     cur_icount = cpu_get_icount_locked();
      delta = cur_icount - cur_time;
      /* FIXME: This is a very crude algorithm, somewhat prone to oscillation.  */
      if (delta > 0
      }
      last_delta = delta;
      qemu_icount_bias = cur_icount - (qemu_icount << icount_time_shift);
+     seqlock_write_unlock(&timers_state.vm_clock_seqlock);
  }
  
  static void icount_adjust_rt(void *opaque)
  {
-     qemu_mod_timer(icount_rt_timer,
-                    qemu_get_clock_ms(rt_clock) + 1000);
+     timer_mod(icount_rt_timer,
+                    qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
      icount_adjust();
  }
  
  static void icount_adjust_vm(void *opaque)
  {
-     qemu_mod_timer(icount_vm_timer,
-                    qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 10);
+     timer_mod(icount_vm_timer,
+                    qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+                    get_ticks_per_sec() / 10);
      icount_adjust();
  }
  
@@@ -243,48 -309,59 +310,59 @@@ static int64_t qemu_icount_round(int64_
  
  static void icount_warp_rt(void *opaque)
  {
-     if (vm_clock_warp_start == -1) {
+     /* The icount_warp_timer is rescheduled soon after vm_clock_warp_start
+      * changes from -1 to another value, so the race here is okay.
+      */
+     if (atomic_read(&vm_clock_warp_start) == -1) {
          return;
      }
  
+     seqlock_write_lock(&timers_state.vm_clock_seqlock);
      if (runstate_is_running()) {
-         int64_t clock = qemu_get_clock_ns(rt_clock);
-         int64_t warp_delta = clock - vm_clock_warp_start;
-         if (use_icount == 1) {
-             qemu_icount_bias += warp_delta;
-         } else {
+         int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
+         int64_t warp_delta;
+         warp_delta = clock - vm_clock_warp_start;
+         if (use_icount == 2) {
              /*
-              * In adaptive mode, do not let the vm_clock run too
+              * In adaptive mode, do not let QEMU_CLOCK_VIRTUAL run too
               * far ahead of real time.
               */
-             int64_t cur_time = cpu_get_clock();
-             int64_t cur_icount = qemu_get_clock_ns(vm_clock);
+             int64_t cur_time = cpu_get_clock_locked();
+             int64_t cur_icount = cpu_get_icount_locked();
              int64_t delta = cur_time - cur_icount;
-             qemu_icount_bias += MIN(warp_delta, delta);
-         }
-         if (qemu_clock_expired(vm_clock)) {
-             qemu_notify_event();
+             warp_delta = MIN(warp_delta, delta);
          }
+         qemu_icount_bias += warp_delta;
      }
      vm_clock_warp_start = -1;
+     seqlock_write_unlock(&timers_state.vm_clock_seqlock);
+     if (qemu_clock_expired(QEMU_CLOCK_VIRTUAL)) {
+         qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
+     }
  }
  
  void qtest_clock_warp(int64_t dest)
  {
-     int64_t clock = qemu_get_clock_ns(vm_clock);
+     int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
      assert(qtest_enabled());
      while (clock < dest) {
-         int64_t deadline = qemu_clock_deadline(vm_clock);
+         int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
          int64_t warp = MIN(dest - clock, deadline);
+         seqlock_write_lock(&timers_state.vm_clock_seqlock);
          qemu_icount_bias += warp;
-         qemu_run_timers(vm_clock);
-         clock = qemu_get_clock_ns(vm_clock);
+         seqlock_write_unlock(&timers_state.vm_clock_seqlock);
+         qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL);
+         clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
      }
-     qemu_notify_event();
+     qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
  }
  
- void qemu_clock_warp(QEMUClock *clock)
+ void qemu_clock_warp(QEMUClockType type)
  {
+     int64_t clock;
      int64_t deadline;
  
      /*
       * applicable to other clocks.  But a clock argument removes the
       * need for if statements all over the place.
       */
-     if (clock != vm_clock || !use_icount) {
+     if (type != QEMU_CLOCK_VIRTUAL || !use_icount) {
          return;
      }
  
      /*
-      * If the CPUs have been sleeping, advance the vm_clock timer now.  This
-      * ensures that the deadline for the timer is computed correctly below.
+      * If the CPUs have been sleeping, advance QEMU_CLOCK_VIRTUAL timer now.
+      * This ensures that the deadline for the timer is computed correctly below.
       * This also makes sure that the insn counter is synchronized before the
       * CPU starts running, in case the CPU is woken by an event other than
-      * the earliest vm_clock timer.
+      * the earliest QEMU_CLOCK_VIRTUAL timer.
       */
      icount_warp_rt(NULL);
-     if (!all_cpu_threads_idle() || !qemu_clock_has_timers(vm_clock)) {
-         qemu_del_timer(icount_warp_timer);
+     timer_del(icount_warp_timer);
+     if (!all_cpu_threads_idle()) {
          return;
      }
  
        return;
      }
  
-     vm_clock_warp_start = qemu_get_clock_ns(rt_clock);
-     deadline = qemu_clock_deadline(vm_clock);
+     /* We want to use the earliest deadline from ALL vm_clocks */
+     clock = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
+     deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+     if (deadline < 0) {
+         return;
+     }
      if (deadline > 0) {
          /*
-          * Ensure the vm_clock proceeds even when the virtual CPU goes to
+          * Ensure QEMU_CLOCK_VIRTUAL proceeds even when the virtual CPU goes to
           * sleep.  Otherwise, the CPU might be waiting for a future timer
           * interrupt to wake it up, but the interrupt never comes because
           * the vCPU isn't running any insns and thus doesn't advance the
-          * vm_clock.
+          * QEMU_CLOCK_VIRTUAL.
           *
           * An extreme solution for this problem would be to never let VCPUs
-          * sleep in icount mode if there is a pending vm_clock timer; rather
-          * time could just advance to the next vm_clock event.  Instead, we
-          * do stop VCPUs and only advance vm_clock after some "real" time,
-          * (related to the time left until the next event) has passed.  This
-          * rt_clock timer will do this.  This avoids that the warps are too
-          * visible externally---for example, you will not be sending network
-          * packets continuously instead of every 100ms.
+          * sleep in icount mode if there is a pending QEMU_CLOCK_VIRTUAL
+          * timer; rather time could just advance to the next QEMU_CLOCK_VIRTUAL
+          * event.  Instead, we do stop VCPUs and only advance QEMU_CLOCK_VIRTUAL
+          * after some e"real" time, (related to the time left until the next
+          * event) has passed. The QEMU_CLOCK_REALTIME timer will do this.
+          * This avoids that the warps are visible externally; for example,
+          * you will not be sending network packets continuously instead of
+          * every 100ms.
           */
-         qemu_mod_timer(icount_warp_timer, vm_clock_warp_start + deadline);
-     } else {
-         qemu_notify_event();
+         seqlock_write_lock(&timers_state.vm_clock_seqlock);
+         if (vm_clock_warp_start == -1 || vm_clock_warp_start > clock) {
+             vm_clock_warp_start = clock;
+         }
+         seqlock_write_unlock(&timers_state.vm_clock_seqlock);
+         timer_mod_anticipate(icount_warp_timer, clock + deadline);
+     } else if (deadline == 0) {
+         qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
      }
  }
  
@@@ -354,12 -442,14 +443,14 @@@ static const VMStateDescription vmstate
  
  void configure_icount(const char *option)
  {
+     seqlock_init(&timers_state.vm_clock_seqlock, NULL);
      vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
      if (!option) {
          return;
      }
  
-     icount_warp_timer = qemu_new_timer_ns(rt_clock, icount_warp_rt, NULL);
+     icount_warp_timer = timer_new_ns(QEMU_CLOCK_REALTIME,
+                                           icount_warp_rt, NULL);
      if (strcmp(option, "auto") != 0) {
          icount_time_shift = strtol(option, NULL, 0);
          use_icount = 1;
         the virtual time trigger catches emulated time passing too fast.
         Realtime triggers occur even when idle, so use them less frequently
         than VM triggers.  */
-     icount_rt_timer = qemu_new_timer_ms(rt_clock, icount_adjust_rt, NULL);
-     qemu_mod_timer(icount_rt_timer,
-                    qemu_get_clock_ms(rt_clock) + 1000);
-     icount_vm_timer = qemu_new_timer_ns(vm_clock, icount_adjust_vm, NULL);
-     qemu_mod_timer(icount_vm_timer,
-                    qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 10);
+     icount_rt_timer = timer_new_ms(QEMU_CLOCK_REALTIME,
+                                         icount_adjust_rt, NULL);
+     timer_mod(icount_rt_timer,
+                    qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
+     icount_vm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+                                         icount_adjust_vm, NULL);
+     timer_mod(icount_vm_timer,
+                    qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+                    get_ticks_per_sec() / 10);
  }
  
  /***********************************************************/
@@@ -395,7 -488,7 +489,7 @@@ void hw_error(const char *fmt, ...
      fprintf(stderr, "qemu: hardware error: ");
      vfprintf(stderr, fmt, ap);
      fprintf(stderr, "\n");
-     for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
+     CPU_FOREACH(cpu) {
          fprintf(stderr, "CPU #%d:\n", cpu->cpu_index);
          cpu_dump_state(cpu, stderr, fprintf, CPU_DUMP_FPU);
      }
@@@ -407,7 -500,7 +501,7 @@@ void cpu_synchronize_all_states(void
  {
      CPUState *cpu;
  
-     for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
+     CPU_FOREACH(cpu) {
          cpu_synchronize_state(cpu);
      }
  }
@@@ -416,7 -509,7 +510,7 @@@ void cpu_synchronize_all_post_reset(voi
  {
      CPUState *cpu;
  
-     for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
+     CPU_FOREACH(cpu) {
          cpu_synchronize_post_reset(cpu);
      }
  }
@@@ -425,16 -518,11 +519,11 @@@ void cpu_synchronize_all_post_init(void
  {
      CPUState *cpu;
  
-     for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
+     CPU_FOREACH(cpu) {
          cpu_synchronize_post_init(cpu);
      }
  }
  
- bool cpu_is_stopped(CPUState *cpu)
- {
-     return !runstate_is_running() || cpu->stopped;
- }
  static int do_vm_stop(RunState state)
  {
      int ret = 0;
@@@ -458,7 -546,7 +547,7 @@@ static bool cpu_can_run(CPUState *cpu
      if (cpu->stop) {
          return false;
      }
-     if (cpu->stopped || !runstate_is_running()) {
+     if (cpu_is_stopped(cpu)) {
          return false;
      }
      return true;
@@@ -736,7 -824,7 +825,7 @@@ static void qemu_tcg_wait_io_event(void
      while (all_cpu_threads_idle()) {
         /* Start accounting real time to the virtual clock if the CPUs
            are idle.  */
-         qemu_clock_warp(vm_clock);
+         qemu_clock_warp(QEMU_CLOCK_VIRTUAL);
          qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
      }
  
          qemu_cond_wait(&qemu_io_proceeded_cond, &qemu_global_mutex);
      }
  
-     for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
+     CPU_FOREACH(cpu) {
          qemu_wait_io_event_common(cpu);
      }
  }
@@@ -838,12 -926,6 +927,6 @@@ static void *qemu_dummy_cpu_thread_fn(v
  
  static void tcg_exec_all(void);
  
- static void tcg_signal_cpu_creation(CPUState *cpu, void *data)
- {
-     cpu->thread_id = qemu_get_thread_id();
-     cpu->created = true;
- }
  static void *qemu_tcg_cpu_thread_fn(void *arg)
  {
      CPUState *cpu = arg;
      qemu_thread_get_self(cpu->thread);
  
      qemu_mutex_lock(&qemu_global_mutex);
-     qemu_for_each_cpu(tcg_signal_cpu_creation, NULL);
+     CPU_FOREACH(cpu) {
+         cpu->thread_id = qemu_get_thread_id();
+         cpu->created = true;
+     }
      qemu_cond_signal(&qemu_cpu_cond);
  
      /* wait for initial kick-off after machine start */
-     while (first_cpu->stopped) {
+     while (QTAILQ_FIRST(&cpus)->stopped) {
          qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
  
          /* process any pending work */
-         for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
+         CPU_FOREACH(cpu) {
              qemu_wait_io_event_common(cpu);
          }
      }
  
      while (1) {
          tcg_exec_all();
-         if (use_icount && qemu_clock_deadline(vm_clock) <= 0) {
-             qemu_notify_event();
+         if (use_icount) {
+             int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+             if (deadline == 0) {
+                 qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
+             }
          }
          qemu_tcg_wait_io_event();
      }
@@@ -886,13 -976,6 +977,13 @@@ static void qemu_cpu_kick_thread(CPUSta
          fprintf(stderr, "qemu:%s: %s", __func__, strerror(err));
          exit(1);
      }
 +/* The cpu thread cannot catch it reliably when shutdown the guest on Mac.
 + * We can double check it and resend it
 + */
 +#ifdef CONFIG_DARWIN
 +    if (!exit_request)
 +        cpu_signal(0);
 +#endif
  #else /* _WIN32 */
      if (!qemu_cpu_is_self(cpu)) {
          CONTEXT tcgContext;
@@@ -977,13 -1060,12 +1068,12 @@@ void qemu_mutex_unlock_iothread(void
  
  static int all_vcpus_paused(void)
  {
-     CPUState *cpu = first_cpu;
+     CPUState *cpu;
  
-     while (cpu) {
+     CPU_FOREACH(cpu) {
          if (!cpu->stopped) {
              return 0;
          }
-         cpu = cpu->next_cpu;
      }
  
      return 1;
  
  void pause_all_vcpus(void)
  {
-     CPUState *cpu = first_cpu;
+     CPUState *cpu;
  
-     qemu_clock_enable(vm_clock, false);
-     while (cpu) {
+     qemu_clock_enable(QEMU_CLOCK_VIRTUAL, false);
+     CPU_FOREACH(cpu) {
          cpu->stop = true;
          qemu_cpu_kick(cpu);
-         cpu = cpu->next_cpu;
      }
  
      if (qemu_in_vcpu_thread()) {
          cpu_stop_current();
          if (!kvm_enabled()) {
-             cpu = first_cpu;
-             while (cpu) {
+             CPU_FOREACH(cpu) {
                  cpu->stop = false;
                  cpu->stopped = true;
-                 cpu = cpu->next_cpu;
              }
              return;
          }
  
      while (!all_vcpus_paused()) {
          qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex);
-         cpu = first_cpu;
-         while (cpu) {
+         CPU_FOREACH(cpu) {
              qemu_cpu_kick(cpu);
-             cpu = cpu->next_cpu;
          }
      }
  }
@@@ -1032,21 -1109,16 +1117,20 @@@ void cpu_resume(CPUState *cpu
  
  void resume_all_vcpus(void)
  {
-     CPUState *cpu = first_cpu;
+     CPUState *cpu;
  
-     qemu_clock_enable(vm_clock, true);
-     while (cpu) {
+     qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
+     CPU_FOREACH(cpu) {
          cpu_resume(cpu);
-         cpu = cpu->next_cpu;
      }
  }
  
  static void qemu_tcg_init_vcpu(CPUState *cpu)
  {
 +#ifdef        CONFIG_HAX
 +      if (hax_enabled())
 +              hax_init_vcpu(cpu->env_ptr);
 +#endif
      /* share a single thread for all cpus with TCG */
      if (!tcg_cpu_thread) {
          cpu->thread = g_malloc0(sizeof(QemuThread));
@@@ -1157,11 -1229,23 +1241,23 @@@ static int tcg_cpu_exec(CPUArchState *e
  #endif
      if (use_icount) {
          int64_t count;
+         int64_t deadline;
          int decr;
          qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
          env->icount_decr.u16.low = 0;
          env->icount_extra = 0;
-         count = qemu_icount_round(qemu_clock_deadline(vm_clock));
+         deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+         /* Maintain prior (possibly buggy) behaviour where if no deadline
+          * was set (as there is no QEMU_CLOCK_VIRTUAL timer) or it is more than
+          * INT32_MAX nanoseconds ahead, we still use INT32_MAX
+          * nanoseconds.
+          */
+         if ((deadline < 0) || (deadline > INT32_MAX)) {
+             deadline = INT32_MAX;
+         }
+         count = qemu_icount_round(deadline);
          qemu_icount += count;
          decr = (count > 0xffff) ? 0xffff : count;
          count -= decr;
@@@ -1187,17 -1271,17 +1283,17 @@@ static void tcg_exec_all(void
  {
      int r;
  
-     /* Account partial waits to the vm_clock.  */
-     qemu_clock_warp(vm_clock);
+     /* Account partial waits to QEMU_CLOCK_VIRTUAL.  */
+     qemu_clock_warp(QEMU_CLOCK_VIRTUAL);
  
      if (next_cpu == NULL) {
          next_cpu = first_cpu;
      }
-     for (; next_cpu != NULL && !exit_request; next_cpu = next_cpu->next_cpu) {
+     for (; next_cpu != NULL && !exit_request; next_cpu = CPU_NEXT(next_cpu)) {
          CPUState *cpu = next_cpu;
          CPUArchState *env = cpu->env_ptr;
  
-         qemu_clock_enable(vm_clock,
+         qemu_clock_enable(QEMU_CLOCK_VIRTUAL,
                            (cpu->singlestep_enabled & SSTEP_NOTIMER) == 0);
  
          if (cpu_can_run(cpu)) {
@@@ -1218,7 -1302,7 +1314,7 @@@ void set_numa_modes(void
      CPUState *cpu;
      int i;
  
-     for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
+     CPU_FOREACH(cpu) {
          for (i = 0; i < nb_numa_nodes; i++) {
              if (test_bit(cpu->cpu_index, node_cpumask[i])) {
                  cpu->numa_node = i;
@@@ -1240,7 -1324,7 +1336,7 @@@ CpuInfoList *qmp_query_cpus(Error **err
      CpuInfoList *head = NULL, *cur_item = NULL;
      CPUState *cpu;
  
-     for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
+     CPU_FOREACH(cpu) {
          CpuInfoList *info;
  #if defined(TARGET_I386)
          X86CPU *x86_cpu = X86_CPU(cpu);
@@@ -1321,7 -1405,10 +1417,10 @@@ void qmp_memsave(int64_t addr, int64_t 
          l = sizeof(buf);
          if (l > size)
              l = size;
-         cpu_memory_rw_debug(cpu, addr, buf, l, 0);
+         if (cpu_memory_rw_debug(cpu, addr, buf, l, 0) != 0) {
+             error_setg(errp, "Invalid addr 0x%016" PRIx64 "specified", addr);
+             goto exit;
+         }
          if (fwrite(buf, 1, l, f) != l) {
              error_set(errp, QERR_IO_ERROR);
              goto exit;
@@@ -1369,7 -1456,7 +1468,7 @@@ void qmp_inject_nmi(Error **errp
  #if defined(TARGET_I386)
      CPUState *cs;
  
-     for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
+     CPU_FOREACH(cs) {
          X86CPU *cpu = X86_CPU(cs);
          CPUX86State *env = &cpu->env;
  
              apic_deliver_nmi(env->apic_state);
          }
      }
+ #elif defined(TARGET_S390X)
+     CPUState *cs;
+     S390CPU *cpu;
+     CPU_FOREACH(cs) {
+         cpu = S390_CPU(cs);
+         if (cpu->env.cpu_num == monitor_get_cpu_index()) {
+             if (s390_cpu_restart(S390_CPU(cs)) == -1) {
+                 error_set(errp, QERR_UNSUPPORTED);
+                 return;
+             }
+             break;
+         }
+     }
  #else
      error_set(errp, QERR_UNSUPPORTED);
  #endif
@@@ -2,7 -2,6 +2,6 @@@
  
  include pci.mak
  include usb.mak
- CONFIG_GDBSTUB_XML=y
  CONFIG_VGA=y
  CONFIG_ISA_MMIO=y
  CONFIG_NAND=y
@@@ -12,7 -11,6 +11,7 @@@ CONFIG_PTIMER=
  CONFIG_SD=y
  CONFIG_MAX7310=y
  CONFIG_WM8750=y
 +CONFIG_WM8994=y
  CONFIG_TWL92230=y
  CONFIG_TSC2005=y
  CONFIG_LM832X=y
@@@ -35,9 -33,9 +34,9 @@@ CONFIG_PFLASH_CFI02=
  CONFIG_MICRODRIVE=y
  CONFIG_USB_MUSB=y
  
- CONFIG_ARM9MPCORE=y
  CONFIG_ARM11MPCORE=y
- CONFIG_ARM15MPCORE=y
+ CONFIG_A9MPCORE=y
+ CONFIG_A15MPCORE=y
  
  CONFIG_ARM_GIC=y
  CONFIG_ARM_GIC_KVM=$(CONFIG_KVM)
@@@ -63,6 -61,7 +62,7 @@@ CONFIG_BITBANG_I2C=
  CONFIG_FRAMEBUFFER=y
  CONFIG_XILINX_SPIPS=y
  
+ CONFIG_ARM11SCU=y
  CONFIG_A9SCU=y
  CONFIG_MARVELL_88W8618=y
  CONFIG_OMAP=y
@@@ -80,5 -79,5 +80,6 @@@ CONFIG_ZYNQ=
  CONFIG_VERSATILE_PCI=y
  CONFIG_VERSATILE_I2C=y
  
 +CONFIG_SOUND=y
  CONFIG_SDHCI=y
+ CONFIG_INTEGRATOR_DEBUG=y
diff --combined exec.c
--- 1/exec.c
--- 2/exec.c
+++ b/exec.c
@@@ -31,7 -31,6 +31,7 @@@
  #include "hw/qdev.h"
  #include "qemu/osdep.h"
  #include "sysemu/kvm.h"
 +#include "sysemu/hax.h"
  #include "sysemu/sysemu.h"
  #include "hw/xen/xen.h"
  #include "qemu/timer.h"
@@@ -70,7 -69,7 +70,7 @@@ static MemoryRegion io_mem_unassigned
  
  #endif
  
CPUState *first_cpu;
struct CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus);
  /* current CPU in the current thread. It is only valid inside
     cpu_exec() */
  DEFINE_TLS(CPUState *, current_cpu);
@@@ -130,7 -129,6 +130,6 @@@ static PhysPageMap next_map
  
  static void io_mem_init(void);
  static void memory_map_init(void);
- static void *qemu_safe_ram_ptr(ram_addr_t addr);
  
  static MemoryRegion io_mem_watch;
  #endif
@@@ -352,44 -350,29 +351,29 @@@ const VMStateDescription vmstate_cpu_co
  
  CPUState *qemu_get_cpu(int index)
  {
-     CPUState *cpu = first_cpu;
+     CPUState *cpu;
  
-     while (cpu) {
+     CPU_FOREACH(cpu) {
          if (cpu->cpu_index == index) {
-             break;
+             return cpu;
          }
-         cpu = cpu->next_cpu;
      }
  
-     return cpu;
- }
- void qemu_for_each_cpu(void (*func)(CPUState *cpu, void *data), void *data)
- {
-     CPUState *cpu;
-     cpu = first_cpu;
-     while (cpu) {
-         func(cpu, data);
-         cpu = cpu->next_cpu;
-     }
+     return NULL;
  }
  
  void cpu_exec_init(CPUArchState *env)
  {
      CPUState *cpu = ENV_GET_CPU(env);
      CPUClass *cc = CPU_GET_CLASS(cpu);
-     CPUState **pcpu;
+     CPUState *some_cpu;
      int cpu_index;
  
  #if defined(CONFIG_USER_ONLY)
      cpu_list_lock();
  #endif
-     cpu->next_cpu = NULL;
-     pcpu = &first_cpu;
      cpu_index = 0;
-     while (*pcpu != NULL) {
-         pcpu = &(*pcpu)->next_cpu;
+     CPU_FOREACH(some_cpu) {
          cpu_index++;
      }
      cpu->cpu_index = cpu_index;
  #ifndef CONFIG_USER_ONLY
      cpu->thread_id = qemu_get_thread_id();
  #endif
-     *pcpu = cpu;
+     QTAILQ_INSERT_TAIL(&cpus, cpu, node);
  #if defined(CONFIG_USER_ONLY)
      cpu_list_unlock();
  #endif
@@@ -426,8 -409,10 +410,10 @@@ static void breakpoint_invalidate(CPUSt
  #else
  static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
  {
-     tb_invalidate_phys_addr(cpu_get_phys_page_debug(cpu, pc) |
-             (pc & ~TARGET_PAGE_MASK));
+     hwaddr phys = cpu_get_phys_page_debug(cpu, pc);
+     if (phys != -1) {
+         tb_invalidate_phys_addr(phys | (pc & ~TARGET_PAGE_MASK));
+     }
  }
  #endif
  #endif /* TARGET_HAS_ICE */
@@@ -641,55 -626,40 +627,40 @@@ void cpu_abort(CPUArchState *env, cons
      abort();
  }
  
- CPUArchState *cpu_copy(CPUArchState *env)
+ #if !defined(CONFIG_USER_ONLY)
+ static RAMBlock *qemu_get_ram_block(ram_addr_t addr)
  {
-     CPUArchState *new_env = cpu_init(env->cpu_model_str);
- #if defined(TARGET_HAS_ICE)
-     CPUBreakpoint *bp;
-     CPUWatchpoint *wp;
- #endif
-     /* Reset non arch specific state */
-     cpu_reset(ENV_GET_CPU(new_env));
-     /* Copy arch specific state into the new CPU */
-     memcpy(new_env, env, sizeof(CPUArchState));
+     RAMBlock *block;
  
-     /* Clone all break/watchpoints.
-        Note: Once we support ptrace with hw-debug register access, make sure
-        BP_CPU break/watchpoints are handled correctly on clone. */
-     QTAILQ_INIT(&env->breakpoints);
-     QTAILQ_INIT(&env->watchpoints);
- #if defined(TARGET_HAS_ICE)
-     QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
-         cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
+     /* The list is protected by the iothread lock here.  */
+     block = ram_list.mru_block;
+     if (block && addr - block->offset < block->length) {
+         goto found;
      }
-     QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
-         cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
-                               wp->flags, NULL);
+     QTAILQ_FOREACH(block, &ram_list.blocks, next) {
+         if (addr - block->offset < block->length) {
+             goto found;
+         }
      }
- #endif
  
-     return new_env;
+     fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
+     abort();
+ found:
+     ram_list.mru_block = block;
+     return block;
  }
  
- #if !defined(CONFIG_USER_ONLY)
  static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t end,
                                        uintptr_t length)
  {
-     uintptr_t start1;
+     RAMBlock *block;
+     ram_addr_t start1;
  
-     /* we modify the TLB cache so that the dirty bit will be set again
-        when accessing the range */
-     start1 = (uintptr_t)qemu_safe_ram_ptr(start);
-     /* Check that we don't span multiple blocks - this breaks the
-        address comparisons below.  */
-     if ((uintptr_t)qemu_safe_ram_ptr(end - 1) - start1
-             != (end - 1) - start) {
-         abort();
-     }
+     block = qemu_get_ram_block(start);
+     assert(block == qemu_get_ram_block(end - 1));
+     start1 = (uintptr_t)block->host + (start - block->offset);
      cpu_tlb_reset_dirty_all(start1, length);
  }
  
  /* Note: start and end must be within the same ram block.  */
@@@ -765,6 -735,18 +736,18 @@@ static int subpage_register (subpage_t 
                               uint16_t section);
  static subpage_t *subpage_init(AddressSpace *as, hwaddr base);
  
+ static void *(*phys_mem_alloc)(size_t size) = qemu_anon_ram_alloc;
+ /*
+  * Set a custom physical guest memory alloator.
+  * Accelerators with unusual needs may need this.  Hopefully, we can
+  * get rid of it eventually.
+  */
+ void phys_mem_set_alloc(void *(*alloc)(size_t))
+ {
+     phys_mem_alloc = alloc;
+ }
  static uint16_t phys_section_add(MemoryRegionSection *section)
  {
      /* The physical section number is ORed with a page-aligned
@@@ -896,7 -878,7 +879,7 @@@ void qemu_mutex_unlock_ramlist(void
      qemu_mutex_unlock(&ram_list.mutex);
  }
  
- #if defined(__linux__) && !defined(TARGET_S390X)
+ #ifdef __linux__
  
  #include <sys/vfs.h>
  
@@@ -999,6 -981,14 +982,14 @@@ static void *file_ram_alloc(RAMBlock *b
      block->fd = fd;
      return area;
  }
+ #else
+ static void *file_ram_alloc(RAMBlock *block,
+                             ram_addr_t memory,
+                             const char *path)
+ {
+     fprintf(stderr, "-mem-path not supported on this host\n");
+     exit(1);
+ }
  #endif
  
  static ram_addr_t find_ram_offset(ram_addr_t size)
@@@ -1115,6 -1105,7 +1106,7 @@@ ram_addr_t qemu_ram_alloc_from_ptr(ram_
  
      size = TARGET_PAGE_ALIGN(size);
      new_block = g_malloc0(sizeof(*new_block));
+     new_block->fd = -1;
  
      /* This assumes the iothread lock is taken here too.  */
      qemu_mutex_lock_ramlist();
      if (host) {
          new_block->host = host;
          new_block->flags |= RAM_PREALLOC_MASK;
-     } else {
+     } else if (xen_enabled()) {
          if (mem_path) {
- #if defined (__linux__) && !defined(TARGET_S390X)
-             new_block->host = file_ram_alloc(new_block, size, mem_path);
-             if (!new_block->host) {
-                 new_block->host = qemu_anon_ram_alloc(size);
-                 memory_try_enable_merging(new_block->host, size);
-             }
- #else
-             fprintf(stderr, "-mem-path option unsupported\n");
+             fprintf(stderr, "-mem-path not supported with Xen\n");
              exit(1);
- #endif
-         } else {
-             if (xen_enabled()) {
-                 xen_ram_alloc(new_block->offset, size, mr);
-             } else if (kvm_enabled()) {
-                 /* some s390/kvm configurations have special constraints */
-                 new_block->host = kvm_ram_alloc(size);
-             } else {
-                 new_block->host = qemu_anon_ram_alloc(size);
- #ifdef CONFIG_HAX
+         }
+         xen_ram_alloc(new_block->offset, size, mr);
+     } else {
+         if (mem_path) {
+             if (phys_mem_alloc != qemu_anon_ram_alloc) {
                  /*
-                  * In Hax, the qemu allocate the virtual address, and HAX kernel
-                  * populate the memory with physical memory. Currently we have no
-                  * paging, so user should make sure enough free memory in advance
+                  * file_ram_alloc() needs to allocate just like
+                  * phys_mem_alloc, but we haven't bothered to provide
+                  * a hook there.
                   */
-                 if (hax_enabled()) {
-                     int ret;
-                     ret = hax_populate_ram((uint64_t)new_block->host, size);
-                     if (ret < 0) {
-                         fprintf(stderr, "Hax failed to populate ram\n");
-                         exit(-1);
-                     }
+                 fprintf(stderr,
+                         "-mem-path not supported with this accelerator\n");
+                 exit(1);
+             }
+             new_block->host = file_ram_alloc(new_block, size, mem_path);
+         }
+         if (!new_block->host) {
+             new_block->host = phys_mem_alloc(size);
++#ifdef CONFIG_HAX
++            /*
++             * In Hax, the qemu allocate the virtual address, and HAX kernel
++             * populate the memory with physical memory. Currently we have no
++             * paging, so user should make sure enough free memory in advance
++             */
++            if (hax_enabled()) {
++                int ret;
++                ret = hax_populate_ram((uint64_t)new_block->host, size);
++                if (ret < 0) {
++                    fprintf(stderr, "Hax failed to populate ram\n");
++                    exit(-1);
 +                }
++            }
 +#endif
+             if (!new_block->host) {
+                 fprintf(stderr, "Cannot set up guest memory '%s': %s\n",
+                         new_block->mr->name, strerror(errno));
+                 exit(1);
              }
              memory_try_enable_merging(new_block->host, size);
          }
@@@ -1232,23 -1214,15 +1230,15 @@@ void qemu_ram_free(ram_addr_t addr
              ram_list.version++;
              if (block->flags & RAM_PREALLOC_MASK) {
                  ;
-             } else if (mem_path) {
- #if defined (__linux__) && !defined(TARGET_S390X)
-                 if (block->fd) {
-                     munmap(block->host, block->length);
-                     close(block->fd);
-                 } else {
-                     qemu_anon_ram_free(block->host, block->length);
-                 }
- #else
-                 abort();
+             } else if (xen_enabled()) {
+                 xen_invalidate_map_cache_entry(block->host);
+ #ifndef _WIN32
+             } else if (block->fd >= 0) {
+                 munmap(block->host, block->length);
+                 close(block->fd);
  #endif
              } else {
-                 if (xen_enabled()) {
-                     xen_invalidate_map_cache_entry(block->host);
-                 } else {
-                     qemu_anon_ram_free(block->host, block->length);
-                 }
+                 qemu_anon_ram_free(block->host, block->length);
              }
              g_free(block);
              break;
@@@ -1272,38 -1246,31 +1262,31 @@@ void qemu_ram_remap(ram_addr_t addr, ra
              vaddr = block->host + offset;
              if (block->flags & RAM_PREALLOC_MASK) {
                  ;
+             } else if (xen_enabled()) {
+                 abort();
              } else {
                  flags = MAP_FIXED;
                  munmap(vaddr, length);
-                 if (mem_path) {
- #if defined(__linux__) && !defined(TARGET_S390X)
-                     if (block->fd) {
+                 if (block->fd >= 0) {
  #ifdef MAP_POPULATE
-                         flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED :
-                             MAP_PRIVATE;
- #else
-                         flags |= MAP_PRIVATE;
- #endif
-                         area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
-                                     flags, block->fd, offset);
-                     } else {
-                         flags |= MAP_PRIVATE | MAP_ANONYMOUS;
-                         area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
-                                     flags, -1, 0);
-                     }
+                     flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED :
+                         MAP_PRIVATE;
  #else
-                     abort();
+                     flags |= MAP_PRIVATE;
  #endif
+                     area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
+                                 flags, block->fd, offset);
                  } else {
- #if defined(TARGET_S390X) && defined(CONFIG_KVM)
-                     flags |= MAP_SHARED | MAP_ANONYMOUS;
-                     area = mmap(vaddr, length, PROT_EXEC|PROT_READ|PROT_WRITE,
-                                 flags, -1, 0);
- #else
+                     /*
+                      * Remap needs to match alloc.  Accelerators that
+                      * set phys_mem_alloc never remap.  If they did,
+                      * we'd need a remap hook here.
+                      */
+                     assert(phys_mem_alloc == qemu_anon_ram_alloc);
                      flags |= MAP_PRIVATE | MAP_ANONYMOUS;
                      area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
                                  flags, -1, 0);
- #endif
                  }
                  if (area != vaddr) {
                      fprintf(stderr, "Could not remap addr: "
  }
  #endif /* !_WIN32 */
  
- static RAMBlock *qemu_get_ram_block(ram_addr_t addr)
- {
-     RAMBlock *block;
-     /* The list is protected by the iothread lock here.  */
-     block = ram_list.mru_block;
-     if (block && addr - block->offset < block->length) {
-         goto found;
-     }
-     QTAILQ_FOREACH(block, &ram_list.blocks, next) {
-         if (addr - block->offset < block->length) {
-             goto found;
-         }
-     }
-     fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
-     abort();
- found:
-     ram_list.mru_block = block;
-     return block;
- }
  /* Return a host pointer to ram allocated with qemu_ram_alloc.
     With the exception of the softmmu code in this file, this should
     only be used for local memory (e.g. video ram) that the device owns,
@@@ -1370,40 -1314,6 +1330,6 @@@ void *qemu_get_ram_ptr(ram_addr_t addr
      return block->host + (addr - block->offset);
  }
  
- /* Return a host pointer to ram allocated with qemu_ram_alloc.  Same as
-  * qemu_get_ram_ptr but do not touch ram_list.mru_block.
-  *
-  * ??? Is this still necessary?
-  */
- static void *qemu_safe_ram_ptr(ram_addr_t addr)
- {
-     RAMBlock *block;
-     /* The list is protected by the iothread lock here.  */
-     QTAILQ_FOREACH(block, &ram_list.blocks, next) {
-         if (addr - block->offset < block->length) {
-             if (xen_enabled()) {
-                 /* We need to check if the requested address is in the RAM
-                  * because we don't want to map the entire memory in QEMU.
-                  * In that case just map until the end of the page.
-                  */
-                 if (block->offset == 0) {
-                     return xen_map_cache(addr, 0, 0);
-                 } else if (block->host == NULL) {
-                     block->host =
-                         xen_map_cache(block->offset, block->length, 1);
-                 }
-             }
-             return block->host + (addr - block->offset);
-         }
-     }
-     fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
-     abort();
-     return NULL;
- }
  /* Return a host pointer to guest's ram. Similar to qemu_get_ram_ptr
   * but takes a size argument */
  static void *qemu_ram_ptr_length(ram_addr_t addr, hwaddr *size)
@@@ -1592,7 -1502,7 +1518,7 @@@ static uint64_t subpage_read(void *opaq
      uint8_t buf[4];
  
  #if defined(DEBUG_SUBPAGE)
-     printf("%s: subpage %p len %d addr " TARGET_FMT_plx "\n", __func__,
+     printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__,
             subpage, len, addr);
  #endif
      address_space_read(subpage->as, addr + subpage->base, buf, len);
@@@ -1615,7 -1525,7 +1541,7 @@@ static void subpage_write(void *opaque
      uint8_t buf[4];
  
  #if defined(DEBUG_SUBPAGE)
-     printf("%s: subpage %p len %d addr " TARGET_FMT_plx
+     printf("%s: subpage %p len %u addr " TARGET_FMT_plx
             " value %"PRIx64"\n",
             __func__, subpage, len, addr, value);
  #endif
  }
  
  static bool subpage_accepts(void *opaque, hwaddr addr,
-                             unsigned size, bool is_write)
+                             unsigned len, bool is_write)
  {
      subpage_t *subpage = opaque;
  #if defined(DEBUG_SUBPAGE)
-     printf("%s: subpage %p %c len %d addr " TARGET_FMT_plx "\n",
+     printf("%s: subpage %p %c len %u addr " TARGET_FMT_plx "\n",
             __func__, subpage, is_write ? 'w' : 'r', len, addr);
  #endif
  
      return address_space_access_valid(subpage->as, addr + subpage->base,
-                                       size, is_write);
+                                       len, is_write);
  }
  
  static const MemoryRegionOps subpage_ops = {
@@@ -1665,8 -1575,8 +1591,8 @@@ static int subpage_register (subpage_t 
      idx = SUBPAGE_IDX(start);
      eidx = SUBPAGE_IDX(end);
  #if defined(DEBUG_SUBPAGE)
-     printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
-            mmio, start, end, idx, eidx, memory);
+     printf("%s: %p start %08x end %08x idx %08x eidx %08x section %d\n",
+            __func__, mmio, start, end, idx, eidx, section);
  #endif
      for (; idx <= eidx; idx++) {
          mmio->sub_section[idx] = section;
@@@ -1687,8 -1597,8 +1613,8 @@@ static subpage_t *subpage_init(AddressS
                            "subpage", TARGET_PAGE_SIZE);
      mmio->iomem.subpage = true;
  #if defined(DEBUG_SUBPAGE)
-     printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
-            mmio, base, TARGET_PAGE_SIZE, subpage_memory);
+     printf("%s: %p base " TARGET_FMT_plx " len %08x\n", __func__,
+            mmio, base, TARGET_PAGE_SIZE);
  #endif
      subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, PHYS_SECTION_UNASSIGNED);
  
@@@ -1779,7 -1689,7 +1705,7 @@@ static void tcg_commit(MemoryListener *
      /* since each CPU stores ram addresses in its TLB cache, we must
         reset the modified entries */
      /* XXX: slow ! */
-     for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
+     CPU_FOREACH(cpu) {
          CPUArchState *env = cpu->env_ptr;
  
          tlb_flush(env, 1);
@@@ -1842,7 -1752,9 +1768,9 @@@ static void memory_map_init(void
      address_space_init(&address_space_io, system_io, "I/O");
  
      memory_listener_register(&core_memory_listener, &address_space_memory);
-     memory_listener_register(&tcg_memory_listener, &address_space_memory);
+     if (tcg_enabled()) {
+         memory_listener_register(&tcg_memory_listener, &address_space_memory);
+     }
  }
  
  MemoryRegion *get_system_memory(void)
@@@ -2189,7 -2101,9 +2117,9 @@@ void *address_space_map(AddressSpace *a
          if (bounce.buffer) {
              return NULL;
          }
-         bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
+         /* Avoid unbounded allocations */
+         l = MIN(l, TARGET_PAGE_SIZE);
+         bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, l);
          bounce.addr = addr;
          bounce.len = l;
  
diff --combined hw/Makefile.objs
@@@ -18,6 -18,7 +18,7 @@@ devices-dirs-$(CONFIG_SOFTMMU) += net
  devices-dirs-$(CONFIG_SOFTMMU) += nvram/
  devices-dirs-$(CONFIG_SOFTMMU) += pci/
  devices-dirs-$(CONFIG_PCI) += pci-bridge/ pci-host/
+ devices-dirs-$(CONFIG_SOFTMMU) += pcmcia/
  devices-dirs-$(CONFIG_SOFTMMU) += scsi/
  devices-dirs-$(CONFIG_SOFTMMU) += sd/
  devices-dirs-$(CONFIG_SOFTMMU) += ssi/
@@@ -27,8 -28,6 +28,8 @@@ devices-dirs-$(CONFIG_SOFTMMU) += usb
  devices-dirs-$(CONFIG_VIRTIO) += virtio/
  devices-dirs-$(CONFIG_SOFTMMU) += watchdog/
  devices-dirs-$(CONFIG_SOFTMMU) += xen/
 +devices-dirs-$(CONFIG_BUILD_VIGS) += yagl/
 +devices-dirs-$(CONFIG_BUILD_VIGS) += vigs/
  devices-dirs-y += core/
  common-obj-y += $(devices-dirs-y)
  obj-y += $(devices-dirs-y)
diff --combined hw/acpi/piix4.c
  #include "exec/ioport.h"
  #include "hw/nvram/fw_cfg.h"
  #include "exec/address-spaces.h"
+ #include "hw/acpi/piix4.h"
  
 +#ifdef CONFIG_MARU
 +#include "tizen/src/hw/maru_pm.h"
 +#endif
 +
  //#define DEBUG
  
  #ifdef DEBUG
@@@ -73,6 -70,8 +74,8 @@@ typedef struct PIIX4PMState 
      /*< public >*/
  
      MemoryRegion io;
+     uint32_t io_base;
      MemoryRegion io_gpe;
      MemoryRegion io_pci;
      MemoryRegion io_cpu;
@@@ -156,14 -155,13 +159,13 @@@ static void apm_ctrl_changed(uint32_t v
  static void pm_io_space_update(PIIX4PMState *s)
  {
      PCIDevice *d = PCI_DEVICE(s);
-     uint32_t pm_io_base;
  
-     pm_io_base = le32_to_cpu(*(uint32_t *)(d->config + 0x40));
-     pm_io_base &= 0xffc0;
+     s->io_base = le32_to_cpu(*(uint32_t *)(d->config + 0x40));
+     s->io_base &= 0xffc0;
  
      memory_region_transaction_begin();
      memory_region_set_enabled(&s->io, d->config[0x80] & 1);
-     memory_region_set_address(&s->io, pm_io_base);
+     memory_region_set_address(&s->io, s->io_base);
      memory_region_transaction_commit();
  }
  
@@@ -267,7 -265,7 +269,7 @@@ static int acpi_load_old(QEMUFile *f, v
          return ret;
      }
  
-     qemu_get_timer(f, s->ar.tmr.timer);
+     timer_get(f, s->ar.tmr.timer);
      qemu_get_sbe64s(f, &s->ar.tmr.overflow_time);
  
      qemu_get_be16s(f, (uint16_t *)s->ar.gpe.sts);
@@@ -330,7 -328,7 +332,7 @@@ static void acpi_piix_eject_slot(PIIX4P
              if (pc->no_hotplug) {
                  slot_free = false;
              } else {
-                 qdev_free(qdev);
+                 object_unparent(OBJECT(qdev));
              }
          }
      }
@@@ -411,6 -409,28 +413,28 @@@ static void piix4_pm_machine_ready(Noti
          (memory_region_present(io_as, 0x2f8) ? 0x90 : 0);
  }
  
+ static void piix4_pm_add_propeties(PIIX4PMState *s)
+ {
+     static const uint8_t acpi_enable_cmd = ACPI_ENABLE;
+     static const uint8_t acpi_disable_cmd = ACPI_DISABLE;
+     static const uint32_t gpe0_blk = GPE_BASE;
+     static const uint32_t gpe0_blk_len = GPE_LEN;
+     static const uint16_t sci_int = 9;
+     object_property_add_uint8_ptr(OBJECT(s), ACPI_PM_PROP_ACPI_ENABLE_CMD,
+                                   &acpi_enable_cmd, NULL);
+     object_property_add_uint8_ptr(OBJECT(s), ACPI_PM_PROP_ACPI_DISABLE_CMD,
+                                   &acpi_disable_cmd, NULL);
+     object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_GPE0_BLK,
+                                   &gpe0_blk, NULL);
+     object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_GPE0_BLK_LEN,
+                                   &gpe0_blk_len, NULL);
+     object_property_add_uint16_ptr(OBJECT(s), ACPI_PM_PROP_SCI_INT,
+                                   &sci_int, NULL);
+     object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_PM_IO_BASE,
+                                   &s->io_base, NULL);
+ }
  static int piix4_pm_initfn(PCIDevice *dev)
  {
      PIIX4PMState *s = PIIX4_PM(dev);
      acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
      acpi_pm1_cnt_init(&s->ar, &s->io, s->s4_val);
      acpi_gpe_init(&s->ar, GPE_LEN);
 +#ifdef CONFIG_MARU
 +    acpi_maru_pm_init(&s->ar, pm_tmr_timer);
 +#endif
  
      s->powerdown_notifier.notify = piix4_pm_powerdown_req;
      qemu_register_powerdown_notifier(&s->powerdown_notifier);
  
      piix4_acpi_system_hot_add_init(pci_address_space_io(dev), dev->bus, s);
  
+     piix4_pm_add_propeties(s);
      return 0;
  }
  
+ Object *piix4_pm_find(void)
+ {
+     bool ambig;
+     Object *o = object_resolve_path_type("", TYPE_PIIX4_PM, &ambig);
+     if (ambig || !o) {
+         return NULL;
+     }
+     return o;
+ }
  i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
                         qemu_irq sci_irq, qemu_irq smi_irq,
                         int kvm_enabled, FWCfgState *fw_cfg)
  
  static Property piix4_pm_properties[] = {
      DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
-     DEFINE_PROP_UINT8("disable_s3", PIIX4PMState, disable_s3, 0),
-     DEFINE_PROP_UINT8("disable_s4", PIIX4PMState, disable_s4, 0),
-     DEFINE_PROP_UINT8("s4_val", PIIX4PMState, s4_val, 2),
+     DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0),
+     DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0),
+     DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2),
      DEFINE_PROP_END_OF_LIST(),
  };
  
@@@ -675,22 -704,14 +711,14 @@@ static void piix4_cpu_added_req(Notifie
      piix4_cpu_hotplug_req(s, CPU(opaque), PLUG);
  }
  
- static void piix4_init_cpu_status(CPUState *cpu, void *data)
- {
-     CPUStatus *g = (CPUStatus *)data;
-     CPUClass *k = CPU_GET_CLASS(cpu);
-     int64_t id = k->get_arch_id(cpu);
-     g_assert((id / 8) < PIIX4_PROC_LEN);
-     g->sts[id / 8] |= (1 << (id % 8));
- }
  static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
                                  PCIHotplugState state);
  
  static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
                                             PCIBus *bus, PIIX4PMState *s)
  {
+     CPUState *cpu;
      memory_region_init_io(&s->io_gpe, OBJECT(s), &piix4_gpe_ops, s,
                            "acpi-gpe0", GPE_LEN);
      memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe);
                                  &s->io_pci);
      pci_bus_hotplug(bus, piix4_device_hotplug, DEVICE(s));
  
-     qemu_for_each_cpu(piix4_init_cpu_status, &s->gpe_cpu);
+     CPU_FOREACH(cpu) {
+         CPUClass *cc = CPU_GET_CLASS(cpu);
+         int64_t id = cc->get_arch_id(cpu);
+         g_assert((id / 8) < PIIX4_PROC_LEN);
+         s->gpe_cpu.sts[id / 8] |= (1 << (id % 8));
+     }
      memory_region_init_io(&s->io_cpu, OBJECT(s), &cpu_hotplug_ops, s,
                            "acpi-cpu-hotplug", PIIX4_PROC_LEN);
      memory_region_add_subregion(parent, PIIX4_PROC_BASE, &s->io_cpu);
diff --combined hw/arm/Makefile.objs
@@@ -1,34 -1,6 +1,34 @@@
 +obj-y = arm_pic.o
 +obj-y += arm_boot.o
 +obj-y += zynq_slcr.o
 +obj-y += arm_gic.o arm_gic_common.o
 +obj-y += realview_gic.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 +obj-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
 +obj-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o
 +obj-y += exynos4210_pmu.o exynos4210_mct.o exynos4210_fimd.o
 +obj-y += exynos4210_rtc.o exynos4210_i2c.o
 +obj-y += exynos4210_cmu.o exynos4210_g3d.o
 +obj-y += exynos4210_i2s.o exynos4210_audio.o
 +obj-y += arm_mptimer.o a15mpcore.o
 +obj-y += armv7m.o armv7m_nvic.o stellaris_enet.o
 +obj-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 +obj-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
 +obj-y += zaurus.o ide/microdrive.o tc6393xb.o
 +obj-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
 +                omap_gpio.o omap_intc.o omap_uart.o
 +obj-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
 +                omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
 +obj-y += tsc210x.o
 +obj-y += blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
 +obj-y += mst_fpga.o
 +obj-y += bitbang_i2c.o marvell_88w8618_audio.o
 +obj-y += framebuffer.o
 +obj-y += strongarm.o
 +obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 +obj-$(CONFIG_FDT) += ../device_tree.o
  obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
  obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o
- obj-y += omap_sx1.o palm.o pic_cpu.o realview.o spitz.o stellaris.o
+ obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
  obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
  
  obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
diff --combined hw/display/vga.c
@@@ -318,7 -318,7 +318,7 @@@ static uint8_t vga_precise_retrace(VGAC
          int cur_line, cur_line_char, cur_char;
          int64_t cur_tick;
  
-         cur_tick = qemu_get_clock_ns(vm_clock);
+         cur_tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  
          cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
          cur_line = cur_char / r->htotal;
@@@ -359,8 -359,6 +359,6 @@@ uint32_t vga_ioport_read(void *opaque, 
      VGACommonState *s = opaque;
      int val, index;
  
-     qemu_flush_coalesced_mmio_buffer();
      if (vga_ioport_invalid(s, addr)) {
          val = 0xff;
      } else {
@@@ -453,8 -451,6 +451,6 @@@ void vga_ioport_write(void *opaque, uin
      VGACommonState *s = opaque;
      int index;
  
-     qemu_flush_coalesced_mmio_buffer();
      /* check port range access depending on color/monochrome mode */
      if (vga_ioport_invalid(s, addr)) {
          return;
@@@ -649,11 -645,7 +645,11 @@@ void vbe_ioport_write_data(void *opaque
              }
              break;
          case VBE_DISPI_INDEX_XRES:
 +#ifdef CONFIG_MARU
 +            if (val <= VBE_DISPI_MAX_XRES) {
 +#else
              if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
 +#endif
                  s->vbe_regs[s->vbe_index] = val;
              }
              break;
@@@ -1308,7 -1300,7 +1304,7 @@@ static void vga_draw_text(VGACommonStat
      uint32_t *ch_attr_ptr;
      vga_draw_glyph8_func *vga_draw_glyph8;
      vga_draw_glyph9_func *vga_draw_glyph9;
-     int64_t now = qemu_get_clock_ms(vm_clock);
+     int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
  
      /* compute font data address (in plane 2) */
      v = s->sr[VGA_SEQ_CHARACTER_MAP];
@@@ -1715,7 -1707,6 +1711,6 @@@ static void vga_draw_graphic(VGACommonS
      } else if (is_buffer_shared(surface) &&
                 (full_update || surface_data(surface) != s->vram_ptr
                  + (s->start_addr * 4))) {
-         DisplaySurface *surface;
          surface = qemu_create_displaysurface_from(disp_width,
                  height, depth, s->line_offset,
                  s->vram_ptr + (s->start_addr * 4), byteswap);
@@@ -1911,7 -1902,7 +1906,7 @@@ static void vga_update_display(void *op
          }
          if (graphic_mode != s->graphic_mode) {
              s->graphic_mode = graphic_mode;
-             s->cursor_blink_time = qemu_get_clock_ms(vm_clock);
+             s->cursor_blink_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
              full_update = 1;
          }
          switch(graphic_mode) {
@@@ -2377,6 -2368,7 +2372,7 @@@ void vga_init(VGACommonState *s, Objec
      memory_region_set_coalescing(vga_io_memory);
      if (init_vga_ports) {
          portio_list_init(vga_port_list, obj, vga_ports, s, "vga");
+         portio_list_set_flush_coalesced(vga_port_list);
          portio_list_add(vga_port_list, address_space_io, 0x3b0);
      }
      if (vbe_ports) {
diff --combined hw/i386/pc.c
  #include "hw/cpu/icc_bus.h"
  #include "hw/boards.h"
  #include "hw/pci/pci_host.h"
+ #include "acpi-build.h"
  
 +#ifdef CONFIG_MARU
 +#include "../../tizen/src/maru_err_table.h"
 +#endif
  /* debug PC/ISA interrupts */
  //#define DEBUG_IRQ
  
@@@ -92,7 -90,9 +93,9 @@@ struct e820_table 
      struct e820_entry entry[E820_NR_ENTRIES];
  } QEMU_PACKED __attribute((__aligned__(4)));
  
- static struct e820_table e820_table;
+ static struct e820_table e820_reserve;
+ static struct e820_entry *e820_table;
+ static unsigned e820_entries;
  struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
  
  void gsi_handler(void *opaque, int n, int level)
@@@ -194,13 -194,12 +197,12 @@@ static void pic_irq_request(void *opaqu
  
      DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
      if (env->apic_state) {
-         while (cs) {
+         CPU_FOREACH(cs) {
              cpu = X86_CPU(cs);
              env = &cpu->env;
              if (apic_accept_pic_intr(env->apic_state)) {
                  apic_deliver_pic_intr(env->apic_state, level);
              }
-             cs = cs->next_cpu;
          }
      } else {
          if (level) {
@@@ -580,19 -579,32 +582,32 @@@ static void handle_a20_line_change(voi
  
  int e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
  {
-     int index = le32_to_cpu(e820_table.count);
+     int index = le32_to_cpu(e820_reserve.count);
      struct e820_entry *entry;
  
-     if (index >= E820_NR_ENTRIES)
-         return -EBUSY;
-     entry = &e820_table.entry[index++];
+     if (type != E820_RAM) {
+         /* old FW_CFG_E820_TABLE entry -- reservations only */
+         if (index >= E820_NR_ENTRIES) {
+             return -EBUSY;
+         }
+         entry = &e820_reserve.entry[index++];
+         entry->address = cpu_to_le64(address);
+         entry->length = cpu_to_le64(length);
+         entry->type = cpu_to_le32(type);
+         e820_reserve.count = cpu_to_le32(index);
+     }
  
-     entry->address = cpu_to_le64(address);
-     entry->length = cpu_to_le64(length);
-     entry->type = cpu_to_le32(type);
+     /* new "etc/e820" file -- include ram too */
+     e820_table = g_realloc(e820_table,
+                            sizeof(struct e820_entry) * (e820_entries+1));
+     e820_table[e820_entries].address = cpu_to_le64(address);
+     e820_table[e820_entries].length = cpu_to_le64(length);
+     e820_table[e820_entries].type = cpu_to_le32(type);
+     e820_entries++;
  
-     e820_table.count = cpu_to_le32(index);
-     return index;
+     return e820_entries;
  }
  
  /* Calculates the limit to CPU APIC ID values
@@@ -643,7 -655,9 +658,9 @@@ static FWCfgState *bochs_bios_init(void
          fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES,
                           smbios_table, smbios_len);
      fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE,
-                      &e820_table, sizeof(e820_table));
+                      &e820_reserve, sizeof(e820_reserve));
+     fw_cfg_add_file(fw_cfg, "etc/e820", e820_table,
+                     sizeof(struct e820_entry) * e820_entries);
  
      fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, &hpet_cfg, sizeof(hpet_cfg));
      /* allocate memory for the NUMA channel: one (64bit) word for the number
@@@ -710,16 -724,6 +727,16 @@@ static void load_linux(FWCfgState *fw_c
          MIN(ARRAY_SIZE(header), kernel_size)) {
          fprintf(stderr, "qemu: could not load kernel '%s': %s\n",
                  kernel_filename, strerror(errno));
 +
 +#ifdef CONFIG_MARU
 +        char *error_msg = NULL;
 +
 +        error_msg = maru_convert_path(error_msg, kernel_filename);
 +        maru_register_exit_msg(MARU_EXIT_KERNEL_FILE_EXCEPTION, error_msg);
 +        if (error_msg) {
 +            g_free(error_msg);
 +        }
 +#endif
          exit(1);
      }
  
@@@ -991,7 -995,7 +1008,7 @@@ void pc_cpus_init(const char *cpu_model
          cpu = pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i),
                           icc_bridge, &error);
          if (error) {
-             fprintf(stderr, "%s\n", error_get_pretty(error));
+             error_report("%s", error_get_pretty(error));
              error_free(error);
              exit(1);
          }
@@@ -1054,6 -1058,7 +1071,7 @@@ void pc_guest_info_machine_done(Notifie
                                                        PcGuestInfoState,
                                                        machine_done);
      pc_fw_cfg_guest_info(&guest_info_state->info);
+     acpi_setup(&guest_info_state->info);
  }
  
  PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
  {
      PcGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state);
      PcGuestInfo *guest_info = &guest_info_state->info;
+     int i, j;
+     guest_info->ram_size = below_4g_mem_size + above_4g_mem_size;
+     guest_info->apic_id_limit = pc_apic_id_limit(max_cpus);
+     guest_info->apic_xrupt_override = kvm_allows_irq0_override();
+     guest_info->numa_nodes = nb_numa_nodes;
+     guest_info->node_mem = g_memdup(node_mem, guest_info->numa_nodes *
+                                     sizeof *guest_info->node_mem);
+     guest_info->node_cpu = g_malloc0(guest_info->apic_id_limit *
+                                      sizeof *guest_info->node_cpu);
+     for (i = 0; i < max_cpus; i++) {
+         unsigned int apic_id = x86_cpu_apic_id_from_index(i);
+         assert(apic_id < guest_info->apic_id_limit);
+         for (j = 0; j < nb_numa_nodes; j++) {
+             if (test_bit(i, node_cpumask[j])) {
+                 guest_info->node_cpu[apic_id] = j;
+                 break;
+             }
+         }
+     }
  
      guest_info_state->machine_done.notify = pc_guest_info_machine_done;
      qemu_add_machine_init_done_notifier(&guest_info_state->machine_done);
@@@ -1107,10 -1133,10 +1146,10 @@@ void pc_acpi_init(const char *default_d
          opts = qemu_opts_parse(qemu_find_opts("acpi"), arg, 0);
          g_assert(opts != NULL);
  
-         acpi_table_add(opts, &err);
+         acpi_table_add_builtin(opts, &err);
          if (err) {
-             fprintf(stderr, "WARNING: failed to load %s: %s\n", filename,
-                     error_get_pretty(err));
+             error_report("WARNING: failed to load %s: %s", filename,
+                          error_get_pretty(err));
              error_free(err);
          }
          g_free(arg);
@@@ -1148,12 -1174,14 +1187,14 @@@ FWCfgState *pc_memory_init(MemoryRegio
      memory_region_init_alias(ram_below_4g, NULL, "ram-below-4g", ram,
                               0, below_4g_mem_size);
      memory_region_add_subregion(system_memory, 0, ram_below_4g);
+     e820_add_entry(0, below_4g_mem_size, E820_RAM);
      if (above_4g_mem_size > 0) {
          ram_above_4g = g_malloc(sizeof(*ram_above_4g));
          memory_region_init_alias(ram_above_4g, NULL, "ram-above-4g", ram,
                                   below_4g_mem_size, above_4g_mem_size);
          memory_region_add_subregion(system_memory, 0x100000000ULL,
                                      ram_above_4g);
+         e820_add_entry(0x100000000ULL, above_4g_mem_size, E820_RAM);
      }
  
  
diff --combined hw/i386/pc_piix.c
@@@ -25,6 -25,7 +25,7 @@@
  #include <glib.h>
  
  #include "hw/hw.h"
+ #include "hw/loader.h"
  #include "hw/i386/pc.h"
  #include "hw/i386/apic.h"
  #include "hw/pci/pci.h"
  
  #define MAX_IDE_BUS 2
  
++#ifdef CONFIG_MARU
++void pc_init_pci(QEMUMachineInitArgs *args);
++
++extern MemoryRegion *global_ram_memory; 
++extern void *preallocated_ptr;
++#endif
++
  static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
  static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
  static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
  
- static bool has_pvpanic;
- static bool has_pci_info = true;
+ static bool has_pci_info;
+ static bool has_acpi_build = true;
  
  /* PC hardware initialisation */
- static void pc_init1(MemoryRegion *system_memory,
-                      MemoryRegion *system_io,
-                      ram_addr_t ram_size,
-                      const char *boot_device,
-                      const char *kernel_filename,
-                      const char *kernel_cmdline,
-                      const char *initrd_filename,
-                      const char *cpu_model,
+ static void pc_init1(QEMUMachineInitArgs *args,
                       int pci_enabled,
                       int kvmclock_enabled)
  {
+     MemoryRegion *system_memory = get_system_memory();
+     MemoryRegion *system_io = get_system_io();
      int i;
      ram_addr_t below_4g_mem_size, above_4g_mem_size;
      PCIBus *pci_bus;
      object_property_add_child(qdev_get_machine(), "icc-bridge",
                                OBJECT(icc_bridge), NULL);
  
-     pc_cpus_init(cpu_model, icc_bridge);
+     pc_cpus_init(args->cpu_model, icc_bridge);
  
      if (kvm_enabled() && kvmclock_enabled) {
          kvmclock_create();
      }
  
-     if (ram_size >= QEMU_BELOW_4G_RAM_END ) {
-         above_4g_mem_size = ram_size - QEMU_BELOW_4G_RAM_END;
-         below_4g_mem_size = QEMU_BELOW_4G_RAM_END;
+     if (args->ram_size >= 0xe0000000) {
+         above_4g_mem_size = args->ram_size - 0xe0000000;
+         below_4g_mem_size = 0xe0000000;
      } else {
          above_4g_mem_size = 0;
-         below_4g_mem_size = ram_size;
+         below_4g_mem_size = args->ram_size;
      }
  
      if (pci_enabled) {
      }
  
      guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
+     guest_info->has_acpi_build = has_acpi_build;
      guest_info->has_pci_info = has_pci_info;
      guest_info->isapc_ram_fw = !pci_enabled;
  
++#ifdef CONFIG_MARU
++    // for ramdump...
++    global_ram_memory = ram_memory;
++#endif
++
      /* allocate ram and load rom/bios */
      if (!xen_enabled()) {
++#ifdef CONFIG_MARU
++        // W/A for allocate larger continuous heap.
++        // see vl.c
++        if(preallocated_ptr != NULL) {
++            g_free(preallocated_ptr);
++        }
++#endif
          fw_cfg = pc_memory_init(system_memory,
-                        kernel_filename, kernel_cmdline, initrd_filename,
 -                       args->kernel_filename, args->kernel_cmdline,
 -                       args->initrd_filename,
--                       below_4g_mem_size, above_4g_mem_size,
--                       rom_memory, &ram_memory, guest_info);
++                args->kernel_filename, args->kernel_cmdline,
++                args->initrd_filename,
++                below_4g_mem_size, above_4g_mem_size,
++                rom_memory, &ram_memory, guest_info);
      }
  
      gsi_state = g_malloc0(sizeof(*gsi_state));
      if (kvm_irqchip_in_kernel()) {
          kvm_pc_setup_irq_routing(pci_enabled);
          gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
--                                 GSI_NUM_PINS);
++                GSI_NUM_PINS);
      } else {
          gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
      }
  
      if (pci_enabled) {
          pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
-                               system_memory, system_io, ram_size,
+                               system_memory, system_io, args->ram_size,
                                below_4g_mem_size,
                                0x100000000ULL - below_4g_mem_size,
                                above_4g_mem_size,
          }
      }
  
-     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
+     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, args->boot_order,
                   floppy, idebus[0], idebus[1], rtc_state);
  
      if (pci_enabled && usb_enabled(false)) {
      if (pci_enabled) {
          pc_pci_device_init(pci_bus);
      }
-     if (has_pvpanic) {
-         pvpanic_init(isa_bus);
-     }
  }
  
++#ifdef CONFIG_MARU
++void pc_init_pci(QEMUMachineInitArgs *args)
++#else
  static void pc_init_pci(QEMUMachineInitArgs *args)
++#endif
  {
-     ram_addr_t ram_size = args->ram_size;
-     const char *cpu_model = args->cpu_model;
-     const char *kernel_filename = args->kernel_filename;
-     const char *kernel_cmdline = args->kernel_cmdline;
-     const char *initrd_filename = args->initrd_filename;
-     const char *boot_device = args->boot_device;
-     pc_init1(get_system_memory(),
-              get_system_io(),
-              ram_size, boot_device,
-              kernel_filename, kernel_cmdline,
-              initrd_filename, cpu_model, 1, 1);
+     pc_init1(args, 1, 1);
  }
  
- static void pc_init_pci_1_6(QEMUMachineInitArgs *args)
+ static void pc_compat_1_6(QEMUMachineInitArgs *args)
  {
      has_pci_info = false;
-     pc_init_pci(args);
+     rom_file_in_ram = false;
+     has_acpi_build = false;
  }
  
- static void pc_init_pci_1_5(QEMUMachineInitArgs *args)
+ static void pc_compat_1_5(QEMUMachineInitArgs *args)
  {
-     has_pvpanic = true;
-     pc_init_pci_1_6(args);
+     pc_compat_1_6(args);
  }
  
- static void pc_init_pci_1_4(QEMUMachineInitArgs *args)
+ static void pc_compat_1_4(QEMUMachineInitArgs *args)
  {
+     pc_compat_1_5(args);
      x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE);
      x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
-     has_pci_info = false;
-     pc_init_pci(args);
  }
  
- static void pc_init_pci_1_3(QEMUMachineInitArgs *args)
+ static void pc_compat_1_3(QEMUMachineInitArgs *args)
  {
+     pc_compat_1_4(args);
      enable_compat_apic_id_mode();
-     pc_init_pci_1_4(args);
  }
  
- /* PC machine init function for pc-1.1 to pc-1.2 */
- static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
+ /* PC compat function for pc-0.14 to pc-1.2 */
+ static void pc_compat_1_2(QEMUMachineInitArgs *args)
  {
+     pc_compat_1_3(args);
      disable_kvm_pv_eoi();
-     pc_init_pci_1_3(args);
  }
  
- /* PC machine init function for pc-0.14 to pc-1.0 */
- static void pc_init_pci_1_0(QEMUMachineInitArgs *args)
+ static void pc_init_pci_1_6(QEMUMachineInitArgs *args)
+ {
+     pc_compat_1_6(args);
+     pc_init_pci(args);
+ }
+ static void pc_init_pci_1_5(QEMUMachineInitArgs *args)
+ {
+     pc_compat_1_5(args);
+     pc_init_pci(args);
+ }
+ static void pc_init_pci_1_4(QEMUMachineInitArgs *args)
+ {
+     pc_compat_1_4(args);
+     pc_init_pci(args);
+ }
+ static void pc_init_pci_1_3(QEMUMachineInitArgs *args)
  {
-     pc_init_pci_1_2(args);
+     pc_compat_1_3(args);
+     pc_init_pci(args);
+ }
+ /* PC machine init function for pc-0.14 to pc-1.2 */
+ static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
+ {
+     pc_compat_1_2(args);
+     pc_init_pci(args);
  }
  
  /* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */
  static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args)
  {
-     ram_addr_t ram_size = args->ram_size;
-     const char *cpu_model = args->cpu_model;
-     const char *kernel_filename = args->kernel_filename;
-     const char *kernel_cmdline = args->kernel_cmdline;
-     const char *initrd_filename = args->initrd_filename;
-     const char *boot_device = args->boot_device;
      has_pci_info = false;
+     has_acpi_build = false;
      disable_kvm_pv_eoi();
      enable_compat_apic_id_mode();
-     pc_init1(get_system_memory(),
-              get_system_io(),
-              ram_size, boot_device,
-              kernel_filename, kernel_cmdline,
-              initrd_filename, cpu_model, 1, 0);
+     pc_init1(args, 1, 0);
  }
  
  static void pc_init_isa(QEMUMachineInitArgs *args)
  {
-     ram_addr_t ram_size = args->ram_size;
-     const char *cpu_model = args->cpu_model;
-     const char *kernel_filename = args->kernel_filename;
-     const char *kernel_cmdline = args->kernel_cmdline;
-     const char *initrd_filename = args->initrd_filename;
-     const char *boot_device = args->boot_device;
      has_pci_info = false;
-     if (cpu_model == NULL)
-         cpu_model = "486";
+     has_acpi_build = false;
+     if (!args->cpu_model) {
+         args->cpu_model = "486";
+     }
      disable_kvm_pv_eoi();
      enable_compat_apic_id_mode();
-     pc_init1(get_system_memory(),
-              get_system_io(),
-              ram_size, boot_device,
-              kernel_filename, kernel_cmdline,
-              initrd_filename, cpu_model, 0, 1);
+     pc_init1(args, 0, 1);
  }
  
  #ifdef CONFIG_XEN
@@@ -341,40 -334,54 +357,54 @@@ static void pc_xen_hvm_init(QEMUMachine
  }
  #endif
  
+ #define PC_I440FX_MACHINE_OPTIONS \
+     PC_DEFAULT_MACHINE_OPTIONS, \
+     .desc = "Standard PC (i440FX + PIIX, 1996)", \
+     .hot_add_cpu = pc_hot_add_cpu
+ #define PC_I440FX_1_7_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
+ static QEMUMachine pc_i440fx_machine_v1_7 = {
+     PC_I440FX_1_7_MACHINE_OPTIONS,
+     .name = "pc-i440fx-1.7",
+     .alias = "pc",
+     .init = pc_init_pci,
+     .is_default = 1,
+ };
+ #define PC_I440FX_1_6_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
  static QEMUMachine pc_i440fx_machine_v1_6 = {
+     PC_I440FX_1_6_MACHINE_OPTIONS,
      .name = "pc-i440fx-1.6",
-     .alias = "pc",
-     .desc = "Standard PC (i440FX + PIIX, 1996)",
      .init = pc_init_pci_1_6,
-     .hot_add_cpu = pc_hot_add_cpu,
-     .max_cpus = 255,
-     .is_default = 1,
-     DEFAULT_MACHINE_OPTIONS,
+     .compat_props = (GlobalProperty[]) {
+         PC_COMPAT_1_6,
+         { /* end of list */ }
+     },
  };
  
  static QEMUMachine pc_i440fx_machine_v1_5 = {
+     PC_I440FX_1_6_MACHINE_OPTIONS,
      .name = "pc-i440fx-1.5",
-     .desc = "Standard PC (i440FX + PIIX, 1996)",
      .init = pc_init_pci_1_5,
-     .hot_add_cpu = pc_hot_add_cpu,
-     .max_cpus = 255,
      .compat_props = (GlobalProperty[]) {
          PC_COMPAT_1_5,
          { /* end of list */ }
      },
-     DEFAULT_MACHINE_OPTIONS,
  };
  
+ #define PC_I440FX_1_4_MACHINE_OPTIONS \
+     PC_I440FX_1_6_MACHINE_OPTIONS, \
+     .hot_add_cpu = NULL
  static QEMUMachine pc_i440fx_machine_v1_4 = {
+     PC_I440FX_1_4_MACHINE_OPTIONS,
      .name = "pc-i440fx-1.4",
-     .desc = "Standard PC (i440FX + PIIX, 1996)",
      .init = pc_init_pci_1_4,
-     .max_cpus = 255,
      .compat_props = (GlobalProperty[]) {
          PC_COMPAT_1_4,
          { /* end of list */ }
      },
-     DEFAULT_MACHINE_OPTIONS,
  };
  
  #define PC_COMPAT_1_3 \
          }
  
  static QEMUMachine pc_machine_v1_3 = {
+     PC_I440FX_1_4_MACHINE_OPTIONS,
      .name = "pc-1.3",
-     .desc = "Standard PC",
      .init = pc_init_pci_1_3,
-     .max_cpus = 255,
      .compat_props = (GlobalProperty[]) {
          PC_COMPAT_1_3,
          { /* end of list */ }
      },
-     DEFAULT_MACHINE_OPTIONS,
  };
  
  #define PC_COMPAT_1_2 \
              .value    = "off",\
          }
  
+ #define PC_I440FX_1_2_MACHINE_OPTIONS \
+     PC_I440FX_1_4_MACHINE_OPTIONS, \
+     .init = pc_init_pci_1_2
  static QEMUMachine pc_machine_v1_2 = {
+     PC_I440FX_1_2_MACHINE_OPTIONS,
      .name = "pc-1.2",
-     .desc = "Standard PC",
-     .init = pc_init_pci_1_2,
-     .max_cpus = 255,
      .compat_props = (GlobalProperty[]) {
          PC_COMPAT_1_2,
          { /* end of list */ }
      },
-     DEFAULT_MACHINE_OPTIONS,
  };
  
  #define PC_COMPAT_1_1 \
          }
  
  static QEMUMachine pc_machine_v1_1 = {
+     PC_I440FX_1_2_MACHINE_OPTIONS,
      .name = "pc-1.1",
-     .desc = "Standard PC",
-     .init = pc_init_pci_1_2,
-     .max_cpus = 255,
      .compat_props = (GlobalProperty[]) {
          PC_COMPAT_1_1,
          { /* end of list */ }
      },
-     DEFAULT_MACHINE_OPTIONS,
  };
  
  #define PC_COMPAT_1_0 \
          }
  
  static QEMUMachine pc_machine_v1_0 = {
+     PC_I440FX_1_2_MACHINE_OPTIONS,
      .name = "pc-1.0",
-     .desc = "Standard PC",
-     .init = pc_init_pci_1_0,
-     .max_cpus = 255,
      .compat_props = (GlobalProperty[]) {
          PC_COMPAT_1_0,
          { /* end of list */ }
      },
      .hw_version = "1.0",
-     DEFAULT_MACHINE_OPTIONS,
  };
  
  #define PC_COMPAT_0_15 \
          PC_COMPAT_1_0
  
  static QEMUMachine pc_machine_v0_15 = {
+     PC_I440FX_1_2_MACHINE_OPTIONS,
      .name = "pc-0.15",
-     .desc = "Standard PC",
-     .init = pc_init_pci_1_0,
-     .max_cpus = 255,
      .compat_props = (GlobalProperty[]) {
          PC_COMPAT_0_15,
          { /* end of list */ }
      },
      .hw_version = "0.15",
-     DEFAULT_MACHINE_OPTIONS,
  };
  
  #define PC_COMPAT_0_14 \
          }
  
  static QEMUMachine pc_machine_v0_14 = {
+     PC_I440FX_1_2_MACHINE_OPTIONS,
      .name = "pc-0.14",
-     .desc = "Standard PC",
-     .init = pc_init_pci_1_0,
-     .max_cpus = 255,
      .compat_props = (GlobalProperty[]) {
          PC_COMPAT_0_14, 
          {
          { /* end of list */ }
      },
      .hw_version = "0.14",
-     DEFAULT_MACHINE_OPTIONS,
  };
  
  #define PC_COMPAT_0_13 \
              .value    = stringify(1),\
          }
  
+ #define PC_I440FX_0_13_MACHINE_OPTIONS \
+     PC_I440FX_1_2_MACHINE_OPTIONS, \
+     .init = pc_init_pci_no_kvmclock
  static QEMUMachine pc_machine_v0_13 = {
+     PC_I440FX_0_13_MACHINE_OPTIONS,
      .name = "pc-0.13",
-     .desc = "Standard PC",
-     .init = pc_init_pci_no_kvmclock,
-     .max_cpus = 255,
      .compat_props = (GlobalProperty[]) {
          PC_COMPAT_0_13,
          {
          { /* end of list */ }
      },
      .hw_version = "0.13",
-     DEFAULT_MACHINE_OPTIONS,
  };
  
  #define PC_COMPAT_0_12 \
          }
  
  static QEMUMachine pc_machine_v0_12 = {
+     PC_I440FX_0_13_MACHINE_OPTIONS,
      .name = "pc-0.12",
-     .desc = "Standard PC",
-     .init = pc_init_pci_no_kvmclock,
-     .max_cpus = 255,
      .compat_props = (GlobalProperty[]) {
          PC_COMPAT_0_12,
          {
          { /* end of list */ }
      },
      .hw_version = "0.12",
-     DEFAULT_MACHINE_OPTIONS,
  };
  
  #define PC_COMPAT_0_11 \
          }
  
  static QEMUMachine pc_machine_v0_11 = {
+     PC_I440FX_0_13_MACHINE_OPTIONS,
      .name = "pc-0.11",
-     .desc = "Standard PC, qemu 0.11",
-     .init = pc_init_pci_no_kvmclock,
-     .max_cpus = 255,
      .compat_props = (GlobalProperty[]) {
          PC_COMPAT_0_11,
          {
          { /* end of list */ }
      },
      .hw_version = "0.11",
-     DEFAULT_MACHINE_OPTIONS,
  };
  
  static QEMUMachine pc_machine_v0_10 = {
+     PC_I440FX_0_13_MACHINE_OPTIONS,
      .name = "pc-0.10",
-     .desc = "Standard PC, qemu 0.10",
-     .init = pc_init_pci_no_kvmclock,
-     .max_cpus = 255,
      .compat_props = (GlobalProperty[]) {
          PC_COMPAT_0_11,
          {
          { /* end of list */ }
      },
      .hw_version = "0.10",
-     DEFAULT_MACHINE_OPTIONS,
  };
  
  static QEMUMachine isapc_machine = {
+     PC_COMMON_MACHINE_OPTIONS,
      .name = "isapc",
      .desc = "ISA-only PC",
      .init = pc_init_isa,
      .compat_props = (GlobalProperty[]) {
          { /* end of list */ }
      },
-     DEFAULT_MACHINE_OPTIONS,
  };
  
  #ifdef CONFIG_XEN
  static QEMUMachine xenfv_machine = {
+     PC_COMMON_MACHINE_OPTIONS,
      .name = "xenfv",
      .desc = "Xen Fully-virtualized PC",
      .init = pc_xen_hvm_init,
      .max_cpus = HVM_MAX_VCPUS,
      .default_machine_opts = "accel=xen",
-     DEFAULT_MACHINE_OPTIONS,
+     .hot_add_cpu = pc_hot_add_cpu,
  };
  #endif
  
  static void pc_machine_init(void)
  {
+     qemu_register_machine(&pc_i440fx_machine_v1_7);
      qemu_register_machine(&pc_i440fx_machine_v1_6);
      qemu_register_machine(&pc_i440fx_machine_v1_5);
      qemu_register_machine(&pc_i440fx_machine_v1_4);
diff --combined hw/i386/pc_sysfw.c
  #include "hw/block/flash.h"
  #include "sysemu/kvm.h"
  
 +#ifdef CONFIG_MARU
 +#include "../../tizen/src/maru_err_table.h"
 +#endif
 +
  #define BIOS_FILENAME "bios.bin"
  
  typedef struct PcSysFwDevice {
@@@ -57,10 -53,7 +57,7 @@@ static void pc_isa_bios_init(MemoryRegi
      flash_size = memory_region_size(flash_mem);
  
      /* map the last 128KB of the BIOS in ISA space */
-     isa_bios_size = flash_size;
-     if (isa_bios_size > (128 * 1024)) {
-         isa_bios_size = 128 * 1024;
-     }
+     isa_bios_size = MIN(flash_size, 128 * 1024);
      isa_bios = g_malloc(sizeof(*isa_bios));
      memory_region_init_ram(isa_bios, NULL, "isa-bios", isa_bios_size);
      vmstate_register_ram_global(isa_bios);
@@@ -141,9 -134,6 +138,9 @@@ static void old_pc_system_rom_init(Memo
      if (ret != 0) {
      bios_error:
          fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name);
 +#ifdef CONFIG_MARU
 +        maru_register_exit_msg(MARU_EXIT_BIOS_FILE_EXCEPTION, bios_name);
 +#endif
          exit(1);
      }
      if (filename) {
diff --combined hw/intc/apic_common.c
@@@ -198,7 -198,7 +198,7 @@@ void apic_init_reset(DeviceState *d
      s->wait_for_sipi = 1;
  
      if (s->timer) {
-         qemu_del_timer(s->timer);
+         timer_del(s->timer);
      }
      s->timer_expiry = -1;
  }
@@@ -305,13 -305,11 +305,13 @@@ static int apic_init_common(ICCDevice *
          mmio_registered = true;
      }
  
 +#ifndef CONFIG_MARU
      /* Note: We need at least 1M to map the VAPIC option ROM */
      if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK &&
          ram_size >= 1024 * 1024) {
          vapic = sysbus_create_simple("kvmvapic", -1, NULL);
      }
 +#endif
      s->vapic = vapic;
      if (apic_report_tpr_access && info->enable_tpr_reporting) {
          info->enable_tpr_reporting(s, true);
diff --combined hw/pci/pci-hotplug-old.c
@@@ -248,7 -248,7 +248,7 @@@ static PCIDevice *qemu_pci_hot_add_stor
          }
          dev = pci_create(bus, devfn, "virtio-blk-pci");
          if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
-             qdev_free(&dev->qdev);
+             object_unparent(OBJECT(dev));
              dev = NULL;
              break;
          }
      return dev;
  }
  
 +#ifdef CONFIG_MARU
 +static PCIDevice *qemu_pci_hot_add_keyboard(Monitor *mon,
 +                                            const char *devaddr,
 +                                            const char *opts)
 +{
 +    PCIDevice *dev;
 +    PCIBus *root = pci_find_primary_bus();
 +    PCIBus *bus;
 +    int devfn;
 +
 +    if (!root) {
 +        monitor_printf(mon, "no primary PCI bus (if there are multiple"
 +                       " PCI roots, you must use device_add instead)");
 +        return NULL;
 +    }
 +
 +    bus = pci_get_bus_devfn(&devfn, root, devaddr);
 +    if (!bus) {
 +        monitor_printf(mon, "Invalid PCI device address %s\n", devaddr);
 +        return NULL;
 +    }
 +
 +    if (!((BusState*)bus)->allow_hotplug) {
 +        monitor_printf(mon, "PCI bus doesn't support hotplug\n");
 +        return NULL;
 +    }
 +
 +    dev = pci_create(bus, devfn, "virtio-keyboard-pci");
 +    if (qdev_init(&dev->qdev) < 0) {
 +        dev = NULL;
 +    }
 +
 +    return dev;
 +}
 +#endif /* CONFIG_MARU */
 +
 +#ifdef CONFIG_MARU
 +void pci_device_hot_add(Monitor *mon, const QDict *qdict)
 +{
 +    do_pci_device_hot_add(mon, qdict);
 +}
 +
 +PCIDevice *do_pci_device_hot_add(Monitor *mon, const QDict *qdict)
 +#else
  void pci_device_hot_add(Monitor *mon, const QDict *qdict)
 +#endif
  {
      PCIDevice *dev = NULL;
      const char *pci_addr = qdict_get_str(qdict, "pci_addr");
          dev = qemu_pci_hot_add_nic(mon, pci_addr, opts);
      } else if (strcmp(type, "storage") == 0) {
          dev = qemu_pci_hot_add_storage(mon, pci_addr, opts);
 +#ifdef CONFIG_MARU
 +    } else if (strcmp(type, "keyboard") == 0) {
 +        dev = qemu_pci_hot_add_keyboard(mon, pci_addr, opts);
 +#endif
      } else {
          monitor_printf(mon, "invalid type: %s\n", type);
      }
                         PCI_FUNC(dev->devfn));
      } else
          monitor_printf(mon, "failed to add %s\n", opts);
 +#ifdef CONFIG_MARU
 +    return dev;
 +#endif
  }
  
  static int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
diff --combined hw/pci/pci.c
@@@ -47,6 -47,7 +47,7 @@@ static void pcibus_dev_print(Monitor *m
  static char *pcibus_get_dev_path(DeviceState *dev);
  static char *pcibus_get_fw_dev_path(DeviceState *dev);
  static int pcibus_reset(BusState *qbus);
+ static void pci_bus_finalize(Object *obj);
  
  static Property pci_props[] = {
      DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
@@@ -73,6 -74,7 +74,7 @@@ static const TypeInfo pci_bus_info = 
      .name = TYPE_PCI_BUS,
      .parent = TYPE_BUS,
      .instance_size = sizeof(PCIBus),
+     .instance_finalize = pci_bus_finalize,
      .class_init = pci_bus_class_init,
  };
  
@@@ -83,7 -85,7 +85,7 @@@ static const TypeInfo pcie_bus_info = 
  
  static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
  static void pci_update_mappings(PCIDevice *d);
- static void pci_set_irq(void *opaque, int irq_num, int level);
+ static void pci_irq_handler(void *opaque, int irq_num, int level);
  static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
  static void pci_del_option_rom(PCIDevice *pdev);
  
@@@ -161,7 -163,7 +163,7 @@@ void pci_device_deassert_intx(PCIDevic
  {
      int i;
      for (i = 0; i < PCI_NUM_PINS; ++i) {
-         qemu_set_irq(dev->irq[i], 0);
+         pci_irq_handler(dev, i, 0);
      }
  }
  
@@@ -312,13 -314,13 +314,13 @@@ bool pci_bus_is_root(PCIBus *bus
      return !bus->parent_dev;
  }
  
- void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
+ void pci_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
                           const char *name,
                           MemoryRegion *address_space_mem,
                           MemoryRegion *address_space_io,
                           uint8_t devfn_min, const char *typename)
  {
-     qbus_create_inplace(bus, typename, parent, name);
+     qbus_create_inplace(bus, bus_size, typename, parent, name);
      pci_bus_init(bus, parent, name, address_space_mem,
                   address_space_io, devfn_min);
  }
@@@ -375,6 -377,12 +377,12 @@@ int pci_bus_num(PCIBus *s
      return s->parent_dev->config[PCI_SECONDARY_BUS];
  }
  
+ static void pci_bus_finalize(Object *obj)
+ {
+     PCIBus *bus = PCI_BUS(obj);
+     vmstate_unregister(NULL, &vmstate_pcibus, bus);
+ }
  static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
  {
      PCIDevice *s = container_of(pv, PCIDevice, config);
@@@ -812,12 -820,7 +820,7 @@@ static PCIDevice *do_pci_register_devic
      }
  
      pci_dev->bus = bus;
-     if (bus->iommu_fn) {
-         dma_as = bus->iommu_fn(bus, bus->iommu_opaque, devfn);
-     } else {
-         /* FIXME: inherit memory region from bus creator */
-         dma_as = &address_space_memory;
-     }
+     dma_as = pci_device_iommu_address_space(pci_dev);
  
      memory_region_init_alias(&pci_dev->bus_master_enable_region,
                               OBJECT(pci_dev), "bus master",
      pci_dev->config_read = config_read;
      pci_dev->config_write = config_write;
      bus->devices[devfn] = pci_dev;
-     pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, PCI_NUM_PINS);
      pci_dev->version_id = 2; /* Current pci device vmstate version */
      return pci_dev;
  }
  
  static void do_pci_unregister_device(PCIDevice *pci_dev)
  {
-     qemu_free_irqs(pci_dev->irq);
      pci_dev->bus->devices[pci_dev->devfn] = NULL;
      pci_config_free(pci_dev);
  
@@@ -1033,8 -1034,10 +1034,10 @@@ static pcibus_t pci_bar_address(PCIDevi
          }
          new_addr = pci_get_long(d->config + bar) & ~(size - 1);
          last_addr = new_addr + size - 1;
-         /* NOTE: we have only 64K ioports on PC */
-         if (last_addr <= new_addr || new_addr == 0 || last_addr > UINT16_MAX) {
+         /* Check if 32 bit BAR wraps around explicitly.
+          * TODO: make priorities correct and remove this work around.
+          */
+         if (last_addr <= new_addr || new_addr == 0 || last_addr >= UINT32_MAX) {
              return PCI_BAR_UNMAPPED;
          }
          return new_addr;
@@@ -1178,7 -1181,7 +1181,7 @@@ void pci_default_write_config(PCIDevic
  /* generic PCI irq support */
  
  /* 0 <= irq_num <= 3. level must be 0 or 1 */
- static void pci_set_irq(void *opaque, int irq_num, int level)
+ static void pci_irq_handler(void *opaque, int irq_num, int level)
  {
      PCIDevice *pci_dev = opaque;
      int change;
      pci_change_irq_level(pci_dev, irq_num, change);
  }
  
+ static inline int pci_intx(PCIDevice *pci_dev)
+ {
+     return pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1;
+ }
+ qemu_irq pci_allocate_irq(PCIDevice *pci_dev)
+ {
+     int intx = pci_intx(pci_dev);
+     return qemu_allocate_irq(pci_irq_handler, pci_dev, intx);
+ }
+ void pci_set_irq(PCIDevice *pci_dev, int level)
+ {
+     int intx = pci_intx(pci_dev);
+     pci_irq_handler(pci_dev, intx, level);
+ }
  /* Special hooks used by device assignment */
  void pci_bus_set_route_irq_fn(PCIBus *bus, pci_route_irq_fn route_intx_to_irq)
  {
@@@ -1466,7 -1487,7 +1487,7 @@@ static PciDeviceInfo *qmp_query_pci_dev
      info->function = PCI_FUNC(dev->devfn);
  
      class = pci_get_word(dev->config + PCI_CLASS_DEVICE);
-     info->class_info.class = class;
+     info->class_info.q_class = class;
      desc = get_class_desc(class);
      if (desc->desc) {
          info->class_info.has_desc = true;
@@@ -1634,10 -1655,6 +1655,10 @@@ PCIDevice *pci_vga_init(PCIBus *bus
          return pci_create_simple(bus, -1, "VGA");
      case VGA_VMWARE:
          return pci_create_simple(bus, -1, "vmware-svga");
 +#ifdef CONFIG_MARU
 +    case VGA_MARU:
 +        return pci_create_simple(bus, -1, "MARU_VGA");
 +#endif
      case VGA_NONE:
      default: /* Other non-PCI types. Checking for unsupported types is already
                  done in vl.c. */
@@@ -2243,12 -2260,83 +2264,83 @@@ static void pci_device_class_init(Objec
      k->props = pci_props;
  }
  
+ AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
+ {
+     PCIBus *bus = PCI_BUS(dev->bus);
+     if (bus->iommu_fn) {
+         return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn);
+     }
+     if (bus->parent_dev) {
+         /** We are ignoring the bus master DMA bit of the bridge
+          *  as it would complicate things such as VFIO for no good reason */
+         return pci_device_iommu_address_space(bus->parent_dev);
+     }
+     return &address_space_memory;
+ }
  void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque)
  {
      bus->iommu_fn = fn;
      bus->iommu_opaque = opaque;
  }
  
+ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
+ {
+     Range *range = opaque;
+     PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+     uint16_t cmd = pci_get_word(dev->config + PCI_COMMAND);
+     int i;
+     if (!(cmd & PCI_COMMAND_MEMORY)) {
+         return;
+     }
+     if (pc->is_bridge) {
+         pcibus_t base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
+         pcibus_t limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
+         base = MAX(base, 0x1ULL << 32);
+         if (limit >= base) {
+             Range pref_range;
+             pref_range.begin = base;
+             pref_range.end = limit + 1;
+             range_extend(range, &pref_range);
+         }
+     }
+     for (i = 0; i < PCI_NUM_REGIONS; ++i) {
+         PCIIORegion *r = &dev->io_regions[i];
+         Range region_range;
+         if (!r->size ||
+             (r->type & PCI_BASE_ADDRESS_SPACE_IO) ||
+             !(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
+             continue;
+         }
+         region_range.begin = pci_bar_address(dev, i, r->type, r->size);
+         region_range.end = region_range.begin + r->size;
+         if (region_range.begin == PCI_BAR_UNMAPPED) {
+             continue;
+         }
+         region_range.begin = MAX(region_range.begin, 0x1ULL << 32);
+         if (region_range.end - 1 >= region_range.begin) {
+             range_extend(range, &region_range);
+         }
+     }
+ }
+ void pci_bus_get_w64_range(PCIBus *bus, Range *range)
+ {
+     range->begin = range->end = 0;
+     pci_for_each_device_under_bus(bus, pci_dev_get_w64, range);
+ }
  static const TypeInfo pci_device_type_info = {
      .name = TYPE_PCI_DEVICE,
      .parent = TYPE_DEVICE,
diff --combined hw/usb/dev-storage.c
  #include "sysemu/sysemu.h"
  #include "sysemu/blockdev.h"
  
 +#ifdef CONFIG_MARU
 +#include "../tizen/src/mloop_event.h"
 +#endif
 +
  //#define DEBUG_MSD
  
  #ifdef DEBUG_MSD
@@@ -550,13 -546,6 +550,13 @@@ static void usb_msd_handle_data(USBDevi
      }
  }
  
 +#ifdef CONFIG_MARU
 +static void usb_msd_handle_destroy(USBDevice *dev)
 +{
 +    mloop_evcmd_set_usbdisk(NULL);
 +}
 +#endif
 +
  static void usb_msd_password_cb(void *opaque, int err)
  {
      MSDState *s = opaque;
@@@ -629,7 -618,8 +629,8 @@@ static int usb_msd_initfn_storage(USBDe
  
      usb_desc_create_serial(dev);
      usb_desc_init(dev);
-     scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_storage, NULL);
+     scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
+                  &usb_msd_scsi_info_storage, NULL);
      scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable,
                                           s->conf.bootindex, dev->serial,
                                           &err);
@@@ -657,7 -647,8 +658,8 @@@ static int usb_msd_initfn_bot(USBDevic
  
      usb_desc_create_serial(dev);
      usb_desc_init(dev);
-     scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_bot, NULL);
+     scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
+                  &usb_msd_scsi_info_bot, NULL);
      s->bus.qbus.allow_hotplug = 0;
      usb_msd_handle_reset(dev);
  
@@@ -671,15 -662,13 +673,15 @@@ static USBDevice *usb_msd_init(USBBus *
      QemuOpts *opts;
      DriveInfo *dinfo;
      USBDevice *dev;
 +#ifndef CONFIG_MARU
      const char *p1;
      char fmt[32];
 +#endif
  
      /* parse -usbdevice disk: syntax into drive opts */
      snprintf(id, sizeof(id), "usb%d", nr++);
      opts = qemu_opts_create(qemu_find_opts("drive"), id, 0, NULL);
 -
 +#ifndef CONFIG_MARU
      p1 = strchr(filename, ':');
      if (p1++) {
          const char *p2;
          }
          filename = p1;
      }
 +#endif
      if (!*filename) {
          printf("block device specification needed\n");
          return NULL;
          return NULL;
      }
      if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
-         qdev_free(&dev->qdev);
+         object_unparent(OBJECT(dev));
          return NULL;
      }
      if (qdev_init(&dev->qdev) < 0)
          return NULL;
  
 +#ifdef CONFIG_MARU
 +    mloop_evcmd_set_usbdisk(dev);
 +#endif
 +
      return dev;
  }
  
@@@ -764,9 -748,6 +766,9 @@@ static void usb_msd_class_initfn_common
      uc->handle_reset   = usb_msd_handle_reset;
      uc->handle_control = usb_msd_handle_control;
      uc->handle_data    = usb_msd_handle_data;
 +#ifdef CONFIG_MARU
 +    uc->handle_destroy = usb_msd_handle_destroy;
 +#endif
      set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
      dc->fw_name = "storage";
      dc->vmsd = &vmstate_usb_msd;
diff --combined hw/vigs/vigs_device.c
index ef8e2d4,0000000..6cc986d
mode 100644,000000..100644
--- /dev/null
@@@ -1,372 -1,0 +1,372 @@@
-         qemu_irq_lower(s->dev.pci_dev.irq[0]);
 +/*
 + * vigs
 + *
 + * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
 + *
 + * Contact:
 + * Stanislav Vorobiov <s.vorobiov@samsung.com>
 + * Jinhyung Jo <jinhyung.jo@samsung.com>
 + * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +#include "vigs_device.h"
 +#include "vigs_log.h"
 +#include "vigs_server.h"
 +#include "vigs_backend.h"
 +#include "vigs_regs.h"
 +#include "hw/hw.h"
 +#include "ui/console.h"
 +
 +#define PCI_VENDOR_ID_VIGS 0x19B2
 +#define PCI_DEVICE_ID_VIGS 0x1011
 +
 +#define VIGS_IO_SIZE 0x1000
 +
 +typedef struct VIGSState
 +{
 +    VIGSDevice dev;
 +
 +    void *display;
 +
 +    MemoryRegion vram_bar;
 +    uint32_t vram_size;
 +
 +    MemoryRegion ram_bar;
 +    uint32_t ram_size;
 +
 +    MemoryRegion io_bar;
 +
 +    struct vigs_server *server;
 +
 +    /*
 +     * Our console.
 +     */
 +    QemuConsole *con;
 +
 +    uint32_t reg_int;
 +} VIGSState;
 +
 +#define TYPE_VIGS_DEVICE "vigs"
 +
 +extern const char *vigs_backend;
 +
 +static void vigs_update_irq(VIGSState *s)
 +{
 +    if ((s->reg_int & VIGS_REG_INT_VBLANK_ENABLE) == 0) {
-         qemu_irq_raise(s->dev.pci_dev.irq[0]);
++        pci_set_irq(&s->dev.pci_dev, 0);
 +        return;
 +    }
 +
 +    if (s->reg_int & VIGS_REG_INT_VBLANK_PENDING) {
-         qemu_irq_lower(s->dev.pci_dev.irq[0]);
++        pci_set_irq(&s->dev.pci_dev, 1);
 +    } else {
++        pci_set_irq(&s->dev.pci_dev, 0);
 +    }
 +}
 +
 +static void vigs_hw_update(void *opaque)
 +{
 +    VIGSState *s = opaque;
 +    DisplaySurface *ds = qemu_console_surface(s->con);
 +
 +    if (!surface_data(ds)) {
 +        return;
 +    }
 +
 +    vigs_server_update_display(s->server);
 +
 +    dpy_gfx_update(s->con, 0, 0, surface_width(ds), surface_height(ds));
 +
 +    if (s->reg_int & VIGS_REG_INT_VBLANK_ENABLE) {
 +        s->reg_int |= VIGS_REG_INT_VBLANK_PENDING;
 +        vigs_update_irq(s);
 +    }
 +}
 +
 +static void vigs_hw_invalidate(void *opaque)
 +{
 +}
 +
 +static void vigs_dpy_resize(void *user_data,
 +                            uint32_t width,
 +                            uint32_t height)
 +{
 +    VIGSState *s = user_data;
 +    DisplaySurface *ds = qemu_console_surface(s->con);
 +
 +    if ((width != surface_width(ds)) ||
 +        (height != surface_height(ds)))
 +    {
 +        qemu_console_resize(s->con, width, height);
 +    }
 +}
 +
 +static uint32_t vigs_dpy_get_stride(void *user_data)
 +{
 +    VIGSState *s = user_data;
 +    DisplaySurface *ds = qemu_console_surface(s->con);
 +
 +    return surface_stride(ds);
 +}
 +
 +static uint32_t vigs_dpy_get_bpp(void *user_data)
 +{
 +    VIGSState *s = user_data;
 +    DisplaySurface *ds = qemu_console_surface(s->con);
 +
 +    return surface_bytes_per_pixel(ds);
 +}
 +
 +static uint8_t *vigs_dpy_get_data(void *user_data)
 +{
 +    VIGSState *s = user_data;
 +    DisplaySurface *ds = qemu_console_surface(s->con);
 +
 +    return surface_data(ds);
 +}
 +
 +static uint64_t vigs_io_read(void *opaque, hwaddr offset,
 +                             unsigned size)
 +{
 +    VIGSState *s = opaque;
 +
 +    switch (offset) {
 +    case VIGS_REG_INT:
 +        return s->reg_int;
 +    default:
 +        VIGS_LOG_CRITICAL("Bad register 0x%X read", (uint32_t)offset);
 +        break;
 +    }
 +
 +    return 0;
 +}
 +
 +static void vigs_io_write(void *opaque, hwaddr offset,
 +                          uint64_t value, unsigned size)
 +{
 +    VIGSState *s = opaque;
 +
 +    switch (offset) {
 +    case VIGS_REG_EXEC:
 +        vigs_server_dispatch(s->server, value);
 +        break;
 +    case VIGS_REG_INT:
 +        if (((s->reg_int & VIGS_REG_INT_VBLANK_PENDING) == 0) &&
 +            (value & VIGS_REG_INT_VBLANK_PENDING)) {
 +            VIGS_LOG_CRITICAL("Attempt to set VBLANK_PENDING");
 +            value &= ~VIGS_REG_INT_VBLANK_PENDING;
 +        }
 +
 +        if (((s->reg_int & VIGS_REG_INT_VBLANK_ENABLE) == 0) &&
 +            (value & VIGS_REG_INT_VBLANK_ENABLE)) {
 +            VIGS_LOG_DEBUG("VBLANK On");
 +        } else if (((value & VIGS_REG_INT_VBLANK_ENABLE) == 0) &&
 +                   (s->reg_int & VIGS_REG_INT_VBLANK_ENABLE)) {
 +            VIGS_LOG_DEBUG("VBLANK Off");
 +        }
 +
 +        s->reg_int = value & VIGS_REG_INT_MASK;
 +        if ((value & VIGS_REG_INT_VBLANK_ENABLE) == 0) {
 +            s->reg_int &= ~VIGS_REG_INT_VBLANK_PENDING;
 +        }
 +        vigs_update_irq(s);
 +        break;
 +    default:
 +        VIGS_LOG_CRITICAL("Bad register 0x%X write", (uint32_t)offset);
 +        break;
 +    }
 +}
 +
 +static struct GraphicHwOps vigs_hw_ops =
 +{
 +    .invalidate = vigs_hw_invalidate,
 +    .gfx_update = vigs_hw_update
 +};
 +
 +static const MemoryRegionOps vigs_io_ops =
 +{
 +    .read = vigs_io_read,
 +    .write = vigs_io_write,
 +    .endianness = DEVICE_NATIVE_ENDIAN,
 +};
 +
 +static struct vigs_display_ops vigs_dpy_ops =
 +{
 +    .resize = vigs_dpy_resize,
 +    .get_stride = vigs_dpy_get_stride,
 +    .get_bpp = vigs_dpy_get_bpp,
 +    .get_data = vigs_dpy_get_data,
 +};
 +
 +static int vigs_device_init(PCIDevice *dev)
 +{
 +    VIGSState *s = DO_UPCAST(VIGSState, dev.pci_dev, dev);
 +    struct vigs_backend *backend = NULL;
 +
 +    vigs_log_init();
 +
 +    if (s->vram_size < 16 * 1024 * 1024) {
 +        VIGS_LOG_WARN("\"vram_size\" is too small, defaulting to 16mb");
 +        s->vram_size = 16 * 1024 * 1024;
 +    }
 +
 +    if (s->ram_size < 1 * 1024 * 1024) {
 +        VIGS_LOG_WARN("\"ram_size\" is too small, defaulting to 1mb");
 +        s->ram_size = 1 * 1024 * 1024;
 +    }
 +
 +    pci_config_set_interrupt_pin(dev->config, 1);
 +
 +    memory_region_init_ram(&s->vram_bar, OBJECT(s),
 +                           TYPE_VIGS_DEVICE ".vram",
 +                           s->vram_size);
 +
 +    memory_region_init_ram(&s->ram_bar, OBJECT(s),
 +                           TYPE_VIGS_DEVICE ".ram",
 +                           s->ram_size);
 +
 +    memory_region_init_io(&s->io_bar, OBJECT(s),
 +                          &vigs_io_ops,
 +                          s,
 +                          TYPE_VIGS_DEVICE ".io",
 +                          VIGS_IO_SIZE);
 +
 +    pci_register_bar(&s->dev.pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->vram_bar);
 +    pci_register_bar(&s->dev.pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_bar);
 +    pci_register_bar(&s->dev.pci_dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io_bar);
 +
 +    if (!strcmp(vigs_backend, "gl")) {
 +        backend = vigs_gl_backend_create(s->display);
 +    } else if (!strcmp(vigs_backend, "sw")) {
 +        backend = vigs_sw_backend_create();
 +    }
 +
 +    if (!backend) {
 +        goto fail;
 +    }
 +
 +    s->con = graphic_console_init(DEVICE(dev), &vigs_hw_ops, s);
 +
 +    if (!s->con) {
 +        goto fail;
 +    }
 +
 +    s->server = vigs_server_create(memory_region_get_ram_ptr(&s->vram_bar),
 +                                   memory_region_get_ram_ptr(&s->ram_bar),
 +                                   &vigs_dpy_ops,
 +                                   s,
 +                                   backend);
 +
 +    if (!s->server) {
 +        goto fail;
 +    }
 +
 +    s->dev.wsi = &s->server->wsi;
 +
 +    VIGS_LOG_INFO("VIGS initialized");
 +
 +    VIGS_LOG_DEBUG("vram_size = %u", s->vram_size);
 +    VIGS_LOG_DEBUG("ram_size = %u", s->ram_size);
 +
 +    return 0;
 +
 +fail:
 +    if (backend) {
 +        backend->destroy(backend);
 +    }
 +
 +    memory_region_destroy(&s->io_bar);
 +    memory_region_destroy(&s->ram_bar);
 +    memory_region_destroy(&s->vram_bar);
 +
 +    vigs_log_cleanup();
 +
 +    return -1;
 +}
 +
 +static void vigs_device_reset(DeviceState *d)
 +{
 +    VIGSState *s = container_of(d, VIGSState, dev.pci_dev.qdev);
 +
 +    vigs_server_reset(s->server);
 +
 +    s->reg_int = 0;
 +
 +    VIGS_LOG_INFO("VIGS reset");
 +}
 +
 +static void vigs_device_exit(PCIDevice *dev)
 +{
 +    VIGSState *s = DO_UPCAST(VIGSState, dev.pci_dev, dev);
 +
 +    vigs_server_destroy(s->server);
 +
 +    memory_region_destroy(&s->io_bar);
 +    memory_region_destroy(&s->ram_bar);
 +    memory_region_destroy(&s->vram_bar);
 +
 +    VIGS_LOG_INFO("VIGS deinitialized");
 +
 +    vigs_log_cleanup();
 +}
 +
 +static Property vigs_properties[] = {
 +    {
 +        .name   = "display",
 +        .info   = &qdev_prop_ptr,
 +        .offset = offsetof(VIGSState, display),
 +    },
 +    DEFINE_PROP_UINT32("vram_size", VIGSState, vram_size,
 +                       32 * 1024 * 1024),
 +    DEFINE_PROP_UINT32("ram_size", VIGSState, ram_size,
 +                       1 * 1024 * 1024),
 +    DEFINE_PROP_END_OF_LIST(),
 +};
 +
 +static void vigs_class_init(ObjectClass *klass, void *data)
 +{
 +    DeviceClass *dc = DEVICE_CLASS(klass);
 +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = vigs_device_init;
 +    k->exit = vigs_device_exit;
 +    k->vendor_id = PCI_VENDOR_ID_VIGS;
 +    k->device_id = PCI_DEVICE_ID_VIGS;
 +    k->class_id = PCI_CLASS_DISPLAY_VGA;
 +    dc->reset = vigs_device_reset;
 +    dc->props = vigs_properties;
 +    dc->desc = "VIGS device";
 +}
 +
 +static TypeInfo vigs_device_info =
 +{
 +    .name          = TYPE_VIGS_DEVICE,
 +    .parent        = TYPE_PCI_DEVICE,
 +    .instance_size = sizeof(VIGSState),
 +    .class_init    = vigs_class_init,
 +};
 +
 +static void vigs_register_types(void)
 +{
 +    type_register_static(&vigs_device_info);
 +}
 +
 +type_init(vigs_register_types)
diff --combined hw/virtio/virtio-pci.c
@@@ -92,7 -92,8 +92,8 @@@
  /* HACK for virtio to determine if it's running a big endian guest */
  bool virtio_is_big_endian(void);
  
- static void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev);
+ static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size,
+                                VirtIOPCIProxy *dev);
  
  /* virtio device */
  /* DeviceState to VirtIOPCIProxy. For use off data-path. TODO: use QOM. */
@@@ -115,7 -116,7 +116,7 @@@ static void virtio_pci_notify(DeviceSta
      if (msix_enabled(&proxy->pci_dev))
          msix_notify(&proxy->pci_dev, vector);
      else
-         qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1);
+         pci_set_irq(&proxy->pci_dev, proxy->vdev->isr & 1);
  }
  
  static void virtio_pci_save_config(DeviceState *d, QEMUFile *f)
@@@ -361,7 -362,7 +362,7 @@@ static uint32_t virtio_ioport_read(Virt
          /* reading from the ISR also clears it. */
          ret = vdev->isr;
          vdev->isr = 0;
-         qemu_set_irq(proxy->pci_dev.irq[0], 0);
+         pci_irq_deassert(&proxy->pci_dev);
          break;
      case VIRTIO_MSI_CONFIG_VECTOR:
          ret = vdev->config_vector;
@@@ -508,7 -509,7 +509,7 @@@ static int kvm_virtio_pci_irqfd_use(Vir
      VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
      EventNotifier *n = virtio_queue_get_guest_notifier(vq);
      int ret;
-     ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, irqfd->virq);
+     ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, NULL, irqfd->virq);
      return ret;
  }
  
@@@ -645,7 -646,7 +646,7 @@@ static void virtio_pci_vq_vector_mask(V
  
      /* If guest supports masking, keep irqfd but mask it.
       * Otherwise, clean it up now.
 -     */ 
 +     */
      if (k->guest_notifier_mask) {
          k->guest_notifier_mask(proxy->vdev, queue_no, true);
      } else {
@@@ -917,7 -918,7 +918,7 @@@ static void virtio_9p_pci_class_init(Ob
  static void virtio_9p_pci_instance_init(Object *obj)
  {
      V9fsPCIState *dev = VIRTIO_9P_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_9P);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_9P);
      object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
  }
  
@@@ -985,7 -986,7 +986,7 @@@ static int virtio_pci_init(PCIDevice *p
  {
      VirtIOPCIProxy *dev = VIRTIO_PCI(pci_dev);
      VirtioPCIClass *k = VIRTIO_PCI_GET_CLASS(pci_dev);
-     virtio_pci_bus_new(&dev->bus, dev);
+     virtio_pci_bus_new(&dev->bus, sizeof(dev->bus), dev);
      if (k->init != NULL) {
          return k->init(dev);
      }
@@@ -1077,7 -1078,7 +1078,7 @@@ static void virtio_blk_pci_class_init(O
  static void virtio_blk_pci_instance_init(Object *obj)
  {
      VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_BLK);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BLK);
      object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
  }
  
@@@ -1147,7 -1148,7 +1148,7 @@@ static void virtio_scsi_pci_class_init(
  static void virtio_scsi_pci_instance_init(Object *obj)
  {
      VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SCSI);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SCSI);
      object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
  }
  
@@@ -1204,7 -1205,7 +1205,7 @@@ static void vhost_scsi_pci_class_init(O
  static void vhost_scsi_pci_instance_init(Object *obj)
  {
      VHostSCSIPCI *dev = VHOST_SCSI_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VHOST_SCSI);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VHOST_SCSI);
      object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
  }
  
@@@ -1285,7 -1286,7 +1286,7 @@@ static void virtio_balloon_pci_class_in
  static void virtio_balloon_pci_instance_init(Object *obj)
  {
      VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_BALLOON);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BALLOON);
      object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
  
      object_property_add(obj, "guest-stats", "guest statistics",
@@@ -1371,7 -1372,7 +1372,7 @@@ static void virtio_serial_pci_class_ini
  static void virtio_serial_pci_instance_init(Object *obj)
  {
      VirtIOSerialPCI *dev = VIRTIO_SERIAL_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SERIAL);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SERIAL);
      object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
  }
  
@@@ -1430,7 -1431,7 +1431,7 @@@ static void virtio_net_pci_class_init(O
  static void virtio_net_pci_instance_init(Object *obj)
  {
      VirtIONetPCI *dev = VIRTIO_NET_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_NET);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_NET);
      object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
  }
  
@@@ -1486,7 -1487,7 +1487,7 @@@ static void virtio_rng_pci_class_init(O
  static void virtio_rng_initfn(Object *obj)
  {
      VirtIORngPCI *dev = VIRTIO_RNG_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_RNG);
+     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG);
      object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
      object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
                               (Object **)&dev->vdev.conf.rng, NULL);
@@@ -1501,353 -1502,16 +1502,354 @@@ static const TypeInfo virtio_rng_pci_in
      .class_init    = virtio_rng_pci_class_init,
  };
  
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_GL);
 +#ifdef CONFIG_MARU
 +/* virtio-gl-pci */
 +
 +static int virtio_gl_pci_init(VirtIOPCIProxy *vpci_dev)
 +{
 +    VirtIOGLPCI *dev = VIRTIO_GL_PCI(vpci_dev);
 +    DeviceState *vdev = DEVICE(&dev->vdev);
 +
 +    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
 +    if (qdev_init(vdev) < 0) {
 +        return -1;
 +    }
 +
 +    return 0;
 +}
 +
 +static void virtio_gl_pci_class_init(ObjectClass *klass, void *data)
 +{
 +    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 +    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = virtio_gl_pci_init;
 +    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
 +    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_GL;
 +    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
 +    pcidev_k->class_id = PCI_CLASS_OTHERS;
 +}
 +
 +static void virtio_gl_pci_instance_init(Object *obj)
 +{
 +    VirtIOGLPCI *dev = VIRTIO_GL_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_TOUCHSCREEN);
++    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_GL);
 +    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 +}
 +
 +static TypeInfo virtio_gl_pci_info = {
 +    .name          = TYPE_VIRTIO_GL_PCI,
 +    .parent        = TYPE_VIRTIO_PCI,
 +    .instance_size = sizeof(VirtIOGLPCI),
 +    .instance_init = virtio_gl_pci_instance_init,
 +    .class_init    = virtio_gl_pci_class_init,
 +};
 +
 +/* virtio-touchscreen-pci */
 +
 +static int virtio_touchscreen_pci_init(VirtIOPCIProxy *vpci_dev)
 +{
 +    VirtIOTouchscreenPCI *dev = VIRTIO_TOUCHSCREEN_PCI(vpci_dev);
 +    DeviceState *vdev = DEVICE(&dev->vdev);
 +
 +    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
 +    if (qdev_init(vdev) < 0) {
 +        return -1;
 +    }
 +    return 0;
 +}
 +
 +static void virtio_touchscreen_pci_class_init(ObjectClass *klass, void *data)
 +{
 +//    DeviceClass *dc = DEVICE_CLASS(klass);
 +    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 +    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = virtio_touchscreen_pci_init;
 +    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
 +    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_TOUCHSCREEN;
 +    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
 +    pcidev_k->class_id = PCI_CLASS_OTHERS;
 +}
 +
 +static void virtio_touchscreen_pci_instance_init(Object *obj)
 +{
 +    VirtIOTouchscreenPCI *dev = VIRTIO_TOUCHSCREEN_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_KEYBOARD);
++    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_TOUCHSCREEN);
 +    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 +}
 +
 +static TypeInfo virtio_touchscreen_pci_info = {
 +    .name          = TYPE_VIRTIO_TOUCHSCREEN_PCI,
 +    .parent        = TYPE_VIRTIO_PCI,
 +    .instance_size = sizeof(VirtIOTouchscreenPCI),
 +      .instance_init = virtio_touchscreen_pci_instance_init,
 +    .class_init    = virtio_touchscreen_pci_class_init,
 +};
 +
 +/* virtio-keyboard-pci */
 +
 +static int virtio_keyboard_pci_init(VirtIOPCIProxy *vpci_dev)
 +{
 +    VirtIOKeyboardPCI *dev = VIRTIO_KEYBOARD_PCI(vpci_dev);
 +    DeviceState *vdev = DEVICE(&dev->vdev);
 +
 +    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
 +    if (qdev_init(vdev) < 0) {
 +        return -1;
 +    }
 +    return 0;
 +}
 +
 +static void virtio_keyboard_pci_class_init(ObjectClass *klass, void *data)
 +{
 +//    DeviceClass *dc = DEVICE_CLASS(klass);
 +    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 +    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = virtio_keyboard_pci_init;
 +    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
 +    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_KEYBOARD;
 +    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
 +    pcidev_k->class_id = PCI_CLASS_OTHERS;
 +}
 +
 +static void virtio_keyboard_pci_instance_init(Object *obj)
 +{
 +    VirtIOKeyboardPCI *dev = VIRTIO_KEYBOARD_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_ESM);
++    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_KEYBOARD);
 +    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 +}
 +
 +static TypeInfo virtio_keyboard_pci_info = {
 +    .name          = TYPE_VIRTIO_KEYBOARD_PCI,
 +    .parent        = TYPE_VIRTIO_PCI,
 +    .instance_size = sizeof(VirtIOKeyboardPCI),
 +      .instance_init = virtio_keyboard_pci_instance_init,
 +    .class_init    = virtio_keyboard_pci_class_init,
 +};
 +
 +/* virtio-esm-pci */
 +
 +static int virtio_esm_pci_init(VirtIOPCIProxy *vpci_dev)
 +{
 +    VirtIOESMPCI *dev = VIRTIO_ESM_PCI(vpci_dev);
 +    DeviceState *vdev = DEVICE(&dev->vdev);
 +
 +    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
 +    if (qdev_init(vdev) < 0) {
 +        return -1;
 +    }
 +    return 0;
 +}
 +
 +static void virtio_esm_pci_class_init(ObjectClass *klass, void *data)
 +{
 +//    DeviceClass *dc = DEVICE_CLASS(klass);
 +    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 +    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = virtio_esm_pci_init;
 +    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
 +    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_ESM;
 +    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
 +    pcidev_k->class_id = PCI_CLASS_OTHERS;
 +}
 +
 +static void virtio_esm_pci_instance_init(Object *obj)
 +{
 +    VirtIOESMPCI *dev = VIRTIO_ESM_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_HWKEY);
++    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_ESM);
 +    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 +}
 +
 +static TypeInfo virtio_esm_pci_info = {
 +    .name          = TYPE_VIRTIO_ESM_PCI,
 +    .parent        = TYPE_VIRTIO_PCI,
 +    .instance_size = sizeof(VirtIOESMPCI),
 +      .instance_init = virtio_esm_pci_instance_init,
 +    .class_init    = virtio_esm_pci_class_init,
 +};
 +
 +/* virtio-hwkey-pci */
 +
 +static int virtio_hwkey_pci_init(VirtIOPCIProxy *vpci_dev)
 +{
 +    VirtIOHWKeyPCI *dev = VIRTIO_HWKEY_PCI(vpci_dev);
 +    DeviceState *vdev = DEVICE(&dev->vdev);
 +
 +    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
 +    if (qdev_init(vdev) < 0) {
 +        return -1;
 +    }
 +    return 0;
 +}
 +
 +static void virtio_hwkey_pci_class_init(ObjectClass *klass, void *data)
 +{
 +//    DeviceClass *dc = DEVICE_CLASS(klass);
 +    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 +    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = virtio_hwkey_pci_init;
 +    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
 +    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_HWKEY;
 +    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
 +    pcidev_k->class_id = PCI_CLASS_OTHERS;
 +}
 +
 +static void virtio_hwkey_pci_instance_init(Object *obj)
 +{
 +    VirtIOHWKeyPCI *dev = VIRTIO_HWKEY_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_EVDI);
++    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_HWKEY);
 +    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 +}
 +
 +static TypeInfo virtio_hwkey_pci_info = {
 +    .name          = TYPE_VIRTIO_HWKEY_PCI,
 +    .parent        = TYPE_VIRTIO_PCI,
 +    .instance_size = sizeof(VirtIOHWKeyPCI),
 +      .instance_init = virtio_hwkey_pci_instance_init,
 +    .class_init    = virtio_hwkey_pci_class_init,
 +};
 +
 +/* virtio-evdi-pci */
 +
 +static int virtio_evdi_pci_init(VirtIOPCIProxy *vpci_dev)
 +{
 +    VirtIOEVDIPCI *dev = VIRTIO_EVDI_PCI(vpci_dev);
 +    DeviceState *vdev = DEVICE(&dev->vdev);
 +
 +    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
 +    if (qdev_init(vdev) < 0) {
 +        return -1;
 +    }
 +    return 0;
 +}
 +
 +static void virtio_evdi_pci_class_init(ObjectClass *klass, void *data)
 +{
 +//    DeviceClass *dc = DEVICE_CLASS(klass);
 +    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 +    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = virtio_evdi_pci_init;
 +    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
 +    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_EVDI;
 +    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
 +    pcidev_k->class_id = PCI_CLASS_OTHERS;
 +}
 +
 +static void virtio_evdi_pci_instance_init(Object *obj)
 +{
 +    VirtIOEVDIPCI *dev = VIRTIO_EVDI_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SENSOR);
++    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_EVDI);
 +    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 +}
 +
 +static TypeInfo virtio_evdi_pci_info = {
 +    .name          = TYPE_VIRTIO_EVDI_PCI,
 +    .parent        = TYPE_VIRTIO_PCI,
 +    .instance_size = sizeof(VirtIOEVDIPCI),
 +      .instance_init = virtio_evdi_pci_instance_init,
 +    .class_init    = virtio_evdi_pci_class_init,
 +};
 +
 +/* virtio-sensor-pci */
 +
 +static int virtio_sensor_pci_init(VirtIOPCIProxy *vpci_dev)
 +{
 +    VirtIOSENSORPCI *dev = VIRTIO_SENSOR_PCI(vpci_dev);
 +    DeviceState *vdev = DEVICE(&dev->vdev);
 +
 +    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
 +    if (qdev_init(vdev) < 0) {
 +        return -1;
 +    }
 +    return 0;
 +}
 +
 +static void virtio_sensor_pci_class_init(ObjectClass *klass, void *data)
 +{
 +    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 +    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = virtio_sensor_pci_init;
 +    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
 +    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SENSOR;
 +    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
 +    pcidev_k->class_id = PCI_CLASS_OTHERS;
 +}
 +
 +static void virtio_sensor_pci_instance_init(Object *obj)
 +{
 +    VirtIOSENSORPCI *dev = VIRTIO_SENSOR_PCI(obj);
-     object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_NFC);
++    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SENSOR);
 +    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 +}
 +
 +static TypeInfo virtio_sensor_pci_info = {
 +    .name          = TYPE_VIRTIO_SENSOR_PCI,
 +    .parent        = TYPE_VIRTIO_PCI,
 +    .instance_size = sizeof(VirtIOSENSORPCI),
 +      .instance_init = virtio_sensor_pci_instance_init,
 +    .class_init    = virtio_sensor_pci_class_init,
 +};
 +
 +/* virtio NFC */
 +
 +static int virtio_nfc_pci_init(VirtIOPCIProxy *vpci_dev)
 +{
 +    VirtIONFCPCI *dev = VIRTIO_NFC_PCI(vpci_dev);
 +    DeviceState *vdev = DEVICE(&dev->vdev);
 +
 +    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
 +    if (qdev_init(vdev) < 0) {
 +        return -1;
 +    }
 +    return 0;
 +}
 +
 +static void virtio_nfc_pci_class_init(ObjectClass *klass, void *data)
 +{
 +    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
 +    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = virtio_nfc_pci_init;
 +    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
 +    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_NFC;
 +    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
 +    pcidev_k->class_id = PCI_CLASS_OTHERS;
 +}
 +
 +static void virtio_nfc_pci_instance_init(Object *obj)
 +{
 +    VirtIONFCPCI *dev = VIRTIO_NFC_PCI(obj);
++    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_NFC);
 +    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 +}
 +
 +static TypeInfo virtio_nfc_pci_info = {
 +    .name          = TYPE_VIRTIO_NFC_PCI,
 +    .parent        = TYPE_VIRTIO_PCI,
 +    .instance_size = sizeof(VirtIONFCPCI),
 +      .instance_init = virtio_nfc_pci_instance_init,
 +    .class_init    = virtio_nfc_pci_class_init,
 +};
 +
 +
 +#endif
 +
  /* virtio-pci-bus */
  
- static void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev)
+ static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size,
+                                VirtIOPCIProxy *dev)
  {
      DeviceState *qdev = DEVICE(dev);
      BusState *qbus;
      char virtio_bus_name[] = "virtio-bus";
  
-     qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_PCI_BUS, qdev,
+     qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_PCI_BUS, qdev,
                          virtio_bus_name);
      qbus = BUS(bus);
      qbus->allow_hotplug = 1;
@@@ -1894,16 -1558,6 +1896,16 @@@ static void virtio_pci_register_types(v
  #ifdef CONFIG_VHOST_SCSI
      type_register_static(&vhost_scsi_pci_info);
  #endif
 +#ifdef CONFIG_MARU
 +    type_register_static(&virtio_evdi_pci_info);
 +    type_register_static(&virtio_esm_pci_info);
 +    type_register_static(&virtio_hwkey_pci_info);
 +    type_register_static(&virtio_keyboard_pci_info);
 +    type_register_static(&virtio_touchscreen_pci_info);
 +    type_register_static(&virtio_gl_pci_info);
 +    type_register_static(&virtio_sensor_pci_info);
 +    type_register_static(&virtio_nfc_pci_info);
 +#endif
  }
  
  type_init(virtio_pci_register_types)
diff --combined include/exec/cpu-defs.h
@@@ -176,13 -176,7 +176,11 @@@ typedef struct CPUWatchpoint 
      sigjmp_buf jmp_env;                                                 \
      int exception_index;                                                \
                                                                          \
 +    /* for hax */                                                       \
 +    int hax_vcpu_dirty;                                                 \
 +    struct hax_vcpu_state *hax_vcpu;                                    \
 +                                                                        \
      /* user data */                                                     \
      void *opaque;                                                       \
-                                                                         \
-     const char *cpu_model_str;
  
  #endif
diff --combined include/hw/i386/pc.h
@@@ -9,6 -9,9 +9,9 @@@
  #include "hw/i386/ioapic.h"
  
  #include "qemu/range.h"
+ #include "qemu/bitmap.h"
+ #include "sysemu/sysemu.h"
+ #include "hw/pci/pci.h"
  
  /* PC-style peripherals (also used by other machines).  */
  
@@@ -17,10 -20,27 +20,27 @@@ typedef struct PcPciInfo 
      Range w64;
  } PcPciInfo;
  
+ #define ACPI_PM_PROP_S3_DISABLED "disable_s3"
+ #define ACPI_PM_PROP_S4_DISABLED "disable_s4"
+ #define ACPI_PM_PROP_S4_VAL "s4_val"
+ #define ACPI_PM_PROP_SCI_INT "sci_int"
+ #define ACPI_PM_PROP_ACPI_ENABLE_CMD "acpi_enable_cmd"
+ #define ACPI_PM_PROP_ACPI_DISABLE_CMD "acpi_disable_cmd"
+ #define ACPI_PM_PROP_PM_IO_BASE "pm_io_base"
+ #define ACPI_PM_PROP_GPE0_BLK "gpe0_blk"
+ #define ACPI_PM_PROP_GPE0_BLK_LEN "gpe0_blk_len"
  struct PcGuestInfo {
      bool has_pci_info;
      bool isapc_ram_fw;
+     hwaddr ram_size;
+     unsigned apic_id_limit;
+     bool apic_xrupt_override;
+     uint64_t numa_nodes;
+     uint64_t *node_mem;
+     uint64_t *node_cpu;
      FWCfgState *fw_cfg;
+     bool has_acpi_build;
  };
  
  /* parallel.c */
@@@ -94,9 -114,6 +114,9 @@@ extern int fd_bootchk
  void pc_register_ferr_irq(qemu_irq irq);
  void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
  
 +#define QEMU_BELOW_4G_RAM_END       0xe0000000
 +#define QEMU_BELOW_4G_MMIO_LENGTH   ((1ULL << 32) - QEMU_BELOW_4G_RAM_END)
 +
  void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge);
  void pc_hot_add_cpu(const int64_t id, Error **errp);
  void pc_acpi_init(const char *default_dsdt);
@@@ -176,6 -193,7 +196,7 @@@ PCIBus *i440fx_init(PCII440FXState **pi
                      MemoryRegion *pci_memory,
                      MemoryRegion *ram_memory);
  
+ PCIBus *find_i440fx(void);
  /* piix4.c */
  extern PCIDevice *piix4_dev;
  int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn);
@@@ -217,7 -235,7 +238,7 @@@ void pc_system_firmware_init(MemoryRegi
                               bool isapc_ram_fw);
  
  /* pvpanic.c */
void pvpanic_init(ISABus *bus);
uint16_t pvpanic_port(void);
  
  /* e820 types */
  #define E820_RAM        1
  
  int e820_add_entry(uint64_t, uint64_t, uint32_t);
  
+ #define PC_COMPAT_1_6 \
+         {\
+             .driver   = "e1000",\
+             .property = "mitigation",\
+             .value    = "off",\
+         },{\
+             .driver   = "qemu64-" TYPE_X86_CPU,\
+             .property = "model",\
+             .value    = stringify(2),\
+         },{\
+             .driver   = "qemu32-" TYPE_X86_CPU,\
+             .property = "model",\
+             .value    = stringify(3),\
+         },{\
+             .driver   = "i440FX-pcihost",\
+             .property = "short_root_bus",\
+             .value    = stringify(1),\
+         },{\
+             .driver   = "q35-pcihost",\
+             .property = "short_root_bus",\
+             .value    = stringify(1),\
+         }
  #define PC_COMPAT_1_5 \
+         PC_COMPAT_1_6, \
          {\
              .driver   = "Conroe-" TYPE_X86_CPU,\
              .property = "model",\
              .driver = TYPE_X86_CPU,\
              .property = "pmu",\
              .value = "on",\
+         },{\
+             .driver   = "i440FX-pcihost",\
+             .property = "short_root_bus",\
+             .value    = stringify(0),\
+         },{\
+             .driver   = "q35-pcihost",\
+             .property = "short_root_bus",\
+             .value    = stringify(0),\
          }
  
  #define PC_COMPAT_1_4 \
              .value    = stringify(0),\
          }
  
+ #define PC_COMMON_MACHINE_OPTIONS \
+     .default_boot_order = "cad"
+ #define PC_DEFAULT_MACHINE_OPTIONS \
+     PC_COMMON_MACHINE_OPTIONS, \
+     .hot_add_cpu = pc_hot_add_cpu, \
+     .max_cpus = 255
  #endif
diff --combined include/qemu-common.h
@@@ -191,6 -191,9 +191,9 @@@ int64_t strtosz_suffix(const char *nptr
  int64_t strtosz_suffix_unit(const char *nptr, char **end,
                              const char default_suffix, int64_t unit);
  
+ /* used to print char* safely */
+ #define STR_OR_NULL(str) ((str) ? (str) : "null")
  /* path.c */
  void init_paths(const char *prefix);
  const char *path(const char *pathname);
@@@ -475,11 -478,4 +478,11 @@@ size_t buffer_find_nonzero_offset(cons
   */
  int parse_debug_env(const char *name, int max, int initial);
  
 +#if defined(CONFIG_MARU) && defined(CONFIG_WIN32)
 +#include "../tizen/src/maru_common.h"
 +
 +int is_wow64(void);
 +bool get_java_path(char **java_path);
 +#endif
 +
  #endif
@@@ -28,13 -28,12 +28,13 @@@ extern const uint32_t arch_type
  
  void select_soundhw(const char *optarg);
  void do_acpitable_option(const QemuOpts *opts);
- void do_smbios_option(const char *optarg);
+ void do_smbios_option(QemuOpts *opts);
  void cpudef_init(void);
  void audio_init(void);
  int tcg_available(void);
  int kvm_available(void);
  int xen_available(void);
 +int hax_available(void);
  
  CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp);
  
diff --combined include/sysemu/kvm.h
@@@ -46,6 -46,7 +46,7 @@@ extern bool kvm_halt_in_kernel_allowed
  extern bool kvm_irqfds_allowed;
  extern bool kvm_msi_via_irqfd_allowed;
  extern bool kvm_gsi_routing_allowed;
+ extern bool kvm_gsi_direct_mapping;
  extern bool kvm_readonly_mem_allowed;
  
  #if defined CONFIG_KVM || !defined NEED_CPU_H
  #define kvm_gsi_routing_enabled() (kvm_gsi_routing_allowed)
  
  /**
+  * kvm_gsi_direct_mapping:
+  *
+  * Returns: true if GSI direct mapping is enabled.
+  */
+ #define kvm_gsi_direct_mapping() (kvm_gsi_direct_mapping)
+ /**
   * kvm_readonly_mem_enabled:
   *
   * Returns: true if KVM readonly memory is enabled (ie the kernel
  #define kvm_irqfds_enabled() (false)
  #define kvm_msi_via_irqfd_enabled() (false)
  #define kvm_gsi_routing_allowed() (false)
+ #define kvm_gsi_direct_mapping() (false)
  #define kvm_readonly_mem_enabled() (false)
  #endif
  
@@@ -161,11 -170,6 +170,6 @@@ int kvm_cpu_exec(CPUState *cpu)
  
  #ifdef NEED_CPU_H
  
- #if !defined(CONFIG_USER_ONLY)
- void *kvm_ram_alloc(ram_addr_t size);
- void *kvm_arch_ram_alloc(ram_addr_t size);
- #endif
  void kvm_setup_guest_memory(void *start, size_t size);
  void kvm_flush_coalesced_mmio_buffer(void);
  
@@@ -271,24 -275,6 +275,6 @@@ int kvm_check_extension(KVMState *s, un
  uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
                                        uint32_t index, int reg);
  
- void kvm_cpu_synchronize_state(CPUState *cpu);
- #ifdef CONFIG_HAX
- void hax_cpu_synchronize_state(CPUState *cpu);
- #endif
- /* generic hooks - to be moved/refactored once there are more users */
- static inline void cpu_synchronize_state(CPUState *cpu)
- {
-     if (kvm_enabled()) {
-         kvm_cpu_synchronize_state(cpu);
-     }
- #ifdef CONFIG_HAX
-     hax_cpu_synchronize_state(cpu);
- #endif
- }
  #if !defined(CONFIG_USER_ONLY)
  int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
                                         hwaddr *phys_addr);
  
  #endif /* NEED_CPU_H */
  
+ void kvm_cpu_synchronize_state(CPUState *cpu);
  void kvm_cpu_synchronize_post_reset(CPUState *cpu);
  void kvm_cpu_synchronize_post_init(CPUState *cpu);
 +#ifdef CONFIG_HAX
 +void hax_cpu_synchronize_post_reset(CPUArchState *env);
 +void hax_cpu_synchronize_post_init(CPUArchState *env);
 +#endif
  
+ /* generic hooks - to be moved/refactored once there are more users */
+ static inline void cpu_synchronize_state(CPUState *cpu)
+ {
+     if (kvm_enabled()) {
+         kvm_cpu_synchronize_state(cpu);
+     }
+ }
  static inline void cpu_synchronize_post_reset(CPUState *cpu)
  {
      if (kvm_enabled()) {
          kvm_cpu_synchronize_post_reset(cpu);
      }
 +#ifdef CONFIG_HAX
 +    CPUArchState *env = cpu->env_ptr;
 +    hax_cpu_synchronize_post_reset(env);
 +#endif
  }
  
  static inline void cpu_synchronize_post_init(CPUState *cpu)
      if (kvm_enabled()) {
          kvm_cpu_synchronize_post_init(cpu);
      }
 +#ifdef CONFIG_HAX
 +    CPUArchState *env = cpu->env_ptr;
 +    hax_cpu_synchronize_post_init(env);
 +#endif
  }
  
  int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
  int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg);
  void kvm_irqchip_release_virq(KVMState *s, int virq);
  
- int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
+ int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
+                                    EventNotifier *rn, int virq);
  int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
  void kvm_pc_gsi_handler(void *opaque, int n, int level);
  void kvm_pc_setup_irq_routing(bool pci_enabled);
diff --combined include/sysemu/sysemu.h
@@@ -16,8 -16,11 +16,11 @@@ extern const char *bios_name
  
  extern const char *qemu_name;
  extern uint8_t qemu_uuid[];
+ extern bool qemu_uuid_set;
  int qemu_uuid_parse(const char *str, uint8_t *uuid);
  #define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
+ #define UUID_NONE "00000000-0000-0000-0000-000000000000"
  
  bool runstate_check(RunState state);
  void runstate_set(RunState new_state);
@@@ -94,9 -97,6 +97,9 @@@ typedef enum DisplayTyp
      DT_SDL,
      DT_GTK,
      DT_NOGRAPHIC,
 +#ifdef CONFIG_MARU
 +    DT_MARU,
 +#endif
      DT_NONE,
  } DisplayType;
  
@@@ -104,16 -104,10 +107,16 @@@ extern int autostart
  
  typedef enum {
      VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_QXL,
 +#ifdef CONFIG_MARU
 +    VGA_MARU,
 +#endif
  } VGAInterfaceType;
  
  extern int vga_interface_type;
  #define xenfb_enabled (vga_interface_type == VGA_XENFB)
 +#ifdef CONFIG_MARU
 +#define maru_vga_enabled (vga_interface_type == VGA_MARU)
 +#endif
  
  extern int graphic_width;
  extern int graphic_height;
@@@ -135,7 -129,7 +138,7 @@@ extern int boot_menu
  extern uint8_t *boot_splash_filedata;
  extern size_t boot_splash_filedata_size;
  extern uint8_t qemu_extra_params_fw[2];
- extern QEMUClock *rtc_clock;
+ extern QEMUClockType rtc_clock;
  
  #define MAX_NODES 64
  #define MAX_CPUMASK_BITS 255
@@@ -156,11 -150,7 +159,11 @@@ extern const char *prom_envs[MAX_PROM_E
  extern unsigned int nb_prom_envs;
  
  /* pci-hotplug */
 +#ifdef CONFIG_MARU
 +PCIDevice *do_pci_device_hot_add(Monitor *mon, const QDict *qdict);
 +#endif
  void pci_device_hot_add(Monitor *mon, const QDict *qdict);
 +
  int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo);
  void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict);
  
@@@ -203,6 -193,8 +206,8 @@@ QemuOpts *qemu_get_machine_opts(void)
  
  bool usb_enabled(bool default_usb);
  
+ extern QemuOptsList qemu_legacy_drive_opts;
+ extern QemuOptsList qemu_common_drive_opts;
  extern QemuOptsList qemu_drive_opts;
  extern QemuOptsList qemu_chardev_opts;
  extern QemuOptsList qemu_device_opts;
diff --combined main-loop.c
@@@ -29,8 -29,6 +29,8 @@@
  #include "qemu/main-loop.h"
  #include "block/aio.h"
  
 +#include "sysemu/hax.h"
 +
  #ifndef _WIN32
  
  #include "qemu/compatfd.h"
@@@ -117,27 -115,11 +117,27 @@@ AioContext *qemu_get_aio_context(void
      return qemu_aio_context;
  }
  
 +#ifdef CONFIG_HAX
 +static void qemu_notify_hax_event(void)
 +{
 +   CPUArchState *env = NULL;
 +
 +   if (hax_enabled()) {
 +       for (env = first_cpu; env != NULL; env = env->next_cpu) {
 +           hax_raise_event(env);
 +       }
 +   }
 +}
 +#endif
 +
  void qemu_notify_event(void)
  {
      if (!qemu_aio_context) {
          return;
      }
 +#ifdef CONFIG_HAX
 +    qemu_notify_hax_event();
 +#endif
      aio_notify(qemu_aio_context);
  }
  
@@@ -149,10 -131,6 +149,6 @@@ int qemu_init_main_loop(void
      GSource *src;
  
      init_clocks();
-     if (init_timer_alarm() < 0) {
-         fprintf(stderr, "could not initialize alarm timer\n");
-         exit(1);
-     }
  
      ret = qemu_signal_init();
      if (ret) {
@@@ -173,10 -151,11 +169,11 @@@ static int max_priority
  static int glib_pollfds_idx;
  static int glib_n_poll_fds;
  
- static void glib_pollfds_fill(uint32_t *cur_timeout)
+ static void glib_pollfds_fill(int64_t *cur_timeout)
  {
      GMainContext *context = g_main_context_default();
      int timeout = 0;
+     int64_t timeout_ns;
      int n;
  
      g_main_context_prepare(context, &max_priority);
                                   glib_n_poll_fds);
      } while (n != glib_n_poll_fds);
  
-     if (timeout >= 0 && timeout < *cur_timeout) {
-         *cur_timeout = timeout;
+     if (timeout < 0) {
+         timeout_ns = -1;
+     } else {
+         timeout_ns = (int64_t)timeout * (int64_t)SCALE_MS;
      }
+     *cur_timeout = qemu_soonest_timeout(timeout_ns, *cur_timeout);
  }
  
  static void glib_pollfds_poll(void)
  
  #define MAX_MAIN_LOOP_SPIN (1000)
  
- static int os_host_main_loop_wait(uint32_t timeout)
+ static int os_host_main_loop_wait(int64_t timeout)
  {
      int ret;
      static int spin_counter;
       * print a message to the screen.  If we run into this condition, create
       * a fake timeout in order to give the VCPU threads a chance to run.
       */
-     if (spin_counter > MAX_MAIN_LOOP_SPIN) {
+     if (!timeout && (spin_counter > MAX_MAIN_LOOP_SPIN)) {
          static bool notified;
  
          if (!notified) {
              notified = true;
          }
  
-         timeout = 1;
+         timeout = SCALE_MS;
      }
  
-     if (timeout > 0) {
+     if (timeout) {
          spin_counter = 0;
          qemu_mutex_unlock_iothread();
      } else {
          spin_counter++;
      }
  
-     ret = g_poll((GPollFD *)gpollfds->data, gpollfds->len, timeout);
+     ret = qemu_poll_ns((GPollFD *)gpollfds->data, gpollfds->len, timeout);
  
-     if (timeout > 0) {
+     if (timeout) {
          qemu_mutex_lock_iothread();
      }
  
@@@ -391,7 -374,7 +392,7 @@@ static void pollfds_poll(GArray *pollfd
      }
  }
  
- static int os_host_main_loop_wait(uint32_t timeout)
+ static int os_host_main_loop_wait(int64_t timeout)
  {
      GMainContext *context = g_main_context_default();
      GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
      PollingEntry *pe;
      WaitObjects *w = &wait_objects;
      gint poll_timeout;
+     int64_t poll_timeout_ns;
      static struct timeval tv0;
      fd_set rfds, wfds, xfds;
      int nfds;
          poll_fds[n_poll_fds + i].events = G_IO_IN;
      }
  
-     if (poll_timeout < 0 || timeout < poll_timeout) {
-         poll_timeout = timeout;
+     if (poll_timeout < 0) {
+         poll_timeout_ns = -1;
+     } else {
+         poll_timeout_ns = (int64_t)poll_timeout * (int64_t)SCALE_MS;
      }
  
+     poll_timeout_ns = qemu_soonest_timeout(poll_timeout_ns, timeout);
      qemu_mutex_unlock_iothread();
-     g_poll_ret = g_poll(poll_fds, n_poll_fds + w->num, poll_timeout);
+     g_poll_ret = qemu_poll_ns(poll_fds, n_poll_fds + w->num, poll_timeout_ns);
      qemu_mutex_lock_iothread();
      if (g_poll_ret > 0) {
          for (i = 0; i < w->num; i++) {
@@@ -467,6 -456,7 +474,7 @@@ int main_loop_wait(int nonblocking
  {
      int ret;
      uint32_t timeout = UINT32_MAX;
+     int64_t timeout_ns;
  
      if (nonblocking) {
          timeout = 0;
      g_array_set_size(gpollfds, 0); /* reset for new iteration */
      /* XXX: separate device handlers from system ones */
  #ifdef CONFIG_SLIRP
-     slirp_update_timeout(&timeout);
-     slirp_pollfds_fill(gpollfds);
+     slirp_pollfds_fill(gpollfds, &timeout);
  #endif
      qemu_iohandler_fill(gpollfds);
-     ret = os_host_main_loop_wait(timeout);
+     if (timeout == UINT32_MAX) {
+         timeout_ns = -1;
+     } else {
+         timeout_ns = (uint64_t)timeout * (int64_t)(SCALE_MS);
+     }
+     timeout_ns = qemu_soonest_timeout(timeout_ns,
+                                       timerlistgroup_deadline_ns(
+                                           &main_loop_tlg));
+     ret = os_host_main_loop_wait(timeout_ns);
      qemu_iohandler_poll(gpollfds, ret);
  #ifdef CONFIG_SLIRP
      slirp_pollfds_poll(gpollfds, (ret < 0));
  #endif
  
-     qemu_run_all_timers();
+     qemu_clock_run_all_timers();
  
      return ret;
  }
@@@ -507,17 -507,14 +525,14 @@@ bool qemu_aio_wait(void
  void qemu_aio_set_fd_handler(int fd,
                               IOHandler *io_read,
                               IOHandler *io_write,
-                              AioFlushHandler *io_flush,
                               void *opaque)
  {
-     aio_set_fd_handler(qemu_aio_context, fd, io_read, io_write, io_flush,
-                        opaque);
+     aio_set_fd_handler(qemu_aio_context, fd, io_read, io_write, opaque);
  }
  #endif
  
  void qemu_aio_set_event_notifier(EventNotifier *notifier,
-                                  EventNotifierHandler *io_read,
-                                  AioFlushEventNotifierHandler *io_flush)
+                                  EventNotifierHandler *io_read)
  {
-     aio_set_event_notifier(qemu_aio_context, notifier, io_read, io_flush);
+     aio_set_event_notifier(qemu_aio_context, notifier, io_read);
  }
diff --combined qapi-schema.json
              'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } }
  
  ##
+ # @ImageInfoSpecificQCow2:
+ #
+ # @compat: compatibility level
+ #
+ # @lazy-refcounts: #optional on or off; only valid for compat >= 1.1
+ #
+ # Since: 1.7
+ ##
+ { 'type': 'ImageInfoSpecificQCow2',
+   'data': {
+       'compat': 'str',
+       '*lazy-refcounts': 'bool'
+   } }
+ ##
+ # @ImageInfoSpecificVmdk:
+ #
+ # @create-type: The create type of VMDK image
+ #
+ # @cid: Content id of image
+ #
+ # @parent-cid: Parent VMDK image's cid
+ #
+ # @extents: List of extent files
+ #
+ # Since: 1.7
+ ##
+ { 'type': 'ImageInfoSpecificVmdk',
+   'data': {
+       'create-type': 'str',
+       'cid': 'int',
+       'parent-cid': 'int',
+       'extents': ['ImageInfo']
+   } }
+ ##
+ # @ImageInfoSpecific:
+ #
+ # A discriminated record of image format specific information structures.
+ #
+ # Since: 1.7
+ ##
+ { 'union': 'ImageInfoSpecific',
+   'data': {
+       'qcow2': 'ImageInfoSpecificQCow2',
+       'vmdk': 'ImageInfoSpecificVmdk'
+   } }
+ ##
  # @ImageInfo:
  #
  # Information about a QEMU image file
  #
  # @encrypted: #optional true if the image is encrypted
  #
+ # @compressed: #optional true if the image is compressed (Since 1.7)
+ #
  # @backing-filename: #optional name of the backing file
  #
  # @full-backing-filename: #optional full path of the backing file
  #
  # @backing-image: #optional info of the backing image (since 1.6)
  #
+ # @format-specific: #optional structure supplying additional format-specific
+ # information (since 1.7)
+ #
  # Since: 1.3
  #
  ##
  { 'type': 'ImageInfo',
    'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool',
             '*actual-size': 'int', 'virtual-size': 'int',
-            '*cluster-size': 'int', '*encrypted': 'bool',
+            '*cluster-size': 'int', '*encrypted': 'bool', '*compressed': 'bool',
             '*backing-filename': 'str', '*full-backing-filename': 'str',
             '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'],
-            '*backing-image': 'ImageInfo' } }
+            '*backing-image': 'ImageInfo',
+            '*format-specific': 'ImageInfoSpecific' } }
  
  ##
  # @ImageCheck:
  #
  # @image: the info of image used (since: 1.6)
  #
+ # @bps_max: #optional total max in bytes (Since 1.7)
+ #
+ # @bps_rd_max: #optional read max in bytes (Since 1.7)
+ #
+ # @bps_wr_max: #optional write max in bytes (Since 1.7)
+ #
+ # @iops_max: #optional total I/O operations max (Since 1.7)
+ #
+ # @iops_rd_max: #optional read I/O operations max (Since 1.7)
+ #
+ # @iops_wr_max: #optional write I/O operations max (Since 1.7)
+ #
+ # @iops_size: #optional an I/O size in bytes (Since 1.7)
+ #
  # Since: 0.14.0
  #
  # Notes: This interface is only found in @BlockInfo.
              'encrypted': 'bool', 'encryption_key_missing': 'bool',
              'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',
              'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int',
-             'image': 'ImageInfo' } }
+             'image': 'ImageInfo',
+             '*bps_max': 'int', '*bps_rd_max': 'int',
+             '*bps_wr_max': 'int', '*iops_max': 'int',
+             '*iops_rd_max': 'int', '*iops_wr_max': 'int',
+             '*iops_size': 'int' } }
  
  ##
  # @BlockDeviceIoStatus:
  { 'enum': 'BlockDeviceIoStatus', 'data': [ 'ok', 'failed', 'nospace' ] }
  
  ##
+ # @BlockDeviceMapEntry:
+ #
+ # Entry in the metadata map of the device (returned by "qemu-img map")
+ #
+ # @start: Offset in the image of the first byte described by this entry
+ #         (in bytes)
+ #
+ # @length: Length of the range described by this entry (in bytes)
+ #
+ # @depth: Number of layers (0 = top image, 1 = top image's backing file, etc.)
+ #         before reaching one for which the range is allocated.  The value is
+ #         in the range 0 to the depth of the image chain - 1.
+ #
+ # @zero: the sectors in this range read as zeros
+ #
+ # @data: reading the image will actually read data from a file (in particular,
+ #        if @offset is present this means that the sectors are not simply
+ #        preallocated, but contain actual data in raw format)
+ #
+ # @offset: if present, the image file stores the data for this range in
+ #          raw format at the given offset.
+ #
+ # Since 1.7
+ ##
+ { 'type': 'BlockDeviceMapEntry',
+   'data': { 'start': 'int', 'length': 'int', 'depth': 'int', 'zero': 'bool',
+             'data': 'bool', '*offset': 'int' } }
+ ##
  # @BlockDirtyInfo:
  #
  # Block dirty bitmap information.
    'data': ['top', 'full', 'none'] }
  
  ##
+ # @BlockJobType:
+ #
+ # Type of a block job.
+ #
+ # @commit: block commit job type, see "block-commit"
+ #
+ # @stream: block stream job type, see "block-stream"
+ #
+ # @mirror: drive mirror job type, see "drive-mirror"
+ #
+ # @backup: drive backup job type, see "drive-backup"
+ #
+ # Since: 1.7
+ ##
+ { 'enum': 'BlockJobType',
+   'data': ['commit', 'stream', 'mirror', 'backup'] }
+ ##
  # @BlockJobInfo:
  #
  # Information about a long-running block device operation.
  # @existing: QEMU should look for an existing image file.
  #
  # @absolute-paths: QEMU should create a new image with absolute paths
- # for the backing file.
+ # for the backing file. If there is no backing file available, the new
+ # image will not be backed either.
  #
  # Since: 1.1
  ##
              '*mode': 'NewImageMode' } }
  
  ##
+ # @BlockdevSnapshotInternal
+ #
+ # @device: the name of the device to generate the snapshot from
+ #
+ # @name: the name of the internal snapshot to be created
+ #
+ # Notes: In transaction, if @name is empty, or any snapshot matching @name
+ #        exists, the operation will fail. Only some image formats support it,
+ #        for example, qcow2, rbd, and sheepdog.
+ #
+ # Since: 1.7
+ ##
+ { 'type': 'BlockdevSnapshotInternal',
+   'data': { 'device': 'str', 'name': 'str' } }
+ ##
  # @DriveBackup
  #
  # @device: the name of the device which should be copied.
    'data': {
         'blockdev-snapshot-sync': 'BlockdevSnapshot',
         'drive-backup': 'DriveBackup',
-        'abort': 'Abort'
+        'abort': 'Abort',
+        'blockdev-snapshot-internal-sync': 'BlockdevSnapshotInternal'
     } }
  
  ##
    'data': 'BlockdevSnapshot' }
  
  ##
+ # @blockdev-snapshot-internal-sync
+ #
+ # Synchronously take an internal snapshot of a block device, when the format
+ # of the image used supports it.
+ #
+ # For the arguments, see the documentation of BlockdevSnapshotInternal.
+ #
+ # Returns: nothing on success
+ #          If @device is not a valid block device, DeviceNotFound
+ #          If any snapshot matching @name exists, or @name is empty,
+ #          GenericError
+ #          If the format of the image used does not support it,
+ #          BlockFormatFeatureNotSupported
+ #
+ # Since 1.7
+ ##
+ { 'command': 'blockdev-snapshot-internal-sync',
+   'data': 'BlockdevSnapshotInternal' }
+ ##
+ # @blockdev-snapshot-delete-internal-sync
+ #
+ # Synchronously delete an internal snapshot of a block device, when the format
+ # of the image used support it. The snapshot is identified by name or id or
+ # both. One of the name or id is required. Return SnapshotInfo for the
+ # successfully deleted snapshot.
+ #
+ # @device: the name of the device to delete the snapshot from
+ #
+ # @id: optional the snapshot's ID to be deleted
+ #
+ # @name: optional the snapshot's name to be deleted
+ #
+ # Returns: SnapshotInfo on success
+ #          If @device is not a valid block device, DeviceNotFound
+ #          If snapshot not found, GenericError
+ #          If the format of the image used does not support it,
+ #          BlockFormatFeatureNotSupported
+ #          If @id and @name are both not specified, GenericError
+ #
+ # Since 1.7
+ ##
+ { 'command': 'blockdev-snapshot-delete-internal-sync',
+   'data': { 'device': 'str', '*id': 'str', '*name': 'str'},
+   'returns': 'SnapshotInfo' }
+ ##
  # @human-monitor-command:
  #
  # Execute a command on the human monitor and return the output.
  #
  # Since: 0.14.0
  #
- # Notes: This command only exists as a stop-gap.  It's use is highly
+ # Notes: This command only exists as a stop-gap.  Its use is highly
  #        discouraged.  The semantics of this command are not guaranteed.
  #
  #        Known limitations:
  #
  # @iops_wr: write I/O operations per second
  #
+ # @bps_max: #optional total max in bytes (Since 1.7)
+ #
+ # @bps_rd_max: #optional read max in bytes (Since 1.7)
+ #
+ # @bps_wr_max: #optional write max in bytes (Since 1.7)
+ #
+ # @iops_max: #optional total I/O operations max (Since 1.7)
+ #
+ # @iops_rd_max: #optional read I/O operations max (Since 1.7)
+ #
+ # @iops_wr_max: #optional write I/O operations max (Since 1.7)
+ #
+ # @iops_size: #optional an I/O size in bytes (Since 1.7)
+ #
  # Returns: Nothing on success
  #          If @device is not a valid block device, DeviceNotFound
  #
  ##
  { 'command': 'block_set_io_throttle',
    'data': { 'device': 'str', 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',
-             'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int' } }
+             'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int',
+             '*bps_max': 'int', '*bps_rd_max': 'int',
+             '*bps_wr_max': 'int', '*iops_max': 'int',
+             '*iops_rd_max': 'int', '*iops_wr_max': 'int',
+             '*iops_size': 'int' } }
  
  ##
  # @block-stream:
  ##
  { 'command': 'query-target', 'returns': 'TargetInfo' }
  
 +## Eric 2013.3.7 ##
 +
 +##
 +# @AccelInfo:
 +#
 +# Information describing the acceleration sensor value
 +#
 +# @Xaxis: x axis value of the acceleration sensor
 +# @Yaxis: y axis value of the acceleration sensor
 +# @Zaxis: z axis value of the acceleration sensor
 +#
 +# Since: 1.2.0
 +##
 +{ 'type': 'AccelInfo',
 +  'data': { 'Xaxis': 'int', 'Yaxis': 'int', 'Zaxis' : 'int'} }
 +
  ##
  # @QKeyCode:
  #
  ##
  { 'command': 'query-rx-filter', 'data': { '*name': 'str' },
    'returns': ['RxFilterInfo'] }
+ ##
+ # @BlockdevDiscardOptions
+ #
+ # Determines how to handle discard requests.
+ #
+ # @ignore:      Ignore the request
+ # @unmap:       Forward as an unmap request
+ #
+ # Since: 1.7
+ ##
+ { 'enum': 'BlockdevDiscardOptions',
+   'data': [ 'ignore', 'unmap' ] }
+ ##
+ # @BlockdevAioOptions
+ #
+ # Selects the AIO backend to handle I/O requests
+ #
+ # @threads:     Use qemu's thread pool
+ # @native:      Use native AIO backend (only Linux and Windows)
+ #
+ # Since: 1.7
+ ##
+ { 'enum': 'BlockdevAioOptions',
+   'data': [ 'threads', 'native' ] }
+ ##
+ # @BlockdevCacheOptions
+ #
+ # Includes cache-related options for block devices
+ #
+ # @writeback:   #optional enables writeback mode for any caches (default: true)
+ # @direct:      #optional enables use of O_DIRECT (bypass the host page cache;
+ #               default: false)
+ # @no-flush:    #optional ignore any flush requests for the device (default:
+ #               false)
+ #
+ # Since: 1.7
+ ##
+ { 'type': 'BlockdevCacheOptions',
+   'data': { '*writeback': 'bool',
+             '*direct': 'bool',
+             '*no-flush': 'bool' } }
+ ##
+ # @BlockdevOptionsBase
+ #
+ # Options that are available for all block devices, independent of the block
+ # driver.
+ #
+ # @driver:      block driver name
+ # @id:          #optional id by which the new block device can be referred to.
+ #               This is a required option on the top level of blockdev-add, and
+ #               currently not allowed on any other level.
+ # @discard:     #optional discard-related options (default: ignore)
+ # @cache:       #optional cache-related options
+ # @aio:         #optional AIO backend (default: threads)
+ # @rerror:      #optional how to handle read errors on the device
+ #               (default: report)
+ # @werror:      #optional how to handle write errors on the device
+ #               (default: enospc)
+ # @read-only:   #optional whether the block device should be read-only
+ #               (default: false)
+ #
+ # Since: 1.7
+ ##
+ { 'type': 'BlockdevOptionsBase',
+   'data': { 'driver': 'str',
+             '*id': 'str',
+             '*discard': 'BlockdevDiscardOptions',
+             '*cache': 'BlockdevCacheOptions',
+             '*aio': 'BlockdevAioOptions',
+             '*rerror': 'BlockdevOnError',
+             '*werror': 'BlockdevOnError',
+             '*read-only': 'bool' } }
+ ##
+ # @BlockdevOptionsFile
+ #
+ # Driver specific block device options for the file backend and similar
+ # protocols.
+ #
+ # @filename:    path to the image file
+ #
+ # Since: 1.7
+ ##
+ { 'type': 'BlockdevOptionsFile',
+   'data': { 'filename': 'str' } }
+ ##
+ # @BlockdevOptionsVVFAT
+ #
+ # Driver specific block device options for the vvfat protocol.
+ #
+ # @dir:         directory to be exported as FAT image
+ # @fat-type:    #optional FAT type: 12, 16 or 32
+ # @floppy:      #optional whether to export a floppy image (true) or
+ #               partitioned hard disk (false; default)
+ # @rw:          #optional whether to allow write operations (default: false)
+ #
+ # Since: 1.7
+ ##
+ { 'type': 'BlockdevOptionsVVFAT',
+   'data': { 'dir': 'str', '*fat-type': 'int', '*floppy': 'bool',
+             '*rw': 'bool' } }
+ ##
+ # @BlockdevOptionsGenericFormat
+ #
+ # Driver specific block device options for image format that have no option
+ # besides their data source.
+ #
+ # @file:        reference to or definition of the data source block device
+ #
+ # Since: 1.7
+ ##
+ { 'type': 'BlockdevOptionsGenericFormat',
+   'data': { 'file': 'BlockdevRef' } }
+ ##
+ # @BlockdevOptionsGenericCOWFormat
+ #
+ # Driver specific block device options for image format that have no option
+ # besides their data source and an optional backing file.
+ #
+ # @backing:     #optional reference to or definition of the backing file block
+ #               device (if missing, taken from the image file content). It is
+ #               allowed to pass an empty string here in order to disable the
+ #               default backing file.
+ #
+ # Since: 1.7
+ ##
+ { 'type': 'BlockdevOptionsGenericCOWFormat',
+   'base': 'BlockdevOptionsGenericFormat',
+   'data': { '*backing': 'BlockdevRef' } }
+ ##
+ # @BlockdevOptionsQcow2
+ #
+ # Driver specific block device options for qcow2.
+ #
+ # @lazy-refcounts:        #optional whether to enable the lazy refcounts
+ #                         feature (default is taken from the image file)
+ #
+ # @pass-discard-request:  #optional whether discard requests to the qcow2
+ #                         device should be forwarded to the data source
+ #
+ # @pass-discard-snapshot: #optional whether discard requests for the data source
+ #                         should be issued when a snapshot operation (e.g.
+ #                         deleting a snapshot) frees clusters in the qcow2 file
+ #
+ # @pass-discard-other:    #optional whether discard requests for the data source
+ #                         should be issued on other occasions where a cluster
+ #                         gets freed
+ #
+ # Since: 1.7
+ ##
+ { 'type': 'BlockdevOptionsQcow2',
+   'base': 'BlockdevOptionsGenericCOWFormat',
+   'data': { '*lazy-refcounts': 'bool',
+             '*pass-discard-request': 'bool',
+             '*pass-discard-snapshot': 'bool',
+             '*pass-discard-other': 'bool' } }
+ ##
+ # @BlockdevOptions
+ #
+ # Options for creating a block device.
+ #
+ # Since: 1.7
+ ##
+ { 'union': 'BlockdevOptions',
+   'base': 'BlockdevOptionsBase',
+   'discriminator': 'driver',
+   'data': {
+       'file':       'BlockdevOptionsFile',
+       'http':       'BlockdevOptionsFile',
+       'https':      'BlockdevOptionsFile',
+       'ftp':        'BlockdevOptionsFile',
+       'ftps':       'BlockdevOptionsFile',
+       'tftp':       'BlockdevOptionsFile',
+ # TODO gluster: Wait for structured options
+ # TODO iscsi: Wait for structured options
+ # TODO nbd: Should take InetSocketAddress for 'host'?
+ # TODO rbd: Wait for structured options
+ # TODO sheepdog: Wait for structured options
+ # TODO ssh: Should take InetSocketAddress for 'host'?
+       'vvfat':      'BlockdevOptionsVVFAT',
+ # TODO blkdebug: Wait for structured options
+ # TODO blkverify: Wait for structured options
+       'bochs':      'BlockdevOptionsGenericFormat',
+       'cloop':      'BlockdevOptionsGenericFormat',
+       'cow':        'BlockdevOptionsGenericCOWFormat',
+       'dmg':        'BlockdevOptionsGenericFormat',
+       'parallels':  'BlockdevOptionsGenericFormat',
+       'qcow':       'BlockdevOptionsGenericCOWFormat',
+       'qcow2':      'BlockdevOptionsQcow2',
+       'qed':        'BlockdevOptionsGenericCOWFormat',
+       'raw':        'BlockdevOptionsGenericFormat',
+       'vdi':        'BlockdevOptionsGenericFormat',
+       'vhdx':       'BlockdevOptionsGenericFormat',
+       'vmdk':       'BlockdevOptionsGenericCOWFormat',
+       'vpc':        'BlockdevOptionsGenericFormat'
+   } }
+ ##
+ # @BlockdevRef
+ #
+ # Reference to a block device.
+ #
+ # @definition:      defines a new block device inline
+ # @reference:       references the ID of an existing block device. An
+ #                   empty string means that no block device should be
+ #                   referenced.
+ #
+ # Since: 1.7
+ ##
+ { 'union': 'BlockdevRef',
+   'discriminator': {},
+   'data': { 'definition': 'BlockdevOptions',
+             'reference': 'str' } }
+ ##
+ # @blockdev-add:
+ #
+ # Creates a new block device.
+ #
+ # @options: block device options for the new device
+ #
+ # Since: 1.7
+ ##
+ { 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } }
diff --combined qemu-char.c
@@@ -193,6 -193,8 +193,8 @@@ void qemu_chr_fe_printf(CharDriverStat
      va_end(ap);
  }
  
+ static void remove_fd_in_watch(CharDriverState *chr);
  void qemu_chr_add_handlers(CharDriverState *s,
                             IOCanReadHandler *fd_can_read,
                             IOReadHandler *fd_read,
  
      if (!opaque && !fd_can_read && !fd_read && !fd_event) {
          fe_open = 0;
+         remove_fd_in_watch(s);
      } else {
          fe_open = 1;
      }
@@@ -281,7 -284,7 +284,7 @@@ static int mux_chr_write(CharDriverStat
                  int64_t ti;
                  int secs;
  
-                 ti = qemu_get_clock_ms(rt_clock);
+                 ti = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
                  if (d->timestamps_start == -1)
                      d->timestamps_start = ti;
                  ti -= d->timestamps_start;
@@@ -725,6 -728,14 +728,14 @@@ static void io_remove_watch_poll(guint 
      g_source_destroy(&iwp->parent);
  }
  
+ static void remove_fd_in_watch(CharDriverState *chr)
+ {
+     if (chr->fd_in_tag) {
+         io_remove_watch_poll(chr->fd_in_tag);
+         chr->fd_in_tag = 0;
+     }
+ }
  #ifndef _WIN32
  static GIOChannel *io_channel_from_fd(int fd)
  {
@@@ -798,7 -809,6 +809,6 @@@ static int io_channel_send(GIOChannel *
  typedef struct FDCharDriver {
      CharDriverState *chr;
      GIOChannel *fd_in, *fd_out;
-     guint fd_in_tag;
      int max_size;
      QTAILQ_ENTRY(FDCharDriver) node;
  } FDCharDriver;
@@@ -830,10 -840,7 +840,7 @@@ static gboolean fd_chr_read(GIOChannel 
      status = g_io_channel_read_chars(chan, (gchar *)buf,
                                       len, &bytes_read, NULL);
      if (status == G_IO_STATUS_EOF) {
-         if (s->fd_in_tag) {
-             io_remove_watch_poll(s->fd_in_tag);
-             s->fd_in_tag = 0;
-         }
+         remove_fd_in_watch(chr);
          qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
          return FALSE;
      }
@@@ -863,13 -870,10 +870,10 @@@ static void fd_chr_update_read_handler(
  {
      FDCharDriver *s = chr->opaque;
  
-     if (s->fd_in_tag) {
-         io_remove_watch_poll(s->fd_in_tag);
-         s->fd_in_tag = 0;
-     }
+     remove_fd_in_watch(chr);
      if (s->fd_in) {
-         s->fd_in_tag = io_add_watch_poll(s->fd_in, fd_chr_read_poll, fd_chr_read, chr);
+         chr->fd_in_tag = io_add_watch_poll(s->fd_in, fd_chr_read_poll,
+                                            fd_chr_read, chr);
      }
  }
  
@@@ -877,11 -881,7 +881,7 @@@ static void fd_chr_close(struct CharDri
  {
      FDCharDriver *s = chr->opaque;
  
-     if (s->fd_in_tag) {
-         io_remove_watch_poll(s->fd_in_tag);
-         s->fd_in_tag = 0;
-     }
+     remove_fd_in_watch(chr);
      if (s->fd_in) {
          g_io_channel_unref(s->fd_in);
      }
@@@ -1012,7 -1012,6 +1012,6 @@@ static CharDriverState *qemu_chr_open_s
  
  typedef struct {
      GIOChannel *fd;
-     guint fd_tag;
      int connected;
      int read_bytes;
      guint timer_tag;
@@@ -1123,10 -1122,7 +1122,7 @@@ static void pty_chr_state(CharDriverSta
      PtyCharDriver *s = chr->opaque;
  
      if (!connected) {
-         if (s->fd_tag) {
-             io_remove_watch_poll(s->fd_tag);
-             s->fd_tag = 0;
-         }
+         remove_fd_in_watch(chr);
          s->connected = 0;
          /* (re-)connect poll interval for idle guests: once per second.
           * We check more frequently in case the guests sends data to
          if (!s->connected) {
              s->connected = 1;
              qemu_chr_be_generic_open(chr);
-             s->fd_tag = io_add_watch_poll(s->fd, pty_chr_read_poll, pty_chr_read, chr);
+             chr->fd_in_tag = io_add_watch_poll(s->fd, pty_chr_read_poll,
+                                                pty_chr_read, chr);
          }
      }
  }
@@@ -1151,10 -1148,7 +1148,7 @@@ static void pty_chr_close(struct CharDr
      PtyCharDriver *s = chr->opaque;
      int fd;
  
-     if (s->fd_tag) {
-         io_remove_watch_poll(s->fd_tag);
-         s->fd_tag = 0;
-     }
+     remove_fd_in_watch(chr);
      fd = g_io_channel_unix_get_fd(s->fd);
      g_io_channel_unref(s->fd);
      close(fd);
@@@ -1665,9 -1659,6 +1659,9 @@@ static int win_chr_init(CharDriverStat
      COMSTAT comstat;
      DWORD size;
      DWORD err;
 +#ifdef CONFIG_MARU
 +    int open_flags, ret;
 +#endif
  
      s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
      if (!s->hsend) {
          fprintf(stderr, "Failed CreateEvent\n");
          goto fail;
      }
 -
 -    s->hcom = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL,
 +#ifndef CONFIG_MARU
 +    s->hcom = CreateFile(filename,
 +                      GENERIC_READ|GENERIC_WRITE, 0, NULL,
                        OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
 +#else
 +    open_flags = O_BINARY | O_RDWR;
 +    // TODO : FILE_FLAG_OVERLAPPED
 +
 +    ret = qemu_open(filename, open_flags, 0644);
 +    if (ret < 0) {
 +        fprintf(stderr, "win_chr_init failed(%d)\n", ret);
 +        goto fail;
 +    }
 +    s->hcom = (HANDLE)_get_osfhandle(ret);
 +#endif
      if (s->hcom == INVALID_HANDLE_VALUE) {
          fprintf(stderr, "Failed CreateFile (%lu)\n", GetLastError());
          s->hcom = NULL;
@@@ -2176,7 -2155,6 +2170,6 @@@ static CharDriverState *qemu_chr_open_s
  typedef struct {
      int fd;
      GIOChannel *chan;
-     guint tag;
      uint8_t buf[READ_BUF_LEN];
      int bufcnt;
      int bufptr;
@@@ -2232,10 -2210,7 +2225,7 @@@ static gboolean udp_chr_read(GIOChanne
      s->bufcnt = bytes_read;
      s->bufptr = s->bufcnt;
      if (status != G_IO_STATUS_NORMAL) {
-         if (s->tag) {
-             io_remove_watch_poll(s->tag);
-             s->tag = 0;
-         }
+         remove_fd_in_watch(chr);
          return FALSE;
      }
  
@@@ -2253,23 -2228,18 +2243,18 @@@ static void udp_chr_update_read_handler
  {
      NetCharDriver *s = chr->opaque;
  
-     if (s->tag) {
-         io_remove_watch_poll(s->tag);
-         s->tag = 0;
-     }
+     remove_fd_in_watch(chr);
      if (s->chan) {
-         s->tag = io_add_watch_poll(s->chan, udp_chr_read_poll, udp_chr_read, chr);
+         chr->fd_in_tag = io_add_watch_poll(s->chan, udp_chr_read_poll,
+                                            udp_chr_read, chr);
      }
  }
  
  static void udp_chr_close(CharDriverState *chr)
  {
      NetCharDriver *s = chr->opaque;
-     if (s->tag) {
-         io_remove_watch_poll(s->tag);
-         s->tag = 0;
-     }
+     remove_fd_in_watch(chr);
      if (s->chan) {
          g_io_channel_unref(s->chan);
          closesocket(s->fd);
@@@ -2319,7 -2289,7 +2304,7 @@@ static CharDriverState *qemu_chr_open_u
  typedef struct {
  
      GIOChannel *chan, *listen_chan;
-     guint tag, listen_tag;
+     guint listen_tag;
      int fd, listen_fd;
      int connected;
      int max_size;
@@@ -2504,10 -2474,7 +2489,7 @@@ static gboolean tcp_chr_read(GIOChanne
          if (s->listen_chan) {
              s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN, tcp_chr_accept, chr);
          }
-         if (s->tag) {
-             io_remove_watch_poll(s->tag);
-             s->tag = 0;
-         }
+         remove_fd_in_watch(chr);
          g_io_channel_unref(s->chan);
          s->chan = NULL;
          closesocket(s->fd);
@@@ -2537,7 -2504,8 +2519,8 @@@ static void tcp_chr_connect(void *opaqu
  
      s->connected = 1;
      if (s->chan) {
-         s->tag = io_add_watch_poll(s->chan, tcp_chr_read_poll, tcp_chr_read, chr);
+         chr->fd_in_tag = io_add_watch_poll(s->chan, tcp_chr_read_poll,
+                                            tcp_chr_read, chr);
      }
      qemu_chr_be_generic_open(chr);
  }
@@@ -2620,10 -2588,7 +2603,7 @@@ static void tcp_chr_close(CharDriverSta
  {
      TCPCharDriver *s = chr->opaque;
      if (s->fd >= 0) {
-         if (s->tag) {
-             io_remove_watch_poll(s->tag);
-             s->tag = 0;
-         }
+         remove_fd_in_watch(chr);
          if (s->chan) {
              g_io_channel_unref(s->chan);
          }
@@@ -3004,11 -2969,11 +2984,11 @@@ QemuOpts *qemu_chr_parse_compat(const c
      if (strstart(filename, "vc", &p)) {
          qemu_opt_set(opts, "backend", "vc");
          if (*p == ':') {
-             if (sscanf(p+1, "%8[0-9]x%8[0-9]", width, height) == 2) {
+             if (sscanf(p+1, "%7[0-9]x%7[0-9]", width, height) == 2) {
                  /* pixels */
                  qemu_opt_set(opts, "width", width);
                  qemu_opt_set(opts, "height", height);
-             } else if (sscanf(p+1, "%8[0-9]Cx%8[0-9]C", width, height) == 2) {
+             } else if (sscanf(p+1, "%7[0-9]Cx%7[0-9]C", width, height) == 2) {
                  /* chars */
                  qemu_opt_set(opts, "cols", width);
                  qemu_opt_set(opts, "rows", height);
@@@ -3286,7 -3251,12 +3266,12 @@@ CharDriverState *qemu_chr_new_from_opts
              backend->kind = CHARDEV_BACKEND_KIND_MUX;
              backend->mux->chardev = g_strdup(bid);
              ret = qmp_chardev_add(id, backend, errp);
-             assert(!error_is_set(errp));
+             if (error_is_set(errp)) {
+                 chr = qemu_chr_find(bid);
+                 qemu_chr_delete(chr);
+                 chr = NULL;
+                 goto qapi_out;
+             }
          }
  
          chr = qemu_chr_find(id);
@@@ -3355,7 -3325,7 +3340,7 @@@ CharDriverState *qemu_chr_new(const cha
  
      chr = qemu_chr_new_from_opts(opts, init, &err);
      if (error_is_set(&err)) {
-         fprintf(stderr, "%s\n", error_get_pretty(err));
+         error_report("%s", error_get_pretty(err));
          error_free(err);
      }
      if (chr && qemu_opt_get_bool(opts, "mux", 0)) {
@@@ -3568,32 -3538,18 +3553,32 @@@ QemuOptsList qemu_chardev_opts = 
  static CharDriverState *qmp_chardev_open_file(ChardevFile *file, Error **errp)
  {
      HANDLE out;
 +#ifdef CONFIG_MARU
 +    int open_flags, ret;
 +#endif
  
      if (file->has_in) {
          error_setg(errp, "input file not supported");
          return NULL;
      }
  
 +#ifndef CONFIG_MARU
      out = CreateFile(file->out, GENERIC_WRITE, FILE_SHARE_READ, NULL,
                       OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
 +#else
 +    open_flags = O_BINARY | O_RDWR | O_CREAT | O_TRUNC;
 +    ret = qemu_open(file->out, open_flags, 0644);
 +    if (ret < 0) {
 +        error_setg(errp, "qemu_chr_open_win_file_out failed(%d)", ret);
 +        return NULL;
 +    }
 +    out = (HANDLE)_get_osfhandle(ret);
 +#endif
      if (out == INVALID_HANDLE_VALUE) {
          error_setg(errp, "open %s failed", file->out);
          return NULL;
      }
 +
      return qemu_chr_open_win_file(out);
  }
  
diff --combined qemu-options.hx
@@@ -409,7 -409,11 +409,11 @@@ DEF("drive", HAS_ARG, QEMU_OPTION_drive
      "       [,cache=writethrough|writeback|none|directsync|unsafe][,format=f]\n"
      "       [,serial=s][,addr=A][,id=name][,aio=threads|native]\n"
      "       [,readonly=on|off][,copy-on-read=on|off]\n"
-     "       [[,bps=b]|[[,bps_rd=r][,bps_wr=w]]][[,iops=i]|[[,iops_rd=r][,iops_wr=w]]\n"
+     "       [[,bps=b]|[[,bps_rd=r][,bps_wr=w]]]\n"
+     "       [[,iops=i]|[[,iops_rd=r][,iops_wr=w]]]\n"
+     "       [[,bps_max=bm]|[[,bps_rd_max=rm][,bps_wr_max=wm]]]\n"
+     "       [[,iops_max=im]|[[,iops_rd_max=irm][,iops_wr_max=iwm]]]\n"
+     "       [[,iops_size=is]]\n"
      "                use 'file' as a drive image\n", QEMU_ARCH_ALL)
  STEXI
  @item -drive @var{option}[,@var{option}[,@var{option}[,...]]]
@@@ -1601,7 -1605,7 +1605,7 @@@ to disable script execution
  
  If running QEMU as an unprivileged user, use the network helper
  @var{helper} to configure the TAP interface. The default network
- helper executable is @file{/usr/local/libexec/qemu-bridge-helper}.
+ helper executable is @file{/path/to/qemu-bridge-helper}.
  
  @option{fd}=@var{h} can be used to specify the handle of an already
  opened host TAP interface.
@@@ -1625,7 -1629,7 +1629,7 @@@ qemu-system-i386 linux.img 
  #launch a QEMU instance with the default network helper to
  #connect a TAP device to bridge br0
  qemu-system-i386 linux.img \
-                  -net nic -net tap,"helper=/usr/local/libexec/qemu-bridge-helper"
+                  -net nic -net tap,"helper=/path/to/qemu-bridge-helper"
  @end example
  
  @item -netdev bridge,id=@var{id}[,br=@var{bridge}][,helper=@var{helper}]
@@@ -1634,7 -1638,7 +1638,7 @@@ Connect a host TAP network interface t
  
  Use the network helper @var{helper} to configure the TAP interface and
  attach it to the bridge. The default network helper executable is
- @file{/usr/local/libexec/qemu-bridge-helper} and the default bridge
+ @file{/path/to/qemu-bridge-helper} and the default bridge
  device is @file{br0}.
  
  Examples:
@@@ -2672,58 -2676,6 +2676,58 @@@ Enable KVM full virtualization support
  if KVM support is enabled when compiling.
  ETEXI
  
 +DEF("enable-gl", 0, QEMU_OPTION_enable_gl, \
 +    "-enable-gl     enable OpenGL passthrough support\n", QEMU_ARCH_ALL)
 +STEXI
 +@item -enable-gl
 +@findex -enable-gl
 +Enable OpenGL passthrough support. This option requires the support of a
 +special libGL installed on the guest OS.
 +ETEXI
 +
 +DEF("enable-yagl", 0, QEMU_OPTION_enable_yagl, \
 +    "-enable-yagl   enable OpenGLES passthrough support\n", QEMU_ARCH_ALL)
 +STEXI
 +@item -enable-yagl
 +@findex -enable-yagl
 +Enable EGL and OpenGLES passthrough support. This option requires special
 +libEGL, libGLES_CM and libGLESv2 to be installed on the guest OS. Corresponding
 +EGL and openGLES calls on target system are translated to host openGL calls.
 +ETEXI
 +
 +DEF("yagl-backend", HAS_ARG, QEMU_OPTION_yagl_backend,
 +    "-yagl-backend offscreen|vigs        Select YaGL backend, default is offscreen\n", QEMU_ARCH_ALL)
 +STEXI
 +@item -yagl-backend @var{backend}
 +@findex -yagl-backend
 +Use @var{backend} as YaGL backend.
 +ETEXI
 +
 +DEF("enable-vigs", 0, QEMU_OPTION_enable_vigs, \
 +    "-enable-vigs   enable VIGS support\n", QEMU_ARCH_ALL)
 +STEXI
 +@item -enable-vigs
 +@findex -enable-vigs
 +Enables VIGS support.
 +ETEXI
 +
 +DEF("vigs-backend", HAS_ARG, QEMU_OPTION_vigs_backend,
 +    "-vigs-backend gl        Select VIGS backend, default is gl\n", QEMU_ARCH_ALL)
 +STEXI
 +@item -vigs-backend @var{backend}
 +@findex -vigs-backend
 +Use @var{backend} as VIGS backend.
 +ETEXI
 +
 +DEF("enable-hax", 0, QEMU_OPTION_enable_hax, \
 +    "-enable-hax     enable HAX virtualization support\n", QEMU_ARCH_I386)
 +STEXI
 +@item -enable-hax
 +@findex -enable-hax
 +Enable HAX (Hardware-based Acceleration eXecution) support. When HAX support detected, emulator will enable it by default. This option will disable the default action
 +HAX is only supported in MAC and Windows platform and is not conflict with KVM.
 +ETEXI
 +
  DEF("xen-domid", HAS_ARG, QEMU_OPTION_xen_domid,
      "-xen-domid id   specify xen guest domain id\n", QEMU_ARCH_ALL)
  DEF("xen-create", 0, QEMU_OPTION_xen_create,
@@@ -3106,32 -3058,6 +3110,32 @@@ the @var{simple} tracing backend
  @end table
  ETEXI
  
 +DEF("max-touch-point", HAS_ARG, QEMU_OPTION_max_touch_point, \
 +    "-max-touch-point [count]\n"
 +    "                define maximum number of touch point\n",
 +    QEMU_ARCH_ALL)
 +STEXI
 +@item -max-touch-point @var{max_count}
 +@findex -max-touch-point
 +Use @var{max_count} as Integer
 +ETEXI
 +
 +DEF("disable-skin", 0, QEMU_OPTION_disable_skin, \
 +    "-disable-skin\n"
 +    "                do not start with java skin process\n",
 +    QEMU_ARCH_ALL)
 +STEXI
 +@item -disable-skin
 +@findex -disable-skin
 +ETEXI
 +
 +DEF("enable-suspend", 0, QEMU_OPTION_enable_suspend, "", QEMU_ARCH_ALL)
 +STEXI
 +@item -enable-suspend
 +@findex -enable-suspend
 +Enable suspend power state. Default is disable.
 +ETEXI
 +
  HXCOMM Internal use
  DEF("qtest", HAS_ARG, QEMU_OPTION_qtest, "", QEMU_ARCH_ALL)
  DEF("qtest-log", HAS_ARG, QEMU_OPTION_qtest_log, "", QEMU_ARCH_ALL)
diff --combined qom/object.c
@@@ -51,6 -51,7 +51,7 @@@ struct TypeImp
      void *class_data;
  
      void (*instance_init)(Object *obj);
+     void (*instance_post_init)(Object *obj);
      void (*instance_finalize)(Object *obj);
  
      bool abstract;
@@@ -111,6 -112,7 +112,7 @@@ static TypeImpl *type_register_internal
      ti->class_data = info->class_data;
  
      ti->instance_init = info->instance_init;
+     ti->instance_post_init = info->instance_post_init;
      ti->instance_finalize = info->instance_finalize;
  
      ti->abstract = info->abstract;
@@@ -298,7 -300,18 +300,18 @@@ static void object_init_with_type(Objec
      }
  }
  
- void object_initialize_with_type(void *data, TypeImpl *type)
+ static void object_post_init_with_type(Object *obj, TypeImpl *ti)
+ {
+     if (ti->instance_post_init) {
+         ti->instance_post_init(obj);
+     }
+     if (type_has_parent(ti)) {
+         object_post_init_with_type(obj, type_get_parent(ti));
+     }
+ }
+ void object_initialize_with_type(void *data, size_t size, TypeImpl *type)
  {
      Object *obj = data;
  
  
      g_assert(type->instance_size >= sizeof(Object));
      g_assert(type->abstract == false);
+     g_assert(size >= type->instance_size);
  
      memset(obj, 0, type->instance_size);
      obj->class = type->class;
      object_ref(obj);
      QTAILQ_INIT(&obj->properties);
      object_init_with_type(obj, type);
+     object_post_init_with_type(obj, type);
  }
  
- void object_initialize(void *data, const char *typename)
+ void object_initialize(void *data, size_t size, const char *typename)
  {
      TypeImpl *type = type_get_by_name(typename);
  
-     object_initialize_with_type(data, type);
+     object_initialize_with_type(data, size, type);
  }
  
  static inline bool object_property_is_child(ObjectProperty *prop)
@@@ -410,7 -425,7 +425,7 @@@ Object *object_new_with_type(Type type
      type_initialize(type);
  
      obj = g_malloc(type->instance_size);
-     object_initialize_with_type(obj, type);
+     object_initialize_with_type(obj, type->instance_size, type);
      obj->free = g_free;
  
      return obj;
@@@ -688,11 -703,6 +703,11 @@@ void object_ref(Object *obj
  
  void object_unref(Object *obj)
  {
 +// WA for avoid QOM bug related with qbus_create_inplace()... see hw/qdev.c
 +    if(obj->ref == 0) { // Object already finalized...
 +         return;
 +    }
 +//
      g_assert(obj->ref > 0);
  
      /* parent always holds a reference to its children */
@@@ -828,8 -838,9 +843,9 @@@ char *object_property_get_str(Object *o
  void object_property_set_link(Object *obj, Object *value,
                                const char *name, Error **errp)
  {
-     object_property_set_str(obj, object_get_canonical_path(value),
-                             name, errp);
+     gchar *path = object_get_canonical_path(value);
+     object_property_set_str(obj, path, name, errp);
+     g_free(path);
  }
  
  Object *object_property_get_link(Object *obj, const char *name,
@@@ -1334,6 -1345,66 +1350,66 @@@ static char *qdev_get_type(Object *obj
      return g_strdup(object_get_typename(obj));
  }
  
+ static void property_get_uint8_ptr(Object *obj, Visitor *v,
+                                    void *opaque, const char *name,
+                                    Error **errp)
+ {
+     uint8_t value = *(uint8_t *)opaque;
+     visit_type_uint8(v, &value, name, errp);
+ }
+ static void property_get_uint16_ptr(Object *obj, Visitor *v,
+                                    void *opaque, const char *name,
+                                    Error **errp)
+ {
+     uint16_t value = *(uint16_t *)opaque;
+     visit_type_uint16(v, &value, name, errp);
+ }
+ static void property_get_uint32_ptr(Object *obj, Visitor *v,
+                                    void *opaque, const char *name,
+                                    Error **errp)
+ {
+     uint32_t value = *(uint32_t *)opaque;
+     visit_type_uint32(v, &value, name, errp);
+ }
+ static void property_get_uint64_ptr(Object *obj, Visitor *v,
+                                    void *opaque, const char *name,
+                                    Error **errp)
+ {
+     uint64_t value = *(uint64_t *)opaque;
+     visit_type_uint64(v, &value, name, errp);
+ }
+ void object_property_add_uint8_ptr(Object *obj, const char *name,
+                                    const uint8_t *v, Error **errp)
+ {
+     object_property_add(obj, name, "uint8", property_get_uint8_ptr,
+                         NULL, NULL, (void *)v, errp);
+ }
+ void object_property_add_uint16_ptr(Object *obj, const char *name,
+                                     const uint16_t *v, Error **errp)
+ {
+     object_property_add(obj, name, "uint16", property_get_uint16_ptr,
+                         NULL, NULL, (void *)v, errp);
+ }
+ void object_property_add_uint32_ptr(Object *obj, const char *name,
+                                     const uint32_t *v, Error **errp)
+ {
+     object_property_add(obj, name, "uint32", property_get_uint32_ptr,
+                         NULL, NULL, (void *)v, errp);
+ }
+ void object_property_add_uint64_ptr(Object *obj, const char *name,
+                                     const uint64_t *v, Error **errp)
+ {
+     object_property_add(obj, name, "uint64", property_get_uint64_ptr,
+                         NULL, NULL, (void *)v, errp);
+ }
  static void object_instance_init(Object *obj)
  {
      object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
diff --combined target-i386/translate.c
@@@ -31,7 -31,6 +31,7 @@@
  #include "helper.h"
  #define GEN_HELPER 1
  #include "helper.h"
 +#include "sysemu/hax.h"
  
  #define PREFIX_REPZ   0x01
  #define PREFIX_REPNZ  0x02
@@@ -2091,6 -2090,7 +2091,7 @@@ static void gen_lea_modrm(CPUX86State *
      int scale;
      int opreg;
      int mod, rm, code, override, must_add_seg;
+     TCGv sum;
  
      override = s->override;
      must_add_seg = s->addseg;
      rm = modrm & 7;
  
      if (s->aflag) {
          havesib = 0;
          base = rm;
-         index = 0;
+         index = -1;
          scale = 0;
  
          if (base == 4) {
              code = cpu_ldub_code(env, s->pc++);
              scale = (code >> 6) & 3;
              index = ((code >> 3) & 7) | REX_X(s);
+             if (index == 4) {
+                 index = -1;  /* no index */
+             }
              base = (code & 7);
          }
          base |= REX_B(s);
              break;
          }
  
-         if (base >= 0) {
-             /* for correct popl handling with esp */
-             if (base == 4 && s->popl_esp_hack)
-                 disp += s->popl_esp_hack;
- #ifdef TARGET_X86_64
-             if (s->aflag == 2) {
-                 gen_op_movq_A0_reg(base);
-                 if (disp != 0) {
-                     gen_op_addq_A0_im(disp);
-                 }
-             } else
- #endif
-             {
-                 gen_op_movl_A0_reg(base);
-                 if (disp != 0)
-                     gen_op_addl_A0_im(disp);
+         /* For correct popl handling with esp.  */
+         if (base == R_ESP && s->popl_esp_hack) {
+             disp += s->popl_esp_hack;
+         }
+         /* Compute the address, with a minimum number of TCG ops.  */
+         TCGV_UNUSED(sum);
+         if (index >= 0) {
+             if (scale == 0) {
+                 sum = cpu_regs[index];
+             } else {
+                 tcg_gen_shli_tl(cpu_A0, cpu_regs[index], scale);
+                 sum = cpu_A0;
              }
-         } else {
- #ifdef TARGET_X86_64
-             if (s->aflag == 2) {
-                 gen_op_movq_A0_im(disp);
-             } else
- #endif
-             {
-                 gen_op_movl_A0_im(disp);
+             if (base >= 0) {
+                 tcg_gen_add_tl(cpu_A0, sum, cpu_regs[base]);
+                 sum = cpu_A0;
              }
+         } else if (base >= 0) {
+             sum = cpu_regs[base];
          }
-         /* index == 4 means no index */
-         if (havesib && (index != 4)) {
- #ifdef TARGET_X86_64
-             if (s->aflag == 2) {
-                 gen_op_addq_A0_reg_sN(scale, index);
-             } else
- #endif
-             {
-                 gen_op_addl_A0_reg_sN(scale, index);
-             }
+         if (TCGV_IS_UNUSED(sum)) {
+             tcg_gen_movi_tl(cpu_A0, disp);
+         } else {
+             tcg_gen_addi_tl(cpu_A0, sum, disp);
          }
          if (must_add_seg) {
              if (override < 0) {
-                 if (base == R_EBP || base == R_ESP)
+                 if (base == R_EBP || base == R_ESP) {
                      override = R_SS;
-                 else
+                 } else {
                      override = R_DS;
+                 }
              }
- #ifdef TARGET_X86_64
-             if (s->aflag == 2) {
-                 gen_op_addq_A0_seg(override);
-             } else
- #endif
-             {
-                 gen_op_addl_A0_seg(s, override);
+             tcg_gen_ld_tl(cpu_tmp0, cpu_env,
+                           offsetof(CPUX86State, segs[override].base));
+             if (CODE64(s)) {
+                 if (s->aflag != 2) {
+                     tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
+                 }
+                 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
+                 goto done;
              }
+             tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
+         }
+         if (s->aflag != 2) {
+             tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
          }
      } else {
          switch (mod) {
          }
      }
  
+  done:
      opreg = OR_A0;
      disp = 0;
      *reg_ptr = opreg;
@@@ -2414,7 -2415,7 +2416,7 @@@ static inline void gen_goto_tb(DisasCon
          /* jump to same page: we can use a direct jump */
          tcg_gen_goto_tb(tb_num);
          gen_jmp_im(eip);
-         tcg_gen_exit_tb((tcg_target_long)tb + tb_num);
+         tcg_gen_exit_tb((uintptr_t)tb + tb_num);
      } else {
          /* jump to another page: currently not optimized */
          gen_jmp_im(eip);
@@@ -6435,12 -6436,18 +6437,18 @@@ static target_ulong disas_insn(CPUX86St
                  }
                  break;
              case 0x1d: /* fucomi */
+                 if (!(s->cpuid_features & CPUID_CMOV)) {
+                     goto illegal_op;
+                 }
                  gen_update_cc_op(s);
                  gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
                  gen_helper_fucomi_ST0_FT0(cpu_env);
                  set_cc_op(s, CC_OP_EFLAGS);
                  break;
              case 0x1e: /* fcomi */
+                 if (!(s->cpuid_features & CPUID_CMOV)) {
+                     goto illegal_op;
+                 }
                  gen_update_cc_op(s);
                  gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
                  gen_helper_fcomi_ST0_FT0(cpu_env);
                  }
                  break;
              case 0x3d: /* fucomip */
+                 if (!(s->cpuid_features & CPUID_CMOV)) {
+                     goto illegal_op;
+                 }
                  gen_update_cc_op(s);
                  gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
                  gen_helper_fucomi_ST0_FT0(cpu_env);
                  set_cc_op(s, CC_OP_EFLAGS);
                  break;
              case 0x3e: /* fcomip */
+                 if (!(s->cpuid_features & CPUID_CMOV)) {
+                     goto illegal_op;
+                 }
                  gen_update_cc_op(s);
                  gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
                  gen_helper_fcomi_ST0_FT0(cpu_env);
                          (JCC_BE << 1),
                          (JCC_P << 1),
                      };
+                     if (!(s->cpuid_features & CPUID_CMOV)) {
+                         goto illegal_op;
+                     }
                      op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
                      l1 = gen_new_label();
                      gen_jcc1_noeob(s, op1, l1);
          gen_ldst_modrm(env, s, modrm, OT_BYTE, OR_TMP0, 1);
          break;
      case 0x140 ... 0x14f: /* cmov Gv, Ev */
+         if (!(s->cpuid_features & CPUID_CMOV)) {
+             goto illegal_op;
+         }
          ot = dflag + OT_WORD;
          modrm = cpu_ldub_code(env, s->pc++);
          reg = ((modrm >> 3) & 7) | rex_r;
              goto do_xchg_reg_eax;
          }
          if (prefixes & PREFIX_REPZ) {
-             gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE);
+             gen_update_cc_op(s);
+             gen_jmp_im(pc_start - s->cs_base);
+             gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
+             s->is_jmp = DISAS_TB_JUMP;
          }
          break;
      case 0x9b: /* fwait */
@@@ -8243,10 -8266,6 +8267,6 @@@ void optimize_flags_init(void
      cpu_regs[R_EDI] = tcg_global_mem_new_i32(TCG_AREG0,
                                               offsetof(CPUX86State, regs[R_EDI]), "edi");
  #endif
-     /* register helpers */
- #define GEN_HELPER 2
- #include "helper.h"
  }
  
  /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
@@@ -8367,14 -8386,6 +8387,14 @@@ static inline void gen_intermediate_cod
  
          pc_ptr = disas_insn(env, dc, pc_ptr);
          num_insns++;
 +#ifdef CONFIG_HAX
 +        if (hax_enabled() && hax_stop_translate(env))
 +        {
 +            gen_jmp_im(pc_ptr - dc->cs_base);
 +            gen_eob(dc);
 +            break;
 +        }
 +#endif
          /* stop translation if indicated */
          if (dc->is_jmp)
              break;
diff --combined tcg/i386/tcg-target.c
@@@ -22,6 -22,8 +22,8 @@@
   * THE SOFTWARE.
   */
  
+ #include "tcg-be-ldst.h"
  #ifndef NDEBUG
  static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
  #if TCG_TARGET_REG_BITS == 64
@@@ -104,9 -106,6 +106,9 @@@ static const int tcg_target_call_oarg_r
  # define have_cmov 1
  #elif defined(CONFIG_CPUID_H)
  #include <cpuid.h>
 +#ifndef bit_CMOV
 +#define bit_CMOV    (1 << 15)
 +#endif
  static bool have_cmov;
  #else
  # define have_cmov 0
  static uint8_t *tb_ret_addr;
  
  static void patch_reloc(uint8_t *code_ptr, int type,
-                         tcg_target_long value, tcg_target_long addend)
+                         intptr_t value, intptr_t addend)
  {
      value += addend;
      switch(type) {
@@@ -193,11 -192,11 +195,11 @@@ static int target_parse_constraint(TCGA
          /* qemu_ld/st address constraint */
      case 'L':
          ct->ct |= TCG_CT_REG;
- #if TCG_TARGET_REG_BITS == 64
+         if (TCG_TARGET_REG_BITS == 64) {
              tcg_regset_set32(ct->u.regs, 0, 0xffff);
- #else
+         } else {
              tcg_regset_set32(ct->u.regs, 0, 0xff);
- #endif
+         }
          tcg_regset_reset_reg(ct->u.regs, TCG_REG_L0);
          tcg_regset_reset_reg(ct->u.regs, TCG_REG_L1);
          break;
@@@ -433,8 -432,7 +435,7 @@@ static void tcg_out_modrm(TCGContext *s
     that will follow the instruction.  */
  
  static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm,
-                                      int index, int shift,
-                                      tcg_target_long offset)
+                                      int index, int shift, intptr_t offset)
  {
      int mod, len;
  
          if (TCG_TARGET_REG_BITS == 64) {
              /* Try for a rip-relative addressing mode.  This has replaced
                 the 32-bit-mode absolute addressing encoding.  */
-             tcg_target_long pc = (tcg_target_long)s->code_ptr + 5 + ~rm;
-             tcg_target_long disp = offset - pc;
+             intptr_t pc = (intptr_t)s->code_ptr + 5 + ~rm;
+             intptr_t disp = offset - pc;
              if (disp == (int32_t)disp) {
                  tcg_out_opc(s, opc, r, 0, 0);
                  tcg_out8(s, (LOWREGMASK(r) << 3) | 5);
  
  /* A simplification of the above with no index or shift.  */
  static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r,
-                                         int rm, tcg_target_long offset)
+                                         int rm, intptr_t offset)
  {
      tcg_out_modrm_sib_offset(s, opc, r, rm, -1, 0, offset);
  }
@@@ -544,20 -542,34 +545,34 @@@ static inline void tcg_out_mov(TCGConte
  static void tcg_out_movi(TCGContext *s, TCGType type,
                           TCGReg ret, tcg_target_long arg)
  {
+     tcg_target_long diff;
      if (arg == 0) {
          tgen_arithr(s, ARITH_XOR, ret, ret);
          return;
-     } else if (arg == (uint32_t)arg || type == TCG_TYPE_I32) {
+     }
+     if (arg == (uint32_t)arg || type == TCG_TYPE_I32) {
          tcg_out_opc(s, OPC_MOVL_Iv + LOWREGMASK(ret), 0, ret, 0);
          tcg_out32(s, arg);
-     } else if (arg == (int32_t)arg) {
+         return;
+     }
+     if (arg == (int32_t)arg) {
          tcg_out_modrm(s, OPC_MOVL_EvIz + P_REXW, 0, ret);
          tcg_out32(s, arg);
-     } else {
-         tcg_out_opc(s, OPC_MOVL_Iv + P_REXW + LOWREGMASK(ret), 0, ret, 0);
-         tcg_out32(s, arg);
-         tcg_out32(s, arg >> 31 >> 1);
+         return;
+     }
+     /* Try a 7 byte pc-relative lea before the 10 byte movq.  */
+     diff = arg - ((uintptr_t)s->code_ptr + 7);
+     if (diff == (int32_t)diff) {
+         tcg_out_opc(s, OPC_LEA | P_REXW, ret, 0, 0);
+         tcg_out8(s, (LOWREGMASK(ret) << 3) | 5);
+         tcg_out32(s, diff);
+         return;
      }
+     tcg_out_opc(s, OPC_MOVL_Iv + P_REXW + LOWREGMASK(ret), 0, ret, 0);
+     tcg_out64(s, arg);
  }
  
  static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
@@@ -584,19 -596,27 +599,27 @@@ static inline void tcg_out_pop(TCGConte
  }
  
  static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
-                               TCGReg arg1, tcg_target_long arg2)
+                               TCGReg arg1, intptr_t arg2)
  {
      int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
      tcg_out_modrm_offset(s, opc, ret, arg1, arg2);
  }
  
  static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
-                               TCGReg arg1, tcg_target_long arg2)
+                               TCGReg arg1, intptr_t arg2)
  {
      int opc = OPC_MOVL_EvGv + (type == TCG_TYPE_I64 ? P_REXW : 0);
      tcg_out_modrm_offset(s, opc, arg, arg1, arg2);
  }
  
+ static inline void tcg_out_sti(TCGContext *s, TCGType type, TCGReg base,
+                                tcg_target_long ofs, tcg_target_long val)
+ {
+     int opc = OPC_MOVL_EvIz + (type == TCG_TYPE_I64 ? P_REXW : 0);
+     tcg_out_modrm_offset(s, opc, 0, base, ofs);
+     tcg_out32(s, val);
+ }
  static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
  {
      /* Propagate an opcode prefix, such as P_DATA16.  */
@@@ -738,7 -758,7 +761,7 @@@ static void tcg_out_jxx(TCGContext *s, 
      TCGLabel *l = &s->labels[label_index];
  
      if (l->has_value) {
-         val = l->u.value - (tcg_target_long)s->code_ptr;
+         val = l->u.value - (intptr_t)s->code_ptr;
          val1 = val - 2;
          if ((int8_t)val1 == val1) {
              if (opc == -1) {
@@@ -978,9 -998,9 +1001,9 @@@ static void tcg_out_movcond64(TCGContex
  }
  #endif
  
- static void tcg_out_branch(TCGContext *s, int call, tcg_target_long dest)
+ static void tcg_out_branch(TCGContext *s, int call, uintptr_t dest)
  {
-     tcg_target_long disp = dest - (tcg_target_long)s->code_ptr - 5;
+     intptr_t disp = dest - (intptr_t)s->code_ptr - 5;
  
      if (disp == (int32_t)disp) {
          tcg_out_opc(s, call ? OPC_CALL_Jz : OPC_JMP_long, 0, 0, 0);
      }
  }
  
- static inline void tcg_out_calli(TCGContext *s, tcg_target_long dest)
+ static inline void tcg_out_calli(TCGContext *s, uintptr_t dest)
  {
      tcg_out_branch(s, 1, dest);
  }
  
- static void tcg_out_jmp(TCGContext *s, tcg_target_long dest)
+ static void tcg_out_jmp(TCGContext *s, uintptr_t dest)
  {
      tcg_out_branch(s, 0, dest);
  }
  
  #if defined(CONFIG_SOFTMMU)
- #include "exec/softmmu_defs.h"
- /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
-    int mmu_idx) */
- static const void *qemu_ld_helpers[4] = {
-     helper_ldb_mmu,
-     helper_ldw_mmu,
-     helper_ldl_mmu,
-     helper_ldq_mmu,
+ /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
+  *                                     int mmu_idx, uintptr_t ra)
+  */
+ static const void * const qemu_ld_helpers[16] = {
+     [MO_UB]   = helper_ret_ldub_mmu,
+     [MO_LEUW] = helper_le_lduw_mmu,
+     [MO_LEUL] = helper_le_ldul_mmu,
+     [MO_LEQ]  = helper_le_ldq_mmu,
+     [MO_BEUW] = helper_be_lduw_mmu,
+     [MO_BEUL] = helper_be_ldul_mmu,
+     [MO_BEQ]  = helper_be_ldq_mmu,
  };
  
- /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
-    uintxx_t val, int mmu_idx) */
- static const void *qemu_st_helpers[4] = {
-     helper_stb_mmu,
-     helper_stw_mmu,
-     helper_stl_mmu,
-     helper_stq_mmu,
+ /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
+  *                                     uintxx_t val, int mmu_idx, uintptr_t ra)
+  */
+ static const void * const qemu_st_helpers[16] = {
+     [MO_UB]   = helper_ret_stb_mmu,
+     [MO_LEUW] = helper_le_stw_mmu,
+     [MO_LEUL] = helper_le_stl_mmu,
+     [MO_LEQ]  = helper_le_stq_mmu,
+     [MO_BEUW] = helper_be_stw_mmu,
+     [MO_BEUL] = helper_be_stl_mmu,
+     [MO_BEQ]  = helper_be_stq_mmu,
  };
  
- static void add_qemu_ldst_label(TCGContext *s,
-                                 int is_ld,
-                                 int opc,
-                                 int data_reg,
-                                 int data_reg2,
-                                 int addrlo_reg,
-                                 int addrhi_reg,
-                                 int mem_index,
-                                 uint8_t *raddr,
-                                 uint8_t **label_ptr);
  /* Perform the TLB load and compare.
  
     Inputs:
-    ADDRLO_IDX contains the index into ARGS of the low part of the
-    address; the high part of the address is at ADDR_LOW_IDX+1.
+    ADDRLO and ADDRHI contain the low and high part of the address.
  
     MEM_INDEX and S_BITS are the memory context and log2 size of the load.
  
  
     First argument register is clobbered.  */
  
- static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
-                                     int mem_index, int s_bits,
-                                     const TCGArg *args,
+ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
+                                     int mem_index, TCGMemOp s_bits,
                                      uint8_t **label_ptr, int which)
  {
-     const int addrlo = args[addrlo_idx];
-     const int r0 = TCG_REG_L0;
-     const int r1 = TCG_REG_L1;
-     TCGType type = TCG_TYPE_I32;
-     int rexw = 0;
+     const TCGReg r0 = TCG_REG_L0;
+     const TCGReg r1 = TCG_REG_L1;
+     TCGType ttype = TCG_TYPE_I32;
+     TCGType htype = TCG_TYPE_I32;
+     int trexw = 0, hrexw = 0;
  
-     if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 64) {
-         type = TCG_TYPE_I64;
-         rexw = P_REXW;
+     if (TCG_TARGET_REG_BITS == 64) {
+         if (TARGET_LONG_BITS == 64) {
+             ttype = TCG_TYPE_I64;
+             trexw = P_REXW;
+         }
+         if (TCG_TYPE_PTR == TCG_TYPE_I64) {
+             htype = TCG_TYPE_I64;
+             hrexw = P_REXW;
+         }
      }
  
-     tcg_out_mov(s, type, r0, addrlo);
-     tcg_out_mov(s, type, r1, addrlo);
+     tcg_out_mov(s, htype, r0, addrlo);
+     tcg_out_mov(s, ttype, r1, addrlo);
  
-     tcg_out_shifti(s, SHIFT_SHR + rexw, r0,
+     tcg_out_shifti(s, SHIFT_SHR + hrexw, r0,
                     TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
  
-     tgen_arithi(s, ARITH_AND + rexw, r1,
+     tgen_arithi(s, ARITH_AND + trexw, r1,
                  TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
-     tgen_arithi(s, ARITH_AND + rexw, r0,
+     tgen_arithi(s, ARITH_AND + hrexw, r0,
                  (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
  
-     tcg_out_modrm_sib_offset(s, OPC_LEA + P_REXW, r0, TCG_AREG0, r0, 0,
+     tcg_out_modrm_sib_offset(s, OPC_LEA + hrexw, r0, TCG_AREG0, r0, 0,
                               offsetof(CPUArchState, tlb_table[mem_index][0])
                               + which);
  
      /* cmp 0(r0), r1 */
-     tcg_out_modrm_offset(s, OPC_CMP_GvEv + rexw, r1, r0, 0);
+     tcg_out_modrm_offset(s, OPC_CMP_GvEv + trexw, r1, r0, 0);
  
-     tcg_out_mov(s, type, r1, addrlo);
+     /* Prepare for both the fast path add of the tlb addend, and the slow
+        path function argument setup.  There are two cases worth note:
+        For 32-bit guest and x86_64 host, MOVL zero-extends the guest address
+        before the fastpath ADDQ below.  For 64-bit guest and x32 host, MOVQ
+        copies the entire guest address for the slow path, while truncation
+        for the 32-bit host happens with the fastpath ADDL below.  */
+     tcg_out_mov(s, ttype, r1, addrlo);
  
      /* jne slow_path */
      tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0);
  
      if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
          /* cmp 4(r0), addrhi */
-         tcg_out_modrm_offset(s, OPC_CMP_GvEv, args[addrlo_idx+1], r0, 4);
+         tcg_out_modrm_offset(s, OPC_CMP_GvEv, addrhi, r0, 4);
  
          /* jne slow_path */
          tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0);
      /* TLB Hit.  */
  
      /* add addend(r0), r1 */
-     tcg_out_modrm_offset(s, OPC_ADD_GvEv + P_REXW, r1, r0,
+     tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, r1, r0,
                           offsetof(CPUTLBEntry, addend) - which);
  }
+ /*
+  * Record the context of a call to the out of line helper code for the slow path
+  * for a load or store, so that we can later generate the correct helper code
+  */
+ static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc,
+                                 TCGReg datalo, TCGReg datahi,
+                                 TCGReg addrlo, TCGReg addrhi,
+                                 int mem_index, uint8_t *raddr,
+                                 uint8_t **label_ptr)
+ {
+     TCGLabelQemuLdst *label = new_ldst_label(s);
+     label->is_ld = is_ld;
+     label->opc = opc;
+     label->datalo_reg = datalo;
+     label->datahi_reg = datahi;
+     label->addrlo_reg = addrlo;
+     label->addrhi_reg = addrhi;
+     label->mem_index = mem_index;
+     label->raddr = raddr;
+     label->label_ptr[0] = label_ptr[0];
+     if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
+         label->label_ptr[1] = label_ptr[1];
+     }
+ }
+ /*
+  * Generate code for the slow path for a load at the end of block
+  */
+ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
+ {
+     TCGMemOp opc = l->opc;
+     TCGReg data_reg;
+     uint8_t **label_ptr = &l->label_ptr[0];
+     /* resolve label address */
+     *(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4);
+     if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
+         *(uint32_t *)label_ptr[1] = (uint32_t)(s->code_ptr - label_ptr[1] - 4);
+     }
+     if (TCG_TARGET_REG_BITS == 32) {
+         int ofs = 0;
+         tcg_out_st(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP, ofs);
+         ofs += 4;
+         tcg_out_st(s, TCG_TYPE_I32, l->addrlo_reg, TCG_REG_ESP, ofs);
+         ofs += 4;
+         if (TARGET_LONG_BITS == 64) {
+             tcg_out_st(s, TCG_TYPE_I32, l->addrhi_reg, TCG_REG_ESP, ofs);
+             ofs += 4;
+         }
+         tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, l->mem_index);
+         ofs += 4;
+         tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, (uintptr_t)l->raddr);
+     } else {
+         tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
+         /* The second argument is already loaded with addrlo.  */
+         tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
+                      l->mem_index);
+         tcg_out_movi(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[3],
+                      (uintptr_t)l->raddr);
+     }
+     tcg_out_calli(s, (uintptr_t)qemu_ld_helpers[opc & ~MO_SIGN]);
+     data_reg = l->datalo_reg;
+     switch (opc & MO_SSIZE) {
+     case MO_SB:
+         tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW);
+         break;
+     case MO_SW:
+         tcg_out_ext16s(s, data_reg, TCG_REG_EAX, P_REXW);
+         break;
+ #if TCG_TARGET_REG_BITS == 64
+     case MO_SL:
+         tcg_out_ext32s(s, data_reg, TCG_REG_EAX);
+         break;
+ #endif
+     case MO_UB:
+     case MO_UW:
+         /* Note that the helpers have zero-extended to tcg_target_long.  */
+     case MO_UL:
+         tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
+         break;
+     case MO_Q:
+         if (TCG_TARGET_REG_BITS == 64) {
+             tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
+         } else if (data_reg == TCG_REG_EDX) {
+             /* xchg %edx, %eax */
+             tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX, 0, 0, 0);
+             tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_EAX);
+         } else {
+             tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
+             tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_EDX);
+         }
+         break;
+     default:
+         tcg_abort();
+     }
+     /* Jump to the code corresponding to next IR of qemu_st */
+     tcg_out_jmp(s, (uintptr_t)l->raddr);
+ }
+ /*
+  * Generate code for the slow path for a store at the end of block
+  */
+ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
+ {
+     TCGMemOp opc = l->opc;
+     TCGMemOp s_bits = opc & MO_SIZE;
+     uint8_t **label_ptr = &l->label_ptr[0];
+     TCGReg retaddr;
+     /* resolve label address */
+     *(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4);
+     if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
+         *(uint32_t *)label_ptr[1] = (uint32_t)(s->code_ptr - label_ptr[1] - 4);
+     }
+     if (TCG_TARGET_REG_BITS == 32) {
+         int ofs = 0;
+         tcg_out_st(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP, ofs);
+         ofs += 4;
+         tcg_out_st(s, TCG_TYPE_I32, l->addrlo_reg, TCG_REG_ESP, ofs);
+         ofs += 4;
+         if (TARGET_LONG_BITS == 64) {
+             tcg_out_st(s, TCG_TYPE_I32, l->addrhi_reg, TCG_REG_ESP, ofs);
+             ofs += 4;
+         }
+         tcg_out_st(s, TCG_TYPE_I32, l->datalo_reg, TCG_REG_ESP, ofs);
+         ofs += 4;
+         if (s_bits == MO_64) {
+             tcg_out_st(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_ESP, ofs);
+             ofs += 4;
+         }
+         tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, l->mem_index);
+         ofs += 4;
+         retaddr = TCG_REG_EAX;
+         tcg_out_movi(s, TCG_TYPE_I32, retaddr, (uintptr_t)l->raddr);
+         tcg_out_st(s, TCG_TYPE_I32, retaddr, TCG_REG_ESP, ofs);
+     } else {
+         tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
+         /* The second argument is already loaded with addrlo.  */
+         tcg_out_mov(s, (s_bits == MO_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
+                     tcg_target_call_iarg_regs[2], l->datalo_reg);
+         tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
+                      l->mem_index);
+         if (ARRAY_SIZE(tcg_target_call_iarg_regs) > 4) {
+             retaddr = tcg_target_call_iarg_regs[4];
+             tcg_out_movi(s, TCG_TYPE_PTR, retaddr, (uintptr_t)l->raddr);
+         } else {
+             retaddr = TCG_REG_RAX;
+             tcg_out_movi(s, TCG_TYPE_PTR, retaddr, (uintptr_t)l->raddr);
+             tcg_out_st(s, TCG_TYPE_PTR, retaddr, TCG_REG_ESP, 0);
+         }
+     }
+     /* "Tail call" to the helper, with the return address back inline.  */
+     tcg_out_push(s, retaddr);
+     tcg_out_jmp(s, (uintptr_t)qemu_st_helpers[opc]);
+ }
  #elif defined(__x86_64__) && defined(__linux__)
  # include <asm/prctl.h>
  # include <sys/prctl.h>
@@@ -1132,29 -1332,26 +1335,26 @@@ static inline void setup_guest_base_seg
  static inline void setup_guest_base_seg(void) { }
  #endif /* SOFTMMU */
  
- static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
-                                    int base, tcg_target_long ofs, int seg,
-                                    int sizeop)
+ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
+                                    TCGReg base, intptr_t ofs, int seg,
+                                    TCGMemOp memop)
  {
- #ifdef TARGET_WORDS_BIGENDIAN
-     const int bswap = 1;
- #else
-     const int bswap = 0;
- #endif
-     switch (sizeop) {
-     case 0:
+     const TCGMemOp bswap = memop & MO_BSWAP;
+     switch (memop & MO_SSIZE) {
+     case MO_UB:
          tcg_out_modrm_offset(s, OPC_MOVZBL + seg, datalo, base, ofs);
          break;
-     case 0 | 4:
+     case MO_SB:
          tcg_out_modrm_offset(s, OPC_MOVSBL + P_REXW + seg, datalo, base, ofs);
          break;
-     case 1:
+     case MO_UW:
          tcg_out_modrm_offset(s, OPC_MOVZWL + seg, datalo, base, ofs);
          if (bswap) {
              tcg_out_rolw_8(s, datalo);
          }
          break;
-     case 1 | 4:
+     case MO_SW:
          if (bswap) {
              tcg_out_modrm_offset(s, OPC_MOVZWL + seg, datalo, base, ofs);
              tcg_out_rolw_8(s, datalo);
                                   datalo, base, ofs);
          }
          break;
-     case 2:
+     case MO_UL:
          tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg, datalo, base, ofs);
          if (bswap) {
              tcg_out_bswap32(s, datalo);
          }
          break;
  #if TCG_TARGET_REG_BITS == 64
-     case 2 | 4:
+     case MO_SL:
          if (bswap) {
              tcg_out_modrm_offset(s, OPC_MOVL_GvEv + seg, datalo, base, ofs);
              tcg_out_bswap32(s, datalo);
          }
          break;
  #endif
-     case 3:
+     case MO_Q:
          if (TCG_TARGET_REG_BITS == 64) {
              tcg_out_modrm_offset(s, OPC_MOVL_GvEv + P_REXW + seg,
                                   datalo, base, ofs);
  /* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
     EAX. It will be useful once fixed registers globals are less
     common. */
- static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
-                             int opc)
+ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
  {
-     int data_reg, data_reg2 = 0;
-     int addrlo_idx;
+     TCGReg datalo, datahi, addrlo;
+     TCGReg addrhi __attribute__((unused));
+     TCGMemOp opc;
  #if defined(CONFIG_SOFTMMU)
-     int mem_index, s_bits;
+     int mem_index;
+     TCGMemOp s_bits;
      uint8_t *label_ptr[2];
  #endif
  
-     data_reg = args[0];
-     addrlo_idx = 1;
-     if (TCG_TARGET_REG_BITS == 32 && opc == 3) {
-         data_reg2 = args[1];
-         addrlo_idx = 2;
-     }
+     datalo = *args++;
+     datahi = (TCG_TARGET_REG_BITS == 32 && is64 ? *args++ : 0);
+     addrlo = *args++;
+     addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0);
+     opc = *args++;
  
  #if defined(CONFIG_SOFTMMU)
-     mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
-     s_bits = opc & 3;
+     mem_index = *args++;
+     s_bits = opc & MO_SIZE;
  
-     tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
+     tcg_out_tlb_load(s, addrlo, addrhi, mem_index, s_bits,
                       label_ptr, offsetof(CPUTLBEntry, addr_read));
  
      /* TLB Hit.  */
-     tcg_out_qemu_ld_direct(s, data_reg, data_reg2, TCG_REG_L1, 0, 0, opc);
+     tcg_out_qemu_ld_direct(s, datalo, datahi, TCG_REG_L1, 0, 0, opc);
  
      /* Record the current context of a load into ldst label */
-     add_qemu_ldst_label(s,
-                         1,
-                         opc,
-                         data_reg,
-                         data_reg2,
-                         args[addrlo_idx],
-                         args[addrlo_idx + 1],
-                         mem_index,
-                         s->code_ptr,
-                         label_ptr);
+     add_qemu_ldst_label(s, 1, opc, datalo, datahi, addrlo, addrhi,
+                         mem_index, s->code_ptr, label_ptr);
  #else
      {
          int32_t offset = GUEST_BASE;
-         int base = args[addrlo_idx];
+         TCGReg base = addrlo;
          int seg = 0;
  
          /* ??? We assume all operations have left us with register contents
              offset = 0;
          }
  
-         tcg_out_qemu_ld_direct(s, data_reg, data_reg2, base, offset, seg, opc);
+         tcg_out_qemu_ld_direct(s, datalo, datahi, base, offset, seg, opc);
      }
  #endif
  }
  
- static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
-                                    int base, tcg_target_long ofs, int seg,
-                                    int sizeop)
+ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
+                                    TCGReg base, intptr_t ofs, int seg,
+                                    TCGMemOp memop)
  {
- #ifdef TARGET_WORDS_BIGENDIAN
-     const int bswap = 1;
- #else
-     const int bswap = 0;
- #endif
+     const TCGMemOp bswap = memop & MO_BSWAP;
      /* ??? Ideally we wouldn't need a scratch register.  For user-only,
         we could perform the bswap twice to restore the original value
         instead of moving to the scratch.  But as it is, the L constraint
         means that TCG_REG_L0 is definitely free here.  */
-     const int scratch = TCG_REG_L0;
+     const TCGReg scratch = TCG_REG_L0;
  
-     switch (sizeop) {
-     case 0:
+     switch (memop & MO_SIZE) {
+     case MO_8:
+         /* In 32-bit mode, 8-byte stores can only happen from [abcd]x.
+            Use the scratch register if necessary.  */
+         if (TCG_TARGET_REG_BITS == 32 && datalo >= 4) {
+             tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
+             datalo = scratch;
+         }
          tcg_out_modrm_offset(s, OPC_MOVB_EvGv + P_REXB_R + seg,
                               datalo, base, ofs);
          break;
-     case 1:
+     case MO_16:
          if (bswap) {
              tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
              tcg_out_rolw_8(s, scratch);
          tcg_out_modrm_offset(s, OPC_MOVL_EvGv + P_DATA16 + seg,
                               datalo, base, ofs);
          break;
-     case 2:
+     case MO_32:
          if (bswap) {
              tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
              tcg_out_bswap32(s, scratch);
          }
          tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, datalo, base, ofs);
          break;
-     case 3:
+     case MO_64:
          if (TCG_TARGET_REG_BITS == 64) {
              if (bswap) {
                  tcg_out_mov(s, TCG_TYPE_I64, scratch, datalo);
      }
  }
  
- static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
-                             int opc)
+ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
  {
-     int data_reg, data_reg2 = 0;
-     int addrlo_idx;
+     TCGReg datalo, datahi, addrlo;
+     TCGReg addrhi __attribute__((unused));
+     TCGMemOp opc;
  #if defined(CONFIG_SOFTMMU)
-     int mem_index, s_bits;
+     int mem_index;
+     TCGMemOp s_bits;
      uint8_t *label_ptr[2];
  #endif
  
-     data_reg = args[0];
-     addrlo_idx = 1;
-     if (TCG_TARGET_REG_BITS == 32 && opc == 3) {
-         data_reg2 = args[1];
-         addrlo_idx = 2;
-     }
+     datalo = *args++;
+     datahi = (TCG_TARGET_REG_BITS == 32 && is64 ? *args++ : 0);
+     addrlo = *args++;
+     addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0);
+     opc = *args++;
  
  #if defined(CONFIG_SOFTMMU)
-     mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
-     s_bits = opc;
+     mem_index = *args++;
+     s_bits = opc & MO_SIZE;
  
-     tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
+     tcg_out_tlb_load(s, addrlo, addrhi, mem_index, s_bits,
                       label_ptr, offsetof(CPUTLBEntry, addr_write));
  
      /* TLB Hit.  */
-     tcg_out_qemu_st_direct(s, data_reg, data_reg2, TCG_REG_L1, 0, 0, opc);
+     tcg_out_qemu_st_direct(s, datalo, datahi, TCG_REG_L1, 0, 0, opc);
  
      /* Record the current context of a store into ldst label */
-     add_qemu_ldst_label(s,
-                         0,
-                         opc,
-                         data_reg,
-                         data_reg2,
-                         args[addrlo_idx],
-                         args[addrlo_idx + 1],
-                         mem_index,
-                         s->code_ptr,
-                         label_ptr);
+     add_qemu_ldst_label(s, 0, opc, datalo, datahi, addrlo, addrhi,
+                         mem_index, s->code_ptr, label_ptr);
  #else
      {
          int32_t offset = GUEST_BASE;
-         int base = args[addrlo_idx];
+         TCGReg base = addrlo;
          int seg = 0;
  
          /* ??? We assume all operations have left us with register contents
              offset = 0;
          }
  
-         tcg_out_qemu_st_direct(s, data_reg, data_reg2, base, offset, seg, opc);
+         tcg_out_qemu_st_direct(s, datalo, datahi, base, offset, seg, opc);
      }
  #endif
  }
  
- #if defined(CONFIG_SOFTMMU)
- /*
-  * Record the context of a call to the out of line helper code for the slow path
-  * for a load or store, so that we can later generate the correct helper code
-  */
- static void add_qemu_ldst_label(TCGContext *s,
-                                 int is_ld,
-                                 int opc,
-                                 int data_reg,
-                                 int data_reg2,
-                                 int addrlo_reg,
-                                 int addrhi_reg,
-                                 int mem_index,
-                                 uint8_t *raddr,
-                                 uint8_t **label_ptr)
- {
-     int idx;
-     TCGLabelQemuLdst *label;
-     if (s->nb_qemu_ldst_labels >= TCG_MAX_QEMU_LDST) {
-         tcg_abort();
-     }
-     idx = s->nb_qemu_ldst_labels++;
-     label = (TCGLabelQemuLdst *)&s->qemu_ldst_labels[idx];
-     label->is_ld = is_ld;
-     label->opc = opc;
-     label->datalo_reg = data_reg;
-     label->datahi_reg = data_reg2;
-     label->addrlo_reg = addrlo_reg;
-     label->addrhi_reg = addrhi_reg;
-     label->mem_index = mem_index;
-     label->raddr = raddr;
-     label->label_ptr[0] = label_ptr[0];
-     if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
-         label->label_ptr[1] = label_ptr[1];
-     }
- }
- /*
-  * Generate code for the slow path for a load at the end of block
-  */
- static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *label)
- {
-     int s_bits;
-     int opc = label->opc;
-     int mem_index = label->mem_index;
- #if TCG_TARGET_REG_BITS == 32
-     int stack_adjust;
-     int addrlo_reg = label->addrlo_reg;
-     int addrhi_reg = label->addrhi_reg;
- #endif
-     int data_reg = label->datalo_reg;
-     int data_reg2 = label->datahi_reg;
-     uint8_t *raddr = label->raddr;
-     uint8_t **label_ptr = &label->label_ptr[0];
-     s_bits = opc & 3;
-     /* resolve label address */
-     *(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4);
-     if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
-         *(uint32_t *)label_ptr[1] = (uint32_t)(s->code_ptr - label_ptr[1] - 4);
-     }
- #if TCG_TARGET_REG_BITS == 32
-     tcg_out_pushi(s, mem_index);
-     stack_adjust = 4;
-     if (TARGET_LONG_BITS == 64) {
-         tcg_out_push(s, addrhi_reg);
-         stack_adjust += 4;
-     }
-     tcg_out_push(s, addrlo_reg);
-     stack_adjust += 4;
-     tcg_out_push(s, TCG_AREG0);
-     stack_adjust += 4;
- #else
-     tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0);
-     /* The second argument is already loaded with addrlo.  */
-     tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], mem_index);
- #endif
-     /* Code generation of qemu_ld/st's slow path calling MMU helper
-        PRE_PROC ...
-        call MMU helper
-        jmp POST_PROC (2b) : short forward jump <- GETRA()
-        jmp next_code (5b) : dummy long backward jump which is never executed
-        POST_PROC ... : do post-processing <- GETRA() + 7
-        jmp next_code : jump to the code corresponding to next IR of qemu_ld/st
-     */
-     tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
-     /* Jump to post-processing code */
-     tcg_out8(s, OPC_JMP_short);
-     tcg_out8(s, 5);
-     /* Dummy backward jump having information of fast path'pc for MMU helpers */
-     tcg_out8(s, OPC_JMP_long);
-     *(int32_t *)s->code_ptr = (int32_t)(raddr - s->code_ptr - 4);
-     s->code_ptr += 4;
- #if TCG_TARGET_REG_BITS == 32
-     if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) {
-         /* Pop and discard.  This is 2 bytes smaller than the add.  */
-         tcg_out_pop(s, TCG_REG_ECX);
-     } else if (stack_adjust != 0) {
-         tcg_out_addi(s, TCG_REG_CALL_STACK, stack_adjust);
-     }
- #endif
-     switch(opc) {
-     case 0 | 4:
-         tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW);
-         break;
-     case 1 | 4:
-         tcg_out_ext16s(s, data_reg, TCG_REG_EAX, P_REXW);
-         break;
-     case 0:
-         tcg_out_ext8u(s, data_reg, TCG_REG_EAX);
-         break;
-     case 1:
-         tcg_out_ext16u(s, data_reg, TCG_REG_EAX);
-         break;
-     case 2:
-         tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
-         break;
- #if TCG_TARGET_REG_BITS == 64
-     case 2 | 4:
-         tcg_out_ext32s(s, data_reg, TCG_REG_EAX);
-         break;
- #endif
-     case 3:
-         if (TCG_TARGET_REG_BITS == 64) {
-             tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
-         } else if (data_reg == TCG_REG_EDX) {
-             /* xchg %edx, %eax */
-             tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX, 0, 0, 0);
-             tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EAX);
-         } else {
-             tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
-             tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EDX);
-         }
-         break;
-     default:
-         tcg_abort();
-     }
-     /* Jump to the code corresponding to next IR of qemu_st */
-     tcg_out_jmp(s, (tcg_target_long)raddr);
- }
- /*
-  * Generate code for the slow path for a store at the end of block
-  */
- static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *label)
- {
-     int s_bits;
-     int stack_adjust;
-     int opc = label->opc;
-     int mem_index = label->mem_index;
-     int data_reg = label->datalo_reg;
- #if TCG_TARGET_REG_BITS == 32
-     int data_reg2 = label->datahi_reg;
-     int addrlo_reg = label->addrlo_reg;
-     int addrhi_reg = label->addrhi_reg;
- #endif
-     uint8_t *raddr = label->raddr;
-     uint8_t **label_ptr = &label->label_ptr[0];
-     s_bits = opc & 3;
-     /* resolve label address */
-     *(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4);
-     if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
-         *(uint32_t *)label_ptr[1] = (uint32_t)(s->code_ptr - label_ptr[1] - 4);
-     }
- #if TCG_TARGET_REG_BITS == 32
-     tcg_out_pushi(s, mem_index);
-     stack_adjust = 4;
-     if (opc == 3) {
-         tcg_out_push(s, data_reg2);
-         stack_adjust += 4;
-     }
-     tcg_out_push(s, data_reg);
-     stack_adjust += 4;
-     if (TARGET_LONG_BITS == 64) {
-         tcg_out_push(s, addrhi_reg);
-         stack_adjust += 4;
-     }
-     tcg_out_push(s, addrlo_reg);
-     stack_adjust += 4;
-     tcg_out_push(s, TCG_AREG0);
-     stack_adjust += 4;
- #else
-     tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0);
-     /* The second argument is already loaded with addrlo.  */
-     tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
-                 tcg_target_call_iarg_regs[2], data_reg);
-     tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3], mem_index);
-     stack_adjust = 0;
- #endif
-     /* Code generation of qemu_ld/st's slow path calling MMU helper
-        PRE_PROC ...
-        call MMU helper
-        jmp POST_PROC (2b) : short forward jump <- GETRA()
-        jmp next_code (5b) : dummy long backward jump which is never executed
-        POST_PROC ... : do post-processing <- GETRA() + 7
-        jmp next_code : jump to the code corresponding to next IR of qemu_ld/st
-     */
-     tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);
-     /* Jump to post-processing code */
-     tcg_out8(s, OPC_JMP_short);
-     tcg_out8(s, 5);
-     /* Dummy backward jump having information of fast path'pc for MMU helpers */
-     tcg_out8(s, OPC_JMP_long);
-     *(int32_t *)s->code_ptr = (int32_t)(raddr - s->code_ptr - 4);
-     s->code_ptr += 4;
-     if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) {
-         /* Pop and discard.  This is 2 bytes smaller than the add.  */
-         tcg_out_pop(s, TCG_REG_ECX);
-     } else if (stack_adjust != 0) {
-         tcg_out_addi(s, TCG_REG_CALL_STACK, stack_adjust);
-     }
-     /* Jump to the code corresponding to next IR of qemu_st */
-     tcg_out_jmp(s, (tcg_target_long)raddr);
- }
- /*
-  * Generate TB finalization at the end of block
-  */
- void tcg_out_tb_finalize(TCGContext *s)
- {
-     int i;
-     TCGLabelQemuLdst *label;
-     /* qemu_ld/st slow paths */
-     for (i = 0; i < s->nb_qemu_ldst_labels; i++) {
-         label = (TCGLabelQemuLdst *)&s->qemu_ldst_labels[i];
-         if (label->is_ld) {
-             tcg_out_qemu_ld_slow_path(s, label);
-         } else {
-             tcg_out_qemu_st_slow_path(s, label);
-         }
-     }
- }
- #endif  /* CONFIG_SOFTMMU */
  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
                                const TCGArg *args, const int *const_args)
  {
      switch(opc) {
      case INDEX_op_exit_tb:
          tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_EAX, args[0]);
-         tcg_out_jmp(s, (tcg_target_long) tb_ret_addr);
+         tcg_out_jmp(s, (uintptr_t)tb_ret_addr);
          break;
      case INDEX_op_goto_tb:
          if (s->tb_jmp_offset) {
          } else {
              /* indirect jump method */
              tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, -1,
-                                  (tcg_target_long)(s->tb_next + args[0]));
+                                  (intptr_t)(s->tb_next + args[0]));
          }
          s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
          break;
          tcg_out_ext16u(s, args[0], args[1]);
          break;
  
-     case INDEX_op_qemu_ld8u:
+     case INDEX_op_qemu_ld_i32:
          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:
+     case INDEX_op_qemu_ld_i64:
          tcg_out_qemu_ld(s, args, 1);
          break;
-     case INDEX_op_qemu_ld16s:
-         tcg_out_qemu_ld(s, args, 1 | 4);
-         break;
- #if TCG_TARGET_REG_BITS == 64
-     case INDEX_op_qemu_ld32u:
- #endif
-     case INDEX_op_qemu_ld32:
-         tcg_out_qemu_ld(s, args, 2);
-         break;
-     case INDEX_op_qemu_ld64:
-         tcg_out_qemu_ld(s, args, 3);
-         break;
-     case INDEX_op_qemu_st8:
+     case INDEX_op_qemu_st_i32:
          tcg_out_qemu_st(s, args, 0);
          break;
-     case INDEX_op_qemu_st16:
+     case INDEX_op_qemu_st_i64:
          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;
  
      OP_32_64(mulu2):
          tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_MUL, args[3]);
              tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]);
          }
          break;
-     case INDEX_op_qemu_ld32s:
-         tcg_out_qemu_ld(s, args, 2 | 4);
-         break;
  
      case INDEX_op_brcond_i64:
          tcg_out_brcond64(s, args[2], args[0], args[1], const_args[1],
@@@ -2149,43 -2053,20 +2056,20 @@@ static const TCGTargetOpDef x86_op_defs
  #endif
  
  #if TCG_TARGET_REG_BITS == 64
-     { 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_ld32, { "r", "L" } },
-     { INDEX_op_qemu_ld32u, { "r", "L" } },
-     { INDEX_op_qemu_ld32s, { "r", "L" } },
-     { INDEX_op_qemu_ld64, { "r", "L" } },
-     { INDEX_op_qemu_st8, { "L", "L" } },
-     { INDEX_op_qemu_st16, { "L", "L" } },
-     { INDEX_op_qemu_st32, { "L", "L" } },
-     { INDEX_op_qemu_st64, { "L", "L" } },
+     { INDEX_op_qemu_ld_i32, { "r", "L" } },
+     { INDEX_op_qemu_st_i32, { "L", "L" } },
+     { INDEX_op_qemu_ld_i64, { "r", "L" } },
+     { INDEX_op_qemu_st_i64, { "L", "L" } },
  #elif TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
-     { 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_ld32, { "r", "L" } },
-     { INDEX_op_qemu_ld64, { "r", "r", "L" } },
-     { INDEX_op_qemu_st8, { "cb", "L" } },
-     { INDEX_op_qemu_st16, { "L", "L" } },
-     { INDEX_op_qemu_st32, { "L", "L" } },
-     { INDEX_op_qemu_st64, { "L", "L", "L" } },
+     { INDEX_op_qemu_ld_i32, { "r", "L" } },
+     { INDEX_op_qemu_st_i32, { "L", "L" } },
+     { INDEX_op_qemu_ld_i64, { "r", "r", "L" } },
+     { INDEX_op_qemu_st_i64, { "L", "L", "L" } },
  #else
-     { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
-     { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
-     { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
-     { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
-     { INDEX_op_qemu_ld32, { "r", "L", "L" } },
-     { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
-     { INDEX_op_qemu_st8, { "cb", "L", "L" } },
-     { INDEX_op_qemu_st16, { "L", "L", "L" } },
-     { INDEX_op_qemu_st32, { "L", "L", "L" } },
-     { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
+     { INDEX_op_qemu_ld_i32, { "r", "L", "L" } },
+     { INDEX_op_qemu_st_i32, { "L", "L", "L" } },
+     { INDEX_op_qemu_ld_i64, { "r", "r", "L", "L" } },
+     { INDEX_op_qemu_st_i64, { "L", "L", "L", "L" } },
  #endif
      { -1 },
  };
@@@ -2387,7 -2268,7 +2271,7 @@@ static DebugFrame debug_frame = 
  #if defined(ELF_HOST_MACHINE)
  void tcg_register_jit(void *buf, size_t buf_size)
  {
-     debug_frame.fde.func_start = (tcg_target_long) buf;
+     debug_frame.fde.func_start = (uintptr_t)buf;
      debug_frame.fde.func_len = buf_size;
  
      tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
diff --combined tcg/tcg.c
+++ b/tcg/tcg.c
  
  #include "tcg-op.h"
  
- #if TCG_TARGET_REG_BITS == 64
- # define ELF_CLASS  ELFCLASS64
- #else
+ #if UINTPTR_MAX == UINT32_MAX
  # define ELF_CLASS  ELFCLASS32
+ #else
+ # define ELF_CLASS  ELFCLASS64
  #endif
  #ifdef HOST_WORDS_BIGENDIAN
  # define ELF_DATA   ELFDATA2MSB
@@@ -65,8 -65,8 +65,8 @@@
  /* Forward declarations for functions declared in tcg-target.c and used here. */
  static void tcg_target_init(TCGContext *s);
  static void tcg_target_qemu_prologue(TCGContext *s);
- static void patch_reloc(uint8_t *code_ptr, int type,
-                         tcg_target_long value, tcg_target_long addend);
+ static void patch_reloc(uint8_t *code_ptr, int type, 
+                         intptr_t value, intptr_t addend);
  
  /* The CIE and FDE header definitions will be common to all hosts.  */
  typedef struct {
@@@ -82,8 -82,8 +82,8 @@@
  typedef struct QEMU_PACKED {
      uint32_t len __attribute__((aligned((sizeof(void *)))));
      uint32_t cie_offset;
-     tcg_target_long func_start;
-     tcg_target_long func_len;
+     uintptr_t func_start;
+     uintptr_t func_len;
  } DebugFrameFDEHeader;
  
  static void tcg_register_jit_int(void *buf, size_t size,
  /* Forward declarations for functions declared and used in tcg-target.c. */
  static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str);
  static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
-                        tcg_target_long arg2);
+                        intptr_t arg2);
  static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
  static void tcg_out_movi(TCGContext *s, TCGType type,
                           TCGReg ret, tcg_target_long arg);
  static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
                         const int *const_args);
  static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
-                        tcg_target_long arg2);
+                        intptr_t arg2);
  static int tcg_target_const_match(tcg_target_long val,
                                    const TCGArgConstraint *arg_ct);
+ static void tcg_out_tb_init(TCGContext *s);
+ static void tcg_out_tb_finalize(TCGContext *s);
  
  TCGOpDef tcg_op_defs[] = {
  #define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
@@@ -121,20 -124,29 +124,29 @@@ static inline void tcg_out8(TCGContext 
  
  static inline void tcg_out16(TCGContext *s, uint16_t v)
  {
-     *(uint16_t *)s->code_ptr = v;
-     s->code_ptr += 2;
+     uint8_t *p = s->code_ptr;
+     *(uint16_t *)p = v;
+     s->code_ptr = p + 2;
  }
  
  static inline void tcg_out32(TCGContext *s, uint32_t v)
  {
-     *(uint32_t *)s->code_ptr = v;
-     s->code_ptr += 4;
+     uint8_t *p = s->code_ptr;
+     *(uint32_t *)p = v;
+     s->code_ptr = p + 4;
+ }
+ static inline void tcg_out64(TCGContext *s, uint64_t v)
+ {
+     uint8_t *p = s->code_ptr;
+     *(uint64_t *)p = v;
+     s->code_ptr = p + 8;
  }
  
  /* label relocation processing */
  
  static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
-                           int label_index, long addend)
+                           int label_index, intptr_t addend)
  {
      TCGLabel *l;
      TCGRelocation *r;
      l = &s->labels[label_index];
      if (l->has_value) {
          /* FIXME: This may break relocations on RISC targets that
 -           modify instruction fields in place.  The caller may not have 
 +           modify instruction fields in place.  The caller may not have
             written the initial value.  */
          patch_reloc(code_ptr, type, l->u.value, addend);
      } else {
@@@ -160,11 -172,12 +172,12 @@@ static void tcg_out_label(TCGContext *s
  {
      TCGLabel *l;
      TCGRelocation *r;
-     tcg_target_long value = (tcg_target_long)ptr;
+     intptr_t value = (intptr_t)ptr;
  
      l = &s->labels[label_index];
-     if (l->has_value)
+     if (l->has_value) {
          tcg_abort();
+     }
      r = l->u.first_reloc;
      while (r != NULL) {
          patch_reloc(r->ptr, r->type, value, r->addend);
@@@ -196,7 -209,7 +209,7 @@@ void *tcg_malloc_internal(TCGContext *s
  {
      TCGPool *p;
      int pool_size;
 -    
 +
      if (size > TCG_POOL_CHUNK_SIZE) {
          /* big malloc: insert a new pool (XXX: could optimize) */
          p = g_malloc(sizeof(TCGPool) + size);
                  p = g_malloc(sizeof(TCGPool) + pool_size);
                  p->size = pool_size;
                  p->next = NULL;
 -                if (s->pool_current) 
 +                if (s->pool_current)
                      s->pool_current->next = p;
                  else
                      s->pool_first = p;
@@@ -244,16 -257,45 +257,45 @@@ void tcg_pool_reset(TCGContext *s
      s->pool_current = NULL;
  }
  
+ #include "helper.h"
+ typedef struct TCGHelperInfo {
+     void *func;
+     const char *name;
+ } TCGHelperInfo;
+ static const TCGHelperInfo all_helpers[] = {
+ #define GEN_HELPER 2
+ #include "helper.h"
+     /* Include tcg-runtime.c functions.  */
+     { tcg_helper_div_i32, "div_i32" },
+     { tcg_helper_rem_i32, "rem_i32" },
+     { tcg_helper_divu_i32, "divu_i32" },
+     { tcg_helper_remu_i32, "remu_i32" },
+     { tcg_helper_shl_i64, "shl_i64" },
+     { tcg_helper_shr_i64, "shr_i64" },
+     { tcg_helper_sar_i64, "sar_i64" },
+     { tcg_helper_div_i64, "div_i64" },
+     { tcg_helper_rem_i64, "rem_i64" },
+     { tcg_helper_divu_i64, "divu_i64" },
+     { tcg_helper_remu_i64, "remu_i64" },
+     { tcg_helper_mulsh_i64, "mulsh_i64" },
+     { tcg_helper_muluh_i64, "muluh_i64" },
+ };
  void tcg_context_init(TCGContext *s)
  {
-     int op, total_args, n;
+     int op, total_args, n, i;
      TCGOpDef *def;
      TCGArgConstraint *args_ct;
      int *sorted_args;
+     GHashTable *helper_table;
  
      memset(s, 0, sizeof(*s));
      s->nb_globals = 0;
 -    
 +
      /* Count total number of arguments and allocate the corresponding
         space */
      total_args = 0;
          args_ct += n;
      }
  
+     /* Register helpers.  */
+     /* Use g_direct_hash/equal for direct pointer comparisons on func.  */
+     s->helpers = helper_table = g_hash_table_new(NULL, NULL);
+     for (i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
+         g_hash_table_insert(helper_table, (gpointer)all_helpers[i].func,
+                             (gpointer)all_helpers[i].name);
+     }
      tcg_target_init(s);
  }
  
@@@ -284,8 -335,7 +335,7 @@@ void tcg_prologue_init(TCGContext *s
      s->code_buf = s->code_gen_prologue;
      s->code_ptr = s->code_buf;
      tcg_target_qemu_prologue(s);
-     flush_icache_range((tcg_target_ulong)s->code_buf,
-                        (tcg_target_ulong)s->code_ptr);
+     flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr);
  
  #ifdef DEBUG_DISAS
      if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
  #endif
  }
  
- void tcg_set_frame(TCGContext *s, int reg,
-                    tcg_target_long start, tcg_target_long size)
+ void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size)
  {
      s->frame_start = start;
      s->frame_end = start + size;
@@@ -324,13 -373,7 +373,7 @@@ void tcg_func_start(TCGContext *s
      s->gen_opc_ptr = s->gen_opc_buf;
      s->gen_opparam_ptr = s->gen_opparam_buf;
  
- #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
-     /* Initialize qemu_ld/st labels to assist code generation at the end of TB
-        for TLB miss cases at the end of TB */
-     s->qemu_ldst_labels = tcg_malloc(sizeof(TCGLabelQemuLdst) *
-                                      TCG_MAX_QEMU_LDST);
-     s->nb_qemu_ldst_labels = 0;
- #endif
+     s->be = tcg_malloc(sizeof(TCGBackendData));
  }
  
  static inline void tcg_temp_alloc(TCGContext *s, int n)
@@@ -382,7 -425,7 +425,7 @@@ TCGv_i64 tcg_global_reg_new_i64(int reg
  }
  
  static inline int tcg_global_mem_new_internal(TCGType type, int reg,
-                                               tcg_target_long offset,
+                                               intptr_t offset,
                                                const char *name)
  {
      TCGContext *s = &tcg_ctx;
      return idx;
  }
  
- TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
-                                 const char *name)
+ TCGv_i32 tcg_global_mem_new_i32(int reg, intptr_t offset, const char *name)
  {
-     int idx;
-     idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
+     int idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
      return MAKE_TCGV_I32(idx);
  }
  
- TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
-                                 const char *name)
+ TCGv_i64 tcg_global_mem_new_i64(int reg, intptr_t offset, const char *name)
  {
-     int idx;
-     idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
+     int idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
      return MAKE_TCGV_I64(idx);
  }
  
@@@ -618,25 -655,6 +655,6 @@@ int tcg_check_temp_count(void
  }
  #endif
  
- void tcg_register_helper(void *func, const char *name)
- {
-     TCGContext *s = &tcg_ctx;
-     int n;
-     if ((s->nb_helpers + 1) > s->allocated_helpers) {
-         n = s->allocated_helpers;
-         if (n == 0) {
-             n = 4;
-         } else {
-             n *= 2;
-         }
-         s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
-         s->allocated_helpers = n;
-     }
-     s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
-     s->helpers[s->nb_helpers].name = name;
-     s->nb_helpers++;
- }
  /* Note: we convert the 64 bit args to 32 bit and do some alignment
     and endian swap. Maybe it would be better to do the alignment
     and endian swap in tcg_reg_alloc_call(). */
@@@ -793,6 -811,188 +811,188 @@@ void tcg_gen_shifti_i64(TCGv_i64 ret, T
  }
  #endif
  
+ static inline TCGMemOp tcg_canonicalize_memop(TCGMemOp op, bool is64, bool st)
+ {
+     switch (op & MO_SIZE) {
+     case MO_8:
+         op &= ~MO_BSWAP;
+         break;
+     case MO_16:
+         break;
+     case MO_32:
+         if (!is64) {
+             op &= ~MO_SIGN;
+         }
+         break;
+     case MO_64:
+         if (!is64) {
+             tcg_abort();
+         }
+         break;
+     }
+     if (st) {
+         op &= ~MO_SIGN;
+     }
+     return op;
+ }
+ static const TCGOpcode old_ld_opc[8] = {
+     [MO_UB] = INDEX_op_qemu_ld8u,
+     [MO_SB] = INDEX_op_qemu_ld8s,
+     [MO_UW] = INDEX_op_qemu_ld16u,
+     [MO_SW] = INDEX_op_qemu_ld16s,
+ #if TCG_TARGET_REG_BITS == 32
+     [MO_UL] = INDEX_op_qemu_ld32,
+     [MO_SL] = INDEX_op_qemu_ld32,
+ #else
+     [MO_UL] = INDEX_op_qemu_ld32u,
+     [MO_SL] = INDEX_op_qemu_ld32s,
+ #endif
+     [MO_Q]  = INDEX_op_qemu_ld64,
+ };
+ static const TCGOpcode old_st_opc[4] = {
+     [MO_UB] = INDEX_op_qemu_st8,
+     [MO_UW] = INDEX_op_qemu_st16,
+     [MO_UL] = INDEX_op_qemu_st32,
+     [MO_Q]  = INDEX_op_qemu_st64,
+ };
+ void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
+ {
+     memop = tcg_canonicalize_memop(memop, 0, 0);
+     if (TCG_TARGET_HAS_new_ldst) {
+         *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_ld_i32;
+         tcg_add_param_i32(val);
+         tcg_add_param_tl(addr);
+         *tcg_ctx.gen_opparam_ptr++ = memop;
+         *tcg_ctx.gen_opparam_ptr++ = idx;
+         return;
+     }
+     /* The old opcodes only support target-endian memory operations.  */
+     assert((memop & MO_BSWAP) == MO_TE || (memop & MO_SIZE) == MO_8);
+     assert(old_ld_opc[memop & MO_SSIZE] != 0);
+     if (TCG_TARGET_REG_BITS == 32) {
+         *tcg_ctx.gen_opc_ptr++ = old_ld_opc[memop & MO_SSIZE];
+         tcg_add_param_i32(val);
+         tcg_add_param_tl(addr);
+         *tcg_ctx.gen_opparam_ptr++ = idx;
+     } else {
+         TCGv_i64 val64 = tcg_temp_new_i64();
+         *tcg_ctx.gen_opc_ptr++ = old_ld_opc[memop & MO_SSIZE];
+         tcg_add_param_i64(val64);
+         tcg_add_param_tl(addr);
+         *tcg_ctx.gen_opparam_ptr++ = idx;
+         tcg_gen_trunc_i64_i32(val, val64);
+         tcg_temp_free_i64(val64);
+     }
+ }
+ void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
+ {
+     memop = tcg_canonicalize_memop(memop, 0, 1);
+     if (TCG_TARGET_HAS_new_ldst) {
+         *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_st_i32;
+         tcg_add_param_i32(val);
+         tcg_add_param_tl(addr);
+         *tcg_ctx.gen_opparam_ptr++ = memop;
+         *tcg_ctx.gen_opparam_ptr++ = idx;
+         return;
+     }
+     /* The old opcodes only support target-endian memory operations.  */
+     assert((memop & MO_BSWAP) == MO_TE || (memop & MO_SIZE) == MO_8);
+     assert(old_st_opc[memop & MO_SIZE] != 0);
+     if (TCG_TARGET_REG_BITS == 32) {
+         *tcg_ctx.gen_opc_ptr++ = old_st_opc[memop & MO_SIZE];
+         tcg_add_param_i32(val);
+         tcg_add_param_tl(addr);
+         *tcg_ctx.gen_opparam_ptr++ = idx;
+     } else {
+         TCGv_i64 val64 = tcg_temp_new_i64();
+         tcg_gen_extu_i32_i64(val64, val);
+         *tcg_ctx.gen_opc_ptr++ = old_st_opc[memop & MO_SIZE];
+         tcg_add_param_i64(val64);
+         tcg_add_param_tl(addr);
+         *tcg_ctx.gen_opparam_ptr++ = idx;
+         tcg_temp_free_i64(val64);
+     }
+ }
+ void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
+ {
+     memop = tcg_canonicalize_memop(memop, 1, 0);
+ #if TCG_TARGET_REG_BITS == 32
+     if ((memop & MO_SIZE) < MO_64) {
+         tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop);
+         if (memop & MO_SIGN) {
+             tcg_gen_sari_i32(TCGV_HIGH(val), TCGV_LOW(val), 31);
+         } else {
+             tcg_gen_movi_i32(TCGV_HIGH(val), 0);
+         }
+         return;
+     }
+ #endif
+     if (TCG_TARGET_HAS_new_ldst) {
+         *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_ld_i64;
+         tcg_add_param_i64(val);
+         tcg_add_param_tl(addr);
+         *tcg_ctx.gen_opparam_ptr++ = memop;
+         *tcg_ctx.gen_opparam_ptr++ = idx;
+         return;
+     }
+     /* The old opcodes only support target-endian memory operations.  */
+     assert((memop & MO_BSWAP) == MO_TE || (memop & MO_SIZE) == MO_8);
+     assert(old_ld_opc[memop & MO_SSIZE] != 0);
+     *tcg_ctx.gen_opc_ptr++ = old_ld_opc[memop & MO_SSIZE];
+     tcg_add_param_i64(val);
+     tcg_add_param_tl(addr);
+     *tcg_ctx.gen_opparam_ptr++ = idx;
+ }
+ void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
+ {
+     memop = tcg_canonicalize_memop(memop, 1, 1);
+ #if TCG_TARGET_REG_BITS == 32
+     if ((memop & MO_SIZE) < MO_64) {
+         tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop);
+         return;
+     }
+ #endif
+     if (TCG_TARGET_HAS_new_ldst) {
+         *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_st_i64;
+         tcg_add_param_i64(val);
+         tcg_add_param_tl(addr);
+         *tcg_ctx.gen_opparam_ptr++ = memop;
+         *tcg_ctx.gen_opparam_ptr++ = idx;
+         return;
+     }
+     /* The old opcodes only support target-endian memory operations.  */
+     assert((memop & MO_BSWAP) == MO_TE || (memop & MO_SIZE) == MO_8);
+     assert(old_st_opc[memop & MO_SIZE] != 0);
+     *tcg_ctx.gen_opc_ptr++ = old_st_opc[memop & MO_SIZE];
+     tcg_add_param_i64(val);
+     tcg_add_param_tl(addr);
+     *tcg_ctx.gen_opparam_ptr++ = idx;
+ }
  
  static void tcg_reg_alloc_start(TCGContext *s)
  {
@@@ -849,47 -1049,14 +1049,14 @@@ char *tcg_get_arg_str_i64(TCGContext *s
      return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
  }
  
- static int helper_cmp(const void *p1, const void *p2)
- {
-     const TCGHelperInfo *th1 = p1;
-     const TCGHelperInfo *th2 = p2;
-     if (th1->func < th2->func)
-         return -1;
-     else if (th1->func == th2->func)
-         return 0;
-     else
-         return 1;
- }
- /* find helper definition (Note: A hash table would be better) */
- static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
+ /* Find helper name.  */
+ static inline const char *tcg_find_helper(TCGContext *s, uintptr_t val)
  {
-     int m, m_min, m_max;
-     TCGHelperInfo *th;
-     tcg_target_ulong v;
-     if (unlikely(!s->helpers_sorted)) {
-         qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
-               helper_cmp);
-         s->helpers_sorted = 1;
+     const char *ret = NULL;
+     if (s->helpers) {
+         ret = g_hash_table_lookup(s->helpers, (gpointer)val);
      }
-     /* binary search */
-     m_min = 0;
-     m_max = s->nb_helpers - 1;
-     while (m_min <= m_max) {
-         m = (m_min + m_max) >> 1;
-         th = &s->helpers[m];
-         v = th->func;
-         if (v == val)
-             return th;
-         else if (val < v) {
-             m_max = m - 1;
-         } else {
-             m_min = m + 1;
-         }
-     }
-     return NULL;
+     return ret;
  }
  
  static const char * const cond_name[] =
      [TCG_COND_GTU] = "gtu"
  };
  
+ static const char * const ldst_name[] =
+ {
+     [MO_UB]   = "ub",
+     [MO_SB]   = "sb",
+     [MO_LEUW] = "leuw",
+     [MO_LESW] = "lesw",
+     [MO_LEUL] = "leul",
+     [MO_LESL] = "lesl",
+     [MO_LEQ]  = "leq",
+     [MO_BEUW] = "beuw",
+     [MO_BESW] = "besw",
+     [MO_BEUL] = "beul",
+     [MO_BESL] = "besl",
+     [MO_BEQ]  = "beq",
+ };
  void tcg_dump_ops(TCGContext *s)
  {
      const uint16_t *opc_ptr;
              }
          } else if (c == INDEX_op_movi_i32 || c == INDEX_op_movi_i64) {
              tcg_target_ulong val;
-             TCGHelperInfo *th;
+             const char *name;
  
              nb_oargs = def->nb_oargs;
              nb_iargs = def->nb_iargs;
              qemu_log(" %s %s,$", def->name,
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
              val = args[1];
-             th = tcg_find_helper(s, val);
-             if (th) {
-                 qemu_log("%s", th->name);
+             name = tcg_find_helper(s, val);
+             if (name) {
+                 qemu_log("%s", name);
              } else {
                  if (c == INDEX_op_movi_i32) {
                      qemu_log("0x%x", (uint32_t)val);
                  }
                  i = 1;
                  break;
+             case INDEX_op_qemu_ld_i32:
+             case INDEX_op_qemu_st_i32:
+             case INDEX_op_qemu_ld_i64:
+             case INDEX_op_qemu_st_i64:
+                 if (args[k] < ARRAY_SIZE(ldst_name) && ldst_name[args[k]]) {
+                     qemu_log(",%s", ldst_name[args[k++]]);
+                 } else {
+                     qemu_log(",$0x%" TCG_PRIlx, args[k++]);
+                 }
+                 i = 1;
+                 break;
              default:
                  i = 0;
                  break;
@@@ -1243,12 -1437,13 +1437,13 @@@ static inline void tcg_la_bb_end(TCGCon
  static void tcg_liveness_analysis(TCGContext *s)
  {
      int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
-     TCGOpcode op, op_new;
+     TCGOpcode op, op_new, op_new2;
      TCGArg *args;
      const TCGOpDef *def;
      uint8_t *dead_temps, *mem_temps;
      uint16_t dead_args;
      uint8_t sync_args;
+     bool have_op_new2;
      
      s->gen_opc_ptr++; /* skip end */
  
              goto do_not_remove;
  
          case INDEX_op_mulu2_i32:
+             op_new = INDEX_op_mul_i32;
+             op_new2 = INDEX_op_muluh_i32;
+             have_op_new2 = TCG_TARGET_HAS_muluh_i32;
+             goto do_mul2;
          case INDEX_op_muls2_i32:
              op_new = INDEX_op_mul_i32;
+             op_new2 = INDEX_op_mulsh_i32;
+             have_op_new2 = TCG_TARGET_HAS_mulsh_i32;
              goto do_mul2;
          case INDEX_op_mulu2_i64:
+             op_new = INDEX_op_mul_i64;
+             op_new2 = INDEX_op_muluh_i64;
+             have_op_new2 = TCG_TARGET_HAS_muluh_i64;
+             goto do_mul2;
          case INDEX_op_muls2_i64:
              op_new = INDEX_op_mul_i64;
+             op_new2 = INDEX_op_mulsh_i64;
+             have_op_new2 = TCG_TARGET_HAS_mulsh_i64;
+             goto do_mul2;
          do_mul2:
              args -= 4;
              nb_iargs = 2;
              nb_oargs = 2;
-             /* Likewise, test for the high part of the operation dead.  */
              if (dead_temps[args[1]] && !mem_temps[args[1]]) {
                  if (dead_temps[args[0]] && !mem_temps[args[0]]) {
+                     /* Both parts of the operation are dead.  */
                      goto do_remove;
                  }
+                 /* The high part of the operation is dead; generate the low. */
                  s->gen_opc_buf[op_index] = op = op_new;
                  args[1] = args[2];
                  args[2] = args[3];
-                 assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
-                 tcg_set_nop(s, s->gen_opc_buf + op_index + 1, args + 3, 1);
-                 /* Fall through and mark the single-word operation live.  */
-                 nb_oargs = 1;
+             } else if (have_op_new2 && dead_temps[args[0]]
+                        && !mem_temps[args[0]]) {
+                 /* The low part of the operation is dead; generate the high.  */
+                 s->gen_opc_buf[op_index] = op = op_new2;
+                 args[0] = args[1];
+                 args[1] = args[2];
+                 args[2] = args[3];
+             } else {
+                 goto do_not_remove;
              }
+             assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
+             tcg_set_nop(s, s->gen_opc_buf + op_index + 1, args + 3, 1);
+             /* Mark the single-word operation live.  */
+             nb_oargs = 1;
              goto do_not_remove;
  
          default:
@@@ -1581,7 -1799,7 +1799,7 @@@ static void temp_allocate_frame(TCGCont
      ts->mem_offset = s->current_frame_offset;
      ts->mem_reg = s->frame_reg;
      ts->mem_allocated = 1;
-     s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long);
+     s->current_frame_offset += sizeof(tcg_target_long);
  }
  
  /* sync register 'reg' by saving it to the corresponding temporary */
@@@ -2044,7 -2262,9 +2262,9 @@@ static int tcg_reg_alloc_call(TCGContex
      int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
      TCGArg arg, func_arg;
      TCGTemp *ts;
-     tcg_target_long stack_offset, call_stack_size, func_addr;
+     intptr_t stack_offset;
+     size_t call_stack_size;
+     uintptr_t func_addr;
      int const_func_arg, allocate_args;
      TCGRegSet allocated_regs;
      const TCGArgConstraint *arg_ct;
@@@ -2283,6 -2503,8 +2503,8 @@@ static inline int tcg_gen_code_common(T
      s->code_buf = gen_code_buf;
      s->code_ptr = gen_code_buf;
  
+     tcg_out_tb_init(s);
      args = s->gen_opparam_buf;
      op_index = 0;
  
  #endif
      }
   the_end:
- #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
      /* Generate TB finalization at the end of block */
      tcg_out_tb_finalize(s);
- #endif
      return -1;
  }
  
@@@ -2382,8 -2602,7 +2602,7 @@@ int tcg_gen_code(TCGContext *s, uint8_
      tcg_gen_code_common(s, gen_code_buf, -1);
  
      /* flush instruction cache */
-     flush_icache_range((tcg_target_ulong)gen_code_buf,
-                        (tcg_target_ulong)s->code_ptr);
+     flush_icache_range((uintptr_t)gen_code_buf, (uintptr_t)s->code_ptr);
  
      return s->code_ptr -  gen_code_buf;
  }
diff --combined tcg/tcg.h
+++ b/tcg/tcg.h
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */
+ #ifndef TCG_H
+ #define TCG_H
  #include "qemu-common.h"
  
- /* Target word size (must be identical to pointer size). */
- #if UINTPTR_MAX == UINT32_MAX
- # define TCG_TARGET_REG_BITS 32
- #elif UINTPTR_MAX == UINT64_MAX
- # define TCG_TARGET_REG_BITS 64
- #else
- # error Unknown pointer size for tcg target
+ #include "tcg-target.h"
+ /* Default target word size to pointer size.  */
+ #ifndef TCG_TARGET_REG_BITS
+ # if UINTPTR_MAX == UINT32_MAX
+ #  define TCG_TARGET_REG_BITS 32
+ # elif UINTPTR_MAX == UINT64_MAX
+ #  define TCG_TARGET_REG_BITS 64
+ # else
+ #  error Unknown pointer size for tcg target
+ # endif
  #endif
  
  #if TCG_TARGET_REG_BITS == 32
@@@ -46,7 -54,6 +54,6 @@@ typedef uint64_t tcg_target_ulong
  #error unsupported
  #endif
  
- #include "tcg-target.h"
  #include "tcg-runtime.h"
  
  #if TCG_TARGET_NB_REGS <= 32
@@@ -85,6 -92,8 +92,8 @@@ typedef uint64_t TCGRegSet
  #define TCG_TARGET_HAS_sub2_i64         0
  #define TCG_TARGET_HAS_mulu2_i64        0
  #define TCG_TARGET_HAS_muls2_i64        0
+ #define TCG_TARGET_HAS_muluh_i64        0
+ #define TCG_TARGET_HAS_mulsh_i64        0
  /* Turn some undef macros into true macros.  */
  #define TCG_TARGET_HAS_add2_i32         1
  #define TCG_TARGET_HAS_sub2_i32         1
@@@ -134,13 -143,13 +143,13 @@@ typedef struct TCGRelocation 
      struct TCGRelocation *next;
      int type;
      uint8_t *ptr;
-     tcg_target_long addend;
- } TCGRelocation;
+     intptr_t addend;
+ } TCGRelocation; 
  
  typedef struct TCGLabel {
      int has_value;
      union {
-         tcg_target_ulong value;
+         uintptr_t value;
          TCGRelocation *first_reloc;
      } u;
  } TCGLabel;
@@@ -173,9 -182,12 +182,12 @@@ typedef enum TCGType 
      TCG_TYPE_REG = TCG_TYPE_I64,
  #endif
  
-     /* An alias for the size of the native pointer.  We don't currently
-        support any hosts with 64-bit registers and 32-bit pointers.  */
-     TCG_TYPE_PTR = TCG_TYPE_REG,
+     /* An alias for the size of the native pointer.  */
+ #if UINTPTR_MAX == UINT32_MAX
+     TCG_TYPE_PTR = TCG_TYPE_I32,
+ #else
+     TCG_TYPE_PTR = TCG_TYPE_I64,
+ #endif
  
      /* An alias for the size of the target "long", aka register.  */
  #if TARGET_LONG_BITS == 64
  #endif
  } TCGType;
  
+ /* Constants for qemu_ld and qemu_st for the Memory Operation field.  */
+ typedef enum TCGMemOp {
+     MO_8     = 0,
+     MO_16    = 1,
+     MO_32    = 2,
+     MO_64    = 3,
+     MO_SIZE  = 3,   /* Mask for the above.  */
+     MO_SIGN  = 4,   /* Sign-extended, otherwise zero-extended.  */
+     MO_BSWAP = 8,   /* Host reverse endian.  */
+ #ifdef HOST_WORDS_BIGENDIAN
+     MO_LE    = MO_BSWAP,
+     MO_BE    = 0,
+ #else
+     MO_LE    = 0,
+     MO_BE    = MO_BSWAP,
+ #endif
+ #ifdef TARGET_WORDS_BIGENDIAN
+     MO_TE    = MO_BE,
+ #else
+     MO_TE    = MO_LE,
+ #endif
+     /* Combinations of the above, for ease of use.  */
+     MO_UB    = MO_8,
+     MO_UW    = MO_16,
+     MO_UL    = MO_32,
+     MO_SB    = MO_SIGN | MO_8,
+     MO_SW    = MO_SIGN | MO_16,
+     MO_SL    = MO_SIGN | MO_32,
+     MO_Q     = MO_64,
+     MO_LEUW  = MO_LE | MO_UW,
+     MO_LEUL  = MO_LE | MO_UL,
+     MO_LESW  = MO_LE | MO_SW,
+     MO_LESL  = MO_LE | MO_SL,
+     MO_LEQ   = MO_LE | MO_Q,
+     MO_BEUW  = MO_BE | MO_UW,
+     MO_BEUL  = MO_BE | MO_UL,
+     MO_BESW  = MO_BE | MO_SW,
+     MO_BESL  = MO_BE | MO_SL,
+     MO_BEQ   = MO_BE | MO_Q,
+     MO_TEUW  = MO_TE | MO_UW,
+     MO_TEUL  = MO_TE | MO_UL,
+     MO_TESW  = MO_TE | MO_SW,
+     MO_TESL  = MO_TE | MO_SL,
+     MO_TEQ   = MO_TE | MO_Q,
+     MO_SSIZE = MO_SIZE | MO_SIGN,
+ } TCGMemOp;
  typedef tcg_target_ulong TCGArg;
  
  /* Define a type and accessor macros for variables.  Using a struct is
     are aliases for target_ulong and host pointer sized values respectively.
   */
  
- #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
- /* Macros/structures for qemu_ld/st IR code optimization:
-    TCG_MAX_HELPER_LABELS is defined as same as OPC_BUF_SIZE in exec-all.h. */
- #define TCG_MAX_QEMU_LDST       640
- typedef struct TCGLabelQemuLdst {
-     int is_ld:1;            /* qemu_ld: 1, qemu_st: 0 */
-     int opc:4;
-     int addrlo_reg;         /* reg index for low word of guest virtual addr */
-     int addrhi_reg;         /* reg index for high word of guest virtual addr */
-     int datalo_reg;         /* reg index for low word to be loaded or stored */
-     int datahi_reg;         /* reg index for high word to be loaded or stored */
-     int mem_index;          /* soft MMU memory index */
-     uint8_t *raddr;         /* gen code addr of the next IR of qemu_ld/st IR */
-     uint8_t *label_ptr[2];  /* label pointers to be updated */
- } TCGLabelQemuLdst;
- #endif
  #ifdef CONFIG_DEBUG_TCG
  #define DEBUG_TCGV 1
  #endif
@@@ -380,7 -428,7 +428,7 @@@ typedef struct TCGTemp 
      int reg;
      tcg_target_long val;
      int mem_reg;
-     tcg_target_long mem_offset;
+     intptr_t mem_offset;
      unsigned int fixed_reg:1;
      unsigned int mem_coherent:1;
      unsigned int mem_allocated:1;
      const char *name;
  } TCGTemp;
  
- typedef struct TCGHelperInfo {
-     tcg_target_ulong func;
-     const char *name;
- } TCGHelperInfo;
  typedef struct TCGContext TCGContext;
  
  struct TCGContext {
      int nb_globals;
      int nb_temps;
      /* index of free temps, -1 if none */
 -    int first_free_temp[TCG_TYPE_COUNT * 2]; 
 +    int first_free_temp[TCG_TYPE_COUNT * 2];
  
      /* goto_tb support */
      uint8_t *code_buf;
         into account fixed registers */
      int reg_to_temp[TCG_TARGET_NB_REGS];
      TCGRegSet reserved_regs;
-     tcg_target_long current_frame_offset;
-     tcg_target_long frame_start;
-     tcg_target_long frame_end;
+     intptr_t current_frame_offset;
+     intptr_t frame_start;
+     intptr_t frame_end;
      int frame_reg;
  
      uint8_t *code_ptr;
      TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */
  
-     TCGHelperInfo *helpers;
-     int nb_helpers;
-     int allocated_helpers;
-     int helpers_sorted;
+     GHashTable *helpers;
  
  #ifdef CONFIG_PROFILER
      /* profiling info */
  
      TBContext tb_ctx;
  
- #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
-     /* labels info for qemu_ld/st IRs
-        The labels help to generate TLB miss case codes at the end of TB */
-     TCGLabelQemuLdst *qemu_ldst_labels;
-     int nb_qemu_ldst_labels;
- #endif
+     /* The TCGBackendData structure is private to tcg-target.c.  */
+     struct TCGBackendData *be;
  };
  
  extern TCGContext tcg_ctx;
@@@ -522,12 -558,10 +558,10 @@@ void tcg_func_start(TCGContext *s)
  int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf);
  int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset);
  
- void tcg_set_frame(TCGContext *s, int reg,
-                    tcg_target_long start, tcg_target_long size);
+ void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size);
  
  TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name);
- TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
-                                 const char *name);
+ TCGv_i32 tcg_global_mem_new_i32(int reg, intptr_t offset, const char *name);
  TCGv_i32 tcg_temp_new_internal_i32(int temp_local);
  static inline TCGv_i32 tcg_temp_new_i32(void)
  {
@@@ -541,8 -575,7 +575,7 @@@ void tcg_temp_free_i32(TCGv_i32 arg)
  char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg);
  
  TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name);
- TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
-                                 const char *name);
+ TCGv_i64 tcg_global_mem_new_i64(int reg, intptr_t offset, const char *name);
  TCGv_i64 tcg_temp_new_internal_i64(int temp_local);
  static inline TCGv_i64 tcg_temp_new_i64(void)
  {
@@@ -637,11 -670,11 +670,11 @@@ do {
  
  void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs);
  
- #if TCG_TARGET_REG_BITS == 32
+ #if UINTPTR_MAX == UINT32_MAX
  #define TCGV_NAT_TO_PTR(n) MAKE_TCGV_PTR(GET_TCGV_I32(n))
  #define TCGV_PTR_TO_NAT(n) MAKE_TCGV_I32(GET_TCGV_PTR(n))
  
- #define tcg_const_ptr(V) TCGV_NAT_TO_PTR(tcg_const_i32((tcg_target_long)(V)))
+ #define tcg_const_ptr(V) TCGV_NAT_TO_PTR(tcg_const_i32((intptr_t)(V)))
  #define tcg_global_reg_new_ptr(R, N) \
      TCGV_NAT_TO_PTR(tcg_global_reg_new_i32((R), (N)))
  #define tcg_global_mem_new_ptr(R, O, N) \
  #define TCGV_NAT_TO_PTR(n) MAKE_TCGV_PTR(GET_TCGV_I64(n))
  #define TCGV_PTR_TO_NAT(n) MAKE_TCGV_I64(GET_TCGV_PTR(n))
  
- #define tcg_const_ptr(V) TCGV_NAT_TO_PTR(tcg_const_i64((tcg_target_long)(V)))
+ #define tcg_const_ptr(V) TCGV_NAT_TO_PTR(tcg_const_i64((intptr_t)(V)))
  #define tcg_global_reg_new_ptr(R, N) \
      TCGV_NAT_TO_PTR(tcg_global_reg_new_i64((R), (N)))
  #define tcg_global_mem_new_ptr(R, O, N) \
@@@ -671,8 -704,6 +704,6 @@@ TCGArg *tcg_optimize(TCGContext *s, uin
                       TCGOpDef *tcg_op_def);
  
  /* only used for debugging purposes */
- void tcg_register_helper(void *func, const char *name);
- const char *tcg_helper_get_name(TCGContext *s, void *func);
  void tcg_dump_ops(TCGContext *s);
  
  void dump_ops(const uint16_t *opc_buf, const TCGArg *opparam_buf);
@@@ -731,13 -762,92 +762,92 @@@ TCGv_i64 tcg_const_local_i64(int64_t va
  
  #if !defined(tcg_qemu_tb_exec)
  # define tcg_qemu_tb_exec(env, tb_ptr) \
-     ((tcg_target_ulong (*)(void *, void *))tcg_ctx.code_gen_prologue)(env, \
-                                                                       tb_ptr)
+     ((uintptr_t (*)(void *, void *))tcg_ctx.code_gen_prologue)(env, tb_ptr)
  #endif
  
  void tcg_register_jit(void *buf, size_t buf_size);
  
- #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
- /* Generate TB finalization at the end of block */
- void tcg_out_tb_finalize(TCGContext *s);
+ /*
+  * Memory helpers that will be used by TCG generated code.
+  */
+ #ifdef CONFIG_SOFTMMU
+ /* Value zero-extended to tcg register size.  */
+ tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr,
+                                      int mmu_idx, uintptr_t retaddr);
+ tcg_target_ulong helper_le_lduw_mmu(CPUArchState *env, target_ulong addr,
+                                     int mmu_idx, uintptr_t retaddr);
+ tcg_target_ulong helper_le_ldul_mmu(CPUArchState *env, target_ulong addr,
+                                     int mmu_idx, uintptr_t retaddr);
+ uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr,
+                            int mmu_idx, uintptr_t retaddr);
+ tcg_target_ulong helper_be_lduw_mmu(CPUArchState *env, target_ulong addr,
+                                     int mmu_idx, uintptr_t retaddr);
+ tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr,
+                                     int mmu_idx, uintptr_t retaddr);
+ uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr,
+                            int mmu_idx, uintptr_t retaddr);
+ /* Value sign-extended to tcg register size.  */
+ tcg_target_ulong helper_ret_ldsb_mmu(CPUArchState *env, target_ulong addr,
+                                      int mmu_idx, uintptr_t retaddr);
+ tcg_target_ulong helper_le_ldsw_mmu(CPUArchState *env, target_ulong addr,
+                                     int mmu_idx, uintptr_t retaddr);
+ tcg_target_ulong helper_le_ldsl_mmu(CPUArchState *env, target_ulong addr,
+                                     int mmu_idx, uintptr_t retaddr);
+ tcg_target_ulong helper_be_ldsw_mmu(CPUArchState *env, target_ulong addr,
+                                     int mmu_idx, uintptr_t retaddr);
+ tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
+                                     int mmu_idx, uintptr_t retaddr);
+ void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
+                         int mmu_idx, uintptr_t retaddr);
+ void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+                        int mmu_idx, uintptr_t retaddr);
+ void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
+                        int mmu_idx, uintptr_t retaddr);
+ void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
+                        int mmu_idx, uintptr_t retaddr);
+ void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+                        int mmu_idx, uintptr_t retaddr);
+ void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
+                        int mmu_idx, uintptr_t retaddr);
+ void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
+                        int mmu_idx, uintptr_t retaddr);
+ /* Temporary aliases until backends are converted.  */
+ #ifdef TARGET_WORDS_BIGENDIAN
+ # define helper_ret_ldsw_mmu  helper_be_ldsw_mmu
+ # define helper_ret_lduw_mmu  helper_be_lduw_mmu
+ # define helper_ret_ldsl_mmu  helper_be_ldsl_mmu
+ # define helper_ret_ldul_mmu  helper_be_ldul_mmu
+ # define helper_ret_ldq_mmu   helper_be_ldq_mmu
+ # define helper_ret_stw_mmu   helper_be_stw_mmu
+ # define helper_ret_stl_mmu   helper_be_stl_mmu
+ # define helper_ret_stq_mmu   helper_be_stq_mmu
+ #else
+ # define helper_ret_ldsw_mmu  helper_le_ldsw_mmu
+ # define helper_ret_lduw_mmu  helper_le_lduw_mmu
+ # define helper_ret_ldsl_mmu  helper_le_ldsl_mmu
+ # define helper_ret_ldul_mmu  helper_le_ldul_mmu
+ # define helper_ret_ldq_mmu   helper_le_ldq_mmu
+ # define helper_ret_stw_mmu   helper_le_stw_mmu
+ # define helper_ret_stl_mmu   helper_le_stl_mmu
+ # define helper_ret_stq_mmu   helper_le_stq_mmu
  #endif
+ uint8_t helper_ldb_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+ uint16_t helper_ldw_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+ uint32_t helper_ldl_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+ uint64_t helper_ldq_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+ void helper_stb_mmu(CPUArchState *env, target_ulong addr,
+                     uint8_t val, int mmu_idx);
+ void helper_stw_mmu(CPUArchState *env, target_ulong addr,
+                     uint16_t val, int mmu_idx);
+ void helper_stl_mmu(CPUArchState *env, target_ulong addr,
+                     uint32_t val, int mmu_idx);
+ void helper_stq_mmu(CPUArchState *env, target_ulong addr,
+                     uint64_t val, int mmu_idx);
+ #endif /* CONFIG_SOFTMMU */
+ #endif /* TCG_H */
diff --combined tizen/src/ecs/ecs.c
index 7bbd271,0000000..67e921d
mode 100644,000000..100644
--- /dev/null
@@@ -1,995 -1,0 +1,995 @@@
-         qemu_del_timer(cs->alive_timer);
 +/*
 + * Emulator Control Server
 + *
 + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
 + *
 + * Contact:
 + *  Jinhyung choi   <jinhyung2.choi@samsung.com>
 + *  MunKyu Im       <munkyu.im@samsung.com>
 + *  Daiyoung Kim    <daiyoung777.kim@samsung.com>
 + *  YeongKyoon Lee  <yeongkyoon.lee@samsung.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +#include <stdbool.h>
 +#include <pthread.h>
 +#include <stdlib.h>
 +
 +#include "hw/qdev.h"
 +#include "net/net.h"
 +#include "ui/console.h"
 +
 +#include "qemu-common.h"
 +#include "qemu/queue.h"
 +#include "qemu/sockets.h"
 +#include "qemu/option.h"
 +#include "qemu/timer.h"
 +#include "qemu/main-loop.h"
 +#include "sysemu/char.h"
 +#include "config.h"
 +#include "qapi/qmp/qint.h"
 +
 +#include "sdb.h"
 +#include "ecs.h"
 +#include "guest_server.h"
 +#include "emul_state.h"
 +
 +#include "genmsg/ecs.pb-c.h"
 +
 +#define DEBUG
 +
 +#ifndef min
 +#define min(a,b) ((a)<(b)?(a):(b))
 +#endif
 +
 +static QTAILQ_HEAD(ECS_ClientHead, ECS_Client)
 +clients = QTAILQ_HEAD_INITIALIZER(clients);
 +
 +static ECS_State *current_ecs;
 +
 +static void* keepalive_buf;
 +static int payloadsize;
 +
 +static int port;
 +static int port_setting = -1;
 +
 +static int log_fd = -1;
 +static int g_client_id = 1;
 +
 +static pthread_mutex_t mutex_clilist = PTHREAD_MUTEX_INITIALIZER;
 +
 +static int suspend_state = 1;
 +
 +void ecs_set_suspend_state(int state)
 +{
 +    suspend_state = state;
 +}
 +
 +int ecs_get_suspend_state(void)
 +{
 +    return suspend_state;
 +}
 +
 +static char* get_emulator_ecs_log_path(void)
 +{
 +    gchar *emulator_ecs_log_path = NULL;
 +    gchar *tizen_sdk_data = NULL;
 +#ifndef CONFIG_WIN32
 +    char emulator_ecs[] = "/emulator/vms/ecs.log";
 +#else
 +    char emulator_ecs[] = "\\emulator\\vms\\ecs.log";
 +#endif
 +
 +    tizen_sdk_data = get_tizen_sdk_data_path();
 +    if (!tizen_sdk_data) {
 +        LOG("failed to get tizen-sdk-data path.\n");
 +        return NULL;
 +    }
 +
 +    emulator_ecs_log_path =
 +        g_malloc(strlen(tizen_sdk_data) + sizeof(emulator_ecs) + 1);
 +    if (!emulator_ecs_log_path) {
 +        LOG("failed to allocate memory.\n");
 +        return NULL;
 +    }
 +
 +    g_snprintf(emulator_ecs_log_path, strlen(tizen_sdk_data) + sizeof(emulator_ecs),
 +             "%s%s", tizen_sdk_data, emulator_ecs);
 +
 +    g_free(tizen_sdk_data);
 +
 +    LOG("ecs log path: %s\n", emulator_ecs_log_path);
 +    return emulator_ecs_log_path;
 +}
 +
 +static char* get_emulator_ecs_prop_path(void)
 +{
 +    int path_len = 0;
 +    gchar *ecs_property_path = NULL;
 +    gchar *tizen_sdk_data = NULL;
 +#ifndef CONFIG_WIN32
 +    char emulator_vms[] = "/emulator/vms/";
 +    char ecs_prop[] = "/.ecs.properties";
 +#else
 +    char emulator_vms[] = "\\emulator\\vms\\";
 +    char ecs_prop[] = "\\.ecs.properties";
 +#endif
 +    char* emul_name = get_emul_vm_name();
 +
 +    tizen_sdk_data = get_tizen_sdk_data_path();
 +    if (!tizen_sdk_data) {
 +        LOG("failed to get tizen-sdk-data path.\n");
 +        return NULL;
 +    }
 +
 +    path_len = strlen(tizen_sdk_data) + sizeof(emulator_vms) + sizeof(ecs_prop) + strlen(emul_name);
 +    ecs_property_path = g_malloc(path_len + 1);
 +    g_snprintf(ecs_property_path, path_len, "%s%s%s%s", tizen_sdk_data, emulator_vms, emul_name, ecs_prop);
 +
 +    g_free(tizen_sdk_data);
 +    LOG("ecs property path: %s", ecs_property_path);
 +
 +    return ecs_property_path;
 +}
 +
 +static inline void start_logging(void) {
 +    char* path = get_emulator_ecs_log_path();
 +    if (!path)
 +        return;
 +
 +#ifdef _WIN32
 +    FILE* fnul;
 +    FILE* flog;
 +
 +    fnul = fopen("NUL", "rt");
 +    if (fnul != NULL)
 +    stdin[0] = fnul[0];
 +
 +    flog = fopen(path, "wt+");
 +    if (flog == NULL)
 +    flog = fnul;
 +
 +    setvbuf(flog, NULL, _IONBF, 0);
 +
 +    stdout[0] = flog[0];
 +    stderr[0] = flog[0];
 +#else
 +    log_fd = open("/dev/null", O_RDONLY);
 +    dup2(log_fd, 0);
 +
 +    log_fd = creat(path, 0640);
 +    if (log_fd < 0) {
 +        log_fd = open("/dev/null", O_WRONLY);
 +    }
 +    dup2(log_fd, 1);
 +    dup2(log_fd, 2);
 +#endif
 +}
 +
 +static inline void stop_logging(void) {
 +    int ret = -1;
 +    if (log_fd >= 0) {
 +        ret = close(log_fd);
 +        if (ret != 0) {
 +            LOG("failed to close log fd.");
 +        }
 +    }
 +}
 +
 +int ecs_write(int fd, const uint8_t *buf, int len) {
 +    LOG("write buflen : %d, buf : %s", len, (char*)buf);
 +    if (fd < 0) {
 +        return -1;
 +    }
 +
 +    return send_all(fd, buf, len);
 +}
 +
 +void ecs_client_close(ECS_Client* clii) {
 +    if (clii == NULL)
 +        return;
 +
 +    pthread_mutex_lock(&mutex_clilist);
 +
 +    if (clii->client_fd > 0) {
 +        LOG("ecs client closed with fd: %d", clii->client_fd);
 +        closesocket(clii->client_fd);
 +#ifndef CONFIG_LINUX
 +        FD_CLR(clii->client_fd, &clii->cs->reads);
 +#endif
 +        clii->client_fd = -1;
 +    }
 +
 +    QTAILQ_REMOVE(&clients, clii, next);
 +
 +    g_free(clii);
 +    clii = NULL;
 +
 +    pthread_mutex_unlock(&mutex_clilist);
 +}
 +
 +bool send_to_all_client(const char* data, const int len) {
 +    LOG("data len: %d, data: %s", len, data);
 +    pthread_mutex_lock(&mutex_clilist);
 +
 +    ECS_Client *clii;
 +
 +    QTAILQ_FOREACH(clii, &clients, next)
 +    {
 +        send_to_client(clii->client_fd, data, len);
 +    }
 +    pthread_mutex_unlock(&mutex_clilist);
 +
 +    return true;
 +}
 +
 +void send_to_single_client(ECS_Client *clii, const char* data, const int len)
 +{
 +    pthread_mutex_lock(&mutex_clilist);
 +    send_to_client(clii->client_fd, data, len);
 +    pthread_mutex_unlock(&mutex_clilist);
 +}
 +
 +void send_to_client(int fd, const char* data, const int len)
 +{
 +    ecs_write(fd, (const uint8_t*) data, len);
 +}
 +
 +void read_val_short(const char* data, unsigned short* ret_val) {
 +    memcpy(ret_val, data, sizeof(unsigned short));
 +}
 +
 +void read_val_char(const char* data, unsigned char* ret_val) {
 +    memcpy(ret_val, data, sizeof(unsigned char));
 +}
 +
 +void read_val_str(const char* data, char* ret_val, int len) {
 +    memcpy(ret_val, data, len);
 +}
 +
 +bool ntf_to_control(const char* data, const int len) {
 +    return true;
 +}
 +
 +bool ntf_to_monitor(const char* data, const int len) {
 +    return true;
 +}
 +
 +void print_binary(const char* data, const int len) {
 +    int i;
 +    printf("[DATA: ");
 +    for(i = 0; i < len; i++) {
 +        if(i == len - 1) {
 +            printf("%02x]\n", data[i]);
 +        } else {
 +            printf("%02x,", data[i]);
 +        }
 +    }
 +}
 +
 +void ecs_make_header(QDict* obj, type_length length, type_group group,
 +        type_action action) {
 +    qdict_put(obj, "length", qint_from_int((int64_t )length));
 +    qdict_put(obj, "group", qint_from_int((int64_t )group));
 +    qdict_put(obj, "action", qint_from_int((int64_t )action));
 +}
 +
 +static Monitor *monitor_create(void) {
 +    Monitor *mon;
 +
 +    mon = g_malloc0(sizeof(*mon));
 +    if (NULL == mon) {
 +        LOG("monitor allocation failed.");
 +        return NULL;
 +    }
 +
 +    return mon;
 +}
 +
 +static void ecs_close(ECS_State *cs) {
 +    ECS_Client *clii;
 +    LOG("### Good bye! ECS ###");
 +
 +    if (cs == NULL)
 +        return;
 +
 +    if (0 <= cs->listen_fd) {
 +        LOG("close listen_fd: %d", cs->listen_fd);
 +        closesocket(cs->listen_fd);
 +        cs->listen_fd = -1;
 +    }
 +
 +    if (cs->mon != NULL) {
 +        g_free(cs->mon);
 +        cs->mon = NULL;
 +    }
 +
 +    if (keepalive_buf) {
 +        g_free(keepalive_buf);
 +    }
 +
 +    if (cs->alive_timer != NULL) {
-     qemu_mod_timer(current_ecs->alive_timer,
-             qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() * TIMER_ALIVE_S);
++        timer_del(cs->alive_timer);
 +        cs->alive_timer = NULL;
 +    }
 +
 +    QTAILQ_FOREACH(clii, &clients, next)
 +    {
 +        ecs_client_close(clii);
 +    }
 +
 +    g_free(cs);
 +    cs = NULL;
 +    current_ecs = NULL;
 +
 +    stop_logging();
 +}
 +
 +#ifndef _WIN32
 +static ssize_t ecs_recv(int fd, char *buf, size_t len) {
 +    struct msghdr msg = { NULL, };
 +    struct iovec iov[1];
 +    union {
 +        struct cmsghdr cmsg;
 +        char control[CMSG_SPACE(sizeof(int))];
 +    } msg_control;
 +    int flags = 0;
 +
 +    iov[0].iov_base = buf;
 +    iov[0].iov_len = len;
 +
 +    msg.msg_iov = iov;
 +    msg.msg_iovlen = 1;
 +    msg.msg_control = &msg_control;
 +    msg.msg_controllen = sizeof(msg_control);
 +
 +#ifdef MSG_CMSG_CLOEXEC
 +    flags |= MSG_CMSG_CLOEXEC;
 +#endif
 +    return recvmsg(fd, &msg, flags);
 +}
 +
 +#else
 +static ssize_t ecs_recv(int fd, char *buf, size_t len)
 +{
 +    return qemu_recv(fd, buf, len, 0);
 +}
 +#endif
 +
 +
 +static void reset_sbuf(sbuf* sbuf)
 +{
 +    memset(sbuf->_buf, 0, 4096);
 +    sbuf->_use = 0;
 +    sbuf->_netlen = 0;
 +}
 +
 +static void ecs_read(ECS_Client *cli) {
 +
 +    int read = 0;
 +    int to_read_bytes = 0;
 +
 +#ifndef __WIN32
 +    if (ioctl(cli->client_fd, FIONREAD, &to_read_bytes) < 0)
 +    {
 +        LOG("ioctl failed");
 +        return;
 +    }
 +#else
 +    unsigned long to_read_bytes_long = 0;
 +    if (ioctlsocket(cli->client_fd, FIONREAD, &to_read_bytes_long) < 0)
 +    {
 +        LOG("ioctl failed");
 +         return;
 +    }
 +     to_read_bytes = (int)to_read_bytes_long;
 +#endif
 +
 +    if (to_read_bytes == 0) {
 +        LOG("ioctl FIONREAD: 0");
 +        goto fail;
 +    }
 +
 +    if (cli->sbuf._netlen == 0)
 +    {
 +        if (to_read_bytes < 4)
 +        {
 +            //LOG("insufficient data size to read");
 +            return;
 +        }
 +
 +        long payloadsize = 0;
 +        read = ecs_recv(cli->client_fd, (char*) &payloadsize, 4);
 +
 +        if (read < 4)
 +        {
 +            LOG("insufficient header size");
 +            goto fail;
 +        }
 +
 +        payloadsize = ntohl(payloadsize);
 +
 +        cli->sbuf._netlen = payloadsize;
 +
 +        LOG("payload size: %ld\n", payloadsize);
 +
 +        to_read_bytes -= 4;
 +    }
 +
 +    if (to_read_bytes == 0)
 +        return;
 +
 +
 +    to_read_bytes = min(to_read_bytes, cli->sbuf._netlen - cli->sbuf._use);
 +
 +    read = ecs_recv(cli->client_fd, (char*)(cli->sbuf._buf + cli->sbuf._use), to_read_bytes);
 +    if (read == 0)
 +        goto fail;
 +
 +
 +    cli->sbuf._use += read;
 +
 +
 +    if (cli->sbuf._netlen == cli->sbuf._use)
 +    {
 +        handle_protobuf_msg(cli, (char*)cli->sbuf._buf, cli->sbuf._use);
 +        reset_sbuf(&cli->sbuf);
 +    }
 +
 +    return;
 +fail:
 +    ecs_client_close(cli);
 +}
 +
 +#ifdef CONFIG_LINUX
 +static void epoll_cli_add(ECS_State *cs, int fd) {
 +    struct epoll_event events;
 +
 +    /* event control set for read event */
 +    events.events = EPOLLIN;
 +    events.data.fd = fd;
 +
 +    if (epoll_ctl(cs->epoll_fd, EPOLL_CTL_ADD, fd, &events) < 0) {
 +        LOG("Epoll control fails.in epoll_cli_add.");
 +    }
 +}
 +#endif
 +
 +static ECS_Client *ecs_find_client(int fd) {
 +    ECS_Client *clii;
 +
 +    QTAILQ_FOREACH(clii, &clients, next)
 +    {
 +        if (clii->client_fd == fd)
 +            return clii;
 +    }
 +    return NULL;
 +}
 +
 +ECS_Client *find_client(unsigned char id, unsigned char type) {
 +    ECS_Client *clii;
 +
 +    QTAILQ_FOREACH(clii, &clients, next)
 +    {
 +        if (clii->client_id == id && clii->client_type == type)
 +            return clii;
 +    }
 +    return NULL;
 +}
 +
 +static int ecs_add_client(ECS_State *cs, int fd) {
 +
 +    ECS_Client *clii = g_malloc0(sizeof(ECS_Client));
 +    if (NULL == clii) {
 +        LOG("ECS_Client allocation failed.");
 +        return -1;
 +    }
 +
 +    reset_sbuf(&clii->sbuf);
 +
 +    qemu_set_nonblock(fd);
 +
 +    clii->client_fd = fd;
 +    clii->cs = cs;
 +    clii->client_type = TYPE_NONE;
 +
 +    ecs_json_message_parser_init(&clii->parser, handle_qmp_command, clii);
 +
 +#ifdef CONFIG_LINUX
 +    epoll_cli_add(cs, fd);
 +#else
 +    FD_SET(fd, &cs->reads);
 +#endif
 +
 +    pthread_mutex_lock(&mutex_clilist);
 +
 +    QTAILQ_INSERT_TAIL(&clients, clii, next);
 +
 +    LOG("Add an ecs client. fd: %d", fd);
 +
 +    pthread_mutex_unlock(&mutex_clilist);
 +
 +//    send_ecs_version_check(clii);
 +
 +    return 0;
 +}
 +
 +static void ecs_accept(ECS_State *cs) {
 +    struct sockaddr_in saddr;
 +#ifndef _WIN32
 +    struct sockaddr_un uaddr;
 +#endif
 +    struct sockaddr *addr;
 +    socklen_t len;
 +    int fd;
 +
 +    for (;;) {
 +#ifndef _WIN32
 +        if (cs->is_unix) {
 +            len = sizeof(uaddr);
 +            addr = (struct sockaddr *) &uaddr;
 +        } else
 +#endif
 +        {
 +            len = sizeof(saddr);
 +            addr = (struct sockaddr *) &saddr;
 +        }
 +        fd = qemu_accept(cs->listen_fd, addr, &len);
 +        if (0 > fd && EINTR != errno) {
 +            return;
 +        } else if (0 <= fd) {
 +            break;
 +        }
 +    }
 +    if (0 > ecs_add_client(cs, fd)) {
 +        LOG("failed to add client.");
 +    }
 +}
 +
 +#ifdef CONFIG_LINUX
 +static void epoll_init(ECS_State *cs) {
 +    struct epoll_event events;
 +
 +    cs->epoll_fd = epoll_create(MAX_EVENTS);
 +    if (cs->epoll_fd < 0) {
 +        closesocket(cs->listen_fd);
 +    }
 +
 +    events.events = EPOLLIN;
 +    events.data.fd = cs->listen_fd;
 +
 +    if (epoll_ctl(cs->epoll_fd, EPOLL_CTL_ADD, cs->listen_fd, &events) < 0) {
 +        close(cs->listen_fd);
 +        close(cs->epoll_fd);
 +    }
 +}
 +#endif
 +
 +static void send_keep_alive_msg(ECS_Client *clii) {
 +    send_to_single_client(clii, keepalive_buf, payloadsize);
 +}
 +
 +static void make_keep_alive_msg(void) {
 +    int len_pack = 0;
 +    char msg [5] = {'s','e','l','f'};
 +
 +    ECS__Master master = ECS__MASTER__INIT;
 +    ECS__KeepAliveReq req = ECS__KEEP_ALIVE_REQ__INIT;
 +
 +    req.time_str = (char*) g_malloc(5);
 +
 +    strncpy(req.time_str, msg, 4);
 +
 +    master.type = ECS__MASTER__TYPE__KEEPALIVE_REQ;
 +    master.keepalive_req = &req;
 +
 +    len_pack = ecs__master__get_packed_size(&master);
 +    payloadsize = len_pack + 4;
 +
 +    keepalive_buf = g_malloc(len_pack + 4);
 +    if (!keepalive_buf) {
 +        LOG("keep alive message creation is failed.");
 +        return;
 +    }
 +
 +    ecs__master__pack(&master, keepalive_buf + 4);
 +
 +    len_pack = htonl(len_pack);
 +    memcpy(keepalive_buf, &len_pack, 4);
 +}
 +
 +static void alive_checker(void *opaque) {
 +
 +    ECS_Client *clii;
 +
 +    if (NULL != current_ecs && !current_ecs->ecs_running) {
 +        return;
 +    }
 +
 +    QTAILQ_FOREACH(clii, &clients, next)
 +    {
 +        if (1 == clii->keep_alive) {
 +            LOG("get client fd %d - keep alive fail", clii->client_fd);
 +            ecs_client_close(clii);
 +            continue;
 +        }
 +        LOG("set client fd %d - keep alive 1", clii->client_fd);
 +        clii->keep_alive = 1;
 +        send_keep_alive_msg(clii);
 +    }
 +
 +    if (current_ecs == NULL) {
 +        LOG("alive checking is failed because current ecs is null.");
 +        return;
 +    }
 +
-     cs->alive_timer = qemu_new_timer_ns(vm_clock, alive_checker, cs);
++    timer_mod(current_ecs->alive_timer,
++            qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + get_ticks_per_sec() * TIMER_ALIVE_S);
 +
 +}
 +
 +static int socket_initialize(ECS_State *cs, QemuOpts *opts) {
 +    int fd = -1;
 +    Error *local_err = NULL;
 +
 +    fd = inet_listen_opts(opts, 0, &local_err);
 +    if (0 > fd || error_is_set(&local_err)) {
 +        qerror_report_err(local_err);
 +        error_free(local_err);
 +        return -1;
 +    }
 +
 +    LOG("Listen fd is %d", fd);
 +
 +    qemu_set_nonblock(fd);
 +
 +    cs->listen_fd = fd;
 +
 +#ifdef CONFIG_LINUX
 +    epoll_init(cs);
 +#else
 +    FD_ZERO(&cs->reads);
 +    FD_SET(fd, &cs->reads);
 +#endif
 +
 +    make_keep_alive_msg();
 +
-     qemu_mod_timer(cs->alive_timer,
-             qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() * TIMER_ALIVE_S);
++    cs->alive_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, alive_checker, cs);
 +
++    timer_mod(cs->alive_timer,
++            qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + get_ticks_per_sec() * TIMER_ALIVE_S);
 +
 +    return 0;
 +}
 +
 +#ifdef CONFIG_LINUX
 +static int ecs_loop(ECS_State *cs) {
 +    int i, nfds;
 +
 +    nfds = epoll_wait(cs->epoll_fd, cs->events, MAX_EVENTS, 100);
 +    if (0 == nfds) {
 +        return 0;
 +    }
 +
 +    if (0 > nfds) {
 +        if (errno == EINTR)
 +            return 0;
 +        perror("epoll wait error");
 +        return -1;
 +    }
 +
 +    for (i = 0; i < nfds; i++) {
 +        if (cs->events[i].data.fd == cs->listen_fd) {
 +            ecs_accept(cs);
 +            continue;
 +        }
 +        ecs_read(ecs_find_client(cs->events[i].data.fd));
 +    }
 +
 +    return 0;
 +}
 +#elif defined(CONFIG_WIN32)
 +static int ecs_loop(ECS_State *cs)
 +{
 +    int index = 0;
 +    TIMEVAL timeout;
 +    fd_set temps = cs->reads;
 +
 +    timeout.tv_sec = 5;
 +    timeout.tv_usec = 0;
 +
 +    if (select(0, &temps, 0, 0, &timeout) < 0) {
 +        LOG("select error.");
 +        return -1;
 +    }
 +
 +    for (index = 0; index < cs->reads.fd_count; index++) {
 +        if (FD_ISSET(cs->reads.fd_array[index], &temps)) {
 +            if (cs->reads.fd_array[index] == cs->listen_fd) {
 +                ecs_accept(cs);
 +                continue;
 +            }
 +
 +            ecs_read(ecs_find_client(cs->reads.fd_array[index]));
 +        }
 +    }
 +
 +    return 0;
 +}
 +#elif defined(CONFIG_DARWIN)
 +static int ecs_loop(ECS_State *cs)
 +{
 +    int index = 0;
 +    int res = 0;
 +    struct timeval timeout;
 +    fd_set temps = cs->reads;
 +
 +    timeout.tv_sec = 5;
 +    timeout.tv_usec = 0;
 +
 +    if ((res = select(MAX_FD_NUM + 1, &temps, NULL, NULL, &timeout)) < 0) {
 +        LOG("select failed..");
 +        return -1;
 +    }
 +
 +    for (index = 0; index < MAX_FD_NUM; index ++) {
 +        if (FD_ISSET(index, &temps)) {
 +            if (index == cs->listen_fd) {
 +                ecs_accept(cs);
 +                continue;
 +            }
 +
 +            ecs_read(ecs_find_client(index));
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +#endif
 +
 +int get_ecs_port(void) {
 +    if (port_setting < 0) {
 +        LOG("ecs port is not determined yet.");
 +        return 0;
 +    }
 +    LOG("requests ecs port, and port is %d", port);
 +    return port;
 +}
 +
 +static int set_ecs_port(int port) {
 +    FILE* fprop;
 +    char* path = get_emulator_ecs_prop_path();
 +    if (!path)
 +        return -1;
 +
 +    fprop = fopen(path, "wt+");
 +    if (fprop == NULL) {
 +        return -1;
 +    }
 +
 +    fprintf(fprop, "%d", port);
 +    fclose(fprop);
 +
 +    g_free(path);
 +
 +    return 0;
 +}
 +
 +static int setting_ecs_port(ECS_State *cs) {
 +    struct sockaddr server_addr;
 +    socklen_t server_len;
 +
 +    server_len = sizeof(server_addr);
 +    memset(&server_addr, 0, sizeof(server_addr));
 +    if (getsockname(cs->listen_fd, (struct sockaddr *) &server_addr, &server_len) < 0) {
 +        return -1;
 +    }
 +
 +    port = ntohs( ((struct sockaddr_in *) &server_addr)->sin_port );
 +    LOG("listen port is %d", port);
 +
 +    return set_ecs_port(port);
 +}
 +
 +static void* ecs_initialize(void* args) {
 +    int ret = 1;
 +    ECS_State *cs = NULL;
 +    QemuOpts *opts = NULL;
 +    Error *local_err = NULL;
 +    Monitor* mon = NULL;
 +    char host_port[16];
 +
 +    start_logging();
 +    LOG("ecs starts initializing.");
 +
 +    opts = qemu_opts_create(qemu_find_opts(ECS_OPTS_NAME), ECS_OPTS_NAME, 1, &local_err);
 +    if (error_is_set(&local_err)) {
 +        qerror_report_err(local_err);
 +        error_free(local_err);
 +        return NULL;
 +    }
 +
 +    qemu_opt_set(opts, "host", HOST_LISTEN_ADDR);
 +
 +    cs = g_malloc0(sizeof(ECS_State));
 +    if (NULL == cs) {
 +        LOG("ECS_State allocation failed.");
 +        return NULL;
 +    }
 +
 +    sprintf(host_port, "%d", port);
 +    qemu_opt_set(opts, "port", host_port);
 +    ret = socket_initialize(cs, opts);
 +    if (ret < 0) {
 +        LOG("Socket initialization is failed.");
 +        ecs_close(cs);
 +        return NULL;
 +    }
 +
 +    if (setting_ecs_port(cs) < 0) {
 +        LOG("Failed to get random port.");
 +        ecs_close(cs);
 +        return NULL;
 +    }
 +
 +    port_setting = 1;
 +
 +    mon = monitor_create();
 +    if (NULL == mon) {
 +        LOG("monitor initialization failed.");
 +        ecs_close(cs);
 +        return NULL;
 +    }
 +
 +    cs->mon = mon;
 +    current_ecs = cs;
 +    cs->ecs_running = 1;
 +
 +    LOG("ecs_loop entered.");
 +    while (cs->ecs_running) {
 +        ret = ecs_loop(cs);
 +        if (0 > ret) {
 +            ecs_close(cs);
 +            break;
 +        }
 +    }
 +    LOG("ecs_loop exited.");
 +
 +    return NULL;
 +}
 +
 +int stop_ecs(void) {
 +    LOG("ecs is closing.");
 +    if (NULL != current_ecs) {
 +        current_ecs->ecs_running = 0;
 +        ecs_close(current_ecs);
 +    }
 +
 +    pthread_mutex_destroy(&mutex_clilist);
 +
 +    return 0;
 +}
 +
 +int start_ecs(void) {
 +    pthread_t thread_id;
 +
 +    if (0 != pthread_create(&thread_id, NULL, ecs_initialize, NULL)) {
 +        LOG("pthread creation failed.");
 +        return -1;
 +    }
 +    return 0;
 +}
 +
 +bool handle_protobuf_msg(ECS_Client* cli, char* data, int len)
 +{
 +    ECS__Master* master = ecs__master__unpack(NULL, (size_t)len, (const uint8_t*)data);
 +    if (!master)
 +        return false;
 +
 +    if (master->type == ECS__MASTER__TYPE__INJECTOR_REQ)
 +    {
 +        ECS__InjectorReq* msg = master->injector_req;
 +        if (!msg)
 +            goto fail;
 +        msgproc_injector_req(cli, msg);
 +    }
 +    else if (master->type == ECS__MASTER__TYPE__MONITOR_REQ)
 +    {
 +        ECS__MonitorReq* msg = master->monitor_req;
 +        if (!msg)
 +            goto fail;
 +        msgproc_monitor_req(cli, msg);
 +    }
 +    else if (master->type == ECS__MASTER__TYPE__DEVICE_REQ)
 +    {
 +        cli->client_type = TYPE_ECP;
 +        ECS__DeviceReq* msg = master->device_req;
 +        if (!msg)
 +            goto fail;
 +        msgproc_device_req(cli, msg);
 +    }
 +    else if (master->type == ECS__MASTER__TYPE__NFC_REQ)
 +    {
 +        ECS__NfcReq* msg = master->nfc_req;
 +        if (!msg)
 +            goto fail;
 +
 +        pthread_mutex_lock(&mutex_clilist);
 +        if(cli->client_type == TYPE_NONE) {
 +            if (!strncmp(msg->category, MSG_TYPE_NFC, 3)) {
 +                QTAILQ_REMOVE(&clients, cli, next);
 +                cli->client_type = TYPE_ECP;
 +                if(g_client_id > 255) {
 +                    g_client_id = 1;
 +                }
 +                cli->client_id = g_client_id++;
 +
 +                QTAILQ_INSERT_TAIL(&clients, cli, next);
 +            }
 +            else if (!strncmp(msg->category, MSG_TYPE_SIMUL_NFC, 9)) {
 +                QTAILQ_REMOVE(&clients, cli, next);
 +                cli->client_type = TYPE_SIMUL_NFC;
 +                if(g_client_id > 255) {
 +                    g_client_id = 1;
 +                }
 +                cli->client_id = g_client_id++;
 +                QTAILQ_INSERT_TAIL(&clients, cli, next);
 +            }
 +            else {
 +                LOG("unsupported category is found: %s", msg->category);
 +                goto fail;
 +            }
 +        }
 +        pthread_mutex_unlock(&mutex_clilist);
 +
 +        msgproc_nfc_req(cli, msg);
 +    }
 +#if 0
 +    else if (master->type == ECS__MASTER__TYPE__CHECKVERSION_REQ)
 +    {
 +        ECS__CheckVersionReq* msg = master->checkversion_req;
 +        if (!msg)
 +            goto fail;
 +        msgproc_checkversion_req(cli, msg);
 +    }
 +#endif
 +    else if (master->type == ECS__MASTER__TYPE__KEEPALIVE_ANS)
 +    {
 +        ECS__KeepAliveAns* msg = master->keepalive_ans;
 +        if (!msg)
 +            goto fail;
 +        msgproc_keepalive_ans(cli, msg);
 +    }
 +    else if (master->type == ECS__MASTER__TYPE__TETHERING_REQ)
 +    {
 +        ECS__TetheringReq* msg = master->tethering_req;
 +        if (!msg)
 +            goto fail;
 +        msgproc_tethering_req(cli, msg);
 +    }
 +
 +    ecs__master__free_unpacked(master, NULL);
 +    return true;
 +fail:
 +    LOG("invalid message type");
 +    ecs__master__free_unpacked(master, NULL);
 +    return false;
 +} 
index e06ebbb,0000000..d0f8518
mode 100644,000000..100644
--- /dev/null
@@@ -1,359 -1,0 +1,164 @@@
- static bool has_pvpanic = true;
 +/*
 + * TIZEN base board
 + *
 + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
 + *
 + * Contact:
 + * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
 + * SeokYeon Hwang <syeon.hwang@samsung.com>
 + * SangJin Kim <sangjin3.kim@samsung.com>
 + * KiTae Kim <kt920.kim@samsung.com>
 + * JinHyung Jo <jinhyung.jo@samsung.com>
 + * SungMin Ha <sungmin82.ha@samsung.com>
 + * MunKyu Im <munkyu.im@samsung.com>
 + * JiHye Kim <jihye1128.kim@samsung.com>
 + * GiWoong Kim <giwoong.kim@samsung.com>
 + * DongKyun Yun
 + * DoHyung Hong
 + * Hyunjun Son
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + * x86 board from pc_piix.c...
 + * add some TIZEN-speciaized device...
 + */
 +
 +#include <glib.h>
 +
 +#include "hw/hw.h"
 +#include "hw/i386/pc.h"
 +#include "hw/i386/apic.h"
 +#include "hw/pci/pci.h"
 +#include "hw/pci/pci_ids.h"
 +#include "hw/usb.h"
 +#include "net/net.h"
 +#include "hw/boards.h"
 +#include "hw/ide.h"
 +#include "sysemu/kvm.h"
 +#include "hw/kvm/clock.h"
 +#include "sysemu/sysemu.h"
 +#include "hw/sysbus.h"
 +#include "hw/cpu/icc_bus.h"
 +#include "sysemu/arch_init.h"
 +#include "sysemu/blockdev.h"
 +#include "hw/i2c/smbus.h"
 +#include "hw/xen/xen.h"
 +#include "exec/memory.h"
 +#include "exec/address-spaces.h"
 +#include "hw/acpi/acpi.h"
 +#include "cpu.h"
 +#ifdef CONFIG_XEN
 +#  include <xen/hvm/hvm_info_table.h>
 +#endif
 +
 +#include "maru_common.h"
 +#include "guest_debug.h"
 +#include "maru_pm.h"
 +#include "maru_brightness.h"
 +#include "maru_overlay.h"
 +#if defined(__linux__)
 +#include <X11/Xlib.h>
 +#endif
 +#include "vigs/vigs_device.h"
 +extern int enable_yagl;
 +extern const char *yagl_backend;
 +extern int enable_vigs;
 +extern const char *vigs_backend;
 +extern int enable_spice;
 +
 +#define MAX_IDE_BUS 2
 +
 +int codec_init(PCIBus *bus);
 +int maru_brill_codec_pci_device_init(PCIBus *bus);
 +
 +static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
 +static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
 +static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
 +
- static void maru_x86_machine_init(MemoryRegion *system_memory,
-                      MemoryRegion *system_io,
-                      ram_addr_t ram_size,
-                      const char *boot_device,
-                      const char *kernel_filename,
-                      const char *kernel_cmdline,
-                      const char *initrd_filename,
-                      const char *cpu_model,
-                      int pci_enabled,
-                      int kvmclock_enabled)
 +static bool has_pci_info = true;
 +
 +MemoryRegion *global_ram_memory;
 +
 +MemoryRegion *get_ram_memory(void)
 +{
 +    return global_ram_memory;
 +}
 +
-     int i;
-     ram_addr_t below_4g_mem_size, above_4g_mem_size;
-     PCIBus *pci_bus;
-     ISABus *isa_bus;
-     PCII440FXState *i440fx_state;
-     int piix3_devfn = -1;
-     qemu_irq *cpu_irq;
-     qemu_irq *gsi;
-     qemu_irq *i8259;
-     qemu_irq *smi_irq;
-     GSIState *gsi_state;
-     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-     BusState *idebus[MAX_IDE_BUS];
-     ISADevice *rtc_state;
-     ISADevice *floppy;
-     MemoryRegion *ram_memory;
-     MemoryRegion *pci_memory;
-     MemoryRegion *rom_memory;
-     DeviceState *icc_bridge;
-     void *fw_cfg = NULL;
-     PcGuestInfo *guest_info;
++/* maru specialized device init */
++static void maru_device_init(void)
 +{
- #if defined(__linux__)
++    PCIBus *pci_bus = (PCIBus *) object_resolve_path_type("", TYPE_PCI_BUS, NULL);
 +
-     if (xen_enabled() && xen_hvm_init(&ram_memory) != 0) {
-         fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
-         exit(1);
-     }
-     icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
-     object_property_add_child(qdev_get_machine(), "icc-bridge",
-                               OBJECT(icc_bridge), NULL);
-     pc_cpus_init(cpu_model, icc_bridge);
-     pc_acpi_init("acpi-dsdt.aml");
-     if (kvmclock_enabled) {
-         kvmclock_create();
-     }
-     if (ram_size >= QEMU_BELOW_4G_RAM_END ) {
-         above_4g_mem_size = ram_size - QEMU_BELOW_4G_RAM_END;
-         below_4g_mem_size = QEMU_BELOW_4G_RAM_END;
-     } else {
-         above_4g_mem_size = 0;
-         below_4g_mem_size = ram_size;
-     }
-     if (pci_enabled) {
-         pci_memory = g_new(MemoryRegion, 1);
-         memory_region_init(pci_memory, NULL, "pci", INT64_MAX);
-         rom_memory = pci_memory;
-     } else {
-         pci_memory = NULL;
-         rom_memory = system_memory;
-     }
-     guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
-     guest_info->has_pci_info = has_pci_info;
-     guest_info->isapc_ram_fw = !pci_enabled;
-     /* allocate ram and load rom/bios */
-     if (!xen_enabled()) {
-       // W/A for allocate larger continuous heap.
-         // see vl.c
-         if(preallocated_ptr != NULL) {
-             g_free(preallocated_ptr);
-         }
-       //
-         fw_cfg = pc_memory_init(system_memory,
-                        kernel_filename, kernel_cmdline, initrd_filename,
-                        below_4g_mem_size, above_4g_mem_size,
-                        rom_memory, &ram_memory, guest_info);
-     }
-     // for ramdump...
-     global_ram_memory = ram_memory;
-     gsi_state = g_malloc0(sizeof(*gsi_state));
-     if (kvm_irqchip_in_kernel()) {
-         kvm_pc_setup_irq_routing(pci_enabled);
-         gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
-                                  GSI_NUM_PINS);
-     } else {
-         gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
-     }
-     if (pci_enabled) {
-         pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
-                               system_memory, system_io, ram_size,
-                               below_4g_mem_size,
-                               0x100000000ULL - below_4g_mem_size,
-                               above_4g_mem_size,
-                               pci_memory, ram_memory);
-     } else {
-         pci_bus = NULL;
-         i440fx_state = NULL;
-         isa_bus = isa_bus_new(NULL, system_io);
-         no_hpet = 1;
-     }
-     isa_bus_irqs(isa_bus, gsi);
-     if (kvm_irqchip_in_kernel()) {
-         i8259 = kvm_i8259_init(isa_bus);
-     } else if (xen_enabled()) {
-         i8259 = xen_interrupt_controller_init();
-     } else {
-         cpu_irq = pc_allocate_cpu_irq();
-         i8259 = i8259_init(isa_bus, cpu_irq[0]);
-     }
-     for (i = 0; i < ISA_NUM_IRQS; i++) {
-         gsi_state->i8259_irq[i] = i8259[i];
-     }
-     if (pci_enabled) {
-         ioapic_init_gsi(gsi_state, "i440fx");
-     }
-     qdev_init_nofail(icc_bridge);
-     pc_register_ferr_irq(gsi[13]);
-     pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
-     if (xen_enabled()) {
-         pci_create_simple(pci_bus, -1, "xen-platform");
-     }
-     /* init basic PC hardware */
-     pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled());
-     pc_nic_init(isa_bus, pci_bus);
-     ide_drive_get(hd, MAX_IDE_BUS);
-     if (pci_enabled) {
-         PCIDevice *dev;
-         if (xen_enabled()) {
-             dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
-         } else {
-             dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
-         }
-         idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
-         idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
-     } else {
-         for(i = 0; i < MAX_IDE_BUS; i++) {
-             ISADevice *dev;
-             dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
-                                ide_irq[i],
-                                hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
-             idebus[i] = qdev_get_child_bus(DEVICE(dev), "ide.0");
-         }
-     }
-     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
-                  floppy, idebus[0], idebus[1], rtc_state);
-     if (pci_enabled && usb_enabled(false)) {
-         pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
-     }
-     if (pci_enabled && acpi_enabled) {
-         i2c_bus *smbus;
-         smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
-         /* TODO: Populate SPD eeprom data.  */
-         smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
-                               gsi[9], *smi_irq,
-                               kvm_enabled(), fw_cfg);
-         smbus_eeprom_init(smbus, 8, NULL, 0);
-     }
-     if (pci_enabled) {
-         pc_pci_device_init(pci_bus);
-     }
-     if (has_pvpanic) {
-         pvpanic_init(isa_bus);
-     }
-     /* maru specialized device init */
-     if (pci_enabled) {
- //        codec_init(pci_bus);
-         pci_maru_overlay_init(pci_bus);
-         pci_maru_brightness_init(pci_bus);
-         maru_brill_codec_pci_device_init(pci_bus);
-     }
++#if defined(CONFIG_LINUX)
 +    Display *display = XOpenDisplay(0);
 +    if (!display && !enable_spice) {
 +        fprintf(stderr, "Cannot open X display\n");
 +        exit(1);
 +    }
 +#else
 +    void *display = NULL;
 +#endif
 +    struct winsys_interface *vigs_wsi = NULL;
 +
-     has_pci_info = false;
++    pci_maru_overlay_init(pci_bus);
++    pci_maru_brightness_init(pci_bus);
++    maru_brill_codec_pci_device_init(pci_bus);
 +
 +    if (enable_vigs) {
 +        PCIDevice *pci_dev = pci_create(pci_bus, -1, "vigs");
 +        qdev_prop_set_ptr(&pci_dev->qdev, "display", display);
 +        qdev_init_nofail(&pci_dev->qdev);
 +        vigs_wsi = DO_UPCAST(VIGSDevice, pci_dev, pci_dev)->wsi;
 +    }
 +
 +    if (enable_yagl) {
 +        PCIDevice *pci_dev = pci_create(pci_bus, -1, "yagl");
 +        qdev_prop_set_ptr(&pci_dev->qdev, "display", display);
 +        if (vigs_wsi &&
 +            (strcmp(yagl_backend, "vigs") == 0) &&
 +            (strcmp(vigs_backend, "gl") == 0)) {
 +            qdev_prop_set_ptr(&pci_dev->qdev, "winsys_gl_interface", vigs_wsi);
 +        }
 +        qdev_init_nofail(&pci_dev->qdev);
 +    }
 +}
 +
++extern void pc_init_pci(QEMUMachineInitArgs *args);
 +static void maru_x86_board_init(QEMUMachineInitArgs *args)
 +{
-     ram_addr_t ram_size = args->ram_size;
-     const char *cpu_model = args->cpu_model;
-     const char *kernel_filename = args->kernel_filename;
-     const char *kernel_cmdline = args->kernel_cmdline;
-     const char *initrd_filename = args->initrd_filename;
-     const char *boot_device = args->boot_device;
-     maru_x86_machine_init(get_system_memory(),
-              get_system_io(),
-              ram_size, boot_device,
-              kernel_filename, kernel_cmdline,
-              initrd_filename, cpu_model, 1, 1);
++    pc_init_pci(args);
 +
-     .max_cpus = 255,
-     DEFAULT_MACHINE_OPTIONS,
++    has_pci_info = false;
++    maru_device_init();
 +}
 +
 +static QEMUMachine maru_x86_machine = {
++    PC_DEFAULT_MACHINE_OPTIONS,
 +    .name = "maru-x86-machine",
 +    .alias = "maru-x86-machine",
 +    .desc = "Maru Board (x86)",
 +    .init = maru_x86_board_init,
 +    .hot_add_cpu = pc_hot_add_cpu,
 +};
 +
 +static void maru_machine_init(void)
 +{
 +    qemu_register_machine(&maru_x86_machine);
 +}
 +
 +machine_init(maru_machine_init);
index fad948f,0000000..702fefa
mode 100644,000000..100644
--- /dev/null
@@@ -1,1802 -1,0 +1,1802 @@@
-         qemu_irq_raise(s->dev.irq[0]);
 +/*
 + * Virtual Codec Device
 + *
 + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
 + *
 + * Contact:
 + *  Kitae Kim <kt920.kim@samsung.com>
 + *  SeokYeon Hwang <syeon.hwang@samsung.com>
 + *  YeongKyoon Lee <yeongkyoon.lee@samsung.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 + * MA 02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +#include "maru_brill_codec.h"
 +
 +/* define debug channel */
 +MULTI_DEBUG_CHANNEL(qemu, brillcodec);
 +
 +// device
 +#define CODEC_DEVICE_NAME   "brilcodec"
 +#define CODEC_VERSION       1
 +
 +// device memory
 +#define CODEC_META_DATA_SIZE    (256)
 +
 +#define CODEC_MEM_SIZE          (32 * 1024 * 1024)
 +#define CODEC_REG_SIZE          (256)
 +
 +// libav
 +#define GEN_MASK(x) ((1 << (x)) - 1)
 +#define ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) & ~GEN_MASK(x))
 +#define ROUND_UP_2(x) ROUND_UP_X(x, 1)
 +#define ROUND_UP_4(x) ROUND_UP_X(x, 2)
 +#define ROUND_UP_8(x) ROUND_UP_X(x, 3)
 +#define DIV_ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) >> (x))
 +
 +#define DEFAULT_VIDEO_GOP_SIZE 15
 +
 +
 +// define a queue to manage ioparam, context data
 +typedef struct DeviceMemEntry {
 +    uint8_t *buf;
 +    uint32_t buf_size;
 +    uint32_t ctx_id;
 +
 +    QTAILQ_ENTRY(DeviceMemEntry) node;
 +} DeviceMemEntry;
 +
 +typedef struct CodecDataStg {
 +    CodecParam *param_buf;
 +    DeviceMemEntry *data_buf;
 +
 +    QTAILQ_ENTRY(CodecDataStg) node;
 +} CodecDataStg;
 +
 +// define two queue to store input and output buffers.
 +static QTAILQ_HEAD(codec_wq, DeviceMemEntry) codec_wq =
 +   QTAILQ_HEAD_INITIALIZER(codec_wq);
 +
 +static QTAILQ_HEAD(codec_rq, CodecDataStg) codec_rq =
 +   QTAILQ_HEAD_INITIALIZER(codec_rq);
 +
 +static DeviceMemEntry *entry[CODEC_CONTEXT_MAX];
 +
 +// pixel info
 +typedef struct PixFmtInfo {
 +    uint8_t x_chroma_shift;
 +    uint8_t y_chroma_shift;
 +} PixFmtInfo;
 +
 +static PixFmtInfo pix_fmt_info[PIX_FMT_NB];
 +
 +// thread
 +// static int idle_thread_cnt = 0;
 +#define DEFAULT_WORKER_THREAD_CNT 8
 +
 +static void *maru_brill_codec_threads(void *opaque);
 +
 +// static void maru_brill_codec_reset_parser_info(MaruBrillCodecState *s, int32_t ctx_index);
 +static int maru_brill_codec_query_list(MaruBrillCodecState *s);
 +static void maru_brill_codec_release_context(MaruBrillCodecState *s, int32_t value);
 +
 +// codec functions
 +static bool codec_init(MaruBrillCodecState *, int, void *);
 +static bool codec_deinit(MaruBrillCodecState *, int, void *);
 +static bool codec_decode_video(MaruBrillCodecState *, int, void *);
 +static bool codec_encode_video(MaruBrillCodecState *, int, void *);
 +static bool codec_decode_audio(MaruBrillCodecState *, int, void *);
 +static bool codec_encode_audio(MaruBrillCodecState *, int, void *);
 +static bool codec_picture_copy(MaruBrillCodecState *, int, void *);
 +static bool codec_flush_buffers(MaruBrillCodecState *, int, void *);
 +
 +typedef bool (*CodecFuncEntry)(MaruBrillCodecState *, int, void *);
 +static CodecFuncEntry codec_func_handler[] = {
 +    codec_init,
 +    codec_decode_video,
 +    codec_encode_video,
 +    codec_decode_audio,
 +    codec_encode_audio,
 +    codec_picture_copy,
 +    codec_deinit,
 +    codec_flush_buffers,
 +};
 +
 +static AVCodecParserContext *maru_brill_codec_parser_init(AVCodecContext *avctx);
 +#if 0
 +static int maru_brill_codec_parser_parse (AVCodecParserContext *pctx, AVCodecContext *avctx,
 +                            uint8_t *inbuf, int inbuf_size,
 +                            int64_t pts, int64_t dts, int64_t pos);
 +#endif
 +
 +static void maru_brill_codec_pop_writequeue(MaruBrillCodecState *s, uint32_t ctx_idx);
 +static void maru_brill_codec_push_readqueue(MaruBrillCodecState *s, CodecParam *ioparam);
 +static void maru_brill_codec_push_writequeue(MaruBrillCodecState *s, void* buf,
 +                                            uint32_t buf_size, int ctx_id);
 +
 +static void *maru_brill_codec_store_inbuf(uint8_t *mem_base_offset, CodecParam *ioparam);
 +
 +static void maru_brill_codec_reset(DeviceState *s);
 +
 +static void maru_brill_codec_get_cpu_cores(MaruBrillCodecState *s)
 +{
 +    s->worker_thread_cnt = get_number_of_processors();
 +    if (s->worker_thread_cnt < DEFAULT_WORKER_THREAD_CNT) {
 +        s->worker_thread_cnt = DEFAULT_WORKER_THREAD_CNT;
 +    }
 +
 +    TRACE("number of threads: %d\n", s->worker_thread_cnt);
 +}
 +
 +static void maru_brill_codec_threads_create(MaruBrillCodecState *s)
 +{
 +    int index;
 +    QemuThread *pthread = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    pthread = g_malloc(sizeof(QemuThread) * s->worker_thread_cnt);
 +    if (!pthread) {
 +        ERR("failed to allocate threadpool memory.\n");
 +        return;
 +    }
 +
 +    qemu_cond_init(&s->threadpool.cond);
 +    qemu_mutex_init(&s->threadpool.mutex);
 +
 +    s->is_thread_running = true;
 +    s->idle_thread_cnt = 0;
 +
 +    for (index = 0; index < s->worker_thread_cnt; index++) {
 +        qemu_thread_create(&pthread[index],
 +            maru_brill_codec_threads, (void *)s, QEMU_THREAD_JOINABLE);
 +    }
 +
 +    s->threadpool.threads = pthread;
 +
 +    TRACE("leave: %s\n", __func__);
 +}
 +
 +static void maru_brill_codec_thread_exit(MaruBrillCodecState *s)
 +{
 +    int index;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    /* stop to run dedicated threads. */
 +    s->is_thread_running = false;
 +
 +    for (index = 0; index < s->worker_thread_cnt; index++) {
 +        qemu_thread_join(&s->threadpool.threads[index]);
 +    }
 +
 +    TRACE("destroy mutex and conditional.\n");
 +    qemu_mutex_destroy(&s->threadpool.mutex);
 +    qemu_cond_destroy(&s->threadpool.cond);
 +
 +    if (s->threadpool.threads) {
 +        g_free(s->threadpool.threads);
 +        s->threadpool.threads = NULL;
 +    }
 +
 +    TRACE("leave: %s\n", __func__);
 +}
 +
 +static void maru_brill_codec_wakeup_threads(MaruBrillCodecState *s, int api_index)
 +{
 +    CodecParam *ioparam = NULL;
 +
 +    ioparam = g_malloc0(sizeof(CodecParam));
 +    if (!ioparam) {
 +        ERR("failed to allocate ioparam\n");
 +        return;
 +    }
 +
 +    memcpy(ioparam, &s->ioparam, sizeof(CodecParam));
 +
 +    TRACE("wakeup thread. ctx_id: %u, api_id: %u, mem_offset: 0x%x\n",
 +        ioparam->ctx_index, ioparam->api_index, ioparam->mem_offset);
 +
 +    maru_brill_codec_push_readqueue(s, ioparam);
 +
 +    qemu_mutex_lock(&s->context_mutex);
 +    // W/A for threads starvation.
 +    while (s->idle_thread_cnt == 0) {
 +        qemu_mutex_unlock(&s->context_mutex);
 +        TRACE("Worker threads are exhausted\n");
 +        usleep(2000); // wait 2ms.
 +        qemu_mutex_lock(&s->context_mutex);
 +    }
 +    qemu_cond_signal(&s->threadpool.cond);
 +    qemu_mutex_unlock(&s->context_mutex);
 +
 +    TRACE("after sending conditional signal\n");
 +}
 +
 +static void *maru_brill_codec_threads(void *opaque)
 +{
 +    MaruBrillCodecState *s = (MaruBrillCodecState *)opaque;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    while (s->is_thread_running) {
 +        int ctx_id, api_id;
 +        CodecDataStg *elem = NULL;
 +        DeviceMemEntry *indata_buf = NULL;
 +
 +        qemu_mutex_lock(&s->context_mutex);
 +        ++(s->idle_thread_cnt); // protected under mutex.
 +        qemu_cond_wait(&s->threadpool.cond, &s->context_mutex);
 +        --(s->idle_thread_cnt); // protected under mutex.
 +        qemu_mutex_unlock(&s->context_mutex);
 +
 +        qemu_mutex_lock(&s->ioparam_queue_mutex);
 +        elem = QTAILQ_FIRST(&codec_rq);
 +        if (elem) {
 +            QTAILQ_REMOVE(&codec_rq, elem, node);
 +            qemu_mutex_unlock(&s->ioparam_queue_mutex);
 +        } else {
 +            qemu_mutex_unlock(&s->ioparam_queue_mutex);
 +            continue;
 +        }
 +
 +        if (!elem->param_buf) {
 +            continue;
 +        }
 +
 +        api_id = elem->param_buf->api_index;
 +        ctx_id = elem->param_buf->ctx_index;
 +        indata_buf = elem->data_buf;
 +
 +        TRACE("api_id: %d ctx_id: %d\n", api_id, ctx_id);
 +
 +        if (!codec_func_handler[api_id](s, ctx_id, indata_buf)) {
 +            ERR("codec_func failure.\n");
 +            continue;
 +        }
 +
 +        TRACE("release a buffer of CodecParam\n");
 +        g_free(elem->param_buf);
 +
 +        if (elem->data_buf) {
 +
 +            if (elem->data_buf->buf) {
 +                TRACE("release inbuf\n");
 +                g_free(elem->data_buf->buf);
 +            }
 +
 +            TRACE("release a buffer indata_buf\n");
 +            g_free(elem->data_buf);
 +        }
 +
 +        TRACE("release an element of CodecDataStg\n");
 +        g_free(elem);
 +
 +        if (api_id == CODEC_DEINIT) {
 +            TRACE("deinit doesn't need to raise interrupt.\n");
 +        } else {
 +            TRACE("switch context to raise interrupt.\n");
 +            qemu_bh_schedule(s->codec_bh);
 +        }
 +    }
 +
 +    maru_brill_codec_thread_exit(s);
 +
 +    TRACE("leave: %s\n", __func__);
 +    return NULL;
 +}
 +
 +// queue
 +static void maru_brill_codec_push_readqueue(MaruBrillCodecState *s,
 +                                            CodecParam *ioparam)
 +{
 +    CodecDataStg *elem = NULL;
 +    DeviceMemEntry *data_buf = NULL;
 +
 +    elem = g_malloc0(sizeof(CodecDataStg));
 +    if (!elem) {
 +        ERR("failed to allocate ioparam_queue. %d\n", sizeof(CodecDataStg));
 +        return;
 +    }
 +
 +    elem->param_buf = ioparam;
 +
 +    switch(ioparam->api_index) {
 +    case CODEC_DECODE_VIDEO ... CODEC_ENCODE_AUDIO:
 +        data_buf = maru_brill_codec_store_inbuf((uint8_t *)s->vaddr, ioparam);
 +        break;
 +    default:
 +        TRACE("no buffer from guest\n");
 +        break;
 +    }
 +
 +    elem->data_buf = data_buf;
 +
 +    qemu_mutex_lock(&s->ioparam_queue_mutex);
 +    QTAILQ_INSERT_TAIL(&codec_rq, elem, node);
 +    qemu_mutex_unlock(&s->ioparam_queue_mutex);
 +}
 +
 +static void *maru_brill_codec_store_inbuf(uint8_t *mem_base_offset,
 +                                        CodecParam *ioparam)
 +{
 +    DeviceMemEntry *elem = NULL;
 +    int readbuf_size, size = 0;
 +    uint8_t *readbuf = NULL;
 +    uint8_t *device_mem = mem_base_offset + ioparam->mem_offset;
 +
 +    elem = g_malloc0(sizeof(DeviceMemEntry));
 +    if (!elem) {
 +        ERR("failed to allocate readqueue node. size: %d\n",
 +            sizeof(DeviceMemEntry));
 +        return NULL;
 +    }
 +
 +    memcpy(&readbuf_size, device_mem, sizeof(readbuf_size));
 +    size = sizeof(readbuf_size);
 +
 +    TRACE("readbuf size: %d\n", readbuf_size);
 +    if (readbuf_size <= 0) {
 +        TRACE("inbuf size is zero. api_id: %d, ctx_id: %d, mem_offset: %x\n",
 +            readbuf_size, ioparam->api_index, ioparam->ctx_index, ioparam->mem_offset);
 +    } else {
 +        readbuf = g_malloc0(readbuf_size);
 +        if (!readbuf) {
 +            ERR("failed to allocate a read buffer. size: %d\n", readbuf_size);
 +        } else {
 +            TRACE("copy input buffer from guest. ctx_id: %d, mem_offset: %x\n",
 +                ioparam->ctx_index, ioparam->mem_offset);
 +            memcpy(readbuf, device_mem + size, readbuf_size);
 +        }
 +    }
 +    memset(device_mem, 0x00, sizeof(readbuf_size));
 +
 +    elem->buf = readbuf;
 +    elem->buf_size = readbuf_size;
 +    elem->ctx_id = ioparam->ctx_index;
 +
 +    return elem;
 +}
 +
 +static void maru_brill_codec_push_writequeue(MaruBrillCodecState *s, void* buf,
 +                                            uint32_t buf_size, int ctx_id)
 +{
 +    DeviceMemEntry *elem = NULL;
 +    elem = g_malloc0(sizeof(DeviceMemEntry));
 +
 +    elem->buf = buf;
 +    elem->buf_size = buf_size;
 +    elem->ctx_id = ctx_id;
 +
 +    qemu_mutex_lock(&s->context_queue_mutex);
 +    QTAILQ_INSERT_TAIL(&codec_wq, elem, node);
 +    qemu_mutex_unlock(&s->context_queue_mutex);
 +}
 +
 +static void maru_brill_codec_pop_writequeue(MaruBrillCodecState *s, uint32_t ctx_idx)
 +{
 +    DeviceMemEntry *elem = NULL;
 +    uint32_t mem_offset = 0;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    if (ctx_idx < 1 || ctx_idx > (CODEC_CONTEXT_MAX - 1)) {
 +        ERR("invalid buffer index. %d\n", ctx_idx);
 +        return;
 +    }
 +
 +    TRACE("pop_writeqeue. context index: %d\n", ctx_idx);
 +    elem = entry[ctx_idx];
 +    if (elem) {
 +        mem_offset = s->ioparam.mem_offset;
 +
 +        // check corrupted mem_offset
 +        if (mem_offset < CODEC_MEM_SIZE) {
 +            if (elem->buf) {
 +                TRACE("write data %d to guest.  mem_offset: 0x%x\n",
 +                        elem->buf_size, mem_offset);
 +                memcpy(s->vaddr + mem_offset, elem->buf, elem->buf_size);
 +
 +                TRACE("release output buffer: %p\n", elem->buf);
 +                g_free(elem->buf);
 +            }
 +        } else {
 +            TRACE("mem_offset is corrupted!!\n");
 +        }
 +
 +        TRACE("pop_writequeue. release elem: %p\n", elem);
 +        g_free(elem);
 +
 +        entry[ctx_idx] = NULL;
 +    } else {
 +        TRACE("there is no buffer to copy data to guest\n");
 +    }
 +
 +    TRACE("leave: %s\n", __func__);
 +}
 +
 +static void serialize_video_data(const struct video_data *video,
 +                                AVCodecContext *avctx)
 +{
 +    if (video->width) {
 +        avctx->width = video->width;
 +    }
 +    if (video->height) {
 +        avctx->height = video->height;
 +    }
 +    if (video->fps_n) {
 +        avctx->time_base.num = video->fps_n;
 +    }
 +    if (video->fps_d) {
 +        avctx->time_base.den = video->fps_d;
 +    }
 +    if (video->pix_fmt > PIX_FMT_NONE) {
 +        avctx->pix_fmt = video->pix_fmt;
 +    }
 +    if (video->par_n) {
 +        avctx->sample_aspect_ratio.num = video->par_n;
 +    }
 +    if (video->par_d) {
 +        avctx->sample_aspect_ratio.den = video->par_d;
 +    }
 +    if (video->bpp) {
 +        avctx->bits_per_coded_sample = video->bpp;
 +    }
 +    if (video->ticks_per_frame) {
 +        avctx->ticks_per_frame = video->ticks_per_frame;
 +    }
 +}
 +
 +static void deserialize_video_data (const AVCodecContext *avctx,
 +                                    struct video_data *video)
 +{
 +    memset(video, 0x00, sizeof(struct video_data));
 +
 +    video->width = avctx->width;
 +    video->height = avctx->height;
 +    video->fps_n = avctx->time_base.num;
 +    video->fps_d = avctx->time_base.den;
 +    video->pix_fmt = avctx->pix_fmt;
 +    video->par_n = avctx->sample_aspect_ratio.num;
 +    video->par_d = avctx->sample_aspect_ratio.den;
 +    video->bpp = avctx->bits_per_coded_sample;
 +    video->ticks_per_frame = avctx->ticks_per_frame;
 +}
 +
 +static void serialize_audio_data (const struct audio_data *audio,
 +                                  AVCodecContext *avctx)
 +{
 +    if (audio->channels) {
 +        avctx->channels = audio->channels;
 +    }
 +    if (audio->sample_rate) {
 +        avctx->sample_rate = audio->sample_rate;
 +    }
 +    if (audio->block_align) {
 +        avctx->block_align = audio->block_align;
 +    }
 +
 +    if (audio->sample_fmt > AV_SAMPLE_FMT_NONE) {
 +        avctx->sample_fmt = audio->sample_fmt;
 +    }
 +}
 +
 +#if 0
 +static void maru_brill_codec_reset_parser_info(MaruBrillCodecState *s, int32_t ctx_index)
 +{
 +    s->context[ctx_index].parser_buf = NULL;
 +    s->context[ctx_index].parser_use = false;
 +}
 +#endif
 +
 +static void maru_brill_codec_release_context(MaruBrillCodecState *s, int32_t context_id)
 +{
 +    DeviceMemEntry *wq_elem = NULL, *wnext = NULL;
 +    CodecDataStg *rq_elem = NULL, *rnext = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    TRACE("release %d of context\n", context_id);
 +    codec_deinit(s, context_id, NULL);
 +    s->context[context_id].occupied = false;
 +
 +    // TODO: check if foreach statment needs lock or not.
 +    QTAILQ_FOREACH_SAFE(rq_elem, &codec_rq, node, rnext) {
 +        if (rq_elem && rq_elem->data_buf &&
 +            (rq_elem->data_buf->ctx_id == context_id)) {
 +
 +            TRACE("remove unused node from codec_rq. ctx_id: %d\n", context_id);
 +            qemu_mutex_lock(&s->context_queue_mutex);
 +            QTAILQ_REMOVE(&codec_rq, rq_elem, node);
 +            qemu_mutex_unlock(&s->context_queue_mutex);
 +            if (rq_elem && rq_elem->data_buf) {
 +                TRACE("release rq_buffer: %p\n", rq_elem->data_buf);
 +                g_free(rq_elem->data_buf);
 +            }
 +
 +            TRACE("release rq_elem: %p\n", rq_elem);
 +            g_free(rq_elem);
 +        } else {
 +            TRACE("no elem of %d context in the codec_rq.\n", context_id);
 +        }
 +    }
 +
 +    QTAILQ_FOREACH_SAFE(wq_elem, &codec_wq, node, wnext) {
 +        if (wq_elem && wq_elem->ctx_id == context_id) {
 +            TRACE("remove unused node from codec_wq. ctx_id: %d\n", context_id);
 +            qemu_mutex_lock(&s->context_queue_mutex);
 +            QTAILQ_REMOVE(&codec_wq, wq_elem, node);
 +            qemu_mutex_unlock(&s->context_queue_mutex);
 +
 +            if (wq_elem && wq_elem->buf) {
 +                TRACE("release wq_buffer: %p\n", wq_elem->buf);
 +                g_free(wq_elem->buf);
 +                wq_elem->buf = NULL;
 +            }
 +
 +            TRACE("release wq_elem: %p\n", wq_elem);
 +            g_free(wq_elem);
 +        } else {
 +            TRACE("no elem of %d context in the codec_wq.\n", context_id);
 +        }
 +    }
 +
 +    TRACE("leave: %s\n", __func__);
 +}
 +
 +
 +// initialize each pixel format.
 +static void maru_brill_codec_pixfmt_info_init(void)
 +{
 +    /* YUV formats */
 +    pix_fmt_info[PIX_FMT_YUV420P].x_chroma_shift = 1;
 +    pix_fmt_info[PIX_FMT_YUV420P].y_chroma_shift = 1;
 +
 +    pix_fmt_info[PIX_FMT_YUV422P].x_chroma_shift = 1;
 +    pix_fmt_info[PIX_FMT_YUV422P].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_YUV444P].x_chroma_shift = 0;
 +    pix_fmt_info[PIX_FMT_YUV444P].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_YUYV422].x_chroma_shift = 1;
 +    pix_fmt_info[PIX_FMT_YUYV422].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_YUV410P].x_chroma_shift = 2;
 +    pix_fmt_info[PIX_FMT_YUV410P].y_chroma_shift = 2;
 +
 +    pix_fmt_info[PIX_FMT_YUV411P].x_chroma_shift = 2;
 +    pix_fmt_info[PIX_FMT_YUV411P].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_YUVJ420P].x_chroma_shift = 1;
 +    pix_fmt_info[PIX_FMT_YUVJ420P].y_chroma_shift = 1;
 +
 +    pix_fmt_info[PIX_FMT_YUVJ422P].x_chroma_shift = 1;
 +    pix_fmt_info[PIX_FMT_YUVJ422P].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_YUVJ444P].x_chroma_shift = 0;
 +    pix_fmt_info[PIX_FMT_YUVJ444P].y_chroma_shift = 0;
 +
 +    /* RGB formats */
 +    pix_fmt_info[PIX_FMT_RGB24].x_chroma_shift = 0;
 +    pix_fmt_info[PIX_FMT_RGB24].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_BGR24].x_chroma_shift = 0;
 +    pix_fmt_info[PIX_FMT_BGR24].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_RGB32].x_chroma_shift = 0;
 +    pix_fmt_info[PIX_FMT_RGB32].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_RGB565].x_chroma_shift = 0;
 +    pix_fmt_info[PIX_FMT_RGB565].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_RGB555].x_chroma_shift = 0;
 +    pix_fmt_info[PIX_FMT_RGB555].y_chroma_shift = 0;
 +
 +    pix_fmt_info[PIX_FMT_YUVA420P].x_chroma_shift = 1;
 +    pix_fmt_info[PIX_FMT_YUVA420P].y_chroma_shift = 1;
 +}
 +
 +static int maru_brill_codec_get_picture_size(AVPicture *picture, uint8_t *ptr,
 +                                    int pix_fmt, int width,
 +                                    int height, bool encode)
 +{
 +    int size, w2, h2, size2;
 +    int stride, stride2;
 +    int fsize;
 +    PixFmtInfo *pinfo;
 +
 +    pinfo = &pix_fmt_info[pix_fmt];
 +
 +    switch (pix_fmt) {
 +    case PIX_FMT_YUV420P:
 +    case PIX_FMT_YUV422P:
 +    case PIX_FMT_YUV444P:
 +    case PIX_FMT_YUV410P:
 +    case PIX_FMT_YUV411P:
 +    case PIX_FMT_YUVJ420P:
 +    case PIX_FMT_YUVJ422P:
 +    case PIX_FMT_YUVJ444P:
 +        stride = ROUND_UP_4(width);
 +        h2 = ROUND_UP_X(height, pinfo->y_chroma_shift);
 +        size = stride * h2;
 +        w2 = DIV_ROUND_UP_X(width, pinfo->x_chroma_shift);
 +        stride2 = ROUND_UP_4(w2);
 +        h2 = DIV_ROUND_UP_X(height, pinfo->y_chroma_shift);
 +        size2 = stride2 * h2;
 +        fsize = size + 2 * size2;
 +        TRACE("stride: %d, stride2: %d, size: %d, size2: %d, fsize: %d\n",
 +            stride, stride2, size, size2, fsize);
 +
 +        if (!encode && !ptr) {
 +            TRACE("allocate a buffer for a decoded picture.\n");
 +            ptr = av_mallocz(fsize);
 +            if (!ptr) {
 +                ERR("[%d] failed to allocate memory.\n", __LINE__);
 +                return -1;
 +            }
 +        }
 +        picture->data[0] = ptr;
 +        picture->data[1] = picture->data[0] + size;
 +        picture->data[2] = picture->data[1] + size2;
 +        picture->data[3] = NULL;
 +        picture->linesize[0] = stride;
 +        picture->linesize[1] = stride2;
 +        picture->linesize[2] = stride2;
 +        picture->linesize[3] = 0;
 +        TRACE("planes %d %d %d\n", 0, size, size + size2);
 +        TRACE("strides %d %d %d\n", 0, stride, stride2, stride2);
 +        break;
 +    case PIX_FMT_YUVA420P:
 +        stride = ROUND_UP_4(width);
 +        h2 = ROUND_UP_X(height, pinfo->y_chroma_shift);
 +        size = stride * h2;
 +        w2 = DIV_ROUND_UP_X(width, pinfo->x_chroma_shift);
 +        stride2 = ROUND_UP_4(w2);
 +        h2 = DIV_ROUND_UP_X(height, pinfo->y_chroma_shift);
 +        size2 = stride2 * h2;
 +        fsize = 2 * size + 2 * size2;
 +        if (!encode && !ptr) {
 +            TRACE("allocate a buffer for a decoded picture.\n");
 +            ptr = av_mallocz(fsize);
 +            if (!ptr) {
 +                ERR("[%d] failed to allocate memory.\n", __LINE__);
 +                return -1;
 +            }
 +        }
 +        picture->data[0] = ptr;
 +        picture->data[1] = picture->data[0] + size;
 +        picture->data[2] = picture->data[1] + size2;
 +        picture->data[3] = picture->data[2] + size2;
 +        picture->linesize[0] = stride;
 +        picture->linesize[1] = stride2;
 +        picture->linesize[2] = stride2;
 +        picture->linesize[3] = stride;
 +        TRACE("planes %d %d %d\n", 0, size, size + size2);
 +        TRACE("strides %d %d %d\n", 0, stride, stride2, stride2);
 +        break;
 +    case PIX_FMT_RGB24:
 +    case PIX_FMT_BGR24:
 +        stride = ROUND_UP_4 (width * 3);
 +        fsize = stride * height;
 +        TRACE("stride: %d, size: %d\n", stride, fsize);
 +
 +        if (!encode && !ptr) {
 +            TRACE("allocate a buffer for a decoded picture.\n");
 +            ptr = av_mallocz(fsize);
 +            if (!ptr) {
 +                ERR("[%d] failed to allocate memory.\n", __LINE__);
 +                return -1;
 +            }
 +        }
 +        picture->data[0] = ptr;
 +        picture->data[1] = NULL;
 +        picture->data[2] = NULL;
 +        picture->data[3] = NULL;
 +        picture->linesize[0] = stride;
 +        picture->linesize[1] = 0;
 +        picture->linesize[2] = 0;
 +        picture->linesize[3] = 0;
 +        break;
 +    case PIX_FMT_RGB32:
 +        stride = width * 4;
 +        fsize = stride * height;
 +        TRACE("stride: %d, size: %d\n", stride, fsize);
 +
 +        if (!encode && !ptr) {
 +            TRACE("allocate a buffer for a decoded picture.\n");
 +            ptr = av_mallocz(fsize);
 +            if (!ptr) {
 +                ERR("[%d] failed to allocate memory.\n", __LINE__);
 +                return -1;
 +            }
 +        }
 +        picture->data[0] = ptr;
 +        picture->data[1] = NULL;
 +        picture->data[2] = NULL;
 +        picture->data[3] = NULL;
 +        picture->linesize[0] = stride;
 +        picture->linesize[1] = 0;
 +        picture->linesize[2] = 0;
 +        picture->linesize[3] = 0;
 +        break;
 +    case PIX_FMT_RGB555:
 +    case PIX_FMT_RGB565:
 +        stride = ROUND_UP_4 (width * 2);
 +        fsize = stride * height;
 +        TRACE("stride: %d, size: %d\n", stride, fsize);
 +
 +        if (!encode && !ptr) {
 +            TRACE("allocate a buffer for a decoded picture.\n");
 +            ptr = av_mallocz(fsize);
 +            if (!ptr) {
 +                ERR("[%d] failed to allocate memory.\n", __LINE__);
 +                return -1;
 +            }
 +        }
 +        picture->data[0] = ptr;
 +        picture->data[1] = NULL;
 +        picture->data[2] = NULL;
 +        picture->data[3] = NULL;
 +        picture->linesize[0] = stride;
 +        picture->linesize[1] = 0;
 +        picture->linesize[2] = 0;
 +        picture->linesize[3] = 0;
 +        break;
 +    case PIX_FMT_PAL8:
 +        stride = ROUND_UP_4(width);
 +        size = stride * height;
 +        fsize = size + 256 * 4;
 +        TRACE("stride: %d, size: %d\n", stride, fsize);
 +
 +        if (!encode && !ptr) {
 +            TRACE("allocate a buffer for a decoded picture.\n");
 +            ptr = av_mallocz(fsize);
 +            if (!ptr) {
 +                ERR("[%d] failed to allocate memory.\n", __LINE__);
 +                return -1;
 +            }
 +        }
 +        picture->data[0] = ptr;
 +        picture->data[1] = ptr + size;
 +        picture->data[2] = NULL;
 +        picture->data[3] = NULL;
 +        picture->linesize[0] = stride;
 +        picture->linesize[1] = 4;
 +        picture->linesize[2] = 0;
 +        picture->linesize[3] = 0;
 +        break;
 +    default:
 +        picture->data[0] = NULL;
 +        picture->data[1] = NULL;
 +        picture->data[2] = NULL;
 +        picture->data[3] = NULL;
 +        fsize = -1;
 +        ERR("pixel format: %d was wrong.\n", pix_fmt);
 +        break;
 +    }
 +
 +    return fsize;
 +}
 +
 +static int maru_brill_codec_query_list (MaruBrillCodecState *s)
 +{
 +    AVCodec *codec = NULL;
 +    uint32_t size = 0, mem_size = 0;
 +    uint32_t data_len = 0, length = 0;
 +    int32_t codec_type, media_type;
 +    int32_t codec_fmts[4], i;
 +
 +    /* register avcodec */
 +    TRACE("register avcodec\n");
 +    av_register_all();
 +
 +    codec = av_codec_next(NULL);
 +    if (!codec) {
 +        ERR("failed to get codec info.\n");
 +        return -1;
 +    }
 +
 +    // a region to store the number of codecs.
 +    length = 32 + 64 + 6 * sizeof(int32_t);
 +    mem_size = size = sizeof(uint32_t);
 +
 +    while (codec) {
 +        codec_type =
 +            codec->decode ? CODEC_TYPE_DECODE : CODEC_TYPE_ENCODE;
 +        media_type = codec->type;
 +
 +        memset(codec_fmts, -1, sizeof(codec_fmts));
 +        if (media_type == AVMEDIA_TYPE_VIDEO) {
 +            if (codec->pix_fmts) {
 +                for (i = 0; codec->pix_fmts[i] != -1; i++) {
 +                    codec_fmts[i] = codec->pix_fmts[i];
 +                }
 +            }
 +        } else if (media_type == AVMEDIA_TYPE_AUDIO) {
 +            if (codec->sample_fmts) {
 +                for (i = 0; codec->sample_fmts[i] != -1; i++) {
 +                    codec_fmts[i] = codec->sample_fmts[i];
 +                }
 +            }
 +        } else {
 +            ERR("%s of media type is unknown.\n", codec->name);
 +        }
 +
 +        memset(s->vaddr + mem_size, 0x00, length);
 +        mem_size += length;
 +
 +        data_len += length;
 +        memcpy(s->vaddr, &data_len, sizeof(data_len));
 +
 +        memcpy(s->vaddr + size, &codec_type, sizeof(codec_type));
 +        size += sizeof(codec_type);
 +        memcpy(s->vaddr + size, &media_type, sizeof(media_type));
 +        size += sizeof(media_type);
 +        memcpy(s->vaddr + size, codec->name, strlen(codec->name));
 +        size += 32;
 +        memcpy(s->vaddr + size,
 +           codec->long_name, strlen(codec->long_name));
 +        size += 64;
 +        memcpy(s->vaddr + size, codec_fmts, sizeof(codec_fmts));
 +        size += sizeof(codec_fmts);
 +
 +        codec = av_codec_next(codec);
 +    }
 +
 +    return 0;
 +}
 +
 +static int maru_brill_codec_get_context_index(MaruBrillCodecState *s)
 +{
 +    int index;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    for (index = 1; index < CODEC_CONTEXT_MAX; index++) {
 +        if (s->context[index].occupied == false) {
 +            TRACE("get %d of codec context successfully.\n", index);
 +            s->context[index].occupied = true;
 +            break;
 +        }
 +    }
 +
 +    if (index == CODEC_CONTEXT_MAX) {
 +        ERR("failed to get available codec context. ");
 +        ERR("try to run codec again.\n");
 +        index = -1;
 +    }
 +
 +    TRACE("leave: %s\n", __func__);
 +
 +    return index;
 +}
 +
 +// allocate avcontext and avframe struct.
 +static AVCodecContext *maru_brill_codec_alloc_context(MaruBrillCodecState *s, int index)
 +{
 +    TRACE("enter: %s\n", __func__);
 +
 +    TRACE("allocate %d of context and frame.\n", index);
 +    s->context[index].avctx = avcodec_alloc_context();
 +    s->context[index].frame = avcodec_alloc_frame();
 +    s->context[index].opened = false;
 +
 +    s->context[index].parser_buf = NULL;
 +    s->context[index].parser_use = false;
 +
 +    TRACE("leave: %s\n", __func__);
 +
 +    return s->context[index].avctx;
 +}
 +
 +static AVCodec *maru_brill_codec_find_avcodec(uint8_t *mem_buf)
 +{
 +    AVCodec *codec = NULL;
 +    int32_t encode, size = 0;
 +    char codec_name[32] = {0, };
 +
 +    memcpy(&encode, mem_buf, sizeof(encode));
 +    size = sizeof(encode);
 +    memcpy(codec_name, mem_buf + size, sizeof(codec_name));
 +    size += sizeof(codec_name);
 +
 +    TRACE("type: %d, name: %s\n", encode, codec_name);
 +
 +    if (encode) {
 +        codec = avcodec_find_encoder_by_name (codec_name);
 +    } else {
 +        codec = avcodec_find_decoder_by_name (codec_name);
 +    }
 +    INFO("%s!! find %s %s\n",
 +        codec ? "success" : "failure",
 +        codec_name, encode ? "encoder" : "decoder");
 +
 +    return codec;
 +}
 +
 +static void read_codec_init_data(AVCodecContext *avctx, uint8_t *mem_buf)
 +{
 +    struct video_data video = { 0, };
 +    struct audio_data audio = { 0, };
 +    int bitrate = 0, size = 0;
 +
 +    memcpy(&video, mem_buf + size, sizeof(video));
 +    size = sizeof(video);
 +    serialize_video_data(&video, avctx);
 +
 +    memcpy(&audio, mem_buf + size, sizeof(int32_t) * 6);
 +    size += sizeof(int32_t) * 6;
 +    memcpy(&audio.bits_per_smp_fmt, mem_buf + size, sizeof(int32_t));
 +    size += sizeof(int32_t);
 +    memcpy(&audio.channel_layout, mem_buf + size, sizeof(int64_t));
 +    size += sizeof(int64_t);
 +    serialize_audio_data(&audio, avctx);
 +
 +    memcpy(&bitrate, mem_buf + size, sizeof(bitrate));
 +    size += sizeof(bitrate);
 +    if (bitrate) {
 +        avctx->bit_rate = bitrate;
 +    }
 +    memcpy(&avctx->codec_tag, mem_buf + size, sizeof(avctx->codec_tag));
 +    size += sizeof(avctx->codec_tag);
 +    memcpy(&avctx->extradata_size,
 +            mem_buf + size, sizeof(avctx->extradata_size));
 +    size += sizeof(avctx->extradata_size);
 +    if (avctx->extradata_size > 0) {
 +        TRACE("extradata size: %d.\n", avctx->extradata_size);
 +        avctx->extradata =
 +            av_mallocz(ROUND_UP_X(avctx->extradata_size +
 +                        FF_INPUT_BUFFER_PADDING_SIZE, 4));
 +        if (avctx->extradata) {
 +            memcpy(avctx->extradata, mem_buf + size, avctx->extradata_size);
 +        }
 +    } else {
 +        TRACE("no extra data.\n");
 +        avctx->extradata =
 +            av_mallocz(ROUND_UP_X(FF_INPUT_BUFFER_PADDING_SIZE, 4));
 +    }
 +}
 +
 +// write the result of codec_init
 +static void write_codec_init_data(AVCodecContext *avctx, uint8_t *mem_buf)
 +{
 +    int size = 0;
 +
 +    if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
 +        int osize = 0;
 +
 +        TRACE("codec_init. audio sample_fmt: %d\n", avctx->sample_fmt);
 +
 +        memcpy(mem_buf, &avctx->sample_fmt, sizeof(avctx->sample_fmt));
 +        size = sizeof(avctx->sample_fmt);
 +        memcpy(mem_buf + size,
 +                &avctx->frame_size, sizeof(avctx->frame_size));
 +        size += sizeof(avctx->frame_size);
 +        osize = av_get_bits_per_sample(avctx->codec->id) / 8;
 +        memcpy(mem_buf + size, &osize, sizeof(osize));
 +    }
 +}
 +
 +// write the result of codec_decode_video
 +static void write_codec_decode_video_data(AVCodecContext *avctx, int len,
 +                                        int got_pic_ptr, uint8_t *mem_buf)
 +{
 +    struct video_data video;
 +    int size = 0;
 +
 +    memcpy(mem_buf, &len, sizeof(len));
 +    size = sizeof(len);
 +    memcpy(mem_buf + size, &got_pic_ptr, sizeof(got_pic_ptr));
 +    size += sizeof(got_pic_ptr);
 +    if (avctx) {
 +        deserialize_video_data(avctx, &video);
 +        memcpy(mem_buf + size, &video, sizeof(struct video_data));
 +    }
 +}
 +
 +// write the result of codec_decode_audio
 +static void write_codec_decode_audio_data(int sample_rate, int channel,
 +                                        int64_t channel_layout, int len,
 +                                        int frame_size_ptr, uint8_t *mem_buf)
 +{
 +    int size = 0;
 +
 +    TRACE("copy decode_audio. len %d, frame_size %d\n", len, frame_size_ptr);
 +
 +    memcpy(mem_buf, &sample_rate, sizeof(sample_rate));
 +    size = sizeof(sample_rate);
 +    memcpy(mem_buf + size, &channel, sizeof(channel));
 +    size += sizeof(channel);
 +    memcpy(mem_buf + size, &channel_layout, sizeof(channel_layout));
 +    size += sizeof(channel_layout);
 +    memcpy(mem_buf + size, &len, sizeof(len));
 +    size += sizeof(len);
 +    memcpy(mem_buf + size, &frame_size_ptr, sizeof(frame_size_ptr));
 +}
 +
 +// codec functions
 +static bool codec_init(MaruBrillCodecState *s, int ctx_id, void *elem)
 +{
 +    AVCodecContext *avctx = NULL;
 +    AVCodec *codec = NULL;
 +    int size = 0, ret = -1;
 +    uint8_t *meta_buf = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    // assign meta_buf
 +    meta_buf = s->vaddr + ((ctx_id - 1) * CODEC_META_DATA_SIZE);
 +    meta_buf += 8; // skipped header.
 +
 +    // allocate AVCodecContext
 +    avctx = maru_brill_codec_alloc_context(s, ctx_id);
 +    if (!avctx) {
 +        ERR("[%d] failed to allocate context.\n", __LINE__);
 +        ret = -1;
 +    } else {
 +        codec = maru_brill_codec_find_avcodec(meta_buf);
 +        if (codec) {
 +            size = sizeof(int32_t) + 32; // buffer size of codec_name
 +            read_codec_init_data(avctx, meta_buf + size);
 +
 +            ret = avcodec_open(avctx, codec);
 +            INFO("avcodec_open done. ctx_id: %d\n", ctx_id);
 +
 +            s->context[ctx_id].opened = true;
 +            s->context[ctx_id].parser_ctx =
 +                maru_brill_codec_parser_init(avctx);
 +        } else {
 +            ERR("failed to find codec. ctx_id: %d\n", ctx_id);
 +        }
 +    }
 +
 +    // return the result of avcodec_open
 +    memcpy(meta_buf, &ret, sizeof(ret));
 +    size = sizeof(ret);
 +    if (ret < 0) {
 +        ERR("failed to open codec contex.\n");
 +    } else {
 +        write_codec_init_data(avctx, meta_buf + size);
 +    }
 +
 +    maru_brill_codec_push_writequeue(s, NULL, 0, ctx_id);
 +
 +    TRACE("leave: %s\n", __func__);
 +
 +    return true;
 +}
 +
 +static bool codec_deinit(MaruBrillCodecState *s, int ctx_id, void *data_buf)
 +{
 +    AVCodecContext *avctx = NULL;
 +    AVFrame *frame = NULL;
 +    AVCodecParserContext *parserctx = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    avctx = s->context[ctx_id].avctx;
 +    frame = s->context[ctx_id].frame;
 +    parserctx = s->context[ctx_id].parser_ctx;
 +    if (!avctx || !frame) {
 +        TRACE("%d of AVCodecContext or AVFrame is NULL. "
 +            " Those resources have been released before.\n", ctx_id);
 +        return false;
 +    } else {
 +        qemu_mutex_lock(&s->threadpool.mutex);
 +        if (!s->context[ctx_id].opened) {
 +            TRACE("%d of context has already been closed\n", ctx_id);
 +            qemu_mutex_unlock(&s->threadpool.mutex);
 +            return false;
 +        }
 +        avcodec_close(avctx);
 +        INFO("close avcontext of %d\n", ctx_id);
 +        s->context[ctx_id].opened = false;
 +        qemu_mutex_unlock(&s->threadpool.mutex);
 +
 +        if (avctx->extradata) {
 +            TRACE("free context extradata\n");
 +            av_free(avctx->extradata);
 +            s->context[ctx_id].avctx->extradata = NULL;
 +        }
 +
 +        if (avctx->palctrl) {
 +            TRACE("free context palctrl \n");
 +            av_free(avctx->palctrl);
 +            s->context[ctx_id].avctx->palctrl = NULL;
 +        }
 +
 +        if (frame) {
 +            TRACE("free frame\n");
 +            av_free(frame);
 +            s->context[ctx_id].frame = NULL;
 +        }
 +
 +        if (avctx) {
 +            TRACE("free codec context\n");
 +            av_free(avctx);
 +            s->context[ctx_id].avctx = NULL;
 +        }
 +
 +        if (parserctx) {
 +            av_parser_close(parserctx);
 +            s->context[ctx_id].parser_ctx = NULL;
 +        }
 +    }
 +
 +    TRACE("leave: %s\n", __func__);
 +
 +    return true;
 +}
 +
 +//
 +static bool codec_flush_buffers(MaruBrillCodecState *s, int ctx_id, void *data_buf)
 +{
 +    AVCodecContext *avctx = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    avctx = s->context[ctx_id].avctx;
 +    if (!avctx) {
 +        ERR("%d of AVCodecContext is NULL.\n", ctx_id);
 +        return false;
 +    } else {
 +        avcodec_flush_buffers(avctx);
 +        TRACE("flush %d context of buffers.\n", ctx_id);
 +    }
 +
 +    TRACE("leave: %s\n", __func__);
 +
 +    return true;
 +}
 +
 +static bool codec_decode_video(MaruBrillCodecState *s, int ctx_id, void *data_buf)
 +{
 +    AVCodecContext *avctx = NULL;
 +    AVFrame *picture = NULL;
 +    AVPacket avpkt;
 +    int got_pic_ptr = 0, len = 0;
 +    uint8_t *inbuf = NULL;
 +    int inbuf_size, idx, size = 0;
 +    int64_t in_offset;
 +
 +    DeviceMemEntry *elem = NULL;
 +    uint8_t *meta_buf = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    meta_buf = s->vaddr + ((ctx_id - 1) * CODEC_META_DATA_SIZE);
 +    meta_buf += 8; // skipped header.
 +
 +    memcpy(&inbuf_size, meta_buf, sizeof(inbuf_size));
 +    size = sizeof(inbuf_size);
 +    memcpy(&idx, meta_buf + size, sizeof(idx));
 +    size += sizeof(idx);
 +    memcpy(&in_offset, meta_buf + size, sizeof(in_offset));
 +    size += sizeof(in_offset);
 +    TRACE("decode_video. input buffer size: %d\n", inbuf_size);
 +
 +    elem = (DeviceMemEntry *)data_buf;
 +    if (elem && elem->buf) {
 +        inbuf = elem->buf;
 +    } else if (elem) {
 +        inbuf_size = 0;
 +        TRACE("decode_video. no input buffer. ctx_id: %d, %p, %d\n",
 +            ctx_id, inbuf, elem->buf_size);
 +    } else {
 +        ERR("wrong input data\n");
 +        return false;
 +    }
 +
 +    av_init_packet(&avpkt);
 +    avpkt.data = inbuf;
 +    avpkt.size = inbuf_size;
 +
 +    avctx = s->context[ctx_id].avctx;
 +    picture = s->context[ctx_id].frame;
 +    if (!avctx || !picture) {
 +        ERR("%d of AVCodecContext or AVFrame is NULL.\n", ctx_id);
 +        len = -1;
 +    } else if (!avctx->codec) {
 +        ERR("%d of AVCodec is NULL.\n", ctx_id);
 +        len = -1;
 +    } else {
 +        // in case of skipping frames
 +        picture->pict_type = -1;
 +
 +        len = avcodec_decode_video2(avctx, picture, &got_pic_ptr, &avpkt);
 +        if (len < 0) {
 +            ERR("failed to decode video. ctx index: %d\n", ctx_id);
 +        }
 +    }
 +
 +    TRACE("after decoding video. len: %d, have_data: %d\n",
 +        len, got_pic_ptr);
 +
 +    write_codec_decode_video_data(avctx, len, got_pic_ptr, meta_buf);
 +    maru_brill_codec_push_writequeue(s, NULL, 0, ctx_id);
 +
 +    TRACE("leave: %s\n", __func__);
 +
 +    return true;
 +}
 +
 +static bool codec_picture_copy (MaruBrillCodecState *s, int ctx_id, void *elem)
 +{
 +    AVCodecContext *avctx;
 +    AVPicture *src;
 +    AVPicture dst;
 +    uint8_t *out_buffer = NULL, *tempbuf = NULL;
 +    int pict_size = 0;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    TRACE("copy decoded image of %d context.\n", ctx_id);
 +
 +    avctx = s->context[ctx_id].avctx;
 +    src = (AVPicture *)s->context[ctx_id].frame;
 +    if (!avctx || !src) {
 +        ERR("%d of AVCodecContext or AVFrame is NULL.\n", ctx_id);
 +    } else if (!avctx->codec) {
 +        ERR("%d of AVCodec is NULL.\n", ctx_id);
 +    } else {
 +        TRACE("decoded image. pix_fmt: %d width: %d, height: %d\n",
 +                avctx->pix_fmt, avctx->width, avctx->height);
 +
 +        pict_size =
 +            maru_brill_codec_get_picture_size(&dst, NULL, avctx->pix_fmt,
 +                    avctx->width, avctx->height, false);
 +        if ((pict_size) < 0) {
 +            ERR("picture size: %d\n", pict_size);
 +        } else {
 +            TRACE("picture size: %d\n", pict_size);
 +            av_picture_copy(&dst, src, avctx->pix_fmt,
 +                            avctx->width, avctx->height);
 +
 +            tempbuf = g_malloc0(pict_size);
 +            if (!tempbuf) {
 +                ERR("failed to allocate a picture buffer. size: %d\n", pict_size);
 +            } else {
 +                out_buffer = dst.data[0];
 +                memcpy(tempbuf, out_buffer, pict_size);
 +            }
 +            av_free(out_buffer);
 +        }
 +    }
 +    maru_brill_codec_push_writequeue(s, tempbuf, pict_size, ctx_id);
 +
 +    TRACE("leave: %s\n", __func__);
 +
 +    return true;
 +}
 +
 +static bool codec_decode_audio(MaruBrillCodecState *s, int ctx_id, void *data_buf)
 +{
 +    AVCodecContext *avctx;
 +    AVPacket avpkt;
 +    int16_t *samples = NULL;
 +    uint8_t *inbuf = NULL;
 +    int inbuf_size = 0;
 +    int len = 0, frame_size_ptr = 0;
 +    uint8_t *meta_buf = NULL;
 +    DeviceMemEntry *elem = NULL;
 +    uint8_t *tempbuf = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    meta_buf = s->vaddr + ((ctx_id - 1) * CODEC_META_DATA_SIZE);
 +    meta_buf += 8; // skipped header.
 +
 +    memcpy(&inbuf_size, meta_buf, sizeof(inbuf_size));
 +    TRACE("before decoding audio. inbuf_size: %d\n", inbuf_size);
 +
 +    elem = (DeviceMemEntry *)data_buf;
 +    if (elem && elem->buf) {
 +        inbuf = elem->buf;
 +    } else if (elem) {
 +        inbuf_size = 0;
 +        TRACE("decode_audio. no input buffer.\n");
 +    } else {
 +        ERR("wrong input data\n");
 +        return false;
 +    }
 +
 +    av_init_packet(&avpkt);
 +    avpkt.data = inbuf;
 +    avpkt.size = inbuf_size;
 +
 +    avctx = s->context[ctx_id].avctx;
 +    if (!avctx) {
 +        ERR("[%s] %d of AVCodecContext is NULL!\n", __func__, ctx_id);
 +        write_codec_decode_audio_data(0, 0, 0, -1, 0, meta_buf);
 +    } else if (!avctx->codec) {
 +        ERR("%d of AVCodec is NULL.\n", ctx_id);
 +        write_codec_decode_audio_data(0, 0, 0, -1, 0, meta_buf);
 +    } else {
 +        frame_size_ptr = AVCODEC_MAX_AUDIO_FRAME_SIZE;
 +        samples = av_mallocz(frame_size_ptr);
 +        if (!samples) {
 +            ERR("failed to allocate an outbuf of audio.\n");
 +            len = -1;
 +        } else {
 +            len =
 +                avcodec_decode_audio3(avctx, samples, &frame_size_ptr, &avpkt);
 +
 +            TRACE("audio. len %d, channel_layout %lld, frame_size %d\n",
 +                len, avctx->channel_layout, frame_size_ptr);
 +        }
 +
 +        write_codec_decode_audio_data(avctx->sample_rate, avctx->channels,
 +                                    avctx->channel_layout, len,
 +                                    frame_size_ptr, meta_buf);
 +    }
 +
 +    if (len < 0) {
 +        ERR("failed to decode audio. ctx_id: %d, len: %d\n", ctx_id, len);
 +        frame_size_ptr = 0;
 +    } else {
 +        if (frame_size_ptr > 0) {
 +            tempbuf = g_malloc0(frame_size_ptr);
 +            if (!tempbuf) {
 +                ERR("failed to allocate decoded audio buffer. "
 +                    "ctx_id: %d, outbuf_size: %d\n", ctx_id, frame_size_ptr);
 +            } else {
 +                memcpy(tempbuf, samples, frame_size_ptr);
 +            }
 +            av_free(samples);
 +        }
 +    }
 +
 +    maru_brill_codec_push_writequeue(s, tempbuf, frame_size_ptr, ctx_id);
 +
 +    TRACE("leave: %s\n", __func__);
 +
 +    return true;
 +}
 +
 +static bool codec_encode_video(MaruBrillCodecState *s, int ctx_id, void *data_buf)
 +{
 +    AVCodecContext *avctx = NULL;
 +    AVFrame *pict = NULL;
 +    uint8_t *inbuf = NULL, *outbuf = NULL;
 +    int inbuf_size, outbuf_size, len = 0;
 +    int ret;
 +    int64_t in_timestamp;
 +
 +    uint8_t *meta_buf = NULL;
 +    DeviceMemEntry *elem = NULL;
 +    uint8_t *tempbuf = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    meta_buf = s->vaddr + ((ctx_id - 1) * CODEC_META_DATA_SIZE);
 +    meta_buf += 8; // skipped header.
 +
 +    memcpy(&inbuf_size, meta_buf, sizeof(inbuf_size));
 +    memcpy(&in_timestamp, meta_buf + sizeof(inbuf_size), sizeof(in_timestamp));
 +    TRACE("input buffer size: %d\n", inbuf_size);
 +
 +    elem = (DeviceMemEntry *)data_buf;
 +    if (elem && elem->buf) {
 +        inbuf = elem->buf;
 +    } else if (elem) {
 +        TRACE("encode_video. no input buffer.\n");
 +        inbuf_size = 0;
 +    } else {
 +        ERR("wrong input data\n");
 +        return false;
 +    }
 +
 +    avctx = s->context[ctx_id].avctx;
 +    pict = s->context[ctx_id].frame;
 +    if (!avctx || !pict) {
 +        ERR("%d of context or frame is NULL\n", ctx_id);
 +        len = -1;
 +    } else if (!avctx->codec) {
 +        ERR("%d of AVCodec is NULL.\n", ctx_id);
 +        len = -1;
 +    } else {
 +        TRACE("pixel format: %d inbuf: %p, picture data: %p\n",
 +                avctx->pix_fmt, inbuf, pict->data[0]);
 +
 +        ret =
 +            maru_brill_codec_get_picture_size((AVPicture *)pict, inbuf,
 +                                            avctx->pix_fmt, avctx->width,
 +                                            avctx->height, true);
 +        if (ret < 0) {
 +            ERR("after avpicture_fill, ret:%d\n", ret);
 +            len = -1;
 +        } else {
 +            if (avctx->time_base.num == 0) {
 +                pict->pts = AV_NOPTS_VALUE;
 +            } else {
 +                AVRational bq =
 +                    {1, (G_USEC_PER_SEC * G_GINT64_CONSTANT(1000))};
 +                pict->pts = av_rescale_q(in_timestamp, bq, avctx->time_base);
 +            }
 +            TRACE("before encode video, ticks_per_frame:%d, pts:%lld\n",
 +                    avctx->ticks_per_frame, pict->pts);
 +
 +            outbuf_size =
 +                (avctx->width * avctx->height * 6) + FF_MIN_BUFFER_SIZE;
 +            outbuf = g_malloc0(outbuf_size);
 +            if (!outbuf) {
 +                ERR("failed to allocate a buffer of encoding video.\n");
 +                len = -1;
 +            } else {
 +                len = avcodec_encode_video(avctx, outbuf, outbuf_size, pict);
 +
 +                TRACE("encode video! len:%d pts:%lld outbuf:%p outbuf size: %d\n",
 +                        len, pict->pts, outbuf, outbuf_size);
 +           }
 +        }
 +    }
 +
 +    // write encoded video data
 +    memcpy(meta_buf, &len, sizeof(len));
 +    if (len < 0) {
 +        ERR("failed to encode video. len: %d\n", len);
 +    } else {
 +        tempbuf = g_malloc0(len);
 +        if (!tempbuf) {
 +            ERR("failed to allocate an element of writequeue.\n");
 +        } else {
 +            memcpy(tempbuf, outbuf, len);
 +        }
 +    }
 +
 +    if (outbuf) {
 +        TRACE("release encoded output buffer. %p\n", outbuf);
 +        g_free(outbuf);
 +    }
 +
 +    maru_brill_codec_push_writequeue(s, tempbuf, len, ctx_id);
 +
 +    TRACE("leave: %s\n", __func__);
 +    return true;
 +}
 +
 +static bool codec_encode_audio(MaruBrillCodecState *s, int ctx_id, void *data_buf)
 +{
 +    AVCodecContext *avctx;
 +    uint8_t *inbuf = NULL, *outbuf = NULL;
 +    int32_t inbuf_size, max_size;
 +    int len = 0;
 +    uint8_t *meta_buf = NULL;
 +
 +    DeviceMemEntry *elem = NULL;
 +    uint8_t *tempbuf = NULL;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    meta_buf = s->vaddr + ((ctx_id - 1) * CODEC_META_DATA_SIZE);
 +    meta_buf += 8; // skipped header.
 +
 +    memcpy(&inbuf_size, meta_buf, sizeof(inbuf_size));
 +    memcpy(&max_size, meta_buf + sizeof(inbuf_size), sizeof(max_size));
 +    TRACE("encoding audio. in_size: %d, max_size: %d\n", inbuf_size, max_size);
 +
 +    elem = (DeviceMemEntry *)data_buf;
 +    if (elem && elem->buf) {
 +        inbuf = elem->buf;
 +    } else if (elem) {
 +        TRACE("no input buffer to encode audio.\n");
 +        inbuf_size = 0;
 +    } else {
 +        ERR("wrong input data\n");
 +        return false;
 +    }
 +
 +    avctx = s->context[ctx_id].avctx;
 +    if (!avctx) {
 +        ERR("[%s] %d of Context is NULL!\n", __func__, ctx_id);
 +    } else if (!avctx->codec) {
 +        ERR("%d of AVCodec is NULL.\n", ctx_id);
 +    } else {
 +        outbuf = g_malloc0(max_size + FF_MIN_BUFFER_SIZE);
 +        if (!outbuf) {
 +            ERR("failed to allocate a buffer of encoding audio.\n");
 +            len = -1;
 +        } else {
 +            len =
 +                avcodec_encode_audio(avctx, outbuf, max_size, (short *)inbuf);
 +            TRACE("after encoding audio. len: %d\n", len);
 +        }
 +    }
 +
 +    // write encoded audio data
 +    memcpy(meta_buf, &len, sizeof(len));
 +    if (len < 0) {
 +        ERR("failed to encode audio. ctx_id: %d len: %d\n", ctx_id, len);
 +    } else {
 +        tempbuf = g_malloc0(len);
 +        if (!tempbuf) {
 +            ERR("encode_audio. failed to allocate temporary buffer.\n");
 +        } else {
 +            memcpy(tempbuf, outbuf, len);
 +        }
 +    }
 +
 +    if (outbuf) {
 +        av_free(outbuf);
 +    }
 +
 +    maru_brill_codec_push_writequeue(s, tempbuf, len, ctx_id);
 +
 +    TRACE("[%s] leave:\n", __func__);
 +    return true;
 +}
 +
 +static AVCodecParserContext *maru_brill_codec_parser_init(AVCodecContext *avctx)
 +{
 +    AVCodecParserContext *parser = NULL;
 +
 +    if (!avctx) {
 +        ERR("context is NULL\n");
 +        return NULL;
 +    }
 +
 +    switch (avctx->codec_id) {
 +    case CODEC_ID_MPEG4:
 +    case CODEC_ID_VC1:
 +        TRACE("not using parser.\n");
 +        break;
 +    case CODEC_ID_H264:
 +        if (avctx->extradata_size == 0) {
 +            TRACE("H.264 with no extradata, creating parser.\n");
 +            parser = av_parser_init (avctx->codec_id);
 +        }
 +        break;
 +    default:
 +        parser = av_parser_init (avctx->codec_id);
 +        if (parser) {
 +            INFO("using parser. %d\n", avctx->codec_id);
 +        }
 +        break;
 +    }
 +
 +    return parser;
 +}
 +
 +//
 +static void maru_brill_codec_bh_callback(void *opaque)
 +{
 +    MaruBrillCodecState *s = (MaruBrillCodecState *)opaque;
 +
 +    TRACE("enter: %s\n", __func__);
 +
 +    qemu_mutex_lock(&s->context_queue_mutex);
 +    if (!QTAILQ_EMPTY(&codec_wq)) {
 +        qemu_mutex_unlock(&s->context_queue_mutex);
 +
 +        TRACE("raise irq\n");
-             qemu_irq_lower(s->dev.irq[0]);
++        pci_set_irq(&s->dev, 1);
 +        s->irq_raised = 1;
 +    } else {
 +        qemu_mutex_unlock(&s->context_queue_mutex);
 +        TRACE("codec_wq is empty!!\n");
 +    }
 +
 +    TRACE("leave: %s\n", __func__);
 +}
 +
 +/*
 + *  Codec Device APIs
 + */
 +static uint64_t maru_brill_codec_read(void *opaque,
 +                                        hwaddr addr,
 +                                        unsigned size)
 +{
 +    MaruBrillCodecState *s = (MaruBrillCodecState *)opaque;
 +    uint64_t ret = 0;
 +
 +    switch (addr) {
 +    case CODEC_CMD_GET_THREAD_STATE:
 +        qemu_mutex_lock(&s->context_queue_mutex);
 +        if (s->irq_raised) {
 +            ret = CODEC_TASK_END;
++            pci_set_irq(&s->dev, 0);
 +            s->irq_raised = 0;
 +        }
 +        qemu_mutex_unlock(&s->context_queue_mutex);
 +
 +        TRACE("get thread_state. ret: %d\n", ret);
 +        break;
 +
 +    case CODEC_CMD_GET_CTX_FROM_QUEUE:
 +    {
 +        DeviceMemEntry *head = NULL;
 +
 +        qemu_mutex_lock(&s->context_queue_mutex);
 +        head = QTAILQ_FIRST(&codec_wq);
 +        if (head) {
 +            ret = head->ctx_id;
 +            QTAILQ_REMOVE(&codec_wq, head, node);
 +            entry[ret] = head;
 +            TRACE("get a elem from codec_wq. 0x%x\n", head);
 +        } else {
 +            ret = 0;
 +        }
 +        qemu_mutex_unlock(&s->context_queue_mutex);
 +
 +        TRACE("get a head from a writequeue. head: %x\n", ret);
 +    }
 +        break;
 +
 +    case CODEC_CMD_GET_VERSION:
 +        ret = CODEC_VERSION;
 +        TRACE("codec version: %d\n", ret);
 +        break;
 +
 +    case CODEC_CMD_GET_ELEMENT:
 +        ret = maru_brill_codec_query_list(s);
 +        break;
 +
 +    case CODEC_CMD_GET_CONTEXT_INDEX:
 +        ret = maru_brill_codec_get_context_index(s);
 +        TRACE("get context index: %d\n", ret);
 +        break;
 +
 +    default:
 +        ERR("no avaiable command for read. %d\n", addr);
 +    }
 +
 +    return ret;
 +}
 +
 +static void maru_brill_codec_write(void *opaque, hwaddr addr,
 +                                    uint64_t value, unsigned size)
 +{
 +    MaruBrillCodecState *s = (MaruBrillCodecState *)opaque;
 +
 +    switch (addr) {
 +    case CODEC_CMD_API_INDEX:
 +        TRACE("set codec_cmd value: %d\n", value);
 +        s->ioparam.api_index = value;
 +        maru_brill_codec_wakeup_threads(s, value);
 +        break;
 +
 +    case CODEC_CMD_CONTEXT_INDEX:
 +        TRACE("set context_index value: %d\n", value);
 +        s->ioparam.ctx_index = value;
 +        break;
 +
 +    case CODEC_CMD_DEVICE_MEM_OFFSET:
 +        TRACE("set mem_offset value: 0x%x\n", value);
 +        s->ioparam.mem_offset = value;
 +        break;
 +
 +    case CODEC_CMD_RELEASE_CONTEXT:
 +        maru_brill_codec_release_context(s, (int32_t)value);
 +        break;
 +
 +    case CODEC_CMD_GET_DATA_FROM_QUEUE:
 +        maru_brill_codec_pop_writequeue(s, (uint32_t)value);
 +        break;
 +
 +    default:
 +        ERR("no available command for write. %d\n", addr);
 +    }
 +}
 +
 +static const MemoryRegionOps maru_brill_codec_mmio_ops = {
 +    .read = maru_brill_codec_read,
 +    .write = maru_brill_codec_write,
 +    .valid = {
 +        .min_access_size = 4,
 +        .max_access_size = 4,
 +        .unaligned = false
 +    },
 +    .endianness = DEVICE_LITTLE_ENDIAN,
 +};
 +
 +static int maru_brill_codec_initfn(PCIDevice *dev)
 +{
 +    MaruBrillCodecState *s = DO_UPCAST(MaruBrillCodecState, dev, dev);
 +    uint8_t *pci_conf = s->dev.config;
 +
 +    INFO("device initialization.\n");
 +    pci_config_set_interrupt_pin(pci_conf, 1);
 +
 +    memory_region_init_ram(&s->vram, OBJECT(s), "maru_brill_codec.vram", CODEC_MEM_SIZE);
 +    s->vaddr = (uint8_t *)memory_region_get_ram_ptr(&s->vram);
 +
 +    memory_region_init_io(&s->mmio, OBJECT(s), &maru_brill_codec_mmio_ops, s,
 +                        "maru_brill_codec.mmio", CODEC_REG_SIZE);
 +
 +    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
 +    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio);
 +
 +//    maru_brill_codec_reset(&s->dev.qdev);
 +
 +    qemu_mutex_init(&s->context_mutex);
 +    qemu_mutex_init(&s->context_queue_mutex);
 +    qemu_mutex_init(&s->ioparam_queue_mutex);
 +
 +    maru_brill_codec_get_cpu_cores(s);
 +    maru_brill_codec_threads_create(s);
 +
 +    // register a function to qemu bottom-halves to switch context.
 +    s->codec_bh = qemu_bh_new(maru_brill_codec_bh_callback, s);
 +
 +    return 0;
 +}
 +
 +static void maru_brill_codec_exitfn(PCIDevice *dev)
 +{
 +    MaruBrillCodecState *s = DO_UPCAST(MaruBrillCodecState, dev, dev);
 +    INFO("device exit\n");
 +
 +    qemu_mutex_destroy(&s->context_mutex);
 +    qemu_mutex_destroy(&s->context_queue_mutex);
 +    qemu_mutex_destroy(&s->ioparam_queue_mutex);
 +
 +    qemu_bh_delete(s->codec_bh);
 +
 +    memory_region_destroy(&s->vram);
 +    memory_region_destroy(&s->mmio);
 +}
 +
 +static void maru_brill_codec_reset(DeviceState *d)
 +{
 +    MaruBrillCodecState *s = (MaruBrillCodecState *)d;
 +    INFO("device reset\n");
 +
 +    s->irq_raised = 0;
 +
 +    memset(&s->context, 0, sizeof(CodecContext) * CODEC_CONTEXT_MAX);
 +    memset(&s->ioparam, 0, sizeof(CodecParam));
 +
 +    maru_brill_codec_pixfmt_info_init();
 +}
 +
 +static void maru_brill_codec_class_init(ObjectClass *klass, void *data)
 +{
 +    DeviceClass *dc = DEVICE_CLASS(klass);
 +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 +
 +    k->init = maru_brill_codec_initfn;
 +    k->exit = maru_brill_codec_exitfn;
 +    k->vendor_id = PCI_VENDOR_ID_TIZEN;
 +    k->device_id = PCI_DEVICE_ID_VIRTUAL_BRILL_CODEC;
 +    k->class_id = PCI_CLASS_OTHERS;
 +    dc->reset = maru_brill_codec_reset;
 +    dc->desc = "Virtual new codec device for Tizen emulator";
 +}
 +
 +static TypeInfo codec_device_info = {
 +    .name          = CODEC_DEVICE_NAME,
 +    .parent        = TYPE_PCI_DEVICE,
 +    .instance_size = sizeof(MaruBrillCodecState),
 +    .class_init    = maru_brill_codec_class_init,
 +};
 +
 +static void codec_register_types(void)
 +{
 +    type_register_static(&codec_device_info);
 +}
 +
 +type_init(codec_register_types)
 +
 +int maru_brill_codec_pci_device_init(PCIBus *bus)
 +{
 +    INFO("device create.\n");
 +    pci_create_simple(bus, -1, CODEC_DEVICE_NAME);
 +    return 0;
 +}
index 840f4da,0000000..dd6c4fa
mode 100644,000000..100644
--- /dev/null
@@@ -1,157 -1,0 +1,158 @@@
 +/*
 + * Virtual Codec device
 + *
 + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
 + *
 + * Contact:
 + *  Kitae Kim <kt920.kim@samsung.com>
 + *  SeokYeon Hwang <syeon.hwang@samsung.com>
 + *  YeongKyoon Lee <yeongkyoon.lee@samsung.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 + * MA 02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +#include <stdio.h>
 +#include <sys/types.h>
 +
 +#include "hw/hw.h"
 +#include "sysemu/kvm.h"
++#include "qemu/main-loop.h"
 +#include "hw/pci/pci.h"
 +#include "hw/pci/pci_ids.h"
 +#include "qemu-common.h"
 +#include "qemu/thread.h"
 +
 +#include "osutil.h"
 +#include "tizen/src/debug_ch.h"
 +#include "maru_device_ids.h"
 +#include "libavformat/avformat.h"
 +
 +#define CODEC_CONTEXT_MAX           1024
 +
 +/*
 + *  Codec Device Structures
 + */
 +typedef struct CodecParam {
 +    int32_t     api_index;
 +    int32_t     ctx_index;
 +    uint32_t    mem_offset;
 +} CodecParam;
 +
 +struct video_data {
 +    int32_t width;
 +    int32_t height;
 +    int32_t fps_n;
 +    int32_t fps_d;
 +    int32_t par_n;
 +    int32_t par_d;
 +    int32_t pix_fmt;
 +    int32_t bpp;
 +    int32_t ticks_per_frame;
 +};
 +
 +struct audio_data {
 +    int32_t channels;
 +    int32_t sample_rate;
 +    int32_t block_align;
 +    int32_t depth;
 +    int32_t sample_fmt;
 +    int32_t frame_size;
 +    int32_t bits_per_smp_fmt;
 +    int64_t channel_layout;
 +};
 +
 +typedef struct CodecContext {
 +    AVCodecContext          *avctx;
 +    AVFrame                 *frame;
 +    AVCodecParserContext    *parser_ctx;
 +    uint8_t                 *parser_buf;
 +    uint16_t                parser_use;
 +    bool                    occupied;
 +    bool                    opened;
 +} CodecContext;
 +
 +typedef struct CodecThreadPool {
 +    QemuThread          *threads;
 +    QemuMutex           mutex;
 +    QemuCond            cond;
 +} CodecThreadPool;
 +
 +typedef struct MaruBrillCodecState {
 +    PCIDevice           dev;
 +
 +    uint8_t             *vaddr;
 +    MemoryRegion        vram;
 +    MemoryRegion        mmio;
 +
 +    QEMUBH              *codec_bh;
 +    QemuMutex           context_mutex;
 +    QemuMutex           context_queue_mutex;
 +    QemuMutex           ioparam_queue_mutex;
 +
 +    CodecThreadPool     threadpool;
 +    bool                is_thread_running;
 +    uint32_t            worker_thread_cnt;
 +    uint32_t            idle_thread_cnt;
 +
 +    int                 irq_raised;
 +
 +    CodecContext        context[CODEC_CONTEXT_MAX];
 +    CodecParam          ioparam;
 +} MaruBrillCodecState;
 +
 +enum codec_io_cmd {
 +    CODEC_CMD_API_INDEX             = 0x28,
 +    CODEC_CMD_CONTEXT_INDEX         = 0x2C,
 +    CODEC_CMD_DEVICE_MEM_OFFSET     = 0x34,
 +    CODEC_CMD_GET_THREAD_STATE      = 0x38,
 +    CODEC_CMD_GET_CTX_FROM_QUEUE    = 0x3C,
 +    CODEC_CMD_GET_DATA_FROM_QUEUE   = 0x40,
 +    CODEC_CMD_RELEASE_CONTEXT       = 0x44,
 +    CODEC_CMD_GET_VERSION           = 0x50,
 +    CODEC_CMD_GET_ELEMENT           = 0x54,
 +    CODEC_CMD_GET_CONTEXT_INDEX     = 0x58,
 +};
 +
 +enum codec_api_type {
 +    CODEC_INIT = 0,
 +    CODEC_DECODE_VIDEO,
 +    CODEC_ENCODE_VIDEO,
 +    CODEC_DECODE_AUDIO,
 +    CODEC_ENCODE_AUDIO,
 +    CODEC_PICTURE_COPY,
 +    CODEC_DEINIT,
 +    CODEC_FLUSH_BUFFERS,
 + };
 +
 +enum codec_type {
 +    CODEC_TYPE_UNKNOWN = -1,
 +    CODEC_TYPE_DECODE,
 +    CODEC_TYPE_ENCODE,
 +};
 +
 +enum thread_state {
 +    CODEC_TASK_START    = 0,
 +    CODEC_TASK_END      = 0x1f,
 +};
 +
 +/*
 + *  Codec Device Functions
 + */
 +int maru_brill_codec_pci_device_init(PCIBus *bus);
index 23f7e66,0000000..7e32e83
mode 100644,000000..100644
--- /dev/null
@@@ -1,288 -1,0 +1,289 @@@
-             qemu_irq_lower(state->dev.irq[2]);
 +/*
 + * Common implementation of MARU Virtual Camera device by PCI bus.
 + *
 + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
 + *
 + * Contact:
 + * JinHyung Jo <jinhyung.jo@samsung.com>
 + * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 + * MA  02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +
 +#include <stdarg.h>
 +#include <stdlib.h>
 +#include <stdio.h>
 +#include <string.h>
 +#include <inttypes.h>
 +#include <signal.h>
 +
 +#include "qemu-common.h"
++#include "qemu/main-loop.h"
 +#include "exec/cpu-common.h"
 +
 +#include "maru_camera_common.h"
 +#include "maru_device_ids.h"
 +#include "tizen/src/debug_ch.h"
 +
 +MULTI_DEBUG_CHANNEL(tizen, camera_pci);
 +
 +#define MARU_PCI_CAMERA_DEVICE_NAME     "maru_camera_pci"
 +
 +#define MARUCAM_MEM_SIZE    (4 * 1024 * 1024)   /* 4MB */
 +#define MARUCAM_REG_SIZE    (256)               /* 64 * 4Byte */
 +
 +/*
 + *  I/O functions
 + */
 +static inline uint32_t
 +marucam_mmio_read(void *opaque, hwaddr offset)
 +{
 +    uint32_t ret = 0;
 +    MaruCamState *state = (MaruCamState *)opaque;
 +
 +    switch (offset & 0xFF) {
 +    case MARUCAM_CMD_ISR:
 +        qemu_mutex_lock(&state->thread_mutex);
 +        ret = state->isr;
 +        if (ret != 0) {
-         qemu_irq_raise(state->dev.irq[2]);
++            pci_set_irq(&state->dev, 0);
 +            state->isr = 0;
 +        }
 +        qemu_mutex_unlock(&state->thread_mutex);
 +        break;
 +    case MARUCAM_CMD_G_DATA:
 +        ret = state->param->stack[state->param->top++];
 +        break;
 +    case MARUCAM_CMD_OPEN:
 +    case MARUCAM_CMD_CLOSE:
 +    case MARUCAM_CMD_START_PREVIEW:
 +    case MARUCAM_CMD_STOP_PREVIEW:
 +    case MARUCAM_CMD_S_PARAM:
 +    case MARUCAM_CMD_G_PARAM:
 +    case MARUCAM_CMD_ENUM_FMT:
 +    case MARUCAM_CMD_TRY_FMT:
 +    case MARUCAM_CMD_S_FMT:
 +    case MARUCAM_CMD_G_FMT:
 +    case MARUCAM_CMD_QCTRL:
 +    case MARUCAM_CMD_S_CTRL:
 +    case MARUCAM_CMD_G_CTRL:
 +    case MARUCAM_CMD_ENUM_FSIZES:
 +    case MARUCAM_CMD_ENUM_FINTV:
 +        ret = state->param->errCode;
 +        state->param->errCode = 0;
 +        break;
 +    default:
 +        ERR("Not supported command: 0x%x\n", offset);
 +        ret = EINVAL;
 +        break;
 +    }
 +    return ret;
 +}
 +
 +static inline void
 +marucam_mmio_write(void *opaque, hwaddr offset, uint32_t value)
 +{
 +    MaruCamState *state = (MaruCamState *)opaque;
 +
 +    switch (offset & 0xFF) {
 +    case MARUCAM_CMD_OPEN:
 +        marucam_device_open(state);
 +        break;
 +    case MARUCAM_CMD_CLOSE:
 +        marucam_device_close(state);
 +        break;
 +    case MARUCAM_CMD_START_PREVIEW:
 +        marucam_device_start_preview(state);
 +        break;
 +    case MARUCAM_CMD_STOP_PREVIEW:
 +        marucam_device_stop_preview(state);
 +        memset(state->vaddr, 0, MARUCAM_MEM_SIZE);
 +        break;
 +    case MARUCAM_CMD_S_PARAM:
 +        marucam_device_s_param(state);
 +        break;
 +    case MARUCAM_CMD_G_PARAM:
 +        marucam_device_g_param(state);
 +        break;
 +    case MARUCAM_CMD_ENUM_FMT:
 +        marucam_device_enum_fmt(state);
 +        break;
 +    case MARUCAM_CMD_TRY_FMT:
 +        marucam_device_try_fmt(state);
 +        break;
 +    case MARUCAM_CMD_S_FMT:
 +        marucam_device_s_fmt(state);
 +        break;
 +    case MARUCAM_CMD_G_FMT:
 +        marucam_device_g_fmt(state);
 +        break;
 +    case MARUCAM_CMD_QCTRL:
 +        marucam_device_qctrl(state);
 +        break;
 +    case MARUCAM_CMD_S_CTRL:
 +        marucam_device_s_ctrl(state);
 +        break;
 +    case MARUCAM_CMD_G_CTRL:
 +        marucam_device_g_ctrl(state);
 +        break;
 +    case MARUCAM_CMD_ENUM_FSIZES:
 +        marucam_device_enum_fsizes(state);
 +        break;
 +    case MARUCAM_CMD_ENUM_FINTV:
 +        marucam_device_enum_fintv(state);
 +        break;
 +    case MARUCAM_CMD_S_DATA:
 +        state->param->stack[state->param->top++] = value;
 +        break;
 +    case MARUCAM_CMD_DATACLR:
 +        memset(state->param, 0, sizeof(MaruCamParam));
 +        break;
 +    case MARUCAM_CMD_REQFRAME:
 +        qemu_mutex_lock(&state->thread_mutex);
 +        state->req_frame = value + 1;
 +        qemu_mutex_unlock(&state->thread_mutex);
 +        break;
 +    default:
 +        ERR("Not supported command: 0x%x\n", offset);
 +        break;
 +    }
 +}
 +
 +static const MemoryRegionOps maru_camera_mmio_ops = {
 +    .old_mmio = {
 +        .read = {
 +            marucam_mmio_read,
 +            marucam_mmio_read,
 +            marucam_mmio_read,
 +        },
 +        .write = {
 +            marucam_mmio_write,
 +            marucam_mmio_write,
 +            marucam_mmio_write,
 +        },
 +    },
 +    .endianness = DEVICE_LITTLE_ENDIAN,
 +};
 +
 +/*
 + *  QEMU bottom half funtion
 + */
 +static void marucam_tx_bh(void *opaque)
 +{
 +    MaruCamState *state = (MaruCamState *)opaque;
 +
 +    qemu_mutex_lock(&state->thread_mutex);
 +    if (state->isr) {
++        pci_set_irq(&state->dev, 1);
 +    }
 +    qemu_mutex_unlock(&state->thread_mutex);
 +}
 +
 +/*
 + *  Initialization function
 + */
 +static int marucam_initfn(PCIDevice *dev)
 +{
 +    MaruCamState *s = DO_UPCAST(MaruCamState, dev, dev);
 +    uint8_t *pci_conf = s->dev.config;
 +
 +    pci_config_set_interrupt_pin(pci_conf, 0x03);
 +
 +    memory_region_init_ram(&s->vram, OBJECT(s), "marucamera.ram", MARUCAM_MEM_SIZE);
 +    s->vaddr = memory_region_get_ram_ptr(&s->vram);
 +    memset(s->vaddr, 0, MARUCAM_MEM_SIZE);
 +
 +    memory_region_init_io(&s->mmio, OBJECT(s),
 +                          &maru_camera_mmio_ops,
 +                          s,
 +                          "maru-camera-mmio",
 +                          MARUCAM_REG_SIZE);
 +
 +    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
 +    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio);
 +
 +    /* for worker thread */
 +    s->param = (MaruCamParam *)g_malloc0(sizeof(MaruCamParam));
 +    qemu_cond_init(&s->thread_cond);
 +    qemu_mutex_init(&s->thread_mutex);
 +
 +    marucam_device_init(s);
 +
 +    s->tx_bh = qemu_bh_new(marucam_tx_bh, s);
 +    INFO("[%s] camera device was initialized.\n", __func__);
 +
 +    return 0;
 +}
 +
 +/*
 + *  Termination function
 + */
 +static void marucam_exitfn(PCIDevice *pci_dev)
 +{
 +    MaruCamState *s =
 +        OBJECT_CHECK(MaruCamState, pci_dev, MARU_PCI_CAMERA_DEVICE_NAME);
 +
 +    marucam_device_exit(s);
 +    g_free(s->param);
 +    qemu_cond_destroy(&s->thread_cond);
 +    qemu_mutex_destroy(&s->thread_mutex);
 +
 +    memory_region_destroy(&s->vram);
 +    memory_region_destroy(&s->mmio);
 +
 +
 +    INFO("[%s] camera device was released.\n", __func__);
 +}
 +
 +int maru_camera_pci_init(PCIBus *bus)
 +{
 +    INFO("[%s] camera device was initialized.\n", __func__);
 +    pci_create_simple(bus, -1, MARU_PCI_CAMERA_DEVICE_NAME);
 +    return 0;
 +}
 +
 +static void maru_camera_pci_class_init(ObjectClass *klass, void *data)
 +{
 +    DeviceClass *dc = DEVICE_CLASS(klass);
 +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 +
 +    k->no_hotplug = 1;
 +    k->init = marucam_initfn;
 +    k->exit = marucam_exitfn;
 +    k->vendor_id = PCI_VENDOR_ID_TIZEN;
 +    k->device_id = PCI_DEVICE_ID_VIRTUAL_CAMERA;
 +    k->class_id = PCI_CLASS_OTHERS;
 +    dc->desc = "MARU Virtual Camera device for Tizen emulator";
 +}
 +
 +static TypeInfo maru_camera_info = {
 +    .name          = MARU_PCI_CAMERA_DEVICE_NAME,
 +    .parent        = TYPE_PCI_DEVICE,
 +    .instance_size = sizeof(MaruCamState),
 +    .class_init    = maru_camera_pci_class_init,
 +};
 +
 +static void maru_camera_pci_register_types(void)
 +{
 +    type_register_static(&maru_camera_info);
 +}
 +
 +type_init(maru_camera_pci_register_types)
diff --combined tizen/src/hw/maru_vga.c
index db547c6,0000000..e8ea00c
mode 100644,000000..100644
--- /dev/null
@@@ -1,1461 -1,0 +1,1461 @@@
-         cur_tick = qemu_get_clock_ns(vm_clock);
 +/*
 + * Maru vga device
 + * Based on qemu/hw/vga.c
 + *
 + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
 + *
 + * Contact:
 + * JinHyung Jo <jinhyung.jo@samsung.com>
 + * GiWoong Kim <giwoong.kim@samsung.com>
 + * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
 + * HyunJun Son
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +#include "hw/hw.h"
 +#include "display/vga.h"
 +#include "ui/console.h"
 +#include "hw/i386/pc.h"
 +#include "hw/pci/pci.h"
 +#include "display/vga_int.h"
 +#include "ui/pixel_ops.h"
 +#include "qemu/timer.h"
 +#include "hw/xen/xen.h"
 +#include "trace.h"
 +
 +#include <pthread.h>
 +
 +#define MARU_VGA
 +#include "maru_common.h"
 +#include "maru_vga_int.h"
 +#include "debug_ch.h"
 +
 +MULTI_DEBUG_CHANNEL(qemu, maru_vga);
 +
 +//#define DEBUG_VGA
 +//#define DEBUG_VGA_MEM
 +//#define DEBUG_VGA_REG
 +
 +//#define DEBUG_BOCHS_VBE
 +
 +/* 16 state changes per vertical frame @60 Hz */
 +#define VGA_TEXT_CURSOR_PERIOD_MS       (1000 * 2 * 16 / 60)
 +
 +#define cbswap_32(__x) \
 +((uint32_t)( \
 +        (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
 +        (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
 +        (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
 +        (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
 +
 +#ifdef HOST_WORDS_BIGENDIAN
 +#define PAT(x) cbswap_32(x)
 +#else
 +#define PAT(x) (x)
 +#endif
 +
 +#ifdef HOST_WORDS_BIGENDIAN
 +#define BIG 1
 +#else
 +#define BIG 0
 +#endif
 +
 +#ifdef HOST_WORDS_BIGENDIAN
 +#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
 +#else
 +#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
 +#endif
 +
 +static const uint32_t mask16[16] = {
 +    PAT(0x00000000),
 +    PAT(0x000000ff),
 +    PAT(0x0000ff00),
 +    PAT(0x0000ffff),
 +    PAT(0x00ff0000),
 +    PAT(0x00ff00ff),
 +    PAT(0x00ffff00),
 +    PAT(0x00ffffff),
 +    PAT(0xff000000),
 +    PAT(0xff0000ff),
 +    PAT(0xff00ff00),
 +    PAT(0xff00ffff),
 +    PAT(0xffff0000),
 +    PAT(0xffff00ff),
 +    PAT(0xffffff00),
 +    PAT(0xffffffff),
 +};
 +
 +#undef PAT
 +
 +#ifdef HOST_WORDS_BIGENDIAN
 +#define PAT(x) (x)
 +#else
 +#define PAT(x) cbswap_32(x)
 +#endif
 +
 +static const uint32_t dmask16[16] = {
 +    PAT(0x00000000),
 +    PAT(0x000000ff),
 +    PAT(0x0000ff00),
 +    PAT(0x0000ffff),
 +    PAT(0x00ff0000),
 +    PAT(0x00ff00ff),
 +    PAT(0x00ffff00),
 +    PAT(0x00ffffff),
 +    PAT(0xff000000),
 +    PAT(0xff0000ff),
 +    PAT(0xff00ff00),
 +    PAT(0xff00ffff),
 +    PAT(0xffff0000),
 +    PAT(0xffff00ff),
 +    PAT(0xffffff00),
 +    PAT(0xffffffff),
 +};
 +
 +static const uint32_t dmask4[4] = {
 +    PAT(0x00000000),
 +    PAT(0x0000ffff),
 +    PAT(0xffff0000),
 +    PAT(0xffffffff),
 +};
 +
 +static uint32_t expand4[256];
 +static uint16_t expand2[256];
 +static uint8_t expand4to8[16];
 +
 +static void vga_dumb_update_retrace_info(VGACommonState *s)
 +{
 +    (void) s;
 +}
 +
 +static void vga_precise_update_retrace_info(VGACommonState *s)
 +{
 +    int htotal_chars;
 +    int hretr_start_char;
 +    int hretr_skew_chars;
 +    int hretr_end_char;
 +
 +    int vtotal_lines;
 +    int vretr_start_line;
 +    int vretr_end_line;
 +
 +    int dots;
 +#if 0
 +    int div2, sldiv2;
 +#endif
 +    int clocking_mode;
 +    int clock_sel;
 +    const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
 +    int64_t chars_per_sec;
 +    struct vga_precise_retrace *r = &s->retrace_info.precise;
 +
 +    htotal_chars = s->cr[VGA_CRTC_H_TOTAL] + 5;
 +    hretr_start_char = s->cr[VGA_CRTC_H_SYNC_START];
 +    hretr_skew_chars = (s->cr[VGA_CRTC_H_SYNC_END] >> 5) & 3;
 +    hretr_end_char = s->cr[VGA_CRTC_H_SYNC_END] & 0x1f;
 +
 +    vtotal_lines = (s->cr[VGA_CRTC_V_TOTAL] |
 +                    (((s->cr[VGA_CRTC_OVERFLOW] & 1) |
 +                      ((s->cr[VGA_CRTC_OVERFLOW] >> 4) & 2)) << 8)) + 2;
 +    vretr_start_line = s->cr[VGA_CRTC_V_SYNC_START] |
 +        ((((s->cr[VGA_CRTC_OVERFLOW] >> 2) & 1) |
 +          ((s->cr[VGA_CRTC_OVERFLOW] >> 6) & 2)) << 8);
 +    vretr_end_line = s->cr[VGA_CRTC_V_SYNC_END] & 0xf;
 +
 +    clocking_mode = (s->sr[VGA_SEQ_CLOCK_MODE] >> 3) & 1;
 +    clock_sel = (s->msr >> 2) & 3;
 +    dots = (s->msr & 1) ? 8 : 9;
 +
 +    chars_per_sec = clk_hz[clock_sel] / dots;
 +
 +    htotal_chars <<= clocking_mode;
 +
 +    r->total_chars = vtotal_lines * htotal_chars;
 +    if (r->freq) {
 +        r->ticks_per_char = get_ticks_per_sec() / (r->total_chars * r->freq);
 +    } else {
 +        r->ticks_per_char = get_ticks_per_sec() / chars_per_sec;
 +    }
 +
 +    r->vstart = vretr_start_line;
 +    r->vend = r->vstart + vretr_end_line + 1;
 +
 +    r->hstart = hretr_start_char + hretr_skew_chars;
 +    r->hend = r->hstart + hretr_end_char + 1;
 +    r->htotal = htotal_chars;
 +
 +#if 0
 +    div2 = (s->cr[VGA_CRTC_MODE] >> 2) & 1;
 +    sldiv2 = (s->cr[VGA_CRTC_MODE] >> 3) & 1;
 +    printf (
 +        "hz=%f\n"
 +        "htotal = %d\n"
 +        "hretr_start = %d\n"
 +        "hretr_skew = %d\n"
 +        "hretr_end = %d\n"
 +        "vtotal = %d\n"
 +        "vretr_start = %d\n"
 +        "vretr_end = %d\n"
 +        "div2 = %d sldiv2 = %d\n"
 +        "clocking_mode = %d\n"
 +        "clock_sel = %d %d\n"
 +        "dots = %d\n"
 +        "ticks/char = %" PRId64 "\n"
 +        "\n",
 +        (double) get_ticks_per_sec() / (r->ticks_per_char * r->total_chars),
 +        htotal_chars,
 +        hretr_start_char,
 +        hretr_skew_chars,
 +        hretr_end_char,
 +        vtotal_lines,
 +        vretr_start_line,
 +        vretr_end_line,
 +        div2, sldiv2,
 +        clocking_mode,
 +        clock_sel,
 +        clk_hz[clock_sel],
 +        dots,
 +        r->ticks_per_char
 +        );
 +#endif
 +}
 +
 +static uint8_t vga_precise_retrace(VGACommonState *s)
 +{
 +    struct vga_precise_retrace *r = &s->retrace_info.precise;
 +    uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
 +
 +    if (r->total_chars) {
 +        int cur_line, cur_line_char, cur_char;
 +        int64_t cur_tick;
 +
-     int64_t now = qemu_get_clock_ms(vm_clock);
++        cur_tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 +
 +        cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
 +        cur_line = cur_char / r->htotal;
 +
 +        if (cur_line >= r->vstart && cur_line <= r->vend) {
 +            val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
 +        } else {
 +            cur_line_char = cur_char % r->htotal;
 +            if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
 +                val |= ST01_DISP_ENABLE;
 +            }
 +        }
 +
 +        return val;
 +    } else {
 +        return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
 +    }
 +}
 +
 +static uint8_t vga_dumb_retrace(VGACommonState *s)
 +{
 +    return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
 +}
 +
 +typedef void maru_vga_draw_glyph8_func(uint8_t *d, int linesize,
 +                             const uint8_t *font_ptr, int h,
 +                             uint32_t fgcol, uint32_t bgcol);
 +typedef void maru_vga_draw_glyph9_func(uint8_t *d, int linesize,
 +                                  const uint8_t *font_ptr, int h,
 +                                  uint32_t fgcol, uint32_t bgcol, int dup9);
 +typedef void maru_vga_draw_line_func(VGACommonState *s1, uint8_t *d,
 +                                const uint8_t *s, int width);
 +
 +#define DEPTH 8
 +#include "maru_vga_template.h"
 +
 +#define DEPTH 15
 +#include "maru_vga_template.h"
 +
 +#define BGR_FORMAT
 +#define DEPTH 15
 +#include "maru_vga_template.h"
 +
 +#define DEPTH 16
 +#include "maru_vga_template.h"
 +
 +#define BGR_FORMAT
 +#define DEPTH 16
 +#include "maru_vga_template.h"
 +
 +#define DEPTH 32
 +#include "maru_vga_template.h"
 +
 +#define BGR_FORMAT
 +#define DEPTH 32
 +#include "maru_vga_template.h"
 +
 +static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
 +{
 +    unsigned int col;
 +    col = rgb_to_pixel8(r, g, b);
 +    col |= col << 8;
 +    col |= col << 16;
 +    return col;
 +}
 +
 +static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
 +{
 +    unsigned int col;
 +    col = rgb_to_pixel15(r, g, b);
 +    col |= col << 16;
 +    return col;
 +}
 +
 +static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
 +                                          unsigned int b)
 +{
 +    unsigned int col;
 +    col = rgb_to_pixel15bgr(r, g, b);
 +    col |= col << 16;
 +    return col;
 +}
 +
 +static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
 +{
 +    unsigned int col;
 +    col = rgb_to_pixel16(r, g, b);
 +    col |= col << 16;
 +    return col;
 +}
 +
 +static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
 +                                          unsigned int b)
 +{
 +    unsigned int col;
 +    col = rgb_to_pixel16bgr(r, g, b);
 +    col |= col << 16;
 +    return col;
 +}
 +
 +static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
 +{
 +    unsigned int col;
 +    col = rgb_to_pixel32(r, g, b);
 +    return col;
 +}
 +
 +static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
 +{
 +    unsigned int col;
 +    col = rgb_to_pixel32bgr(r, g, b);
 +    return col;
 +}
 +
 +/* return true if the palette was modified */
 +static int update_palette16(VGACommonState *s)
 +{
 +    int full_update, i;
 +    uint32_t v, col, *palette;
 +
 +    full_update = 0;
 +    palette = s->last_palette;
 +    for(i = 0; i < 16; i++) {
 +        v = s->ar[i];
 +        if (s->ar[VGA_ATC_MODE] & 0x80) {
 +            v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xf) << 4) | (v & 0xf);
 +        } else {
 +            v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xc) << 4) | (v & 0x3f);
 +        }
 +        v = v * 3;
 +        col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
 +                              c6_to_8(s->palette[v + 1]),
 +                              c6_to_8(s->palette[v + 2]));
 +        if (col != palette[i]) {
 +            full_update = 1;
 +            palette[i] = col;
 +        }
 +    }
 +    return full_update;
 +}
 +
 +/* return true if the palette was modified */
 +static int update_palette256(VGACommonState *s)
 +{
 +    int full_update, i;
 +    uint32_t v, col, *palette;
 +
 +    full_update = 0;
 +    palette = s->last_palette;
 +    v = 0;
 +    for(i = 0; i < 256; i++) {
 +        if (s->dac_8bit) {
 +          col = s->rgb_to_pixel(s->palette[v],
 +                                s->palette[v + 1],
 +                                s->palette[v + 2]);
 +        } else {
 +          col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
 +                                c6_to_8(s->palette[v + 1]),
 +                                c6_to_8(s->palette[v + 2]));
 +        }
 +        if (col != palette[i]) {
 +            full_update = 1;
 +            palette[i] = col;
 +        }
 +        v += 3;
 +    }
 +    return full_update;
 +}
 +
 +static void vga_get_offsets(VGACommonState *s,
 +                            uint32_t *pline_offset,
 +                            uint32_t *pstart_addr,
 +                            uint32_t *pline_compare)
 +{
 +    uint32_t start_addr, line_offset, line_compare;
 +
 +    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
 +        line_offset = s->vbe_line_offset;
 +        start_addr = s->vbe_start_addr;
 +        line_compare = 65535;
 +    } else {
 +        /* compute line_offset in bytes */
 +        line_offset = s->cr[VGA_CRTC_OFFSET];
 +        line_offset <<= 3;
 +
 +        /* starting address */
 +        start_addr = s->cr[VGA_CRTC_START_LO] |
 +            (s->cr[VGA_CRTC_START_HI] << 8);
 +
 +        /* line compare */
 +        line_compare = s->cr[VGA_CRTC_LINE_COMPARE] |
 +            ((s->cr[VGA_CRTC_OVERFLOW] & 0x10) << 4) |
 +            ((s->cr[VGA_CRTC_MAX_SCAN] & 0x40) << 3);
 +    }
 +    *pline_offset = line_offset;
 +    *pstart_addr = start_addr;
 +    *pline_compare = line_compare;
 +}
 +
 +/* update start_addr and line_offset. Return TRUE if modified */
 +static int update_basic_params(VGACommonState *s)
 +{
 +    int full_update;
 +    uint32_t start_addr, line_offset, line_compare;
 +
 +    full_update = 0;
 +
 +    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
 +
 +    if (line_offset != s->line_offset ||
 +        start_addr != s->start_addr ||
 +        line_compare != s->line_compare) {
 +        s->line_offset = line_offset;
 +        s->start_addr = start_addr;
 +        s->line_compare = line_compare;
 +        full_update = 1;
 +    }
 +    return full_update;
 +}
 +
 +#define NB_DEPTHS 7
 +
 +static inline int get_depth_index(DisplaySurface *s)
 +{
 +    switch (surface_bits_per_pixel(s)) {
 +    default:
 +    case 8:
 +        return 0;
 +    case 15:
 +        return 1;
 +    case 16:
 +        return 2;
 +    case 32:
 +        if (is_surface_bgr(s)) {
 +            return 4;
 +        } else {
 +            return 3;
 +        }
 +    }
 +}
 +
 +static maru_vga_draw_glyph8_func * const maru_vga_draw_glyph8_table[NB_DEPTHS] = {
 +    maru_vga_draw_glyph8_8,
 +    maru_vga_draw_glyph8_16,
 +    maru_vga_draw_glyph8_16,
 +    maru_vga_draw_glyph8_32,
 +    maru_vga_draw_glyph8_32,
 +    maru_vga_draw_glyph8_16,
 +    maru_vga_draw_glyph8_16,
 +};
 +
 +static maru_vga_draw_glyph8_func * const maru_vga_draw_glyph16_table[NB_DEPTHS] = {
 +    maru_vga_draw_glyph16_8,
 +    maru_vga_draw_glyph16_16,
 +    maru_vga_draw_glyph16_16,
 +    maru_vga_draw_glyph16_32,
 +    maru_vga_draw_glyph16_32,
 +    maru_vga_draw_glyph16_16,
 +    maru_vga_draw_glyph16_16,
 +};
 +
 +static maru_vga_draw_glyph9_func * const maru_vga_draw_glyph9_table[NB_DEPTHS] = {
 +    maru_vga_draw_glyph9_8,
 +    maru_vga_draw_glyph9_16,
 +    maru_vga_draw_glyph9_16,
 +    maru_vga_draw_glyph9_32,
 +    maru_vga_draw_glyph9_32,
 +    maru_vga_draw_glyph9_16,
 +    maru_vga_draw_glyph9_16,
 +};
 +
 +static const uint8_t cursor_glyph[32 * 4] = {
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 +};
 +
 +static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
 +                                    int *pcwidth, int *pcheight)
 +{
 +    int width, cwidth, height, cheight;
 +
 +    /* total width & height */
 +    cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
 +    cwidth = 8;
 +    if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
 +        cwidth = 9;
 +    }
 +    if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
 +        cwidth = 16; /* NOTE: no 18 pixel wide */
 +    }
 +    width = (s->cr[VGA_CRTC_H_DISP] + 1);
 +    if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
 +        /* ugly hack for CGA 160x100x16 - explain me the logic */
 +        height = 100;
 +    } else {
 +        height = s->cr[VGA_CRTC_V_DISP_END] |
 +            ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
 +            ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
 +        height = (height + 1) / cheight;
 +    }
 +
 +    *pwidth = width;
 +    *pheight = height;
 +    *pcwidth = cwidth;
 +    *pcheight = cheight;
 +}
 +
 +typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
 +
 +static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = {
 +    rgb_to_pixel8_dup,
 +    rgb_to_pixel15_dup,
 +    rgb_to_pixel16_dup,
 +    rgb_to_pixel32_dup,
 +    rgb_to_pixel32bgr_dup,
 +    rgb_to_pixel15bgr_dup,
 +    rgb_to_pixel16bgr_dup,
 +};
 +
 +/*
 + * Text mode update
 + * Missing:
 + * - double scan
 + * - double width
 + * - underline
 + * - flashing
 + */
 +static void vga_draw_text(VGACommonState *s, int full_update)
 +{
 +    DisplaySurface *surface = qemu_console_surface(s->con);
 +    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
 +    int cx_min, cx_max, linesize, x_incr, line, line1;
 +    uint32_t offset, fgcol, bgcol, v, cursor_offset;
 +    uint8_t *d1, *d, *src, *dest, *cursor_ptr;
 +    const uint8_t *font_ptr, *font_base[2];
 +    int dup9, line_offset, depth_index;
 +    uint32_t *palette;
 +    uint32_t *ch_attr_ptr;
 +    maru_vga_draw_glyph8_func *maru_vga_draw_glyph8;
 +    maru_vga_draw_glyph9_func *maru_vga_draw_glyph9;
-             s->cursor_blink_time = qemu_get_clock_ms(vm_clock);
++    int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
 +
 +    /* compute font data address (in plane 2) */
 +    v = s->sr[VGA_SEQ_CHARACTER_MAP];
 +    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
 +    if (offset != s->font_offsets[0]) {
 +        s->font_offsets[0] = offset;
 +        full_update = 1;
 +    }
 +    font_base[0] = s->vram_ptr + offset;
 +
 +    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
 +    font_base[1] = s->vram_ptr + offset;
 +    if (offset != s->font_offsets[1]) {
 +        s->font_offsets[1] = offset;
 +        full_update = 1;
 +    }
 +    if (s->plane_updated & (1 << 2) || s->chain4_alias) {
 +        /* if the plane 2 was modified since the last display, it
 +           indicates the font may have been modified */
 +        s->plane_updated = 0;
 +        full_update = 1;
 +    }
 +    full_update |= update_basic_params(s);
 +
 +    line_offset = s->line_offset;
 +
 +    vga_get_text_resolution(s, &width, &height, &cw, &cheight);
 +    if ((height * width) <= 1) {
 +        /* better than nothing: exit if transient size is too small */
 +        return;
 +    }
 +    if ((height * width) > CH_ATTR_SIZE) {
 +        /* better than nothing: exit if transient size is too big */
 +        return;
 +    }
 +
 +    if (width != s->last_width || height != s->last_height ||
 +        cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
 +        s->last_scr_width = width * cw;
 +        s->last_scr_height = height * cheight;
 +        qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
 +        surface = qemu_console_surface(s->con);
 +        dpy_text_resize(s->con, width, height);
 +        s->last_depth = 0;
 +        s->last_width = width;
 +        s->last_height = height;
 +        s->last_ch = cheight;
 +        s->last_cw = cw;
 +        full_update = 1;
 +    }
 +    s->rgb_to_pixel =
 +        rgb_to_pixel_dup_table[get_depth_index(surface)];
 +    full_update |= update_palette16(s);
 +    palette = s->last_palette;
 +    x_incr = cw * surface_bytes_per_pixel(surface);
 +
 +    if (full_update) {
 +        s->full_update_text = 1;
 +    }
 +    if (s->full_update_gfx) {
 +        s->full_update_gfx = 0;
 +        full_update |= 1;
 +    }
 +
 +    cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
 +                     s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
 +    if (cursor_offset != s->cursor_offset ||
 +        s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
 +        s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end) {
 +      /* if the cursor position changed, we update the old and new
 +         chars */
 +        if (s->cursor_offset < CH_ATTR_SIZE)
 +            s->last_ch_attr[s->cursor_offset] = -1;
 +        if (cursor_offset < CH_ATTR_SIZE)
 +            s->last_ch_attr[cursor_offset] = -1;
 +        s->cursor_offset = cursor_offset;
 +        s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
 +        s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
 +    }
 +    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
 +    if (now >= s->cursor_blink_time) {
 +        s->cursor_blink_time = now + VGA_TEXT_CURSOR_PERIOD_MS / 2;
 +        s->cursor_visible_phase = !s->cursor_visible_phase;
 +    }
 +
 +    depth_index = get_depth_index(surface);
 +    if (cw == 16)
 +        maru_vga_draw_glyph8 = maru_vga_draw_glyph16_table[depth_index];
 +    else
 +        maru_vga_draw_glyph8 = maru_vga_draw_glyph8_table[depth_index];
 +    maru_vga_draw_glyph9 = maru_vga_draw_glyph9_table[depth_index];
 +
 +    dest = surface_data(surface);
 +    linesize = surface_stride(surface);
 +    ch_attr_ptr = s->last_ch_attr;
 +    line = 0;
 +    offset = s->start_addr * 4;
 +    for(cy = 0; cy < height; cy++) {
 +        d1 = dest;
 +        src = s->vram_ptr + offset;
 +        cx_min = width;
 +        cx_max = -1;
 +        for(cx = 0; cx < width; cx++) {
 +            ch_attr = *(uint16_t *)src;
 +            if (full_update || ch_attr != *ch_attr_ptr || src == cursor_ptr) {
 +                if (cx < cx_min)
 +                    cx_min = cx;
 +                if (cx > cx_max)
 +                    cx_max = cx;
 +                *ch_attr_ptr = ch_attr;
 +#ifdef HOST_WORDS_BIGENDIAN
 +                ch = ch_attr >> 8;
 +                cattr = ch_attr & 0xff;
 +#else
 +                ch = ch_attr & 0xff;
 +                cattr = ch_attr >> 8;
 +#endif
 +                font_ptr = font_base[(cattr >> 3) & 1];
 +                font_ptr += 32 * 4 * ch;
 +                bgcol = palette[cattr >> 4];
 +                fgcol = palette[cattr & 0x0f];
 +                if (cw != 9) {
 +                    maru_vga_draw_glyph8(d1, linesize,
 +                                    font_ptr, cheight, fgcol, bgcol);
 +                } else {
 +                    dup9 = 0;
 +                    if (ch >= 0xb0 && ch <= 0xdf &&
 +                        (s->ar[VGA_ATC_MODE] & 0x04)) {
 +                        dup9 = 1;
 +                    }
 +                    maru_vga_draw_glyph9(d1, linesize,
 +                                    font_ptr, cheight, fgcol, bgcol, dup9);
 +                }
 +                if (src == cursor_ptr &&
 +                    !(s->cr[VGA_CRTC_CURSOR_START] & 0x20) &&
 +                    s->cursor_visible_phase) {
 +                    int line_start, line_last, h;
 +                    /* draw the cursor */
 +                    line_start = s->cr[VGA_CRTC_CURSOR_START] & 0x1f;
 +                    line_last = s->cr[VGA_CRTC_CURSOR_END] & 0x1f;
 +                    /* XXX: check that */
 +                    if (line_last > cheight - 1)
 +                        line_last = cheight - 1;
 +                    if (line_last >= line_start && line_start < cheight) {
 +                        h = line_last - line_start + 1;
 +                        d = d1 + linesize * line_start;
 +                        if (cw != 9) {
 +                            maru_vga_draw_glyph8(d, linesize,
 +                                            cursor_glyph, h, fgcol, bgcol);
 +                        } else {
 +                            maru_vga_draw_glyph9(d, linesize,
 +                                            cursor_glyph, h, fgcol, bgcol, 1);
 +                        }
 +                    }
 +                }
 +            }
 +            d1 += x_incr;
 +            src += 4;
 +            ch_attr_ptr++;
 +        }
 +        if (cx_max != -1) {
 +            dpy_gfx_update(s->con, cx_min * cw, cy * cheight,
 +                           (cx_max - cx_min + 1) * cw, cheight);
 +        }
 +        dest += linesize * cheight;
 +        line1 = line + cheight;
 +        offset += line_offset;
 +        if (line < s->line_compare && line1 >= s->line_compare) {
 +            offset = 0;
 +        }
 +        line = line1;
 +    }
 +}
 +
 +enum {
 +    maru_vga_draw_line2,
 +    maru_vga_draw_line2D2,
 +    maru_vga_draw_line4,
 +    maru_vga_draw_line4D2,
 +    maru_vga_draw_line8D2,
 +    maru_vga_draw_line8,
 +    maru_vga_draw_line15,
 +    maru_vga_draw_line16,
 +    maru_vga_draw_line24,
 +    maru_vga_draw_line32,
 +    maru_vga_draw_line_NB,
 +};
 +
 +static maru_vga_draw_line_func * const maru_vga_draw_line_table[NB_DEPTHS * maru_vga_draw_line_NB] = {
 +    maru_vga_draw_line2_8,
 +    maru_vga_draw_line2_16,
 +    maru_vga_draw_line2_16,
 +    maru_vga_draw_line2_32,
 +    maru_vga_draw_line2_32,
 +    maru_vga_draw_line2_16,
 +    maru_vga_draw_line2_16,
 +
 +    maru_vga_draw_line2d2_8,
 +    maru_vga_draw_line2d2_16,
 +    maru_vga_draw_line2d2_16,
 +    maru_vga_draw_line2d2_32,
 +    maru_vga_draw_line2d2_32,
 +    maru_vga_draw_line2d2_16,
 +    maru_vga_draw_line2d2_16,
 +
 +    maru_vga_draw_line4_8,
 +    maru_vga_draw_line4_16,
 +    maru_vga_draw_line4_16,
 +    maru_vga_draw_line4_32,
 +    maru_vga_draw_line4_32,
 +    maru_vga_draw_line4_16,
 +    maru_vga_draw_line4_16,
 +
 +    maru_vga_draw_line4d2_8,
 +    maru_vga_draw_line4d2_16,
 +    maru_vga_draw_line4d2_16,
 +    maru_vga_draw_line4d2_32,
 +    maru_vga_draw_line4d2_32,
 +    maru_vga_draw_line4d2_16,
 +    maru_vga_draw_line4d2_16,
 +
 +    maru_vga_draw_line8d2_8,
 +    maru_vga_draw_line8d2_16,
 +    maru_vga_draw_line8d2_16,
 +    maru_vga_draw_line8d2_32,
 +    maru_vga_draw_line8d2_32,
 +    maru_vga_draw_line8d2_16,
 +    maru_vga_draw_line8d2_16,
 +
 +    maru_vga_draw_line8_8,
 +    maru_vga_draw_line8_16,
 +    maru_vga_draw_line8_16,
 +    maru_vga_draw_line8_32,
 +    maru_vga_draw_line8_32,
 +    maru_vga_draw_line8_16,
 +    maru_vga_draw_line8_16,
 +
 +    maru_vga_draw_line15_8,
 +    maru_vga_draw_line15_15,
 +    maru_vga_draw_line15_16,
 +    maru_vga_draw_line15_32,
 +    maru_vga_draw_line15_32bgr,
 +    maru_vga_draw_line15_15bgr,
 +    maru_vga_draw_line15_16bgr,
 +
 +    maru_vga_draw_line16_8,
 +    maru_vga_draw_line16_15,
 +    maru_vga_draw_line16_16,
 +    maru_vga_draw_line16_32,
 +    maru_vga_draw_line16_32bgr,
 +    maru_vga_draw_line16_15bgr,
 +    maru_vga_draw_line16_16bgr,
 +
 +    maru_vga_draw_line24_8,
 +    maru_vga_draw_line24_15,
 +    maru_vga_draw_line24_16,
 +    maru_vga_draw_line24_32,
 +    maru_vga_draw_line24_32bgr,
 +    maru_vga_draw_line24_15bgr,
 +    maru_vga_draw_line24_16bgr,
 +
 +    maru_vga_draw_line32_8,
 +    maru_vga_draw_line32_15,
 +    maru_vga_draw_line32_16,
 +    maru_vga_draw_line32_32,
 +    maru_vga_draw_line32_32bgr,
 +    maru_vga_draw_line32_15bgr,
 +    maru_vga_draw_line32_16bgr,
 +};
 +
 +static int vga_get_bpp(VGACommonState *s)
 +{
 +    int ret;
 +
 +    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
 +        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
 +    } else {
 +        ret = 0;
 +    }
 +    return ret;
 +}
 +
 +static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
 +{
 +    int width, height;
 +
 +    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
 +        width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
 +        height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
 +    } else {
 +        width = (s->cr[VGA_CRTC_H_DISP] + 1) * 8;
 +        height = s->cr[VGA_CRTC_V_DISP_END] |
 +            ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
 +            ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
 +        height = (height + 1);
 +    }
 +    *pwidth = width;
 +    *pheight = height;
 +}
 +
 +/*
 + * graphic modes
 + */
 +static void vga_draw_graphic(VGACommonState *s, int full_update)
 +{
 +    DisplaySurface *surface = qemu_console_surface(s->con);
 +    int y1, y, update, linesize, y_start, double_scan, mask, depth;
 +    int width, height, shift_control, line_offset, bwidth, bits;
 +    ram_addr_t page0, page1, page_min, page_max;
 +    int disp_width, multi_scan, multi_run;
 +    uint8_t *d;
 +    uint32_t v, addr1, addr;
 +    maru_vga_draw_line_func *maru_vga_draw_line;
 +#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
 +    static const bool byteswap = false;
 +#else
 +    static const bool byteswap = true;
 +#endif
 +
 +    full_update |= update_basic_params(s);
 +
 +    if (!full_update)
 +        vga_sync_dirty_bitmap(s);
 +
 +    s->get_resolution(s, &width, &height);
 +    disp_width = width;
 +
 +    shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
 +    double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
 +    if (shift_control != 1) {
 +        multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
 +            - 1;
 +    } else {
 +        /* in CGA modes, multi_scan is ignored */
 +        /* XXX: is it correct ? */
 +        multi_scan = double_scan;
 +    }
 +    multi_run = multi_scan;
 +    if (shift_control != s->shift_control ||
 +        double_scan != s->double_scan) {
 +        full_update = 1;
 +        s->shift_control = shift_control;
 +        s->double_scan = double_scan;
 +    }
 +
 +    if (shift_control == 0) {
 +        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
 +            disp_width <<= 1;
 +        }
 +    } else if (shift_control == 1) {
 +        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
 +            disp_width <<= 1;
 +        }
 +    }
 +
 +    depth = s->get_bpp(s);
 +    if (s->line_offset != s->last_line_offset ||
 +        disp_width != s->last_width ||
 +        height != s->last_height ||
 +        s->last_depth != depth) {
 +        if (depth == 32 || (depth == 16 && !byteswap)) {
 +#ifdef MARU_VGA /* create new sufrace by g_new0 in MARU VGA */
 +            TRACE("create the display surface\n");
 +            surface = qemu_create_displaysurface(disp_width, height);
 +#else /* MARU_VGA */
 +            surface = qemu_create_displaysurface_from(disp_width,
 +                    height, depth, s->line_offset,
 +                    s->vram_ptr + (s->start_addr * 4), byteswap);
 +#endif /* MARU_VGA */
 +            dpy_gfx_replace_surface(s->con, surface);
 +        } else {
 +            qemu_console_resize(s->con, disp_width, height);
 +            surface = qemu_console_surface(s->con);
 +        }
 +        s->last_scr_width = disp_width;
 +        s->last_scr_height = height;
 +        s->last_width = disp_width;
 +        s->last_height = height;
 +        s->last_line_offset = s->line_offset;
 +        s->last_depth = depth;
 +        full_update = 1;
 +    } else if (is_buffer_shared(surface) &&
 +               (full_update || surface_data(surface) != s->vram_ptr
 +                + (s->start_addr * 4))) {
 +        DisplaySurface *surface;
 +        surface = qemu_create_displaysurface_from(disp_width,
 +                height, depth, s->line_offset,
 +                s->vram_ptr + (s->start_addr * 4), byteswap);
 +        dpy_gfx_replace_surface(s->con, surface);
 +    }
 +
 +    s->rgb_to_pixel =
 +        rgb_to_pixel_dup_table[get_depth_index(surface)];
 +
 +    if (shift_control == 0) {
 +        full_update |= update_palette16(s);
 +        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
 +            v = maru_vga_draw_line4D2;
 +        } else {
 +            v = maru_vga_draw_line4;
 +        }
 +        bits = 4;
 +    } else if (shift_control == 1) {
 +        full_update |= update_palette16(s);
 +        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
 +            v = maru_vga_draw_line2D2;
 +        } else {
 +            v = maru_vga_draw_line2;
 +        }
 +        bits = 4;
 +    } else {
 +        switch(s->get_bpp(s)) {
 +        default:
 +        case 0:
 +            full_update |= update_palette256(s);
 +            v = maru_vga_draw_line8D2;
 +            bits = 4;
 +            break;
 +        case 8:
 +            full_update |= update_palette256(s);
 +            v = maru_vga_draw_line8;
 +            bits = 8;
 +            break;
 +        case 15:
 +            v = maru_vga_draw_line15;
 +            bits = 16;
 +            break;
 +        case 16:
 +            v = maru_vga_draw_line16;
 +            bits = 16;
 +            break;
 +        case 24:
 +            v = maru_vga_draw_line24;
 +            bits = 24;
 +            break;
 +        case 32:
 +            v = maru_vga_draw_line32;
 +            bits = 32;
 +            break;
 +        }
 +    }
 +    maru_vga_draw_line = maru_vga_draw_line_table[v * NB_DEPTHS +
 +                                        get_depth_index(surface)];
 +
 +    if (!is_buffer_shared(surface) && s->cursor_invalidate) {
 +        s->cursor_invalidate(s);
 +    }
 +
 +    line_offset = s->line_offset;
 +#if 0
 +    printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
 +           width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
 +           s->line_compare, s->sr[VGA_SEQ_CLOCK_MODE]);
 +#endif
 +    addr1 = (s->start_addr * 4);
 +    bwidth = (width * bits + 7) / 8;
 +    y_start = -1;
 +    page_min = -1;
 +    page_max = 0;
 +    d = surface_data(surface);
 +    linesize = surface_stride(surface);
 +    y1 = 0;
 +    for(y = 0; y < height; y++) {
 +        addr = addr1;
 +        if (!(s->cr[VGA_CRTC_MODE] & 1)) {
 +            int shift;
 +            /* CGA compatibility handling */
 +            shift = 14 + ((s->cr[VGA_CRTC_MODE] >> 6) & 1);
 +            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
 +        }
 +        if (!(s->cr[VGA_CRTC_MODE] & 2)) {
 +            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
 +        }
 +        update = full_update;
 +        page0 = addr;
 +        page1 = addr + bwidth - 1;
 +        update |= memory_region_get_dirty(&s->vram, page0, page1 - page0,
 +                                          DIRTY_MEMORY_VGA);
 +        /* explicit invalidation for the hardware cursor */
 +        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
 +#ifdef MARU_VGA /* needs full update */
 +        update |= 1;
 +#endif
 +        if (update) {
 +            if (y_start < 0)
 +                y_start = y;
 +            if (page0 < page_min)
 +                page_min = page0;
 +            if (page1 > page_max)
 +                page_max = page1;
 +            if (!(is_buffer_shared(surface))) {
 +                maru_vga_draw_line(s, d, s->vram_ptr + addr, width);
 +                if (s->cursor_draw_line)
 +                    s->cursor_draw_line(s, d, y);
 +            }
 +        } else {
 +            if (y_start >= 0) {
 +                /* flush to display */
 +                dpy_gfx_update(s->con, 0, y_start,
 +                               disp_width, y - y_start);
 +                y_start = -1;
 +            }
 +        }
 +        if (!multi_run) {
 +            mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3;
 +            if ((y1 & mask) == mask)
 +                addr1 += line_offset;
 +            y1++;
 +            multi_run = multi_scan;
 +        } else {
 +            multi_run--;
 +        }
 +        /* line compare acts on the displayed lines */
 +        if (y == s->line_compare)
 +            addr1 = 0;
 +        d += linesize;
 +    }
 +    if (y_start >= 0) {
 +        /* flush to display */
 +        dpy_gfx_update(s->con, 0, y_start,
 +                       disp_width, y - y_start);
 +    }
 +    /* reset modified pages */
 +    if (page_max >= page_min) {
 +        memory_region_reset_dirty(&s->vram,
 +                                  page_min,
 +                                  page_max - page_min,
 +                                  DIRTY_MEMORY_VGA);
 +    }
 +    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
 +}
 +
 +static void vga_draw_blank(VGACommonState *s, int full_update)
 +{
 +    DisplaySurface *surface = qemu_console_surface(s->con);
 +    int i, w, val;
 +    uint8_t *d;
 +
 +    if (!full_update)
 +        return;
 +    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
 +        return;
 +
 +    s->rgb_to_pixel =
 +        rgb_to_pixel_dup_table[get_depth_index(surface)];
 +    if (surface_bits_per_pixel(surface) == 8) {
 +        val = s->rgb_to_pixel(0, 0, 0);
 +    } else {
 +        val = 0;
 +    }
 +    w = s->last_scr_width * surface_bytes_per_pixel(surface);
 +    d = surface_data(surface);
 +    for(i = 0; i < s->last_scr_height; i++) {
 +        memset(d, val, w);
 +        d += surface_stride(surface);
 +    }
 +    dpy_gfx_update(s->con, 0, 0,
 +                   s->last_scr_width, s->last_scr_height);
 +}
 +
 +#define GMODE_TEXT     0
 +#define GMODE_GRAPH    1
 +#define GMODE_BLANK 2
 +
 +static void vga_update_display(void *opaque)
 +{
 +    VGACommonState *s = opaque;
 +    DisplaySurface *surface = qemu_console_surface(s->con);
 +    int full_update, graphic_mode;
 +
 +    qemu_flush_coalesced_mmio_buffer();
 +
 +    if (surface_bits_per_pixel(surface) == 0) {
 +        /* nothing to do */
 +    } else {
 +        full_update = 0;
 +        if (!(s->ar_index & 0x20)) {
 +            graphic_mode = GMODE_BLANK;
 +        } else {
 +            graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
 +        }
 +        if (graphic_mode != s->graphic_mode) {
 +            s->graphic_mode = graphic_mode;
++            s->cursor_blink_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
 +            full_update = 1;
 +        }
 +        switch(graphic_mode) {
 +        case GMODE_TEXT:
 +            vga_draw_text(s, full_update);
 +            break;
 +        case GMODE_GRAPH:
 +            vga_draw_graphic(s, full_update);
 +            break;
 +        case GMODE_BLANK:
 +        default:
 +            vga_draw_blank(s, full_update);
 +            break;
 +        }
 +    }
 +}
 +
 +/* force a full display refresh */
 +static void vga_invalidate_display(void *opaque)
 +{
 +    VGACommonState *s = opaque;
 +
 +    s->last_width = -1;
 +    s->last_height = -1;
 +}
 +
 +#define TEXTMODE_X(x)    ((x) % width)
 +#define TEXTMODE_Y(x)    ((x) / width)
 +#define VMEM2CHTYPE(v)   ((v & 0xff0007ff) | \
 +        ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
 +/* relay text rendering to the display driver
 + * instead of doing a full vga_update_display() */
 +static void vga_update_text(void *opaque, console_ch_t *chardata)
 +{
 +    VGACommonState *s =  opaque;
 +    int graphic_mode, i, cursor_offset, cursor_visible;
 +    int cw, cheight, width, height, size, c_min, c_max;
 +    uint32_t *src;
 +    console_ch_t *dst, val;
 +    char msg_buffer[80];
 +    int full_update = 0;
 +
 +    qemu_flush_coalesced_mmio_buffer();
 +
 +    if (!(s->ar_index & 0x20)) {
 +        graphic_mode = GMODE_BLANK;
 +    } else {
 +        graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
 +    }
 +    if (graphic_mode != s->graphic_mode) {
 +        s->graphic_mode = graphic_mode;
 +        full_update = 1;
 +    }
 +    if (s->last_width == -1) {
 +        s->last_width = 0;
 +        full_update = 1;
 +    }
 +
 +    switch (graphic_mode) {
 +    case GMODE_TEXT:
 +        /* TODO: update palette */
 +        full_update |= update_basic_params(s);
 +
 +        /* total width & height */
 +        cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
 +        cw = 8;
 +        if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
 +            cw = 9;
 +        }
 +        if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
 +            cw = 16; /* NOTE: no 18 pixel wide */
 +        }
 +        width = (s->cr[VGA_CRTC_H_DISP] + 1);
 +        if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
 +            /* ugly hack for CGA 160x100x16 - explain me the logic */
 +            height = 100;
 +        } else {
 +            height = s->cr[VGA_CRTC_V_DISP_END] |
 +                ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
 +                ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
 +            height = (height + 1) / cheight;
 +        }
 +
 +        size = (height * width);
 +        if (size > CH_ATTR_SIZE) {
 +            if (!full_update)
 +                return;
 +
 +            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
 +                     width, height);
 +            break;
 +        }
 +
 +        if (width != s->last_width || height != s->last_height ||
 +            cw != s->last_cw || cheight != s->last_ch) {
 +            s->last_scr_width = width * cw;
 +            s->last_scr_height = height * cheight;
 +            qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
 +            dpy_text_resize(s->con, width, height);
 +            s->last_depth = 0;
 +            s->last_width = width;
 +            s->last_height = height;
 +            s->last_ch = cheight;
 +            s->last_cw = cw;
 +            full_update = 1;
 +        }
 +
 +        if (full_update) {
 +            s->full_update_gfx = 1;
 +        }
 +        if (s->full_update_text) {
 +            s->full_update_text = 0;
 +            full_update |= 1;
 +        }
 +
 +        /* Update "hardware" cursor */
 +        cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
 +                         s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
 +        if (cursor_offset != s->cursor_offset ||
 +            s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
 +            s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
 +            cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
 +            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
 +                dpy_text_cursor(s->con,
 +                                TEXTMODE_X(cursor_offset),
 +                                TEXTMODE_Y(cursor_offset));
 +            else
 +                dpy_text_cursor(s->con, -1, -1);
 +            s->cursor_offset = cursor_offset;
 +            s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
 +            s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
 +        }
 +
 +        src = (uint32_t *) s->vram_ptr + s->start_addr;
 +        dst = chardata;
 +
 +        if (full_update) {
 +            for (i = 0; i < size; src ++, dst ++, i ++)
 +                console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
 +
 +            dpy_text_update(s->con, 0, 0, width, height);
 +        } else {
 +            c_max = 0;
 +
 +            for (i = 0; i < size; src ++, dst ++, i ++) {
 +                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
 +                if (*dst != val) {
 +                    *dst = val;
 +                    c_max = i;
 +                    break;
 +                }
 +            }
 +            c_min = i;
 +            for (; i < size; src ++, dst ++, i ++) {
 +                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
 +                if (*dst != val) {
 +                    *dst = val;
 +                    c_max = i;
 +                }
 +            }
 +
 +            if (c_min <= c_max) {
 +                i = TEXTMODE_Y(c_min);
 +                dpy_text_update(s->con, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
 +            }
 +        }
 +
 +        return;
 +    case GMODE_GRAPH:
 +        if (!full_update)
 +            return;
 +
 +        s->get_resolution(s, &width, &height);
 +        snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
 +                 width, height);
 +        break;
 +    case GMODE_BLANK:
 +    default:
 +        if (!full_update)
 +            return;
 +
 +        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
 +        break;
 +    }
 +
 +    /* Display a message */
 +    s->last_width = 60;
 +    s->last_height = height = 3;
 +    dpy_text_cursor(s->con, -1, -1);
 +    dpy_text_resize(s->con, s->last_width, height);
 +
 +    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
 +        console_write_ch(dst ++, ' ');
 +
 +    size = strlen(msg_buffer);
 +    width = (s->last_width - size) / 2;
 +    dst = chardata + s->last_width + width;
 +    for (i = 0; i < size; i ++)
 +        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
 +
 +    dpy_text_update(s->con, 0, 0, s->last_width, height);
 +}
 +
 +static const GraphicHwOps vga_ops = {
 +    .invalidate  = vga_invalidate_display,
 +    .gfx_update  = vga_update_display,
 +    .text_update = vga_update_text,
 +};
 +
 +void maru_vga_common_init(VGACommonState *s, Object *obj)
 +{
 +    int i, j, v, b;
 +
 +    for(i = 0;i < 256; i++) {
 +        v = 0;
 +        for(j = 0; j < 8; j++) {
 +            v |= ((i >> j) & 1) << (j * 4);
 +        }
 +        expand4[i] = v;
 +
 +        v = 0;
 +        for(j = 0; j < 4; j++) {
 +            v |= ((i >> (2 * j)) & 3) << (j * 4);
 +        }
 +        expand2[i] = v;
 +    }
 +    for(i = 0; i < 16; i++) {
 +        v = 0;
 +        for(j = 0; j < 4; j++) {
 +            b = ((i >> j) & 1);
 +            v |= b << (2 * j);
 +            v |= b << (2 * j + 1);
 +        }
 +        expand4to8[i] = v;
 +    }
 +
 +    /* valid range: 1 MB -> 256 MB */
 +    s->vram_size = 1024 * 1024;
 +    while (s->vram_size < (s->vram_size_mb << 20) &&
 +           s->vram_size < (256 << 20)) {
 +        s->vram_size <<= 1;
 +    }
 +    s->vram_size_mb = s->vram_size >> 20;
 +
 +    s->is_vbe_vmstate = 1;
 +    memory_region_init_ram(&s->vram, obj, "maru_vga.vram", s->vram_size);
 +    vmstate_register_ram_global(&s->vram);
 +    xen_register_framebuffer(&s->vram);
 +    s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
 +    s->get_bpp = vga_get_bpp;
 +    s->get_offsets = vga_get_offsets;
 +    s->get_resolution = vga_get_resolution;
 +    s->hw_ops = &vga_ops;
 +    switch (vga_retrace_method) {
 +    case VGA_RETRACE_DUMB:
 +        s->retrace = vga_dumb_retrace;
 +        s->update_retrace_info = vga_dumb_update_retrace_info;
 +        break;
 +
 +    case VGA_RETRACE_PRECISE:
 +        s->retrace = vga_precise_retrace;
 +        s->update_retrace_info = vga_precise_update_retrace_info;
 +        break;
 +    }
 +    vga_dirty_log_start(s);
 +    TRACE("%s\n", __func__);
 +}
 +
 +void maru_vga_common_fini(void)
 +{
 +    /* do nothing */
 +    TRACE("%s\n", __func__);
 +}
index 126036e,0000000..8772b9e
mode 100644,000000..100644
--- /dev/null
@@@ -1,465 -1,0 +1,465 @@@
-         cpu_to_32wu((uint32_t *)d, (dmask16[(font_data >> 4)] & xorcol) ^ bgcol);
 +/*
 + *  vga device
 + * Based on qemu/hw/vga_template.h
 + *
 + * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
 + *
 + * Contact:
 + * GiWoong Kim <giwoong.kim@samsung.com>
 + * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
 + * Hyunjun Son
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +#if DEPTH == 8
 +#define BPP 1
 +#define PIXEL_TYPE uint8_t
 +#elif DEPTH == 15 || DEPTH == 16
 +#define BPP 2
 +#define PIXEL_TYPE uint16_t
 +#elif DEPTH == 32
 +#define BPP 4
 +#define PIXEL_TYPE uint32_t
 +#else
 +#error unsupport depth
 +#endif
 +
 +#ifdef BGR_FORMAT
 +#define PIXEL_NAME glue(DEPTH, bgr)
 +#else
 +#define PIXEL_NAME DEPTH
 +#endif /* BGR_FORMAT */
 +
 +#if DEPTH != 15 && !defined(BGR_FORMAT)
 +
 +static inline void glue(maru_vga_draw_glyph_line_, DEPTH)(uint8_t *d,
 +                                                     uint32_t font_data,
 +                                                     uint32_t xorcol,
 +                                                     uint32_t bgcol)
 +{
 +#if BPP == 1
 +        ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
 +#elif BPP == 2
 +        ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
 +#else
 +        ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
 +#endif
 +}
 +
 +static void glue(maru_vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
 +                                          const uint8_t *font_ptr, int h,
 +                                          uint32_t fgcol, uint32_t bgcol)
 +{
 +    uint32_t font_data, xorcol;
 +
 +    xorcol = bgcol ^ fgcol;
 +    do {
 +        font_data = font_ptr[0];
 +        glue(maru_vga_draw_glyph_line_, DEPTH)(d, font_data, xorcol, bgcol);
 +        font_ptr += 4;
 +        d += linesize;
 +    } while (--h);
 +}
 +
 +static void glue(maru_vga_draw_glyph16_, DEPTH)(uint8_t *d, int linesize,
 +                                          const uint8_t *font_ptr, int h,
 +                                          uint32_t fgcol, uint32_t bgcol)
 +{
 +    uint32_t font_data, xorcol;
 +
 +    xorcol = bgcol ^ fgcol;
 +    do {
 +        font_data = font_ptr[0];
 +        glue(maru_vga_draw_glyph_line_, DEPTH)(d,
 +                                          expand4to8[font_data >> 4],
 +                                          xorcol, bgcol);
 +        glue(maru_vga_draw_glyph_line_, DEPTH)(d + 8 * BPP,
 +                                          expand4to8[font_data & 0x0f],
 +                                          xorcol, bgcol);
 +        font_ptr += 4;
 +        d += linesize;
 +    } while (--h);
 +}
 +
 +static void glue(maru_vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize,
 +                                          const uint8_t *font_ptr, int h,
 +                                          uint32_t fgcol, uint32_t bgcol, int dup9)
 +{
 +    uint32_t font_data, xorcol, v;
 +
 +    xorcol = bgcol ^ fgcol;
 +    do {
 +        font_data = font_ptr[0];
 +#if BPP == 1
-         cpu_to_32wu(((uint32_t *)d)+1, v);
++        stl_p((uint32_t *)d, (dmask16[(font_data >> 4)] & xorcol) ^ bgcol);
 +        v = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
-         cpu_to_32wu(((uint32_t *)d)+0, (dmask4[(font_data >> 6)] & xorcol) ^ bgcol);
-         cpu_to_32wu(((uint32_t *)d)+1, (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol);
-         cpu_to_32wu(((uint32_t *)d)+2, (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol);
++        stl_p(((uint32_t *)d)+1, v);
 +        if (dup9)
 +            ((uint8_t *)d)[8] = v >> (24 * (1 - BIG));
 +        else
 +            ((uint8_t *)d)[8] = bgcol;
 +
 +#elif BPP == 2
-         cpu_to_32wu(((uint32_t *)d)+3, v);
++        stl_p(((uint32_t *)d)+0, (dmask4[(font_data >> 6)] & xorcol) ^ bgcol);
++        stl_p(((uint32_t *)d)+1, (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol);
++        stl_p(((uint32_t *)d)+2, (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol);
 +        v = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
++        stl_p(((uint32_t *)d)+3, v);
 +        if (dup9)
 +            ((uint16_t *)d)[8] = v >> (16 * (1 - BIG));
 +        else
 +            ((uint16_t *)d)[8] = bgcol;
 +#else
 +        ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
 +        v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
 +        ((uint32_t *)d)[7] = v;
 +        if (dup9)
 +            ((uint32_t *)d)[8] = v;
 +        else
 +            ((uint32_t *)d)[8] = bgcol;
 +#endif
 +        font_ptr += 4;
 +        d += linesize;
 +    } while (--h);
 +}
 +
 +/*
 + * 4 color mode
 + */
 +static void glue(maru_vga_draw_line2_, DEPTH)(VGACommonState *s1, uint8_t *d,
 +                                         const uint8_t *s, int width)
 +{
 +    uint32_t plane_mask, *palette, data, v;
 +    int x;
 +
 +    palette = s1->last_palette;
 +    plane_mask = mask16[s1->ar[0x12] & 0xf];
 +    width >>= 3;
 +    for(x = 0; x < width; x++) {
 +        data = ((uint32_t *)s)[0];
 +        data &= plane_mask;
 +        v = expand2[GET_PLANE(data, 0)];
 +        v |= expand2[GET_PLANE(data, 2)] << 2;
 +        ((PIXEL_TYPE *)d)[0] = palette[v >> 12];
 +        ((PIXEL_TYPE *)d)[1] = palette[(v >> 8) & 0xf];
 +        ((PIXEL_TYPE *)d)[2] = palette[(v >> 4) & 0xf];
 +        ((PIXEL_TYPE *)d)[3] = palette[(v >> 0) & 0xf];
 +
 +        v = expand2[GET_PLANE(data, 1)];
 +        v |= expand2[GET_PLANE(data, 3)] << 2;
 +        ((PIXEL_TYPE *)d)[4] = palette[v >> 12];
 +        ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
 +        ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
 +        ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
 +        d += BPP * 8;
 +        s += 4;
 +    }
 +}
 +
 +#if BPP == 1
 +#define PUT_PIXEL2(d, n, v) ((uint16_t *)d)[(n)] = (v)
 +#elif BPP == 2
 +#define PUT_PIXEL2(d, n, v) ((uint32_t *)d)[(n)] = (v)
 +#else
 +#define PUT_PIXEL2(d, n, v) \
 +((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v)
 +#endif
 +
 +/*
 + * 4 color mode, dup2 horizontal
 + */
 +static void glue(maru_vga_draw_line2d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
 +                                           const uint8_t *s, int width)
 +{
 +    uint32_t plane_mask, *palette, data, v;
 +    int x;
 +
 +    palette = s1->last_palette;
 +    plane_mask = mask16[s1->ar[0x12] & 0xf];
 +    width >>= 3;
 +    for(x = 0; x < width; x++) {
 +        data = ((uint32_t *)s)[0];
 +        data &= plane_mask;
 +        v = expand2[GET_PLANE(data, 0)];
 +        v |= expand2[GET_PLANE(data, 2)] << 2;
 +        PUT_PIXEL2(d, 0, palette[v >> 12]);
 +        PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]);
 +        PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]);
 +        PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]);
 +
 +        v = expand2[GET_PLANE(data, 1)];
 +        v |= expand2[GET_PLANE(data, 3)] << 2;
 +        PUT_PIXEL2(d, 4, palette[v >> 12]);
 +        PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
 +        PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
 +        PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
 +        d += BPP * 16;
 +        s += 4;
 +    }
 +}
 +
 +/*
 + * 16 color mode
 + */
 +static void glue(maru_vga_draw_line4_, DEPTH)(VGACommonState *s1, uint8_t *d,
 +                                         const uint8_t *s, int width)
 +{
 +    uint32_t plane_mask, data, v, *palette;
 +    int x;
 +
 +    palette = s1->last_palette;
 +    plane_mask = mask16[s1->ar[0x12] & 0xf];
 +    width >>= 3;
 +    for(x = 0; x < width; x++) {
 +        data = ((uint32_t *)s)[0];
 +        data &= plane_mask;
 +        v = expand4[GET_PLANE(data, 0)];
 +        v |= expand4[GET_PLANE(data, 1)] << 1;
 +        v |= expand4[GET_PLANE(data, 2)] << 2;
 +        v |= expand4[GET_PLANE(data, 3)] << 3;
 +        ((PIXEL_TYPE *)d)[0] = palette[v >> 28];
 +        ((PIXEL_TYPE *)d)[1] = palette[(v >> 24) & 0xf];
 +        ((PIXEL_TYPE *)d)[2] = palette[(v >> 20) & 0xf];
 +        ((PIXEL_TYPE *)d)[3] = palette[(v >> 16) & 0xf];
 +        ((PIXEL_TYPE *)d)[4] = palette[(v >> 12) & 0xf];
 +        ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
 +        ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
 +        ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
 +        d += BPP * 8;
 +        s += 4;
 +    }
 +}
 +
 +/*
 + * 16 color mode, dup2 horizontal
 + */
 +static void glue(maru_vga_draw_line4d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
 +                                           const uint8_t *s, int width)
 +{
 +    uint32_t plane_mask, data, v, *palette;
 +    int x;
 +
 +    palette = s1->last_palette;
 +    plane_mask = mask16[s1->ar[0x12] & 0xf];
 +    width >>= 3;
 +    for(x = 0; x < width; x++) {
 +        data = ((uint32_t *)s)[0];
 +        data &= plane_mask;
 +        v = expand4[GET_PLANE(data, 0)];
 +        v |= expand4[GET_PLANE(data, 1)] << 1;
 +        v |= expand4[GET_PLANE(data, 2)] << 2;
 +        v |= expand4[GET_PLANE(data, 3)] << 3;
 +        PUT_PIXEL2(d, 0, palette[v >> 28]);
 +        PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]);
 +        PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]);
 +        PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]);
 +        PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]);
 +        PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
 +        PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
 +        PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
 +        d += BPP * 16;
 +        s += 4;
 +    }
 +}
 +
 +/*
 + * 256 color mode, double pixels
 + *
 + * XXX: add plane_mask support (never used in standard VGA modes)
 + */
 +static void glue(maru_vga_draw_line8d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
 +                                           const uint8_t *s, int width)
 +{
 +    uint32_t *palette;
 +    int x;
 +
 +    palette = s1->last_palette;
 +    width >>= 3;
 +    for(x = 0; x < width; x++) {
 +        PUT_PIXEL2(d, 0, palette[s[0]]);
 +        PUT_PIXEL2(d, 1, palette[s[1]]);
 +        PUT_PIXEL2(d, 2, palette[s[2]]);
 +        PUT_PIXEL2(d, 3, palette[s[3]]);
 +        d += BPP * 8;
 +        s += 4;
 +    }
 +}
 +
 +/*
 + * standard 256 color mode
 + *
 + * XXX: add plane_mask support (never used in standard VGA modes)
 + */
 +static void glue(maru_vga_draw_line8_, DEPTH)(VGACommonState *s1, uint8_t *d,
 +                                         const uint8_t *s, int width)
 +{
 +    uint32_t *palette;
 +    int x;
 +
 +    palette = s1->last_palette;
 +    width >>= 3;
 +    for(x = 0; x < width; x++) {
 +        ((PIXEL_TYPE *)d)[0] = palette[s[0]];
 +        ((PIXEL_TYPE *)d)[1] = palette[s[1]];
 +        ((PIXEL_TYPE *)d)[2] = palette[s[2]];
 +        ((PIXEL_TYPE *)d)[3] = palette[s[3]];
 +        ((PIXEL_TYPE *)d)[4] = palette[s[4]];
 +        ((PIXEL_TYPE *)d)[5] = palette[s[5]];
 +        ((PIXEL_TYPE *)d)[6] = palette[s[6]];
 +        ((PIXEL_TYPE *)d)[7] = palette[s[7]];
 +        d += BPP * 8;
 +        s += 8;
 +    }
 +}
 +
 +#endif /* DEPTH != 15 */
 +
 +
 +/* XXX: optimize */
 +
 +/*
 + * 15 bit color
 + */
 +static void glue(maru_vga_draw_line15_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
 +                                          const uint8_t *s, int width)
 +{
 +#if DEPTH == 15 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
 +    memcpy(d, s, width * 2);
 +#else
 +    int w;
 +    uint32_t v, r, g, b;
 +
 +    w = width;
 +    do {
 +        v = lduw_raw((void *)s);
 +        r = (v >> 7) & 0xf8;
 +        g = (v >> 2) & 0xf8;
 +        b = (v << 3) & 0xf8;
 +        ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
 +        s += 2;
 +        d += BPP;
 +    } while (--w != 0);
 +#endif
 +}
 +
 +/*
 + * 16 bit color
 + */
 +static void glue(maru_vga_draw_line16_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
 +                                          const uint8_t *s, int width)
 +{
 +#if DEPTH == 16 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
 +    memcpy(d, s, width * 2);
 +#else
 +    int w;
 +    uint32_t v, r, g, b;
 +
 +    w = width;
 +    do {
 +        v = lduw_raw((void *)s);
 +        r = (v >> 8) & 0xf8;
 +        g = (v >> 3) & 0xfc;
 +        b = (v << 3) & 0xf8;
 +        ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
 +        s += 2;
 +        d += BPP;
 +    } while (--w != 0);
 +#endif
 +}
 +
 +/*
 + * 24 bit color
 + */
 +static void glue(maru_vga_draw_line24_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
 +                                          const uint8_t *s, int width)
 +{
 +    int w;
 +    uint32_t r, g, b;
 +
 +    w = width;
 +    do {
 +#if defined(TARGET_WORDS_BIGENDIAN)
 +        r = s[0];
 +        g = s[1];
 +        b = s[2];
 +#else
 +        b = s[0];
 +        g = s[1];
 +        r = s[2];
 +#endif
 +        ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
 +        s += 3;
 +        d += BPP;
 +    } while (--w != 0);
 +}
 +
 +/*
 + * 32 bit color
 + */
 +static void glue(maru_vga_draw_line32_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
 +                                          const uint8_t *s, int width)
 +{
 +#if DEPTH == 32 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) && !defined(BGR_FORMAT)
 +    memcpy(d, s, width * 4);
 +#else
 +    int w;
 +    uint32_t r, g, b;
 +
 +    w = width;
 +    do {
 +#if defined(TARGET_WORDS_BIGENDIAN)
 +        r = s[1];
 +        g = s[2];
 +        b = s[3];
 +#else
 +        b = s[0];
 +        g = s[1];
 +        r = s[2];
 +#endif
 +        ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
 +        s += 4;
 +        d += BPP;
 +    } while (--w != 0);
 +#endif
 +}
 +
 +#undef PUT_PIXEL2
 +#undef DEPTH
 +#undef BPP
 +#undef PIXEL_TYPE
 +#undef PIXEL_NAME
 +#undef BGR_FORMAT
diff --combined tizen/src/maru_sdl.c
index 5b37ebf,0000000..b3f1cff
mode 100644,000000..100644
--- /dev/null
@@@ -1,892 -1,0 +1,893 @@@
 +/*
 + * SDL_WINDOWID hack
 + *
 + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
 + *
 + * Contact:
 + * Jinhyung Jo <jinhyung.jo@samsung.com>
 + * GiWoong Kim <giwoong.kim@samsung.com>
 + * SeokYeon Hwang <syeon.hwang@samsung.com>
 + * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +
 +#include <pthread.h>
 +#include <math.h>
 +#include <png.h>
 +#include "ui/console.h"
++#include "qemu/main-loop.h"
 +#include "maru_sdl.h"
 +#include "maru_display.h"
 +#include "emul_state.h"
 +#include "emulator.h"
 +#include "maru_finger.h"
 +#include "hw/maru_pm.h"
 +#include "hw/maru_brightness.h"
 +#include "hw/maru_overlay.h"
 +#include "debug_ch.h"
 +
 +MULTI_DEBUG_CHANNEL(tizen, maru_sdl);
 +
 +static QEMUBH *sdl_init_bh;
 +static QEMUBH *sdl_resize_bh;
 +static DisplaySurface *dpy_surface;
 +
 +static SDL_Surface *surface_screen;
 +static SDL_Surface *surface_qemu;
 +static SDL_Surface *scaled_screen;
 +static SDL_Surface *rotated_screen;
 +static SDL_Surface *surface_guide; /* blank guide image */
 +
 +static double current_scale_factor = 1.0;
 +static double current_screen_degree;
 +static pixman_filter_t sdl_pixman_filter;
 +
 +static int sdl_alteration;
 +
 +static unsigned int sdl_skip_update;
 +static unsigned int sdl_skip_count;
 +
 +static bool blank_guide_enable;
 +static unsigned int blank_cnt;
 +#define MAX_BLANK_FRAME_CNT 10
 +#define BLANK_GUIDE_IMAGE_PATH "../images/"
 +#define BLANK_GUIDE_IMAGE_NAME "blank-guide.png"
 +
 +
 +#define SDL_THREAD
 +
 +static pthread_mutex_t sdl_mutex = PTHREAD_MUTEX_INITIALIZER;
 +#ifdef SDL_THREAD
 +static pthread_cond_t sdl_cond = PTHREAD_COND_INITIALIZER;
 +static int sdl_thread_initialized;
 +#endif
 +
 +#define SDL_FLAGS (SDL_SWSURFACE | SDL_ASYNCBLIT | SDL_NOFRAME)
 +#define SDL_BPP 32
 +
 +/* Image processing functions using the pixman library */
 +static void maru_do_pixman_dpy_surface(pixman_image_t *dst_image)
 +{
 +    /* overlay0 */
 +    if (overlay0_power) {
 +        pixman_image_composite(PIXMAN_OP_OVER,
 +                               overlay0_image, NULL, dst_image,
 +                               0, 0, 0, 0, overlay0_left, overlay0_top,
 +                               overlay0_width, overlay0_height);
 +    }
 +    /* overlay1 */
 +    if (overlay1_power) {
 +        pixman_image_composite(PIXMAN_OP_OVER,
 +                               overlay1_image, NULL, dst_image,
 +                               0, 0, 0, 0, overlay1_left, overlay1_top,
 +                               overlay1_width, overlay1_height);
 +    }
 +    /* apply the brightness level */
 +    if (brightness_level < BRIGHTNESS_MAX) {
 +        pixman_image_composite(PIXMAN_OP_OVER,
 +                               brightness_image, NULL, dst_image,
 +                               0, 0, 0, 0, 0, 0,
 +                               pixman_image_get_width(dst_image),
 +                               pixman_image_get_height(dst_image));
 +    }
 +}
 +
 +static SDL_Surface *maru_do_pixman_scale(SDL_Surface *rz_src,
 +                                         SDL_Surface *rz_dst,
 +                                         pixman_filter_t filter)
 +{
 +    pixman_image_t *src = NULL;
 +    pixman_image_t *dst = NULL;
 +    double sx = 0;
 +    double sy = 0;
 +    pixman_transform_t matrix;
 +    struct pixman_f_transform matrix_f;
 +
 +    SDL_LockSurface(rz_src);
 +    SDL_LockSurface(rz_dst);
 +
 +    src = pixman_image_create_bits(PIXMAN_a8r8g8b8,
 +        rz_src->w, rz_src->h, rz_src->pixels, rz_src->w * 4);
 +    dst = pixman_image_create_bits(PIXMAN_a8r8g8b8,
 +        rz_dst->w, rz_dst->h, rz_dst->pixels, rz_dst->w * 4);
 +
 +    sx = (double)rz_src->w / (double)rz_dst->w;
 +    sy = (double)rz_src->h / (double)rz_dst->h;
 +    pixman_f_transform_init_identity(&matrix_f);
 +    pixman_f_transform_scale(&matrix_f, NULL, sx, sy);
 +    pixman_transform_from_pixman_f_transform(&matrix, &matrix_f);
 +    pixman_image_set_transform(src, &matrix);
 +    pixman_image_set_filter(src, filter, NULL, 0);
 +    pixman_image_composite(PIXMAN_OP_SRC, src, NULL, dst,
 +                           0, 0, 0, 0, 0, 0,
 +                           rz_dst->w, rz_dst->h);
 +
 +    pixman_image_unref(src);
 +    pixman_image_unref(dst);
 +
 +    SDL_UnlockSurface(rz_src);
 +    SDL_UnlockSurface(rz_dst);
 +
 +    return rz_dst;
 +}
 +
 +static SDL_Surface *maru_do_pixman_rotate(SDL_Surface *rz_src,
 +                                          SDL_Surface *rz_dst,
 +                                          int angle)
 +{
 +    pixman_image_t *src = NULL;
 +    pixman_image_t *dst = NULL;
 +    pixman_transform_t matrix;
 +    struct pixman_f_transform matrix_f;
 +
 +    SDL_LockSurface(rz_src);
 +    SDL_LockSurface(rz_dst);
 +
 +    src = pixman_image_create_bits(PIXMAN_a8r8g8b8,
 +        rz_src->w, rz_src->h, rz_src->pixels, rz_src->w * 4);
 +    dst = pixman_image_create_bits(PIXMAN_a8r8g8b8,
 +        rz_dst->w, rz_dst->h, rz_dst->pixels, rz_dst->w * 4);
 +
 +    pixman_f_transform_init_identity(&matrix_f);
 +    switch(angle) {
 +        case 0:
 +            pixman_f_transform_rotate(&matrix_f, NULL, 1.0, 0.0);
 +            pixman_f_transform_translate(&matrix_f, NULL, 0.0, 0.0);
 +            break;
 +        case 90:
 +            pixman_f_transform_rotate(&matrix_f, NULL, 0.0, 1.0);
 +            pixman_f_transform_translate(&matrix_f, NULL,
 +                                         (double)rz_dst->h, 0.0);
 +            break;
 +        case 180:
 +            pixman_f_transform_rotate(&matrix_f, NULL, -1.0, 0.0);
 +            pixman_f_transform_translate(&matrix_f, NULL,
 +                                         (double)rz_dst->w, (double)rz_dst->h);
 +            break;
 +        case 270:
 +            pixman_f_transform_rotate(&matrix_f, NULL, 0.0, -1.0);
 +            pixman_f_transform_translate(&matrix_f, NULL,
 +                                         0.0, (double)rz_dst->w);
 +            break;
 +        default:
 +            fprintf(stdout, "not supported angle factor (angle=%d)\n", angle);
 +            break;
 +    }
 +    pixman_transform_from_pixman_f_transform(&matrix, &matrix_f);
 +    pixman_image_set_transform(src, &matrix);
 +    //pixman_image_set_filter(src, PIXMAN_FILTER_BILINEAR, NULL, 0);
 +    pixman_image_composite(PIXMAN_OP_SRC, src, NULL, dst,
 +                           0, 0, 0, 0, 0, 0,
 +                           rz_dst->w, rz_dst->h);
 +
 +    pixman_image_unref(src);
 +    pixman_image_unref(dst);
 +
 +    SDL_UnlockSurface(rz_src);
 +    SDL_UnlockSurface(rz_dst);
 +
 +    return rz_dst;
 +}
 +
 +static void qemu_ds_sdl_update(DisplayChangeListener *dcl,
 +                               int x, int y, int w, int h)
 +{
 +    /* call sdl update */
 +#ifdef SDL_THREAD
 +    pthread_mutex_lock(&sdl_mutex);
 +
 +    pthread_cond_signal(&sdl_cond);
 +
 +    pthread_mutex_unlock(&sdl_mutex);
 +#else
 +    qemu_update();
 +#endif
 +}
 +
 +static void qemu_ds_sdl_switch(DisplayChangeListener *dcl,
 +                               struct DisplaySurface *new_surface)
 +{
 +    int console_width = 0, console_height = 0;
 +
 +    sdl_skip_update = 0;
 +    sdl_skip_count = 0;
 +
 +    if (!new_surface) {
 +        ERR("qemu_ds_sdl_switch : new_surface is NULL\n");
 +        return;
 +    }
 +
 +    dpy_surface = new_surface;
 +    console_width = surface_width(new_surface);
 +    console_height = surface_height(new_surface);
 +
 +    INFO("qemu_ds_sdl_switch : (%d, %d)\n",
 +        console_width, console_height);
 +
 +#ifdef SDL_THREAD
 +    pthread_mutex_lock(&sdl_mutex);
 +#endif
 +
 +    if (surface_qemu != NULL) {
 +        SDL_FreeSurface(surface_qemu);
 +        surface_qemu = NULL;
 +    }
 +
 +    /* create surface_qemu */
 +    if (console_width == get_emul_resolution_width() &&
 +        console_height == get_emul_resolution_height()) {
 +        INFO("create SDL screen : (%d, %d)\n",
 +             console_width, console_height);
 +
 +        surface_qemu = SDL_CreateRGBSurfaceFrom(
 +            surface_data(dpy_surface),
 +            console_width, console_height,
 +            surface_bits_per_pixel(dpy_surface),
 +            surface_stride(dpy_surface),
 +            dpy_surface->pf.rmask,
 +            dpy_surface->pf.gmask,
 +            dpy_surface->pf.bmask,
 +            dpy_surface->pf.amask);
 +    } else {
 +        INFO("create blank screen : (%d, %d)\n",
 +             get_emul_resolution_width(), get_emul_resolution_height());
 +
 +        surface_qemu = SDL_CreateRGBSurface(
 +            SDL_SWSURFACE,
 +            console_width, console_height,
 +            surface_bits_per_pixel(dpy_surface),
 +            0, 0, 0, 0);
 +    }
 +
 +#ifdef SDL_THREAD
 +    pthread_mutex_unlock(&sdl_mutex);
 +#endif
 +
 +    if (surface_qemu == NULL) {
 +        ERR("Unable to set the RGBSurface: %s\n", SDL_GetError());
 +        return;
 +    }
 +}
 +
 +static png_bytep read_png_file(const char *file_name,
 +    unsigned int *width_out, unsigned int *height_out)
 +{
 +#define PNG_HEADER_SIZE 8
 +
 +    FILE *fp = NULL;
 +    png_byte header[PNG_HEADER_SIZE] = { 0, };
 +    png_structp png_ptr = NULL;
 +
 +    png_infop info_ptr = NULL;
 +    png_uint_32 width = 0;
 +    png_uint_32 height = 0;
 +    png_byte channels = 0;
 +    unsigned int stride = 0;
 +    int bit_depth = 0;
 +    int color_type = 0;
 +    int i = 0;
 +
 +    png_bytep pixel_data = NULL;
 +    png_bytepp row_ptr_data = NULL;
 +
 +    if (file_name == NULL) {
 +        ERR("file name is empty\n");
 +        return NULL;
 +    }
 +
 +    fp = fopen(file_name, "rb");
 +    if (fp == NULL) {
 +        ERR("file %s could not be opened\n", file_name);
 +        return NULL;
 +    }
 +
 +    if (fread(header, sizeof(png_byte), PNG_HEADER_SIZE, fp) != PNG_HEADER_SIZE) {
 +        ERR("failed to read header from png file\n");
 +        fclose(fp);
 +        return NULL;
 +    }
 +
 +    if (png_sig_cmp(header, 0, PNG_HEADER_SIZE) != 0) {
 +        ERR("file %s is not recognized as a PNG image\n", file_name);
 +        fclose(fp);
 +        return NULL;
 +    }
 +
 +    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
 +    if (png_ptr == NULL) {
 +        ERR("failed to allocate png read struct\n");
 +        fclose(fp);
 +        return NULL;
 +    }
 +
 +    info_ptr = png_create_info_struct(png_ptr);
 +    if (info_ptr == NULL) {
 +        ERR("failed to allocate png info struct\n");
 +        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
 +        fclose(fp);
 +        return NULL;
 +    }
 +
 +    if (setjmp(png_jmpbuf(png_ptr)) != 0) {
 +        ERR("error during init_io\n");
 +        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
 +        png_destroy_info_struct(png_ptr, &info_ptr);
 +        fclose(fp);
 +        return NULL;
 +    }
 +
 +    png_init_io(png_ptr, fp);
 +    png_set_sig_bytes(png_ptr, PNG_HEADER_SIZE);
 +
 +    /* read the PNG image information */
 +    png_read_info(png_ptr, info_ptr);
 +    png_get_IHDR(png_ptr, info_ptr,
 +        &width, &height, &bit_depth, &color_type,
 +        NULL, NULL, NULL);
 +
 +    channels = png_get_channels(png_ptr, info_ptr);
 +    stride = width * bit_depth * channels / 8;
 +
 +    pixel_data = (png_bytep) g_malloc0(stride * height);
 +    if (pixel_data == NULL) {
 +        ERR("could not allocate data buffer for pixels\n");
 +
 +        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
 +        png_destroy_info_struct(png_ptr, &info_ptr);
 +        fclose(fp);
 +        return NULL;
 +    }
 +
 +    row_ptr_data = (png_bytepp) g_malloc0(sizeof(png_bytep) * height);
 +    if (row_ptr_data == NULL) {
 +        ERR("could not allocate data buffer for row_ptr\n");
 +
 +        g_free(pixel_data);
 +        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
 +        png_destroy_info_struct(png_ptr, &info_ptr);
 +        fclose(fp);
 +        return NULL;
 +    }
 +
 +    switch(color_type) {
 +        case PNG_COLOR_TYPE_PALETTE :
 +            png_set_palette_to_rgb(png_ptr);
 +            break;
 +        case PNG_COLOR_TYPE_RGB :
 +            if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
 +                /* transparency data for image */
 +                png_set_tRNS_to_alpha(png_ptr);
 +            } else {
 +                png_set_filter(png_ptr, 0xff, PNG_FILLER_AFTER);
 +            }
 +            break;
 +        case PNG_COLOR_TYPE_RGB_ALPHA :
 +            break;
 +        default :
 +            INFO("png file has an unsupported color type\n");
 +            break;
 +    }
 +
 +    for (i = 0; i < height; i++) {
 +        row_ptr_data[i] = pixel_data + (stride * i);
 +    }
 +
 +    /* read the entire image into memory */
 +    png_read_image(png_ptr, row_ptr_data);
 +
 +    /* image information */
 +    INFO("=== blank guide image was loaded ===============\n");
 +    INFO("file path : %s\n", file_name);
 +    INFO("width : %d, height : %d, stride : %d\n",
 +        width, height, stride);
 +    INFO("color type : %d, channels : %d, bit depth : %d\n",
 +        color_type, channels, bit_depth);
 +    INFO("================================================\n");
 +
 +    if (width_out != NULL) {
 +        *width_out = (unsigned int) width;
 +    }
 +    if (height_out != NULL) {
 +        *height_out = (unsigned int) height;
 +    }
 +
 +    g_free(row_ptr_data);
 +    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
 +    png_destroy_info_struct(png_ptr, &info_ptr);
 +    fclose(fp);
 +
 +    return pixel_data;
 +}
 +
 +static SDL_Surface *get_blank_guide_image(void)
 +{
 +    if (surface_guide == NULL) {
 +        unsigned int width = 0;
 +        unsigned int height = 0;
 +        char *guide_image_path = NULL;
 +        void *guide_image_data = NULL;
 +
 +        /* load png image */
 +        int path_len = strlen(get_bin_path()) +
 +            strlen(BLANK_GUIDE_IMAGE_PATH) +
 +            strlen(BLANK_GUIDE_IMAGE_NAME) + 1;
 +        guide_image_path = g_malloc0(sizeof(char) * path_len);
 +        snprintf(guide_image_path, path_len, "%s%s%s",
 +            get_bin_path(), BLANK_GUIDE_IMAGE_PATH,
 +            BLANK_GUIDE_IMAGE_NAME);
 +
 +        guide_image_data = (void *) read_png_file(
 +            guide_image_path, &width, &height);
 +
 +        if (guide_image_data != NULL) {
 +            surface_guide = SDL_CreateRGBSurfaceFrom(
 +                guide_image_data, width, height,
 +                get_emul_sdl_bpp(), width * 4,
 +                dpy_surface->pf.bmask,
 +                dpy_surface->pf.gmask,
 +                dpy_surface->pf.rmask,
 +                dpy_surface->pf.amask);
 +        } else {
 +            ERR("failed to draw a blank guide image\n");
 +        }
 +
 +        g_free(guide_image_path);
 +    }
 +
 +    return surface_guide;
 +}
 +
 +static void qemu_ds_sdl_refresh(DisplayChangeListener *dcl)
 +{
 +    if (sdl_alteration == 1) {
 +        sdl_alteration = 0;
 +        sdl_skip_update = 0;
 +        sdl_skip_count = 0;
 +    }
 +
 +    /* If the display is turned off,
 +       the screen does not update until the display is turned on */
 +    if (sdl_skip_update && brightness_off) {
 +        if (blank_cnt > MAX_BLANK_FRAME_CNT) {
 +            /* do nothing */
 +            return;
 +        } else if (blank_cnt == MAX_BLANK_FRAME_CNT) {
 +            if (blank_guide_enable == true) {
 +                INFO("draw a blank guide image\n");
 +
 +                SDL_Surface *guide = get_blank_guide_image();
 +                if (guide != NULL && get_emul_skin_enable() == 1) {
 +                    /* draw guide image */
 +                    int dst_x = 0; int dst_y = 0;
 +                    int dst_w = 0; int dst_h = 0;
 +
 +                    unsigned int screen_width =
 +                        get_emul_resolution_width() * current_scale_factor;
 +                    unsigned int screen_height =
 +                        get_emul_resolution_height() * current_scale_factor;
 +
 +                    int margin_w = screen_width - guide->w;
 +                    int margin_h = screen_height - guide->h;
 +
 +                    if (margin_w < 0 || margin_h < 0) {
 +                        /* guide image scaling */
 +                        int margin = (margin_w < margin_h)? margin_w : margin_h;
 +                        dst_w = guide->w + margin;
 +                        dst_h = guide->h + margin;
 +
 +                        SDL_Surface *scaled_guide = SDL_CreateRGBSurface(
 +                            SDL_SWSURFACE, dst_w, dst_h, get_emul_sdl_bpp(),
 +                            guide->format->Rmask, guide->format->Gmask,
 +                            guide->format->Bmask, guide->format->Amask);
 +
 +                        scaled_guide = maru_do_pixman_scale(
 +                            guide, scaled_guide, PIXMAN_FILTER_BEST);
 +
 +                        dst_x = (surface_screen->w - dst_w) / 2;
 +                        dst_y = (surface_screen->h - dst_h) / 2;
 +                        SDL_Rect dst_rect = { dst_x, dst_y, dst_w, dst_h };
 +
 +                        SDL_BlitSurface(scaled_guide, NULL,
 +                            surface_screen, &dst_rect);
 +                        SDL_UpdateRect(surface_screen, 0, 0, 0, 0);
 +
 +                        SDL_FreeSurface(scaled_guide);
 +                    } else {
 +                        dst_w = guide->w;
 +                        dst_h = guide->h;
 +                        dst_x = (surface_screen->w - dst_w) / 2;
 +                        dst_y = (surface_screen->h - dst_h) / 2;
 +                        SDL_Rect dst_rect = { dst_x, dst_y, dst_w, dst_h };
 +
 +                        SDL_BlitSurface(guide, NULL,
 +                            surface_screen, &dst_rect);
 +                        SDL_UpdateRect(surface_screen, 0, 0, 0, 0);
 +                    }
 +                }
 +            }
 +        } else if (blank_cnt == 0) {
 +            INFO("skipping of the display updating is started\n");
 +        }
 +
 +        blank_cnt++;
 +
 +        return;
 +    } else {
 +        if (blank_cnt != 0) {
 +            INFO("skipping of the display updating is ended\n");
 +            blank_cnt = 0;
 +        }
 +    }
 +
 +    graphic_hw_update(NULL);
 +
 +    /* Usually, continuously updated.
 +       When the display is turned off,
 +       ten more updates the screen for a black screen. */
 +    if (brightness_off) {
 +        if (++sdl_skip_count > 10) {
 +            sdl_skip_update = 1;
 +        } else {
 +            sdl_skip_update = 0;
 +        }
 +    } else {
 +        sdl_skip_count = 0;
 +        sdl_skip_update = 0;
 +    }
 +
 +#ifdef TARGET_ARM
 +#ifdef SDL_THREAD
 +    pthread_mutex_lock(&sdl_mutex);
 +#endif
 +
 +    /*
 +    * It is necessary only for exynos4210 FIMD in connection with
 +    * some WM (xfwm4, for example)
 +    */
 +
 +    SDL_UpdateRect(surface_screen, 0, 0, 0, 0);
 +
 +#ifdef SDL_THREAD
 +    pthread_mutex_unlock(&sdl_mutex);
 +#endif
 +#endif
 +}
 +
 +DisplayChangeListenerOps maru_dcl_ops = {
 +    .dpy_name          = "maru_sdl",
 +    .dpy_gfx_update    = qemu_ds_sdl_update,
 +    .dpy_gfx_switch    = qemu_ds_sdl_switch,
 +    .dpy_refresh       = qemu_ds_sdl_refresh,
 +};
 +
 +void maruskin_sdl_interpolation(bool on)
 +{
 +    if (on == true) {
 +        INFO("set PIXMAN_FILTER_BEST filter for image processing\n");
 +
 +        /* PIXMAN_FILTER_BILINEAR */
 +        sdl_pixman_filter = PIXMAN_FILTER_BEST;
 +    } else {
 +        INFO("set PIXMAN_FILTER_FAST filter for image processing\n");
 +
 +        /* PIXMAN_FILTER_NEAREST */
 +        sdl_pixman_filter = PIXMAN_FILTER_FAST;
 +    }
 +}
 +
 +static void qemu_update(void)
 +{
 +    if (sdl_alteration == -1) {
 +        SDL_FreeSurface(scaled_screen);
 +        SDL_FreeSurface(rotated_screen);
 +        SDL_FreeSurface(surface_qemu);
 +        surface_qemu = NULL;
 +
 +        return;
 +    }
 +
 +    if (surface_qemu != NULL) {
 +        int i = 0;
 +
 +        maru_do_pixman_dpy_surface(dpy_surface->image);
 +        set_maru_screenshot(dpy_surface);
 +
 +        if (current_scale_factor != 1.0) {
 +            rotated_screen = maru_do_pixman_rotate(
 +                surface_qemu, rotated_screen,
 +                (int)current_screen_degree);
 +            scaled_screen = maru_do_pixman_scale(
 +                rotated_screen, scaled_screen, sdl_pixman_filter);
 +
 +            SDL_BlitSurface(scaled_screen, NULL, surface_screen, NULL);
 +        }
 +        else {/* current_scale_factor == 1.0 */
 +            if (current_screen_degree != 0.0) {
 +                rotated_screen = maru_do_pixman_rotate(
 +                    surface_qemu, rotated_screen,
 +                    (int)current_screen_degree);
 +
 +                SDL_BlitSurface(rotated_screen, NULL, surface_screen, NULL);
 +            } else {
 +                /* as-is */
 +                SDL_BlitSurface(surface_qemu, NULL, surface_screen, NULL);
 +            }
 +        }
 +
 +        /* draw multi-touch finger points */
 +        MultiTouchState *mts = get_emul_multi_touch_state();
 +        if (mts->multitouch_enable != 0 && mts->finger_point_surface != NULL) {
 +            FingerPoint *finger = NULL;
 +            int finger_point_size_half = mts->finger_point_size / 2;
 +            SDL_Rect rect;
 +
 +            for (i = 0; i < mts->finger_cnt; i++) {
 +                finger = get_finger_point_from_slot(i);
 +                if (finger != NULL && finger->id != 0) {
 +                    rect.x = finger->origin_x - finger_point_size_half;
 +                    rect.y = finger->origin_y - finger_point_size_half;
 +                    rect.w = rect.h = mts->finger_point_size;
 +
 +                    SDL_BlitSurface(
 +                        (SDL_Surface *)mts->finger_point_surface,
 +                        NULL, surface_screen, &rect);
 +                }
 +            }
 +        } /* end of draw multi-touch */
 +    }
 +
 +    SDL_UpdateRect(surface_screen, 0, 0, 0, 0);
 +}
 +
 +
 +#ifdef SDL_THREAD
 +static void *run_qemu_update(void *arg)
 +{
 +    while(1) {
 +        pthread_mutex_lock(&sdl_mutex);
 +
 +        pthread_cond_wait(&sdl_cond, &sdl_mutex);
 +
 +        qemu_update();
 +
 +        pthread_mutex_unlock(&sdl_mutex);
 +    }
 +
 +    return NULL;
 +}
 +#endif
 +
 +static void maru_sdl_resize_bh(void *opaque)
 +{
 +    int surface_width = 0, surface_height = 0;
 +    int display_width = 0, display_height = 0;
 +    int temp = 0;
 +
 +    INFO("Set up a video mode with the specified width, "
 +         "height and bits-per-pixel\n");
 +
 +    sdl_alteration = 1;
 +    sdl_skip_update = 0;
 +
 +#ifdef SDL_THREAD
 +    pthread_mutex_lock(&sdl_mutex);
 +#endif
 +
 +    /* get current setting information and calculate screen size */
 +    display_width = get_emul_resolution_width();
 +    display_height = get_emul_resolution_height();
 +    current_scale_factor = get_emul_win_scale();
 +
 +    short rotaton_type = get_emul_rotation();
 +    if (rotaton_type == ROTATION_PORTRAIT) {
 +        current_screen_degree = 0.0;
 +    } else if (rotaton_type == ROTATION_LANDSCAPE) {
 +        current_screen_degree = 90.0;
 +        temp = display_width;
 +        display_width = display_height;
 +        display_height = temp;
 +    } else if (rotaton_type == ROTATION_REVERSE_PORTRAIT) {
 +        current_screen_degree = 180.0;
 +    } else if (rotaton_type == ROTATION_REVERSE_LANDSCAPE) {
 +        current_screen_degree = 270.0;
 +        temp = display_width;
 +        display_width = display_height;
 +        display_height = temp;
 +    }
 +
 +    surface_width = display_width * current_scale_factor;
 +    surface_height = display_height * current_scale_factor;
 +
 +    surface_screen = SDL_SetVideoMode(
 +        surface_width, surface_height,
 +        get_emul_sdl_bpp(), SDL_FLAGS);
 +
 +    INFO("SDL_SetVideoMode\n");
 +
 +    if (surface_screen == NULL) {
 +        ERR("Could not open SDL display (%dx%dx%d) : %s\n",
 +            surface_width, surface_height,
 +            get_emul_sdl_bpp(), SDL_GetError());
 +
 +#ifdef SDL_THREAD
 +        pthread_mutex_unlock(&sdl_mutex);
 +#endif
 +
 +        return;
 +    }
 +
 +    /* create buffer for image processing */
 +    SDL_FreeSurface(scaled_screen);
 +    scaled_screen = SDL_CreateRGBSurface(SDL_SWSURFACE,
 +        surface_width, surface_height,
 +        get_emul_sdl_bpp(),
 +        surface_qemu->format->Rmask,
 +        surface_qemu->format->Gmask,
 +        surface_qemu->format->Bmask,
 +        surface_qemu->format->Amask);
 +
 +    SDL_FreeSurface(rotated_screen);
 +    rotated_screen = SDL_CreateRGBSurface(SDL_SWSURFACE,
 +        display_width, display_height,
 +        get_emul_sdl_bpp(),
 +        surface_qemu->format->Rmask,
 +        surface_qemu->format->Gmask,
 +        surface_qemu->format->Bmask,
 +        surface_qemu->format->Amask);
 +
 +    /* rearrange multi-touch finger points */
 +    if (get_emul_multi_touch_state()->multitouch_enable == 1 ||
 +            get_emul_multi_touch_state()->multitouch_enable == 2) {
 +        rearrange_finger_points(get_emul_resolution_width(), get_emul_resolution_height(),
 +            current_scale_factor, rotaton_type);
 +    }
 +
 +#ifdef SDL_THREAD
 +    pthread_mutex_unlock(&sdl_mutex);
 +#endif
 +}
 +
 +static void maru_sdl_init_bh(void *opaque)
 +{
 +    SDL_SysWMinfo info;
 +
 +    INFO("SDL_Init\n");
 +
 +    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
 +        ERR("unable to init SDL: %s\n", SDL_GetError());
 +        // TODO:
 +    }
 +
 +#ifndef _WIN32
 +    SDL_VERSION(&info.version);
 +    SDL_GetWMInfo(&info);
 +#endif
 +
 +    qemu_bh_schedule(sdl_resize_bh);
 +
 +#ifdef SDL_THREAD
 +    if (sdl_thread_initialized == 0) {
 +        sdl_thread_initialized = 1;
 +
 +        INFO("sdl update thread create\n");
 +
 +        pthread_t thread_id;
 +        if (pthread_create(
 +            &thread_id, NULL, run_qemu_update, NULL) != 0) {
 +            ERR("pthread_create fail\n");
 +            return;
 +        }
 +    }
 +#endif
 +}
 +
 +void maruskin_sdl_init(uint64 swt_handle,
 +    unsigned int display_width, unsigned int display_height,
 +    bool blank_guide)
 +{
 +    gchar SDL_windowhack[32] = { 0, };
 +    long window_id = swt_handle;
 +    blank_guide_enable = blank_guide;
 +
 +    INFO("maru sdl init\n");
 +
 +    sdl_init_bh = qemu_bh_new(maru_sdl_init_bh, NULL);
 +    sdl_resize_bh = qemu_bh_new(maru_sdl_resize_bh, NULL);
 +
 +    sprintf(SDL_windowhack, "%ld", window_id);
 +    g_setenv("SDL_WINDOWID", SDL_windowhack, 1);
 +
 +    INFO("register SDL environment variable. "
 +        "(SDL_WINDOWID = %s)\n", SDL_windowhack);
 +
 +    set_emul_resolution(display_width, display_height);
 +    set_emul_sdl_bpp(SDL_BPP);
 +    maruskin_sdl_interpolation(false);
 +    init_multi_touch_state();
 +
 +    if (blank_guide_enable == true) {
 +        INFO("blank guide is on\n");
 +    }
 +
 +    qemu_bh_schedule(sdl_init_bh);
 +}
 +
 +void maruskin_sdl_quit(void)
 +{
 +    INFO("maru sdl quit\n");
 +
 +    if (surface_guide != NULL) {
 +        g_free(surface_guide->pixels);
 +        SDL_FreeSurface(surface_guide);
 +    }
 +
 +    /* remove multi-touch finger points */
 +    cleanup_multi_touch_state();
 +
 +    if (sdl_init_bh != NULL) {
 +        qemu_bh_delete(sdl_init_bh);
 +    }
 +    if (sdl_resize_bh != NULL) {
 +        qemu_bh_delete(sdl_resize_bh);
 +    }
 +
 +    sdl_alteration = -1;
 +
 +#ifdef SDL_THREAD
 +    pthread_mutex_lock(&sdl_mutex);
 +#endif
 +
 +    SDL_Quit();
 +
 +#ifdef SDL_THREAD
 +    pthread_mutex_unlock(&sdl_mutex);
 +    pthread_cond_destroy(&sdl_cond);
 +#endif
 +
 +    pthread_mutex_destroy(&sdl_mutex);
 +}
 +
 +void maruskin_sdl_resize(void)
 +{
 +    INFO("maru sdl resize\n");
 +
 +    qemu_bh_schedule(sdl_resize_bh);
 +}
diff --combined tizen/src/mloop_event.c
index 88797e2,0000000..b51436c
mode 100644,000000..100644
--- /dev/null
@@@ -1,659 -1,0 +1,659 @@@
-             qdev_free(&usbdisk->qdev);
 +/*
 + * mainloop_evhandle.c
 + *
 + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
 + *
 + * Contact:
 + * Kitae Kim <kt920.kim@samsung.com>
 + * GiWoong Kim <giwoong.kim@samsung.com>
 + * DoHyung Hong
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 + *
 + * Contributors:
 + * - S-Core Co., Ltd
 + *
 + */
 +
 +
 +#ifdef _WIN32
 +#include <winsock.h>
 +#define socklen_t     int
 +#else
 +#include <netinet/in.h>
 +#include <sys/ioctl.h>
 +#endif
 +
 +//#include "qobject.h"
 +#include "qemu-common.h"
 +#include "hw/usb.h"
 +#include "hw/irq.h"
 +#include "mloop_event.h"
 +#include "ui/console.h"
 +#include "emul_state.h"
 +#include "debug_ch.h"
 +#include "monitor/monitor.h"
 +#include "hw/pci/pci.h"
 +#include "sysemu/sysemu.h"
 +#include "exec/memory-internal.h"
 +
 +#include "emulator.h"
 +#include "guest_debug.h"
 +#include "skin/maruskin_server.h"
 +#include "hw/maru_virtio_touchscreen.h"
 +#include "hw/maru_virtio_keyboard.h"
 +
 +MULTI_DEBUG_CHANNEL(qemu, mloop_event);
 +
 +struct mloop_evsock {
 +    int sockno;
 +    unsigned short portno;
 +    unsigned char status;
 +};
 +
 +#define MLOOP_EVSOCK_NULL        0
 +#define MLOOP_EVSOCK_CREATED    1
 +#define MLOOP_EVSOCK_NOTBOUND    2
 +#define MLOOP_EVSOCK_BOUND        3
 +#define MLOOP_EVSOCK_CONNECTED    4
 +
 +#define PACKET_LEN 512
 +struct mloop_evpack {
 +    short type;
 +    short size;
 +    char data[PACKET_LEN-4];
 +};
 +
 +#define MLOOP_EVTYPE_USB_ADD    1
 +#define MLOOP_EVTYPE_USB_DEL    2
 +#define MLOOP_EVTYPE_INTR_UP    3
 +#define MLOOP_EVTYPE_INTR_DOWN  4
 +#define MLOOP_EVTYPE_TOUCH      6
 +#define MLOOP_EVTYPE_KEYBOARD   7
 +#define MLOOP_EVTYPE_KBD_ADD    8
 +#define MLOOP_EVTYPE_KBD_DEL    9
 +#define MLOOP_EVTYPE_RAMDUMP    10
 +#define MLOOP_EVTYPE_SDCARD_ATTACH  11
 +#define MLOOP_EVTYPE_SDCARD_DETACH  12
 +
 +
 +static struct mloop_evsock mloop = {-1, 0, 0};
 +
 +static int mloop_evsock_create(struct mloop_evsock *ev)
 +{
 +    struct sockaddr sa;
 +    socklen_t sa_size;
 +    int ret;
 +    unsigned long nonblock = 1;
 +
 +    if (ev == NULL) {
 +        ERR("null pointer\n");
 +        return -1;
 +    }
 +
 +    ev->sockno = socket(AF_INET, SOCK_DGRAM, 0);
 +    if ( ev->sockno == -1 ) {
 +        ERR("socket() failed\n");
 +        return -1;
 +    }
 +
 +#ifdef _WIN32
 +    ioctlsocket(ev->sockno, FIONBIO, &nonblock );
 +#else
 +    ioctl(ev->sockno, FIONBIO, &nonblock);
 +#endif // _WIN32
 +
 +    nonblock = 1 ;
 +    setsockopt( ev->sockno, SOL_SOCKET, SO_REUSEADDR, (char *)&nonblock, sizeof(nonblock) ) ;
 +
 +    memset(&sa, '\0', sizeof(sa));
 +    ((struct sockaddr_in *) &sa)->sin_family = AF_INET;
 +    memcpy(&((struct sockaddr_in *) &sa)->sin_addr, "\177\000\000\001", 4); // 127.0.0.1
 +    ((struct sockaddr_in *) &sa)->sin_port = htons(ev->portno);
 +    sa_size = sizeof(struct sockaddr_in);
 +
 +    ret = bind(ev->sockno, &sa, sa_size);
 +    if (ret) {
 +        ERR("bind() failed\n");
 +#ifdef _WIN32
 +        closesocket(ev->sockno);
 +#else
 +        close(ev->sockno);
 +#endif
 +        ev->sockno = -1;
 +        ev->status = 0;
 +        return ret;
 +    }
 +
 +    if (ev->portno == 0) {
 +        memset(&sa, '\0', sizeof(sa));
 +        getsockname(ev->sockno, (struct sockaddr *) &sa, &sa_size);
 +        ev->portno = ntohs(((struct sockaddr_in *) &sa)->sin_port);
 +    }
 +
 +    ret = connect(ev->sockno, (struct sockaddr *) &sa, sa_size);
 +    if (ret) {
 +        ERR("connect() failed\n");
 +#ifdef _WIN32
 +        closesocket(ev->sockno);
 +#else
 +        close(ev->sockno);
 +#endif
 +        ev->sockno = -1;
 +        ev->status = 0;
 +        return ret;
 +    }
 +
 +    ev->status = MLOOP_EVSOCK_CONNECTED;
 +    return 0;
 +}
 +
 +static void mloop_evsock_remove(struct mloop_evsock *ev)
 +{
 +    if (!ev) {
 +        return ;
 +    }
 +
 +    if (ev->sockno > 0) {
 +#ifdef _WIN32
 +        shutdown(ev->sockno, SD_BOTH);
 +        closesocket(ev->sockno);
 +#else
 +        shutdown(ev->sockno, SHUT_RDWR);
 +        close(ev->sockno);
 +#endif
 +        ev->sockno = -1;
 +        ev->status = 0;
 +    }
 +}
 +
 +static int mloop_evsock_send(struct mloop_evsock *ev, struct mloop_evpack *p)
 +{
 +    int ret;
 +
 +    if (ev == NULL || ev->sockno == -1) {
 +        ERR("invalid mloop_evsock\n");
 +        return -1;
 +    }
 +
 +    if (p == NULL || p->size <= 0) {
 +        ERR("invalid mloop_evpack\n");
 +        return -1;
 +    }
 +
 +    do {
 +        ret = send(ev->sockno, p, p->size, 0);
 +#ifdef _WIN32
 +    } while (ret == -1 && (WSAGetLastError() == WSAEWOULDBLOCK));
 +#else
 +    } while (ret == -1 && (errno == EWOULDBLOCK || errno == EINTR));
 +#endif // _WIN32
 +
 +    return ret;
 +}
 +
 +static USBDevice *usbkbd = NULL;
 +static USBDevice *usbdisk = NULL;
 +#ifdef TARGET_I386
 +static PCIDevice *hostkbd = NULL;
 +static PCIDevice *virtio_sdcard = NULL;
 +#endif
 +
 +static void mloop_evhandle_usb_add(char *name)
 +{
 +    if (name == NULL) {
 +        ERR("Packet data for usb device is NULL\n");
 +        return;
 +    }
 +
 +    if (strcmp(name, "keyboard") == 0) {
 +        if (usbkbd == NULL) {
 +            usbkbd = usbdevice_create(name);
 +        } else if (usbkbd->attached == 0) {
 +            usb_device_attach(usbkbd);
 +        }
 +    } else if (strncmp(name, "disk:", 5) == 0) {
 +        if (usbdisk == NULL) {
 +            usbdisk = usbdevice_create(name);
 +        }
 +    } else {
 +        WARN("There is no usb-device for %s.\n", name);
 +     }
 +}
 +
 +static void mloop_evhandle_usb_del(char *name)
 +{
 +    if (name == NULL) {
 +        ERR("Packet data for usb device is NULL\n");
 +        return;
 +    }
 +
 +    if (strcmp(name, "keyboard") == 0) {
 +        if (usbkbd && usbkbd->attached != 0) {
 +            usb_device_detach(usbkbd);
 +        }
 +    } else if (strncmp(name, "disk:", 5) == 0) {
 +        if (usbdisk) {
++//            qdev_free(&usbdisk->qdev);
 +        }
 +    } else {
 +        WARN("There is no usb-device for %s.\n", name);
 +    }
 +}
 +
 +static void mloop_evhandle_intr_up(long data)
 +{
 +    if (data == 0) {
 +        return;
 +    }
 +
 +    qemu_irq_raise((qemu_irq)data);
 +}
 +
 +static void mloop_evhandle_intr_down(long data)
 +{
 +    if (data == 0) {
 +        return;
 +    }
 +
 +    qemu_irq_lower((qemu_irq)data);
 +}
 +
 +static void mloop_evhandle_touch(struct mloop_evpack* pack)
 +{
 +    maru_virtio_touchscreen_notify();
 +}
 +
 +static void mloop_evhandle_keyboard(long data)
 +{
 +    virtio_keyboard_notify((void*)data);
 +}
 +
 +#ifdef TARGET_I386
 +static void mloop_evhandle_kbd_add(char *name)
 +{
 +    QDict *qdict;
 +
 +    TRACE("try to add a keyboard device.\n");
 +
 +    if (name == NULL) {
 +        ERR("packet data is NULL.\n");
 +        return;
 +    }
 +
 +    if (hostkbd) {
 +        INFO("virtio-keyboard has already been added.\n");
 +        return;
 +    }
 +
 +    qdict = qdict_new();
 +    qdict_put(qdict, "pci_addr", qstring_from_str("auto"));
 +    qdict_put(qdict, "type", qstring_from_str(name));
 +
 +    hostkbd = do_pci_device_hot_add(cur_mon, qdict);
 +    if (hostkbd) {
 +        TRACE("virtio-keyboard device: root_bus_path %s, bus %d, slot %d, function %d\n",
 +                pci_root_bus_path(hostkbd), pci_bus_num(hostkbd->bus),
 +                PCI_SLOT(hostkbd->devfn), PCI_FUNC(hostkbd->devfn));
 +    } else {
 +        ERR("failed to hot_add keyboard device.\n");
 +    }
 +
 +    QDECREF(qdict);
 +}
 +
 +static void mloop_evhandle_kbd_del(void)
 +{
 +    QDict *qdict;
 +    int slot = 0;
 +    char slotbuf[4] = {0,};
 +
 +    TRACE("try to remove a keyboard device.\n");
 +
 +    if (!hostkbd) {
 +        ERR("Failed to remove a keyboard device "
 +            "because the device has not been created yet.\n");
 +        return;
 +    }
 +
 +    slot = PCI_SLOT(hostkbd->devfn);
 +    snprintf(slotbuf, sizeof(slotbuf), "%x", slot);
 +    TRACE("virtio-keyboard slot %s.\n", slotbuf);
 +
 +    qdict = qdict_new();
 +    qdict_put(qdict, "pci_addr", qstring_from_str(slotbuf));
 +
 +    do_pci_device_hot_remove(cur_mon, qdict);
 +    INFO("hot_remove keyboard.\n");
 +
 +    hostkbd = NULL;
 +
 +    QDECREF(qdict);
 +}
 +
 +static void mloop_evhandle_sdcard_attach(char *name)
 +{
 +    char opts[PATH_MAX];
 +
 +    INFO("try to attach sdcard.\n");
 +
 +    if (name == NULL) {
 +        ERR("Packet data is NULL.\n");
 +        return;
 +    }
 +
 +    if (virtio_sdcard) {
 +        ERR("sdcard is already attached.\n");
 +        return;
 +    }
 +
 +    QDict *qdict = qdict_new();
 +
 +    qdict_put(qdict, "pci_addr", qstring_from_str("auto"));
 +    qdict_put(qdict, "type", qstring_from_str("storage"));
 +    snprintf(opts, sizeof(opts), "file=%s,if=virtio", name);
 +    qdict_put(qdict, "opts", qstring_from_str(opts));
 +
 +    virtio_sdcard = do_pci_device_hot_add(cur_mon, qdict);
 +    if (virtio_sdcard) {
 +        INFO("hot add virtio storage device with [%s]\n", opts);
 +        INFO("virtio-sdcard device: root_bus_path %s, bus %d, slot %d, function %d\n",
 +            pci_root_bus_path(virtio_sdcard), pci_bus_num(virtio_sdcard->bus),
 +            PCI_SLOT(virtio_sdcard->devfn), PCI_FUNC(virtio_sdcard->devfn));
 +    } else {
 +        ERR("failed to create a sdcard device.\n");
 +    }
 +
 +    QDECREF(qdict);
 +}
 +
 +static void mloop_evhandle_sdcard_detach(void)
 +{
 +    INFO("try to detach sdcard.\n");
 +
 +    if (!virtio_sdcard) {
 +        ERR("sdcard is not attached yet.\n");
 +        return;
 +    }
 +
 +    QDict *qdict = qdict_new();
 +    int slot = 0;
 +    char slotbuf[4] = {0,};
 +
 +    slot = PCI_SLOT(virtio_sdcard->devfn);
 +    snprintf(slotbuf, sizeof(slotbuf), "%x", slot);
 +    INFO("virtio-sdcard slot [%d].\n", slot);
 +    qdict_put(qdict, "pci_addr", qstring_from_str(slotbuf));
 +
 +    do_pci_device_hot_remove(cur_mon, qdict);
 +
 +    virtio_sdcard = NULL;
 +
 +    INFO("hot remove virtio storage device.\n");
 +
 +    QDECREF(qdict);
 +}
 +
 +int mloop_evcmd_get_hostkbd_status(void)
 +{
 +    return hostkbd ? 1 : 0;
 +}
 +#endif
 +
 +static void mloop_evhandle_ramdump(struct mloop_evpack* pack)
 +{
 +#define MAX_PATH 256
 +    INFO("dumping...\n");
 +
 +#if defined(CONFIG_LINUX) && !defined(TARGET_ARM) /* FIXME: Handle ARM ram as list */
 +    MemoryRegion* mr = get_ram_memory();
 +    size_t size = mr->size.lo;
 +    char dump_fullpath[MAX_PATH];
 +    char dump_filename[MAX_PATH];
 +
 +    char* dump_path = g_path_get_dirname(get_log_path());
 +
 +    sprintf(dump_filename, "0x%08x%s0x%08x%s", (unsigned int)mr->ram_addr, "-",
 +        (unsigned int)(mr->ram_addr + size), "_RAM.dump");
 +    sprintf(dump_fullpath, "%s/%s", dump_path, dump_filename);
 +    free(dump_path);
 +
 +    FILE *dump_file = fopen(dump_fullpath, "w+");
 +    if(!dump_file) {
 +        fprintf(stderr, "Dump file create failed [%s]\n", dump_fullpath);
 +
 +        return;
 +    }
 +
 +    size_t written;
 +    written = fwrite(qemu_get_ram_ptr(mr->ram_addr), sizeof(char), size, dump_file);
 +    fprintf(stdout, "Dump file written [%08x][%zu bytes]\n", (unsigned int)mr->ram_addr, written);
 +    if(written != size) {
 +        fprintf(stderr, "Dump file size error [%zu, %zu, %d]\n", written, size, errno);
 +    }
 +
 +    fprintf(stdout, "Dump file create success [%s, %zu bytes]\n", dump_fullpath, size);
 +
 +    fclose(dump_file);
 +#endif
 +
 +    /* notify to skin process */
 +    notify_ramdump_completed();
 +}
 +
 +static void mloop_evcb_recv(struct mloop_evsock *ev)
 +{
 +    struct mloop_evpack pack;
 +    int ret;
 +
 +    do {
 +        ret = recv(ev->sockno, (void *)&pack, sizeof(pack), 0);
 +#ifdef _WIN32
 +    } while (ret == -1 && WSAGetLastError() == WSAEINTR);
 +#else
 +    } while (ret == -1 && errno == EINTR);
 +#endif // _WIN32
 +
 +    if (ret == -1) {
 +        return;
 +    }
 +
 +    if (ret == 0) {
 +        return;
 +    }
 +
 +    switch (pack.type) {
 +    case MLOOP_EVTYPE_USB_ADD:
 +        mloop_evhandle_usb_add(pack.data);
 +        break;
 +    case MLOOP_EVTYPE_USB_DEL:
 +        mloop_evhandle_usb_del(pack.data);
 +        break;
 +    case MLOOP_EVTYPE_INTR_UP:
 +        mloop_evhandle_intr_up(*(long*)&pack.data[0]);
 +        break;
 +    case MLOOP_EVTYPE_INTR_DOWN:
 +        mloop_evhandle_intr_down(*(long*)&pack.data[0]);
 +        break;
 +    case MLOOP_EVTYPE_TOUCH:
 +        mloop_evhandle_touch(&pack);
 +        break;
 +    case MLOOP_EVTYPE_KEYBOARD:
 +        mloop_evhandle_keyboard(*(uint64_t*)&pack.data[0]);
 +        break;
 +#ifdef TARGET_I386
 +    case MLOOP_EVTYPE_KBD_ADD:
 +        mloop_evhandle_kbd_add(pack.data);
 +        break;
 +    case MLOOP_EVTYPE_KBD_DEL:
 +        mloop_evhandle_kbd_del();
 +        break;
 +#endif
 +    case MLOOP_EVTYPE_RAMDUMP:
 +        mloop_evhandle_ramdump(&pack);
 +        break;
 +#ifdef TARGET_I386
 +    case MLOOP_EVTYPE_SDCARD_ATTACH:
 +        mloop_evhandle_sdcard_attach(pack.data);
 +        break;
 +    case MLOOP_EVTYPE_SDCARD_DETACH:
 +        mloop_evhandle_sdcard_detach();
 +        break;
 +#endif
 +    default:
 +        break;
 +    }
 +}
 +
 +void mloop_ev_init(void)
 +{
 +    int ret = mloop_evsock_create(&mloop);
 +    if (ret == 0) {
 +        qemu_set_fd_handler(mloop.sockno, (IOHandler *)mloop_evcb_recv, NULL, &mloop);
 +    }
 +}
 +
 +void mloop_ev_stop(void)
 +{
 +    qemu_set_fd_handler(mloop.sockno, NULL, NULL, NULL);
 +    mloop_evsock_remove(&mloop);
 +}
 +
 +void mloop_evcmd_raise_intr(void *irq)
 +{
 +    struct mloop_evpack pack;
 +    memset((void*)&pack, 0, sizeof(struct mloop_evpack));
 +    pack.type = MLOOP_EVTYPE_INTR_UP;
 +    pack.size = 8;
 +    *(long*)&pack.data[0] = (long)irq;
 +    mloop_evsock_send(&mloop, &pack);
 +}
 +
 +void mloop_evcmd_lower_intr(void *irq)
 +{
 +    struct mloop_evpack pack;
 +    memset((void*)&pack, 0, sizeof(struct mloop_evpack));
 +    pack.type = MLOOP_EVTYPE_INTR_DOWN;
 +    pack.size = 8;
 +    *(long*)&pack.data[0] = (long)irq;
 +    mloop_evsock_send(&mloop, &pack);
 +}
 +
 +void mloop_evcmd_usbkbd(int on)
 +{
 +    struct mloop_evpack pack = { MLOOP_EVTYPE_USB_ADD, 13, "keyboard" };
 +    if (on == 0) {
 +        pack.type = MLOOP_EVTYPE_USB_DEL;
 +    }
 +    mloop_evsock_send(&mloop, &pack);
 +}
 +
 +void mloop_evcmd_hostkbd(int on)
 +{
 +    struct mloop_evpack pack
 +        = {MLOOP_EVTYPE_KBD_ADD, 13, "keyboard"};
 +    if (on == 0) {
 +        pack.type = MLOOP_EVTYPE_KBD_DEL;
 +    }
 +    mloop_evsock_send(&mloop, &pack);
 +}
 +
 +void mloop_evcmd_usbdisk(char *img)
 +{
 +    struct mloop_evpack pack;
 +
 +    if (img) {
 +        if (strlen(img) > PACKET_LEN-5) {
 +            ERR("The length of disk image path is greater than "
 +                "lenth of maximum packet.\n");
 +            return;
 +        }
 +
 +        pack.type = MLOOP_EVTYPE_USB_ADD;
 +        pack.size = 5 + sprintf(pack.data, "disk:%s", img);
 +    } else {
 +        pack.type = MLOOP_EVTYPE_USB_DEL;
 +        pack.size = 5 + sprintf(pack.data, "disk:");
 +    }
 +
 +    mloop_evsock_send(&mloop, &pack);
 +}
 +
 +void mloop_evcmd_sdcard(char *img)
 +{
 +    struct mloop_evpack pack;
 +
 +    if (img) {
 +        if (strlen(img) > PACKET_LEN-5) {
 +            ERR("The length of disk image path is greater than "
 +                "lenth of maximum packet.\n");
 +            return;
 +        }
 +
 +        pack.type = MLOOP_EVTYPE_SDCARD_ATTACH;
 +        pack.size = 5 + sprintf(pack.data, "%s", img);
 +    } else {
 +        pack.type = MLOOP_EVTYPE_SDCARD_DETACH;
 +        pack.size = 5;
 +    }
 +
 +    mloop_evsock_send(&mloop, &pack);
 +}
 +
 +int mloop_evcmd_get_usbkbd_status(void)
 +{
 +    return (usbkbd && usbkbd->attached ? 1 : 0);
 +}
 +
 +void mloop_evcmd_set_usbkbd(void *dev)
 +{
 +    usbkbd = (USBDevice *)dev;
 +}
 +
 +void mloop_evcmd_set_usbdisk(void *dev)
 +{
 +    usbdisk = (USBDevice *)dev;
 +}
 +
 +void mloop_evcmd_touch(void)
 +{
 +    struct mloop_evpack pack;
 +    memset(&pack, 0, sizeof(struct mloop_evpack));
 +
 +    pack.type = MLOOP_EVTYPE_TOUCH;
 +    pack.size = 5;
 +    mloop_evsock_send(&mloop, &pack);
 +}
 +
 +void mloop_evcmd_keyboard(void *data)
 +{
 +    struct mloop_evpack pack;
 +    memset(&pack, 0, sizeof(struct mloop_evpack));
 +
 +    pack.type = MLOOP_EVTYPE_KEYBOARD;
 +    pack.size = 4 + 8;
 +    *((VirtIOKeyboard **)pack.data) = (VirtIOKeyboard *)data;
 +    mloop_evsock_send(&mloop, &pack);
 +}
 +
 +void mloop_evcmd_ramdump(void)
 +{
 +    struct mloop_evpack pack;
 +    memset(&pack, 0, sizeof(struct mloop_evpack));
 +
 +    pack.type = MLOOP_EVTYPE_RAMDUMP;
 +    pack.size = 5;
 +    mloop_evsock_send(&mloop, &pack);
 +}
diff --combined ui/input.c
  #include "qapi-types.h"
  #include "ui/keymaps.h"
  
 +//#include "tizen/src/debug_ch.h"
 +
 +//MULTI_DEBUG_CHANNEL(tizen, input);
 +
  struct QEMUPutMouseEntry {
      QEMUPutMouseEvent *qemu_put_mouse_event;
      void *qemu_put_mouse_event_opaque;
@@@ -281,11 -277,11 +281,11 @@@ void qmp_send_key(KeyValueList *keys, b
      KeyValueList *p;
  
      if (!key_timer) {
-         key_timer = qemu_new_timer_ns(vm_clock, release_keys, NULL);
+         key_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, release_keys, NULL);
      }
  
      if (keycodes != NULL) {
-         qemu_del_timer(key_timer);
+         timer_del(key_timer);
          release_keys(NULL);
      }
  
      }
  
      /* delayed key up events */
-     qemu_mod_timer(key_timer, qemu_get_clock_ns(vm_clock) +
+     timer_mod(key_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
                     muldiv64(get_ticks_per_sec(), hold_time, 1000));
  }
  
@@@ -445,32 -441,11 +445,32 @@@ void kbd_mouse_event(int dx, int dy, in
      if (QTAILQ_EMPTY(&mouse_handlers)) {
          return;
      }
 +#if defined (CONFIG_MARU)
 +    QTAILQ_FOREACH(entry, &mouse_handlers, node) {
 +        /* if mouse event is wheelup ,wheeldown or move
 +              then go to ps2 mouse event(index == 0) */
 +        if (buttons_state > 3  && entry->index == 0) {
 +            //INFO("input device: %s, event: %d\n", entry->qemu_put_mouse_event_name, buttons_state);
 +            buttons_state = 0;
 +            mouse_event = entry->qemu_put_mouse_event;
 +            mouse_event_opaque = entry->qemu_put_mouse_event_opaque;
 +            break;
 +        }
 +    }
 +    /* other events(mouse up, down and drag), go to touch screen */
 +    if (!entry) {
 +        entry = QTAILQ_FIRST(&mouse_handlers);
 +        mouse_event = entry->qemu_put_mouse_event;
 +        mouse_event_opaque = entry->qemu_put_mouse_event_opaque;
 +        //INFO("input device: %s, event: %d\n", entry->qemu_put_mouse_event_name, buttons_state);
 +    }
 +#else
  
      entry = QTAILQ_FIRST(&mouse_handlers);
  
      mouse_event = entry->qemu_put_mouse_event;
      mouse_event_opaque = entry->qemu_put_mouse_event_opaque;
 +#endif
  
      if (mouse_event) {
          if (entry->qemu_put_mouse_event_absolute) {
diff --combined ui/sdl.c
+++ b/ui/sdl.c
@@@ -86,6 -86,7 +86,7 @@@ static void sdl_update(DisplayChangeLis
  static void do_sdl_resize(int width, int height, int bpp)
  {
      int flags;
+     SDL_Surface *tmp_screen;
  
      //    printf("resizing to %d %d\n", w, h);
  
      if (gui_noframe)
          flags |= SDL_NOFRAME;
  
-     real_screen = SDL_SetVideoMode(width, height, bpp, flags);
+     tmp_screen = SDL_SetVideoMode(width, height, bpp, flags);
      if (!real_screen) {
-       fprintf(stderr, "Could not open SDL display (%dx%dx%d): %s\n", width, 
-               height, bpp, SDL_GetError());
-         exit(1);
+         if (!tmp_screen) {
+             fprintf(stderr, "Could not open SDL display (%dx%dx%d): %s\n",
+                     width, height, bpp, SDL_GetError());
+             exit(1);
+         }
+     } else {
+         /*
+          * Revert to the previous video mode if the change of resizing or
+          * resolution failed.
+          */
+         if (!tmp_screen) {
+             fprintf(stderr, "Failed to set SDL display (%dx%dx%d): %s\n",
+                     width, height, bpp, SDL_GetError());
+             return;
+         }
      }
+     real_screen = tmp_screen;
  }
  
  static void sdl_switch(DisplayChangeListener *dcl,
@@@ -165,7 -180,7 +180,7 @@@ static uint8_t sdl_keyevent_to_keycode(
  
  #else
  
 -#if defined(SDL_VIDEO_DRIVER_X11)
 +#if (defined(SDL_VIDEO_DRIVER_X11) && !defined(__APPLE__))
  #include <X11/XKBlib.h>
  
  static int check_for_evdev(void)
@@@ -328,7 -343,7 +343,7 @@@ static void sdl_update_caption(void
          else
              status = " - Press Ctrl-Alt to exit mouse grab";
      }
 -
 +    
      if (qemu_name) {
          snprintf(win_title, sizeof(win_title), "QEMU (%s)%s", qemu_name, status);
          snprintf(icon_title, sizeof(icon_title), "QEMU (%s)", qemu_name);
diff --combined util/oslib-posix.c
@@@ -59,10 -59,6 +59,10 @@@ extern int daemon(int, int)
  #include <sys/syscall.h>
  #endif
  
 +#ifdef CONFIG_MARU
 +#include "../../tizen/src/maru_common.h"
 +#endif
 +
  int qemu_get_thread_id(void)
  {
  #if defined(__linux__)
@@@ -79,28 -75,8 +79,28 @@@ int qemu_daemon(int nochdir, int noclos
  
  void *qemu_oom_check(void *ptr)
  {
 +#ifdef CONFIG_MARU
 +    const char _msg[] = "Failed to allocate memory in qemu.";
 +    char cmd[JAVA_MAX_COMMAND_LENGTH] = { 0, };
 +    int len;
 +#endif
 +
      if (ptr == NULL) {
          fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno));
 +#ifdef CONFIG_MARU
 +        len = strlen(JAVA_EXEFILE_PATH) + strlen(JAVA_EXEOPTION) +
 +            strlen(JAR_SKINFILE) + strlen(JAVA_SIMPLEMODE_OPTION) +
 +            strlen(_msg) + 7;
 +        if (len > JAVA_MAX_COMMAND_LENGTH) {
 +            len = JAVA_MAX_COMMAND_LENGTH;
 +        }
 +
 +        snprintf(cmd, len, "%s %s %s %s=\"%s\"",
 +            JAVA_EXEFILE_PATH, JAVA_EXEOPTION, JAR_SKINFILE, JAVA_SIMPLEMODE_OPTION, _msg);
 +        if (system(cmd) == -1) {
 +            fprintf(stderr, "failed to execute this command: %s\n", cmd);
 +        }
 +#endif
          abort();
      }
      return ptr;
@@@ -136,9 -112,7 +136,7 @@@ void *qemu_anon_ram_alloc(size_t size
      size_t offset = QEMU_ALIGN_UP((uintptr_t)ptr, align) - (uintptr_t)ptr;
  
      if (ptr == MAP_FAILED) {
-         fprintf(stderr, "Failed to allocate %zu B: %s\n",
-                 size, strerror(errno));
-         abort();
+         return NULL;
      }
  
      ptr += offset;
@@@ -183,6 -157,18 +181,18 @@@ void qemu_set_nonblock(int fd
      fcntl(fd, F_SETFL, f | O_NONBLOCK);
  }
  
+ int socket_set_fast_reuse(int fd)
+ {
+     int val = 1, ret;
+     ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+                      (const char *)&val, sizeof(val));
+     assert(ret == 0);
+     return ret;
+ }
  void qemu_set_cloexec(int fd)
  {
      int f;
diff --combined util/oslib-win32.c
  #include "qemu/main-loop.h"
  #include "trace.h"
  #include "qemu/sockets.h"
 -
  /* this must come after including "trace.h" */
  #include <shlobj.h>
  
 +#ifdef CONFIG_MARU
 +typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
 +LPFN_ISWOW64PROCESS fnIsWow64Process;
 +
 +int is_wow64(void)
 +{
 +    int result = 0;
 +
 +    /* IsWow64Process is not available on all supported versions of Windows.
 +       Use GetModuleHandle to get a handle to the DLL that contains the function
 +       and GetProcAddress to get a pointer to the function if available. */
 +
 +    fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
 +        GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
 +
 +    if (NULL != fnIsWow64Process) {
 +        if (!fnIsWow64Process(GetCurrentProcess(),&result)) {
 +            // handle error
 +            fprintf(stderr, "Cannot find 'IsWow64Process'\n");
 +        }
 +    }
 +    return result;
 +}
 +
 +bool get_java_path(char** java_path)
 +{
 +    HKEY hKeyNew;
 +    HKEY hKey;
 +    //char strJavaRuntimePath[JAVA_MAX_COMMAND_LENGTH] = {0};
 +    char strChoosenName[JAVA_MAX_COMMAND_LENGTH] = {0};
 +    char strSubKeyName[JAVA_MAX_COMMAND_LENGTH] = {0};
 +    char strJavaHome[JAVA_MAX_COMMAND_LENGTH] = {0};
 +    int index;
 +    DWORD dwSubKeyNameMax = JAVA_MAX_COMMAND_LENGTH;
 +    DWORD dwBufLen = JAVA_MAX_COMMAND_LENGTH;
 +
 +    RegOpenKeyEx(HKEY_LOCAL_MACHINE,
 +                "SOFTWARE\\JavaSoft\\Java Runtime Environment",
 +                0,
 +                KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | MY_KEY_WOW64_64KEY,
 +                &hKey);
 +    RegEnumKeyEx(hKey, 0, (LPSTR)strSubKeyName, &dwSubKeyNameMax,
 +                NULL, NULL, NULL, NULL);
 +    strcpy(strChoosenName, strSubKeyName);
 +
 +    index = 1;
 +    while (ERROR_SUCCESS ==
 +            RegEnumKeyEx(hKey, index, (LPSTR)strSubKeyName, &dwSubKeyNameMax,
 +            NULL, NULL, NULL, NULL)) {
 +        if (strcmp(strChoosenName, strSubKeyName) < 0) {
 +            strcpy(strChoosenName, strSubKeyName);
 +        }
 +        index++;
 +    }
 +
 +    RegOpenKeyEx(hKey, strChoosenName, 0,
 +                KEY_QUERY_VALUE | MY_KEY_WOW64_64KEY, &hKeyNew);
 +    RegQueryValueEx(hKeyNew, "JavaHome", NULL,
 +                    NULL, (LPBYTE)strJavaHome, &dwBufLen);
 +    RegCloseKey(hKey);
 +    if (strJavaHome[0] != '\0') {
 +        sprintf(*java_path, "\"%s\\bin\\java\"", strJavaHome);
 +        //strcpy(*java_path, strJavaHome);
 +        //strcat(*java_path, "\\bin\\java");
 +    } else {
 +        return false;
 +    }
 +
 +    return true;
 +}
 +#endif
 +
  void *qemu_oom_check(void *ptr)
  {
 +#ifdef CONFIG_MARU
 +    const char _msg[] = "Failed to allocate memory in qemu.";
 +    char cmd[JAVA_MAX_COMMAND_LENGTH] = { 0, };
 +    char *JAVA_EXEFILE_PATH = NULL;
 +    int len, ret;
 +#endif
 +
      if (ptr == NULL) {
          fprintf(stderr, "Failed to allocate memory: %lu\n", GetLastError());
 +#ifdef CONFIG_MARU
 +        JAVA_EXEFILE_PATH = malloc(JAVA_MAX_COMMAND_LENGTH);
 +        if (!JAVA_EXEFILE_PATH) {
 +            // TODO: print error message.
 +            return ptr;
 +        }
 +
 +        memset(JAVA_EXEFILE_PATH, 0, JAVA_MAX_COMMAND_LENGTH);
 +        if (is_wow64()) {
 +            if (!get_java_path(&JAVA_EXEFILE_PATH)) {
 +                strcpy(JAVA_EXEFILE_PATH, "java");
 +            }
 +        } else {
 +            strcpy(JAVA_EXEFILE_PATH, "java");
 +        }
 +        len = strlen(JAVA_EXEFILE_PATH) + strlen(JAVA_EXEOPTION) +
 +                  strlen(JAR_SKINFILE) + strlen(JAVA_SIMPLEMODE_OPTION) +
 +                  strlen(_msg) + 7;
 +        if (len > JAVA_MAX_COMMAND_LENGTH) {
 +            len = JAVA_MAX_COMMAND_LENGTH;
 +        }
 +
 +        snprintf(cmd, len, "%s %s %s %s=\"%s\"",
 +            JAVA_EXEFILE_PATH, JAVA_EXEOPTION, JAR_SKINFILE,
 +            JAVA_SIMPLEMODE_OPTION, _msg);
 +        ret = WinExec(cmd, SW_SHOW);
 +        if (ret < 32) {
 +            // TODO: error handling...
 +        }
 +
 +        /* for 64bit windows */
 +        free(JAVA_EXEFILE_PATH);
 +        JAVA_EXEFILE_PATH=0;
 +#endif
          abort();
      }
      return ptr;
@@@ -177,10 -65,7 +177,7 @@@ void *qemu_anon_ram_alloc(size_t size
      /* FIXME: this is not exactly optimal solution since VirtualAlloc
         has 64Kb granularity, but at least it guarantees us that the
         memory is page aligned. */
-     if (!size) {
-         abort();
-     }
-     ptr = qemu_oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE));
+     ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
      trace_qemu_anon_ram_alloc(size, ptr);
      return ptr;
  }
@@@ -239,6 -124,16 +236,16 @@@ void qemu_set_nonblock(int fd
      qemu_fd_register(fd);
  }
  
+ int socket_set_fast_reuse(int fd)
+ {
+     /* Enabling the reuse of an endpoint that was used by a socket still in
+      * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows
+      * fast reuse is the default and SO_REUSEADDR does strange things. So we
+      * don't have to do anything here. More info can be found at:
+      * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */
+     return 0;
+ }
  int inet_aton(const char *cp, struct in_addr *ia)
  {
      uint32_t addr = inet_addr(cp);
diff --combined util/qemu-sockets.c
@@@ -155,7 -155,7 +155,7 @@@ int inet_listen_opts(QemuOpts *opts, in
              continue;
          }
  
-         qemu_setsockopt(slisten, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+         socket_set_fast_reuse(slisten);
  #ifdef IPV6_V6ONLY
          if (e->ai_family == PF_INET6) {
              /* listen on both ipv4 and ipv6 */
@@@ -274,7 -274,7 +274,7 @@@ static int inet_connect_addr(struct add
          error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED);
          return -1;
      }
-     qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+     socket_set_fast_reuse(sock);
      if (connect_state != NULL) {
          qemu_set_nonblock(sock);
      }
@@@ -326,14 -326,6 +326,14 @@@ static struct addrinfo *inet_parse_conn
          ai.ai_family = PF_INET6;
      }
  
 +#ifdef CONFIG_MARU
 +    // for lookup loopback interface...
 +    if (addr[0] == '\0') {
 +        ai.ai_flags = 0;
 +        addr = NULL;
 +    }
 +#endif
 +
      /* lookup */
      rc = getaddrinfo(addr, port, &ai, &res);
      if (rc != 0) {
@@@ -463,7 -455,7 +463,7 @@@ int inet_dgram_opts(QemuOpts *opts, Err
          error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED);
          goto err;
      }
-     qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+     socket_set_fast_reuse(sock);
  
      /* bind socket */
      if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) {
diff --combined vl.c
--- 1/vl.c
--- 2/vl.c
+++ b/vl.c
@@@ -96,7 -96,6 +96,7 @@@
  #ifdef CONFIG_SDL
  #if defined(__APPLE__) || defined(main)
  #include <SDL.h>
 +#ifndef CONFIG_MARU
  int qemu_main(int argc, char **argv, char **envp);
  int main(int argc, char **argv)
  {
  #undef main
  #define main qemu_main
  #endif
 +#endif
  #endif /* CONFIG_SDL */
  
  #ifdef CONFIG_COCOA
  #define main qemu_main
  #endif /* CONFIG_COCOA */
  
 +#ifdef CONFIG_MARU
 +#ifdef main
 +#undef main
 +#endif
 +int qemu_main(int argc, char **argv, char **envp);
 +#define main qemu_main
 +#endif
 +
  #include <glib.h>
  
  #include "hw/hw.h"
  #include "audio/audio.h"
  #include "migration/migration.h"
  #include "sysemu/kvm.h"
 +#include "sysemu/hax.h"
  #include "qapi/qmp/qjson.h"
  #include "qemu/option.h"
  #include "qemu/config-file.h"
  #include "ui/qemu-spice.h"
  #include "qapi/string-input-visitor.h"
  
 +#ifdef CONFIG_MARU
 +#include "tizen/src/maru_common.h"
 +#include "tizen/src/emulator.h"
 +#include "tizen/src/maru_err_table.h"
 +#include "tizen/src/emul_state.h"
 +#include "tizen/src/maru_display.h"
 +#include "tizen/src/skin/maruskin_operation.h"
 +#include "tizen/src/ecs/ecs.h"
 +#endif
 +
  //#define DEBUG_NET
  //#define DEBUG_SLIRP
  
  #define MAX_VIRTIO_CONSOLES 1
  #define MAX_SCLP_CONSOLES 1
  
 +#ifdef CONFIG_MARU
 +int skin_disabled = 0;
 +//virtio-gl
 +extern int enable_gl;
 +extern int enable_yagl;
 +extern int enable_spice;
 +const char *yagl_backend = NULL;
 +int enable_vigs = 0;
 +char *vigs_backend = NULL;
 +#endif
 +
  static const char *data_dir[16];
  static int data_dir_idx;
  const char *bios_name = NULL;
@@@ -228,7 -196,7 +228,7 @@@ NICInfo nd_table[MAX_NICS]
  int autostart;
  static int rtc_utc = 1;
  static int rtc_date_offset = -1; /* -1 means no change */
- QEMUClock *rtc_clock;
+ QEMUClockType rtc_clock;
  int vga_interface_type = VGA_NONE;
  static int full_screen = 0;
  static int no_frame = 0;
@@@ -286,6 -254,7 +286,7 @@@ uint64_t node_mem[MAX_NODES]
  unsigned long *node_cpumask[MAX_NODES];
  
  uint8_t qemu_uuid[16];
+ bool qemu_uuid_set;
  
  static QEMUBootSetHandler *boot_set_handler;
  static void *boot_set_opaque;
@@@ -298,9 -267,6 +299,9 @@@ static NotifierList machine_init_done_n
  
  static bool tcg_allowed = true;
  bool xen_allowed;
 +// FIXME: ??
 +int hax_allowed = 0;
 +//
  uint32_t xen_domid;
  enum xen_mode xen_mode = XEN_EMULATE;
  static int tcg_tb_size;
@@@ -672,9 -638,8 +673,8 @@@ static const RunStateTransition runstat
      { RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
      { RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE },
  
-     { RUN_STATE_GUEST_PANICKED, RUN_STATE_PAUSED },
+     { RUN_STATE_GUEST_PANICKED, RUN_STATE_RUNNING },
      { RUN_STATE_GUEST_PANICKED, RUN_STATE_FINISH_MIGRATE },
-     { RUN_STATE_GUEST_PANICKED, RUN_STATE_DEBUG },
  
      { RUN_STATE_MAX, RUN_STATE_MAX },
  };
@@@ -720,8 -685,7 +720,7 @@@ int runstate_is_running(void
  bool runstate_needs_reset(void)
  {
      return runstate_check(RUN_STATE_INTERNAL_ERROR) ||
-         runstate_check(RUN_STATE_SHUTDOWN) ||
-         runstate_check(RUN_STATE_GUEST_PANICKED);
+         runstate_check(RUN_STATE_SHUTDOWN);
  }
  
  StatusInfo *qmp_query_status(Error **errp)
@@@ -840,11 -804,11 +839,11 @@@ static void configure_rtc(QemuOpts *opt
      value = qemu_opt_get(opts, "clock");
      if (value) {
          if (!strcmp(value, "host")) {
-             rtc_clock = host_clock;
+             rtc_clock = QEMU_CLOCK_HOST;
          } else if (!strcmp(value, "rt")) {
-             rtc_clock = rt_clock;
+             rtc_clock = QEMU_CLOCK_REALTIME;
          } else if (!strcmp(value, "vm")) {
-             rtc_clock = vm_clock;
+             rtc_clock = QEMU_CLOCK_VIRTUAL;
          } else {
              fprintf(stderr, "qemu: invalid option value '%s'\n", value);
              exit(1);
@@@ -878,45 -842,6 +877,6 @@@ static int nb_hcis
  static int cur_hci;
  static struct HCIInfo *hci_table[MAX_NICS];
  
- static struct bt_vlan_s {
-     struct bt_scatternet_s net;
-     int id;
-     struct bt_vlan_s *next;
- } *first_bt_vlan;
- /* find or alloc a new bluetooth "VLAN" */
- static struct bt_scatternet_s *qemu_find_bt_vlan(int id)
- {
-     struct bt_vlan_s **pvlan, *vlan;
-     for (vlan = first_bt_vlan; vlan != NULL; vlan = vlan->next) {
-         if (vlan->id == id)
-             return &vlan->net;
-     }
-     vlan = g_malloc0(sizeof(struct bt_vlan_s));
-     vlan->id = id;
-     pvlan = &first_bt_vlan;
-     while (*pvlan != NULL)
-         pvlan = &(*pvlan)->next;
-     *pvlan = vlan;
-     return &vlan->net;
- }
- static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len)
- {
- }
- static int null_hci_addr_set(struct HCIInfo *hci, const uint8_t *bd_addr)
- {
-     return -ENOTSUP;
- }
- static struct HCIInfo null_hci = {
-     .cmd_send = null_hci_send,
-     .sco_send = null_hci_send,
-     .acl_send = null_hci_send,
-     .bdaddr_set = null_hci_addr_set,
- };
  struct HCIInfo *qemu_next_hci(void)
  {
      if (cur_hci == nb_hcis)
      return hci_table[cur_hci++];
  }
  
- static struct HCIInfo *hci_init(const char *str)
- {
-     char *endp;
-     struct bt_scatternet_s *vlan = 0;
-     if (!strcmp(str, "null"))
-         /* null */
-         return &null_hci;
-     else if (!strncmp(str, "host", 4) && (str[4] == '\0' || str[4] == ':'))
-         /* host[:hciN] */
-         return bt_host_hci(str[4] ? str + 5 : "hci0");
-     else if (!strncmp(str, "hci", 3)) {
-         /* hci[,vlan=n] */
-         if (str[3]) {
-             if (!strncmp(str + 3, ",vlan=", 6)) {
-                 vlan = qemu_find_bt_vlan(strtol(str + 9, &endp, 0));
-                 if (*endp)
-                     vlan = 0;
-             }
-         } else
-             vlan = qemu_find_bt_vlan(0);
-         if (vlan)
-            return bt_new_hci(vlan);
-     }
-     fprintf(stderr, "qemu: Unknown bluetooth HCI `%s'.\n", str);
-     return 0;
- }
  static int bt_hci_parse(const char *str)
  {
      struct HCIInfo *hci;
@@@ -1561,8 -1456,10 +1491,10 @@@ static void configure_msg(QemuOpts *opt
  
  static int usb_device_add(const char *devname)
  {
-     const char *p;
      USBDevice *dev = NULL;
+ #ifndef CONFIG_LINUX
+     const char *p;
+ #endif
  
      if (!usb_enabled(false)) {
          return -1;
      /* only the linux version is qdev-ified, usb-bsd still needs this */
      if (strstart(devname, "host:", &p)) {
          dev = usb_host_device_open(usb_bus_find(-1), p);
-     } else
- #endif
-     if (!strcmp(devname, "bt") || strstart(devname, "bt:", &p)) {
-         dev = usb_bt_init(usb_bus_find(-1),
-                           devname[2] ? hci_init(p)
-                                      : bt_new_hci(qemu_find_bt_vlan(0)));
-     } else {
-         return -1;
      }
+ #endif
      if (!dev)
          return -1;
  
@@@ -1996,7 -1886,6 +1921,7 @@@ void qemu_register_suspend_notifier(Not
  
  void qemu_system_wakeup_request(WakeupReason reason)
  {
 +
      if (!runstate_check(RUN_STATE_SUSPENDED)) {
          return;
      }
@@@ -2027,12 -1916,7 +1952,12 @@@ void qemu_system_killed(int signal, pid
      shutdown_signal = signal;
      shutdown_pid = pid;
      no_shutdown = 0;
 +
 +#ifdef CONFIG_MARU
 +    shutdown_qemu_gracefully();
 +#else
      qemu_system_shutdown_request();
 +#endif
  }
  
  void qemu_system_shutdown_request(void)
@@@ -2100,13 -1984,7 +2025,13 @@@ static bool main_loop_should_exit(void
      if (qemu_wakeup_requested()) {
          pause_all_vcpus();
          cpu_synchronize_all_states();
 +#ifndef CONFIG_MARU
 +        // A "system reset" causes "virtio_queue" malfunction.
 +        // It might be a bug of virtio bus or virtio devices.
 +        // We don't want suspend(deep sleep), so It's OK now.
 +        // However, we should fix it later.
          qemu_system_reset(VMRESET_SILENT);
 +#endif
          notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
          wakeup_reason = QEMU_WAKEUP_REASON_NONE;
          resume_all_vcpus();
@@@ -2128,11 -2006,8 +2053,11 @@@ static void main_loop(void
  #ifdef CONFIG_PROFILER
      int64_t ti;
  #endif
 +
 +    hax_sync_vcpus();
 +
      do {
 -        nonblocking = !kvm_enabled() && !xen_enabled() && last_io > 0;
 +        nonblocking = !kvm_enabled() && !xen_enabled() && !hax_enabled() && last_io > 0;
  #ifdef CONFIG_PROFILER
          ti = profile_getclock();
  #endif
@@@ -2205,13 -2080,6 +2130,13 @@@ static bool qxl_vga_available(void
      return object_class_by_name("qxl-vga");
  }
  
 +#ifdef CONFIG_MARU
 +static bool maru_vga_available(void)
 +{
 +    return object_class_by_name("MARU_VGA");
 +}
 +#endif
 +
  static void select_vgahw (const char *p)
  {
      const char *opts;
              fprintf(stderr, "Error: QXL VGA not available\n");
              exit(0);
          }
 +#ifdef CONFIG_MARU
 +    } else if (strstart(p, "maru", &opts)) {
 +        if (maru_vga_available()) {
 +            vga_interface_type = VGA_MARU;
 +        } else {
 +            fprintf(stderr, "Error: MARU VGA not available\n");
 +            exit(0);
 +        }
 +#endif
      } else if (!strstart(p, "none", &opts)) {
      invalid_vga:
          fprintf(stderr, "Unknown vga type: %s\n", p);
@@@ -2445,12 -2304,6 +2370,12 @@@ static int device_init_func(QemuOpts *o
  {
      DeviceState *dev;
  
 +#ifdef CONFIG_MARU
 +    if(maru_device_check(opts) == -1) {
 +        return 0;
 +    }
 +#endif
 +      
      dev = qdev_device_add(opts);
      if (!dev)
          return -1;
@@@ -2464,7 -2317,7 +2389,7 @@@ static int chardev_init_func(QemuOpts *
  
      qemu_chr_new_from_opts(opts, NULL, &local_err);
      if (error_is_set(&local_err)) {
-         fprintf(stderr, "%s\n", error_get_pretty(local_err));
+         error_report("%s", error_get_pretty(local_err));
          error_free(local_err);
          return -1;
      }
@@@ -2755,10 -2608,8 +2680,10 @@@ static QEMUMachine *machine_parse(cons
  
  static int tcg_init(void)
  {
 +    int ret = 0;
      tcg_exec_init(tcg_tb_size * 1024 * 1024);
 -    return 0;
 +    ret = hax_accel_init();
 +    return ret;
  }
  
  static struct {
@@@ -2823,9 -2674,6 +2748,9 @@@ static int configure_accelerator(void
          if (!init_failed) {
              fprintf(stderr, "No accelerator found!\n");
          }
 +#ifdef CONFIG_MARU
 +        maru_register_exit_msg(MARU_EXIT_UNKNOWN, "No accelerator found.");
 +#endif
          exit(1);
      }
  
@@@ -2878,9 -2726,6 +2803,9 @@@ static const QEMUOption *lookup_opt(in
      for(;;) {
          if (!popt->name) {
              error_report("invalid option");
 +#ifdef CONFIG_MARU
 +            maru_register_exit_msg(MARU_EXIT_UNKNOWN, "invalid option.");
 +#endif
              exit(1);
          }
          if (!strcmp(popt->name, r + 1))
      if (popt->flags & HAS_ARG) {
          if (optind >= argc) {
              error_report("requires an argument");
 +#ifdef CONFIG_MARU
 +            maru_register_exit_msg(MARU_EXIT_UNKNOWN, "requires an argument.");
 +#endif
              exit(1);
          }
          optarg = argv[optind++];
@@@ -2974,12 -2816,6 +2899,12 @@@ static int object_create(QemuOpts *opts
      return 0;
  }
  
 +#ifdef CONFIG_MARU
 +int use_qemu_display = 0; //0:use tizen qemu sdl, 1:use original qemu sdl
 +// W/A for preserve larger continuous heap for RAM.
 +void *preallocated_ptr = 0;
 +#endif
 +
  int main(int argc, char **argv, char **envp)
  {
      int i;
      const char *icount_option = NULL;
      const char *initrd_filename;
      const char *kernel_filename, *kernel_cmdline;
-     const char *boot_order = NULL;
+     const char *boot_order;
      DisplayState *ds;
      int cyls, heads, secs, translation;
      QemuOpts *hda_opts = NULL, *opts, *machine_opts;
      module_call_init(MODULE_INIT_QOM);
  
      qemu_add_opts(&qemu_drive_opts);
+     qemu_add_drive_opts(&qemu_legacy_drive_opts);
+     qemu_add_drive_opts(&qemu_common_drive_opts);
+     qemu_add_drive_opts(&qemu_drive_opts);
      qemu_add_opts(&qemu_chardev_opts);
      qemu_add_opts(&qemu_device_opts);
      qemu_add_opts(&qemu_netdev_opts);
      runstate_init();
  
      init_clocks();
-     rtc_clock = host_clock;
+     rtc_clock = QEMU_CLOCK_HOST;
  
      qemu_cache_utils_init(envp);
  
                  do_acpitable_option(opts);
                  break;
              case QEMU_OPTION_smbios:
-                 do_smbios_option(optarg);
+                 opts = qemu_opts_parse(qemu_find_opts("smbios"), optarg, 0);
+                 do_smbios_option(opts);
                  break;
              case QEMU_OPTION_enable_kvm:
                  olist = qemu_find_opts("machine");
                  qemu_opts_parse(olist, "accel=kvm", 0);
                  break;
 +           case QEMU_OPTION_enable_gl:
 +#if defined(CONFIG_MARU) && defined(CONFIG_GL_BACKEND)
 +                enable_gl = 1;
 +#else
 +                fprintf(stderr, "Virtio GL support is disabled, ignoring -enable-gl\n");
 +#endif
 +                break;
 +           case QEMU_OPTION_enable_yagl:
 +#if defined(CONFIG_YAGL)
 +                enable_yagl = 1;
 +#else
 +                fprintf(stderr, "YaGL openGLES passthrough support is disabled,"
 +                    " ignoring -enable-yagl\n");
 +#endif
 +                break;
 +           case QEMU_OPTION_yagl_backend:
 +#if defined(CONFIG_YAGL)
 +                yagl_backend = optarg;
 +#else
 +                fprintf(stderr, "YaGL openGLES passthrough support is disabled,"
 +                    " ignoring -yagl-backend\n");
 +#endif
 +                break;
 +           case QEMU_OPTION_enable_vigs:
 +#if defined(CONFIG_VIGS)
 +                enable_vigs = 1;
 +#else
 +                fprintf(stderr, "VIGS support is disabled,"
 +                    " ignoring -enable-vigs\n");
 +#endif
 +                break;
 +           case QEMU_OPTION_vigs_backend:
 +#if defined(CONFIG_VIGS)
 +                vigs_backend = g_strdup(optarg);
 +#else
 +                fprintf(stderr, "VIGS support is disabled,"
 +                    " ignoring -vigs-backend\n");
 +#endif
 +                break;
              case QEMU_OPTION_machine:
                  olist = qemu_find_opts("machine");
                  opts = qemu_opts_parse(olist, optarg, 1);
                              " Wrong format.\n");
                      exit(1);
                  }
+                 qemu_uuid_set = true;
                  break;
            case QEMU_OPTION_option_rom:
                if (nb_option_roms >= MAX_OPTION_ROMS) {
                  old_param = 1;
                  break;
              case QEMU_OPTION_clock:
-                 configure_alarms(optarg);
+                 /* Clock options no longer exist.  Keep this option for
+                  * backward compatibility.
+                  */
                  break;
              case QEMU_OPTION_startdate:
                  configure_rtc_date_offset(optarg, 1);
                      fprintf(stderr, "spice is not supported by this qemu build.\n");
                      exit(1);
                  }
 +#ifdef CONFIG_MARU
 +                enable_spice = 1;
 +#endif
                  opts = qemu_opts_parse(olist, optarg, 0);
                  if (!opts) {
                      exit(1);
                      exit(1);
                  }
                  break;
 +            case QEMU_OPTION_enable_hax:
 +#ifdef CONFIG_HAX_BACKEND
 +                olist = qemu_find_opts("machine");
 +                //qemu_opts_reset(olist);
 +                hax_disable(0);
 +                //qemu_opts_parse(olist, "accel=hax", 0);
 +#else
 +                fprintf(stderr,
 +                        "HAX support is disabled, ignoring -enable-hax\n");
 +#endif
 +                break;
 +#ifdef CONFIG_MARU
 +            case QEMU_OPTION_max_touch_point:
 +                {
 +                    int cnt = atoi(optarg);
 +                    fprintf(stderr, "maxTouchPoint:%d\n", cnt);
 +                    set_emul_max_touch_point(cnt);
 +                    break;
 +                }
 +            case QEMU_OPTION_disable_skin:
 +                skin_disabled = 1;
 +                break;
 +#endif
              case QEMU_OPTION_add_fd:
  #ifndef _WIN32
                  opts = qemu_opts_parse(qemu_find_opts("add-fd"), optarg, 0);
                  exit(1);
  #endif
                  break;
 +#ifdef CONFIG_MARU
 +            case QEMU_OPTION_enable_suspend:
 +                ecs_set_suspend_state(SUSPEND_UNLOCK);
 +                break;
 +#endif
              case QEMU_OPTION_object:
                  opts = qemu_opts_parse(qemu_find_opts("object"), optarg, 1);
                  if (!opts) {
          exit(0);
      }
  
 +#if defined(CONFIG_MARU)
 +    if (enable_gl && enable_yagl) {
 +        fprintf (stderr, "Error: only one openGL passthrough device can be used at one time!\n");
 +        exit(1);
 +    }
 +
 +    if (enable_vigs) {
 +        if (!vigs_backend) {
 +            vigs_backend = g_strdup("gl");
 +        }
 +
 +        if (strcmp(vigs_backend, "gl") != 0 && strcmp(vigs_backend, "sw") != 0) {
 +            fprintf (stderr, "Error: Bad VIGS backend - %s!\n", vigs_backend);
 +            exit(1);
 +        }
 +    }
 +
 +    if (enable_yagl) {
 +        if (!yagl_backend) {
 +            yagl_backend = "offscreen";
 +        }
 +
 +        if (strcmp(yagl_backend, "offscreen") != 0) {
 +            if (strcmp(yagl_backend, "vigs") == 0) {
 +                if (!enable_vigs) {
 +                    fprintf (stderr, "Error: Bad YaGL backend - %s, VIGS not enabled!\n", yagl_backend);
 +                    exit(1);
 +                }
 +                if (strcmp(vigs_backend, "gl") != 0) {
 +                    fprintf (stderr, "Error: Bad YaGL backend - %s, VIGS is not configured with gl backend!\n", yagl_backend);
 +                    exit(1);
 +                }
 +            } else {
 +                fprintf (stderr, "Error: Bad YaGL backend - %s!\n", yagl_backend);
 +                exit(1);
 +            }
 +        }
 +    }
 +#endif
      /* Open the logfile at this point, if necessary. We can't open the logfile
       * when encountering either of the logging options (-d or -D) because the
       * other one may be encountered later on the command line, changing the
      }
  
      if (display_type == DT_DEFAULT && !display_remote) {
 -#if defined(CONFIG_GTK)
 +#if defined(CONFIG_MARU)
 +        display_type = DT_MARU;
 +#elif defined(CONFIG_GTK)
          display_type = DT_GTK;
  #elif defined(CONFIG_SDL) || defined(CONFIG_COCOA)
          display_type = DT_SDL;
      }
  #endif
  
 +#ifndef CONFIG_MARU
      socket_init();
 +#endif
  
      if (qemu_opts_foreach(qemu_find_opts("chardev"), chardev_init_func, NULL, 1) != 0)
          exit(1);
      if (ram_size == 0) {
          ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
      }
 +#ifdef CONFIG_MARU
 +    // W/A for preserve larger continuous heap for RAM.
 +    preallocated_ptr = g_malloc(ram_size);
 +#endif
 +
 +    hax_pre_init(ram_size);
  
      if (qemu_opts_foreach(qemu_find_opts("device"), device_help_func, NULL, 0)
          != 0) {
      initrd_filename = qemu_opt_get(machine_opts, "initrd");
      kernel_cmdline = qemu_opt_get(machine_opts, "append");
  
-     if (!boot_order) {
-         boot_order = machine->boot_order;
-     }
+     boot_order = machine->default_boot_order;
      opts = qemu_opts_find(qemu_find_opts("boot-opts"), NULL);
      if (opts) {
          char *normal_boot_order;
      qemu_spice_init();
  #endif
  
 -    if (icount_option && (kvm_enabled() || xen_enabled())) {
 +    if (icount_option && (kvm_enabled() || xen_enabled() || hax_enabled())) {
          fprintf(stderr, "-icount is not allowed with kvm or xen\n");
          exit(1);
      }
  
      qdev_machine_init();
  
 +#ifdef CONFIG_MARU
 +    // Returned variable points different address from input variable.
 +    kernel_cmdline = prepare_maru_devices(kernel_cmdline);
 +#endif
      QEMUMachineInitArgs args = { .ram_size = ram_size,
-                                  .boot_device = boot_order,
+                                  .boot_order = boot_order,
                                   .kernel_filename = kernel_filename,
                                   .kernel_cmdline = kernel_cmdline,
                                   .initrd_filename = initrd_filename,
                                   .cpu_model = cpu_model };
      machine->init(&args);
  
 +    // TODO: Check about it...
      audio_init();
  
      cpu_synchronize_all_post_init();
  
      current_machine = machine;
  
 +    if (hax_enabled()) {
 +        hax_sync_vcpus();
 +    }
 +
      /* init USB devices */
      if (usb_enabled(false)) {
          if (foreach_device_config(DEV_USB, usb_parse) < 0)
      /* init local displays */
      switch (display_type) {
      case DT_NOGRAPHIC:
+         (void)ds;     /* avoid warning if no display is configured */
          break;
  #if defined(CONFIG_CURSES)
      case DT_CURSES:
          curses_display_init(ds, full_screen);
          break;
  #endif
 +#if defined(CONFIG_MARU)
 +    case DT_MARU:
 +        maru_display_init(ds);
 +
 +        if (skin_disabled == 1) {
 +            /* do not start skin client process */
 +            set_emul_skin_enable(0);
 +        } else {
 +            set_emul_skin_enable(1);
 +        }
 +        break;
 +#endif
  #if defined(CONFIG_SDL)
      case DT_SDL:
          sdl_display_init(ds, full_screen, no_frame);
          vnc_display_init(ds);
          vnc_display_open(ds, vnc_display, &local_err);
          if (local_err != NULL) {
-             fprintf(stderr, "Failed to start VNC server on `%s': %s\n",
-                     vnc_display, error_get_pretty(local_err));
+             error_report("Failed to start VNC server on `%s': %s",
+                          vnc_display, error_get_pretty(local_err));
              error_free(local_err);
              exit(1);
          }
      }
  #endif
  #ifdef CONFIG_SPICE
-     if (using_spice && !spice_displays) {
-         qemu_spice_display_init(ds);
+     if (using_spice) {
+         qemu_spice_display_init();
      }
  #endif
  
      qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
      qemu_run_machine_init_done_notifiers();
  
+     /* Done notifiers can load ROMs */
+     rom_load_done();
      qemu_system_reset(VMRESET_SILENT);
      if (loadvm) {
          if (load_vmstate(loadvm) < 0) {
          Error *local_err = NULL;
          qemu_start_incoming_migration(incoming, &local_err);
          if (local_err) {
-             fprintf(stderr, "-incoming %s: %s\n", incoming, error_get_pretty(local_err));
+             error_report("-incoming %s: %s", incoming,
+                          error_get_pretty(local_err));
              error_free(local_err);
              exit(1);
          }
          vm_start();
      }
  
 +#ifdef CONFIG_MARU
 +    prepare_maru();
 +#endif
 +
      os_setup_post();
  
      main_loop();
diff --combined xen-all.c
+++ b/xen-all.c
@@@ -162,19 -162,19 +162,19 @@@ static void xen_ram_init(ram_addr_t ram
      ram_addr_t block_len;
  
      block_len = ram_size;
 -    if (ram_size >= HVM_BELOW_4G_RAM_END) {
 +    if (ram_size >= QEMU_BELOW_4G_RAM_END) {
          /* Xen does not allocate the memory continuously, and keep a hole at
 -         * HVM_BELOW_4G_MMIO_START of HVM_BELOW_4G_MMIO_LENGTH
 +         * QEMU_BELOW_4G_RAM_END of QEMU_BELOW_4G_MMIO_LENGTH
           */
 -        block_len += HVM_BELOW_4G_MMIO_LENGTH;
 +        block_len += QEMU_BELOW_4G_MMIO_LENGTH;
      }
      memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len);
      *ram_memory_p = &ram_memory;
      vmstate_register_ram_global(&ram_memory);
  
 -    if (ram_size >= HVM_BELOW_4G_RAM_END) {
 -        above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END;
 -        below_4g_mem_size = HVM_BELOW_4G_RAM_END;
 +    if (ram_size >= QEMU_BELOW_4G_RAM_END) {
 +        above_4g_mem_size = ram_size - QEMU_BELOW_4G_RAM_END;
 +        below_4g_mem_size = QEMU_BELOW_4G_RAM_END;
      } else {
          below_4g_mem_size = ram_size;
      }
@@@ -608,19 -608,19 +608,19 @@@ static ioreq_t *cpu_get_ioreq(XenIOStat
  
      port = xc_evtchn_pending(state->xce_handle);
      if (port == state->bufioreq_local_port) {
-         qemu_mod_timer(state->buffered_io_timer,
-                 BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));
+         timer_mod(state->buffered_io_timer,
+                 BUFFER_IO_MAX_DELAY + qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
          return NULL;
      }
  
      if (port != -1) {
-         for (i = 0; i < smp_cpus; i++) {
+         for (i = 0; i < max_cpus; i++) {
              if (state->ioreq_local_port[i] == port) {
                  break;
              }
          }
  
-         if (i == smp_cpus) {
+         if (i == max_cpus) {
              hw_error("Fatal error while trying to get io event!\n");
          }
  
@@@ -830,10 -830,10 +830,10 @@@ static void handle_buffered_io(void *op
      XenIOState *state = opaque;
  
      if (handle_buffered_iopage(state)) {
-         qemu_mod_timer(state->buffered_io_timer,
-                 BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));
+         timer_mod(state->buffered_io_timer,
+                 BUFFER_IO_MAX_DELAY + qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
      } else {
-         qemu_del_timer(state->buffered_io_timer);
+         timer_del(state->buffered_io_timer);
          xc_evtchn_unmask(state->xce_handle, state->bufioreq_local_port);
      }
  }
@@@ -949,7 -949,7 +949,7 @@@ static void xenstore_record_dm_state(st
          exit(1);
      }
  
-     snprintf(path, sizeof (path), "/local/domain/0/device-model/%u/state", xen_domid);
+     snprintf(path, sizeof (path), "device-model/%u/state", xen_domid);
      if (!xs_write(xs, XBT_NULL, path, state, strlen(state))) {
          fprintf(stderr, "error recording dm state\n");
          exit(1);
@@@ -964,7 -964,7 +964,7 @@@ static void xen_main_loop_prepare(XenIO
          evtchn_fd = xc_evtchn_fd(state->xce_handle);
      }
  
-     state->buffered_io_timer = qemu_new_timer_ms(rt_clock, handle_buffered_io,
+     state->buffered_io_timer = timer_new_ms(QEMU_CLOCK_REALTIME, handle_buffered_io,
                                                   state);
  
      if (evtchn_fd != -1) {
@@@ -1115,10 -1115,10 +1115,10 @@@ int xen_hvm_init(MemoryRegion **ram_mem
          hw_error("map buffered IO page returned error %d", errno);
      }
  
-     state->ioreq_local_port = g_malloc0(smp_cpus * sizeof (evtchn_port_t));
+     state->ioreq_local_port = g_malloc0(max_cpus * sizeof (evtchn_port_t));
  
      /* FIXME: how about if we overflow the page here? */
-     for (i = 0; i < smp_cpus; i++) {
+     for (i = 0; i < max_cpus; i++) {
          rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
                                          xen_vcpu_eport(state->shared_page, i));
          if (rc == -1) {