[Spice-commits] 231 commits - Makefile Makefile.objs Makefile.target QMP/qmp-events.txt arm-dis.c audio/alsaaudio.c audio/sdlaudio.c block-migration.c block.c block.h block/blkdebug.c block/bochs.c block/cloop.c block/cow.c block/curl.c block/dmg.c block/nbd.c block/parallels.c block/qcow.c block/qcow2-cluster.c block/qcow2-refcount.c block/qcow2-snapshot.c block/qcow2.c block/qcow2.h block/raw-posix.c block/raw-win32.c block/raw.c block/vdi.c block/vmdk.c block/vpc.c block/vvfat.c block_int.h bswap.h bt-host.c cmd.c configure console.c cpu-all.h cpu-common.h cpus.c cpus.h default-configs/sparc-softmmu.mak exec-all.h exec.c fsdev/qemu-fsdev.c fsdev/qemu-fsdev.h hw/9p.h hw/acpi.c hw/alpha_palcode.c hw/armv7m_nvic.c hw/bt-hci-csr.c hw/bt-hci.c hw/bt-l2cap.c hw/bt-sdp.c hw/cuda.c hw/empty_slot.c hw/empty_slot.h hw/etraxfs_eth.c hw/fdc.c hw/file-op-9p.h hw/i8259.c hw/ide hw/iov.c hw/iov.h hw/lsi53c895a.c hw/omap1.c hw/omap2.c hw/omap_sx1.c hw/palm.c hw/parallel.c hw/pc.c hw/pc.h hw/pci- hotplug.c hw/pci.c hw/petalogix_s3adsp1800_mmu.c hw/pflash_cfi01.c hw/pflash_cfi02.c hw/piix_pci.c hw/ppc405_boards.c hw/ppc405_uc.c hw/qdev-properties.c hw/qdev.c hw/qdev.h hw/r2d.c hw/rc4030.c hw/sd.c hw/smc91c111.c hw/spitz.c hw/stellaris.c hw/sun4m.c hw/tusb6010.c hw/usb-bus.c hw/usb-hub.c hw/usb-net.c hw/usb-ohci.c hw/usb-serial.c hw/usb-uhci.c hw/vga.c hw/virtio-9p-debug.c hw/virtio-9p-debug.h hw/virtio-9p-local.c hw/virtio-9p.c hw/virtio-9p.h hw/virtio-balloon.c hw/virtio-blk.c hw/virtio-console.c hw/virtio-net.c hw/virtio-pci.c hw/virtio-serial-bus.c hw/virtio-serial.h hw/virtio.h hw/wm8750.c hw/xen_disk.c i386-dis.c kvm-all.c kvm-stub.c kvm.h linux-aio.c linux-user/elfload32.c linux-user/linuxload.c linux-user/main.c linux-user/qemu.h linux-user/syscall.c m68k-dis.c microblaze-dis.c monitor.c monitor.h net.c net.h net/tap.c qemu-char.c qemu-config.c qemu-config.h qemu-img-cmds.hx qemu-img.c qemu-img.texi qemu-io.c qemu-monitor.hx qemu-nbd.c qemu-option.c qemu-option s.hx qemu-timer.h qerror.c qerror.h rules.mak savevm.c slirp/cksum.c slirp/socket.c sysemu.h target-alpha/cpu.h target-alpha/helper.c target-alpha/helper.h target-alpha/op_helper.c target-alpha/translate.c target-arm/translate.c target-cris/mmu.c target-cris/translate.c target-i386/helper.c target-i386/kvm.c target-i386/translate.c target-m68k/helper.c target-m68k/translate.c target-microblaze/mmu.c target-ppc/helper.c target-ppc/translate.c target-sparc/cpu.h target-sparc/op_helper.c target-sparc/translate.c tcg/arm tcg/hppa tcg/ppc tcg/tcg.c usb-linux.c vl.c vnc-auth-sasl.c vnc-encoding-hextile.c vnc-encoding-zlib.c vnc.c vnc.h

Gerd Hoffmann kraxel at kemper.freedesktop.org
Fri May 7 13:41:13 PDT 2010


 Makefile                          |    6 
 Makefile.objs                     |   20 
 Makefile.target                   |    9 
 QMP/qmp-events.txt                |   14 
 arm-dis.c                         |    1 
 audio/alsaaudio.c                 |   11 
 audio/sdlaudio.c                  |   11 
 block-migration.c                 |   63 -
 block.c                           |  491 +++++--
 block.h                           |   68 -
 block/blkdebug.c                  |  470 +++++++
 block/bochs.c                     |    2 
 block/cloop.c                     |    2 
 block/cow.c                       |    2 
 block/curl.c                      |   10 
 block/dmg.c                       |    2 
 block/nbd.c                       |    2 
 block/parallels.c                 |    2 
 block/qcow.c                      |   67 -
 block/qcow2-cluster.c             |  102 +
 block/qcow2-refcount.c            |   72 -
 block/qcow2-snapshot.c            |   22 
 block/qcow2.c                     |  579 +++++----
 block/qcow2.h                     |    8 
 block/raw-posix.c                 |  127 --
 block/raw-win32.c                 |   16 
 block/raw.c                       |  144 ++
 block/vdi.c                       |   29 
 block/vmdk.c                      |  140 --
 block/vpc.c                       |   32 
 block/vvfat.c                     |    9 
 block_int.h                       |   15 
 bswap.h                           |    2 
 bt-host.c                         |    4 
 cmd.c                             |    3 
 configure                         |    8 
 console.c                         |    1 
 cpu-all.h                         |   12 
 cpu-common.h                      |    1 
 cpus.c                            |   13 
 cpus.h                            |    2 
 default-configs/sparc-softmmu.mak |    1 
 exec-all.h                        |   16 
 exec.c                            |  113 -
 fsdev/qemu-fsdev.c                |   70 +
 fsdev/qemu-fsdev.h                |   54 
 hw/9p.h                           |   26 
 hw/acpi.c                         |    5 
 hw/alpha_palcode.c                |    2 
 hw/armv7m_nvic.c                  |    8 
 hw/bt-hci-csr.c                   |    4 
 hw/bt-hci.c                       |    7 
 hw/bt-l2cap.c                     |    6 
 hw/bt-sdp.c                       |    4 
 hw/cuda.c                         |    4 
 hw/empty_slot.c                   |   92 +
 hw/empty_slot.h                   |    2 
 hw/etraxfs_eth.c                  |    2 
 hw/fdc.c                          |    3 
 hw/file-op-9p.h                   |   60 
 hw/i8259.c                        |    2 
 hw/ide/cmd646.c                   |   66 -
 hw/ide/internal.h                 |    1 
 hw/ide/piix.c                     |    1 
 hw/iov.c                          |   70 +
 hw/iov.h                          |   19 
 hw/lsi53c895a.c                   |   21 
 hw/omap1.c                        |    1 
 hw/omap2.c                        |    2 
 hw/omap_sx1.c                     |    6 
 hw/palm.c                         |    3 
 hw/parallel.c                     |    7 
 hw/pc.c                           |   14 
 hw/pc.h                           |    2 
 hw/pci-hotplug.c                  |    5 
 hw/pci.c                          |   25 
 hw/petalogix_s3adsp1800_mmu.c     |    3 
 hw/pflash_cfi01.c                 |    2 
 hw/pflash_cfi02.c                 |    2 
 hw/piix_pci.c                     |    7 
 hw/ppc405_boards.c                |    4 
 hw/ppc405_uc.c                    |    1 
 hw/qdev-properties.c              |   19 
 hw/qdev.c                         |   13 
 hw/qdev.h                         |    3 
 hw/r2d.c                          |    3 
 hw/rc4030.c                       |    3 
 hw/sd.c                           |    8 
 hw/smc91c111.c                    |   35 
 hw/spitz.c                        |    2 
 hw/stellaris.c                    |    2 
 hw/sun4m.c                        |    5 
 hw/tusb6010.c                     |    2 
 hw/usb-bus.c                      |    3 
 hw/usb-hub.c                      |    3 
 hw/usb-net.c                      |    5 
 hw/usb-ohci.c                     |   26 
 hw/usb-serial.c                   |    2 
 hw/usb-uhci.c                     |    6 
 hw/vga.c                          |   13 
 hw/virtio-9p-debug.c              |  484 +++++++
 hw/virtio-9p-debug.h              |    7 
 hw/virtio-9p-local.c              |  294 ++++
 hw/virtio-9p.c                    | 2375 ++++++++++++++++++++++++++++++++++++++
 hw/virtio-9p.h                    |  166 ++
 hw/virtio-balloon.c               |   35 
 hw/virtio-blk.c                   |    7 
 hw/virtio-console.c               |   11 
 hw/virtio-net.c                   |   20 
 hw/virtio-pci.c                   |   32 
 hw/virtio-serial-bus.c            |  341 ++++-
 hw/virtio-serial.h                |   34 
 hw/virtio.h                       |    7 
 hw/wm8750.c                       |    5 
 hw/xen_disk.c                     |    6 
 i386-dis.c                        |   56 
 kvm-all.c                         |  141 +-
 kvm-stub.c                        |  137 ++
 kvm.h                             |   14 
 linux-aio.c                       |    2 
 linux-user/elfload32.c            |   30 
 linux-user/linuxload.c            |    6 
 linux-user/main.c                 |   67 +
 linux-user/qemu.h                 |    5 
 linux-user/syscall.c              |    4 
 m68k-dis.c                        |   64 -
 microblaze-dis.c                  |   62 
 monitor.c                         |   73 -
 monitor.h                         |    1 
 net.c                             |  112 +
 net.h                             |    4 
 net/tap.c                         |    2 
 qemu-char.c                       |    9 
 qemu-config.c                     |   89 +
 qemu-config.h                     |    8 
 qemu-img-cmds.hx                  |    6 
 qemu-img.c                        |  197 +--
 qemu-img.texi                     |   12 
 qemu-io.c                         |   28 
 qemu-monitor.hx                   |   49 
 qemu-nbd.c                        |    2 
 qemu-option.c                     |   28 
 qemu-options.hx                   |  104 +
 qemu-timer.h                      |   24 
 qerror.c                          |   26 
 qerror.h                          |   20 
 rules.mak                         |    2 
 savevm.c                          |    2 
 slirp/cksum.c                     |    4 
 slirp/socket.c                    |    1 
 sysemu.h                          |    2 
 target-alpha/cpu.h                |   36 
 target-alpha/helper.c             |    8 
 target-alpha/helper.h             |    7 
 target-alpha/op_helper.c          |   60 
 target-alpha/translate.c          |  694 +++++++----
 target-arm/translate.c            |    1 
 target-cris/mmu.c                 |    4 
 target-cris/translate.c           |    5 
 target-i386/helper.c              |    1 
 target-i386/kvm.c                 |   91 +
 target-i386/translate.c           |    4 
 target-m68k/helper.c              |    5 
 target-m68k/translate.c           |    3 
 target-microblaze/mmu.c           |    7 
 target-ppc/helper.c               |   12 
 target-ppc/translate.c            |   10 
 target-sparc/cpu.h                |   12 
 target-sparc/op_helper.c          |   25 
 target-sparc/translate.c          |   66 -
 tcg/arm/tcg-target.c              |  873 ++++++++-----
 tcg/arm/tcg-target.h              |   14 
 tcg/hppa/tcg-target.c             |  437 +++---
 tcg/hppa/tcg-target.h             |   10 
 tcg/ppc/tcg-target.c              |    6 
 tcg/tcg.c                         |    7 
 usb-linux.c                       |  376 +++---
 vl.c                              |  236 ++-
 vnc-auth-sasl.c                   |    3 
 vnc-encoding-hextile.c            |  115 +
 vnc-encoding-zlib.c               |  142 ++
 vnc.c                             |  235 ---
 vnc.h                             |   29 
 183 files changed, 9115 insertions(+), 3126 deletions(-)

New commits:
commit 262353cb1fd8a78f6f0c9d1ddd2fdce32d3fdf95
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Tue May 4 19:55:35 2010 +0000

    Fix cpu list("-cpu ?") breakage, spotted by TeLeMan
    
    Fix breakage by 04c9a0cbc2bf496889cef6da2d61bf00ef190a4f.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index 2bf87d2..29462e5 100644
--- a/cpus.c
+++ b/cpus.c
@@ -801,3 +801,14 @@ int64_t cpu_get_icount(void)
     }
     return qemu_icount_bias + (icount << icount_time_shift);
 }
+
+void list_cpus(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+               const char *optarg)
+{
+    /* XXX: implement xxx_cpu_list for targets that still miss it */
+#if defined(cpu_list_id)
+    cpu_list_id(f, cpu_fprintf, optarg);
+#elif defined(cpu_list)
+    cpu_list(f, cpu_fprintf); /* deprecated */
+#endif
+}
diff --git a/cpus.h b/cpus.h
index 4ebad3a..774150a 100644
--- a/cpus.h
+++ b/cpus.h
@@ -16,5 +16,7 @@ void vm_state_notify(int running, int reason);
 bool tcg_cpu_exec(void);
 void set_numa_modes(void);
 void set_cpu_log(const char *optarg);
+void list_cpus(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+               const char *optarg);
 
 #endif
diff --git a/vl.c b/vl.c
index 999aac8..85bcc84 100644
--- a/vl.c
+++ b/vl.c
@@ -2726,12 +2726,7 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_cpu:
                 /* hw initialization will check this */
                 if (*optarg == '?') {
-/* XXX: implement xxx_cpu_list for targets that still miss it */
-#if defined(cpu_list_id)
-                    cpu_list_id(stdout, &fprintf, optarg);
-#elif defined(cpu_list)
-                    cpu_list(stdout, &fprintf);	        /* deprecated */
-#endif
+                    list_cpus(stdout, &fprintf, optarg);
                     exit(0);
                 } else {
                     cpu_model = optarg;
commit 0684bf1b0fa1823bf0614dd8d1c8b10cc0ef3f35
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue May 4 08:28:13 2010 -0500

    vnc: make sure to send pointer type change event on SetEncodings
    
    Commit 37c34d9d5d87ea9d51760310c8863b82cb8c055a introduced a regression when
    using relative mouse mode with a client that understands the PointerTypeChange
    pseudo-encoding.
    
    Reported-by: Marcelo Tosatti <mtosatti at redhat.com>
    Reported-by: Gerhard Wiesinger <lists at wiesinger.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vnc.c b/vnc.c
index 5241a6a..b1a3fdb 100644
--- a/vnc.c
+++ b/vnc.c
@@ -1642,6 +1642,8 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
             break;
         }
     }
+
+    check_pointer_type_change(&vs->mouse_mode_notifier);
 }
 
 static void set_pixel_conversion(VncState *vs)
commit ec5f92ce6ac8ec09056be77e03c941be188648fa
Author: Bernhard M. Wiedemann <qemudevbmw at lsmod.de>
Date:   Tue Apr 20 20:48:06 2010 +0200

    hw: better i440 emulation
    
    updated version of an old patch
    http://xenon.stanford.edu/~eswierk/misc/qemu-linuxbios/qemu-piix-ram-size.patch
    that together with
    http://www.mail-archive.com/linuxbios@linuxbios.org/msg02390.html
    (which is already in coreboot trunk) allows coreboot to autodetect the amount of RAM within qemu/kvm from a register in i440 northbridge.
    
    The message on the old patch states:
    Unfortunately the current version of qemu does not set these
    registers, but I have patched qemu so that it emulates the i440 more
    faithfully in this regard.
    
    Signed-off-by: Bernhard M. Wiedemann <qemudevbmw at lsmod.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pc.c b/hw/pc.c
index b659344..db2b9a2 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -924,7 +924,7 @@ static void pc_init1(ram_addr_t ram_size,
     isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
 
     if (pci_enabled) {
-        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq);
+        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
     } else {
         pci_bus = NULL;
         isa_bus_new(NULL);
diff --git a/hw/pc.h b/hw/pc.h
index 5f86b37..d11a576 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -107,7 +107,7 @@ int pcspk_audio_init(qemu_irq *pic);
 struct PCII440FXState;
 typedef struct PCII440FXState PCII440FXState;
 
-PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, qemu_irq *pic);
+PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, qemu_irq *pic, int ram_size);
 void i440fx_set_smm(PCII440FXState *d, int val);
 void i440fx_init_memory_mappings(PCII440FXState *d);
 
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index cd12212..97519db 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -213,7 +213,7 @@ static int i440fx_initfn(PCIDevice *dev)
     return 0;
 }
 
-PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *pic)
+PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *pic, int ram_size)
 {
     DeviceState *dev;
     PCIBus *b;
@@ -238,6 +238,11 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *
 
     *piix3_devfn = piix3->dev.devfn;
 
+    ram_size = ram_size / 8 / 1024 / 1024;
+    if (ram_size > 255)
+        ram_size = 255;
+    (*pi440fx_state)->dev.config[0x57]=ram_size;
+
     return b;
 }
 
commit cb4e5f8ed1b648c451491b10dc92b1af1e324535
Author: Naphtali Sprei <nsprei at redhat.com>
Date:   Sun Apr 25 19:30:37 2010 +0300

    block: read-only: open cdrom as read-only when using monitor's change command
    
    Current code of monitor command: 'change', used to open file for read-write
    uncoditionally. Change to open it as read-only for CDROM, and read-write for all others.
    
    Signed-off-by: Naphtali Sprei <nsprei at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/monitor.c b/monitor.c
index bb87479..46d0b47 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1087,6 +1087,7 @@ static int do_change_block(Monitor *mon, const char *device,
 {
     BlockDriverState *bs;
     BlockDriver *drv = NULL;
+    int bdrv_flags;
 
     bs = bdrv_find(device);
     if (!bs) {
@@ -1103,7 +1104,8 @@ static int do_change_block(Monitor *mon, const char *device,
     if (eject_device(mon, bs, 0) < 0) {
         return -1;
     }
-    if (bdrv_open(bs, filename, BDRV_O_RDWR, drv) < 0) {
+    bdrv_flags = bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM ? 0 : BDRV_O_RDWR;
+    if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) {
         qerror_report(QERR_OPEN_FILE_FAILED, filename);
         return -1;
     }
commit 288e7bccf1719df4d05abc872e75d544089aa139
Author: Nathan Froyd <froydnj at codesourcery.com>
Date:   Mon Apr 26 14:52:23 2010 -0700

    fix whitespace bogon in some versions of make
    
    With three different make binaries I have available, configuring a
    pristine QEMU tree and attempting to make gives the cryptic:
    
    Makefile:27: *** missing separator.  Stop.
    
    This patch fixes it (presumably because it makes the output of
    `set-vpath' be an empty string, rather than a bit of whitespace), but I
    don't understand why this hasn't been a problem for other folks before.
    
    Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/rules.mak b/rules.mak
index 5941b73..7e10432 100644
--- a/rules.mak
+++ b/rules.mak
@@ -40,7 +40,7 @@ cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \
               >/dev/null 2>&1 && echo OK), $2, $3)
 
 VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi
-set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES), $(eval vpath $(PATTERN) $1)))
+set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1)))
 
 # Generate timestamp files for .h include files
 
commit 2791104cfb40314110f96dc5eeab98613e5ab1a0
Author: David Ahern <daahern at cisco.com>
Date:   Sat Apr 24 10:26:22 2010 -0600

    Changes to usb-linux to conform to coding style
    
    Signed-off-by: David Ahern <daahern at cisco.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/usb-linux.c b/usb-linux.c
index ecfe668..88273ff 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -105,9 +105,9 @@ enum {
 
 /*
  * Control transfer state.
- * Note that 'buffer' _must_ follow 'req' field because 
+ * Note that 'buffer' _must_ follow 'req' field because
  * we need contigious buffer when we submit control URB.
- */ 
+ */
 struct ctrl_struct {
     uint16_t len;
     uint16_t offset;
@@ -170,10 +170,10 @@ static void set_halt(USBHostDevice *s, int ep)
     s->endp_table[ep - 1].halted = 1;
 }
 
-/* 
+/*
  * Async URB state.
  * We always allocate one isoc descriptor even for bulk transfers
- * to simplify allocation and casts. 
+ * to simplify allocation and casts.
  */
 typedef struct AsyncURB
 {
@@ -220,15 +220,16 @@ static void async_complete(void *opaque)
     AsyncURB *aurb;
 
     while (1) {
-    	USBPacket *p;
+        USBPacket *p;
 
-	int r = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &aurb);
+        int r = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &aurb);
         if (r < 0) {
-            if (errno == EAGAIN)
+            if (errno == EAGAIN) {
                 return;
-
+            }
             if (errno == ENODEV && !s->closing) {
-                printf("husb: device %d.%d disconnected\n", s->bus_num, s->addr);
+                printf("husb: device %d.%d disconnected\n",
+                       s->bus_num, s->addr);
                 usb_host_close(s);
                 usb_host_auto_check(NULL);
                 return;
@@ -240,21 +241,22 @@ static void async_complete(void *opaque)
 
         p = aurb->packet;
 
-	DPRINTF("husb: async completed. aurb %p status %d alen %d\n", 
+        DPRINTF("husb: async completed. aurb %p status %d alen %d\n",
                 aurb, aurb->urb.status, aurb->urb.actual_length);
 
-	if (p) {
+        if (p) {
             switch (aurb->urb.status) {
             case 0:
                 p->len = aurb->urb.actual_length;
-                if (aurb->urb.type == USBDEVFS_URB_TYPE_CONTROL)
+                if (aurb->urb.type == USBDEVFS_URB_TYPE_CONTROL) {
                     async_complete_ctrl(s, p);
+                }
                 break;
 
             case -EPIPE:
                 set_halt(s, p->devep);
-		p->len = USB_RET_STALL;
-		break;
+                p->len = USB_RET_STALL;
+                break;
 
             default:
                 p->len = USB_RET_NAK;
@@ -262,7 +264,7 @@ static void async_complete(void *opaque)
             }
 
             usb_packet_complete(p);
-	}
+        }
 
         async_free(aurb);
     }
@@ -297,12 +299,14 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
 
     i = 0;
     dev_descr_len = dev->descr[0];
-    if (dev_descr_len > dev->descr_len)
+    if (dev_descr_len > dev->descr_len) {
         goto fail;
+    }
 
     i += dev_descr_len;
     while (i < dev->descr_len) {
-        DPRINTF("husb: i is %d, descr_len is %d, dl %d, dt %d\n", i, dev->descr_len,
+        DPRINTF("husb: i is %d, descr_len is %d, dl %d, dt %d\n",
+                i, dev->descr_len,
                dev->descr[i], dev->descr[i+1]);
 
         if (dev->descr[i+1] != USB_DT_CONFIG) {
@@ -311,7 +315,7 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
         }
         config_descr_len = dev->descr[i];
 
-	printf("husb: config #%d need %d\n", dev->descr[i + 5], configuration); 
+        printf("husb: config #%d need %d\n", dev->descr[i + 5], configuration);
 
         if (configuration < 0 || configuration == dev->descr[i + 5]) {
             configuration = dev->descr[i + 5];
@@ -322,7 +326,8 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
     }
 
     if (i >= dev->descr_len) {
-        fprintf(stderr, "husb: update iface failed. no matching configuration\n");
+        fprintf(stderr,
+                "husb: update iface failed. no matching configuration\n");
         goto fail;
     }
     nb_interfaces = dev->descr[i + 4];
@@ -415,15 +420,16 @@ static int usb_host_handle_data(USBHostDevice *s, USBPacket *p)
 
     urb = &aurb->urb;
 
-    if (p->pid == USB_TOKEN_IN)
-    	urb->endpoint = p->devep | 0x80;
-    else
-    	urb->endpoint = p->devep;
+    if (p->pid == USB_TOKEN_IN) {
+        urb->endpoint = p->devep | 0x80;
+    } else {
+        urb->endpoint = p->devep;
+    }
 
     if (is_halted(s, p->devep)) {
-	ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &urb->endpoint);
+        ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &urb->endpoint);
         if (ret < 0) {
-            DPRINTF("husb: failed to clear halt. ep 0x%x errno %d\n", 
+            DPRINTF("husb: failed to clear halt. ep 0x%x errno %d\n",
                    urb->endpoint, errno);
             return USB_RET_NAK;
         }
@@ -448,7 +454,8 @@ static int usb_host_handle_data(USBHostDevice *s, USBPacket *p)
 
     ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
 
-    DPRINTF("husb: data submit. ep 0x%x len %u aurb %p\n", urb->endpoint, p->len, aurb);
+    DPRINTF("husb: data submit. ep 0x%x len %u aurb %p\n",
+            urb->endpoint, p->len, aurb);
 
     if (ret < 0) {
         DPRINTF("husb: submit failed. errno %d\n", errno);
@@ -469,10 +476,11 @@ static int usb_host_handle_data(USBHostDevice *s, USBPacket *p)
 
 static int ctrl_error(void)
 {
-    if (errno == ETIMEDOUT)
+    if (errno == ETIMEDOUT) {
         return USB_RET_NAK;
-    else 
+    } else {
         return USB_RET_STALL;
+    }
 }
 
 static int usb_host_set_address(USBHostDevice *s, int addr)
@@ -487,12 +495,12 @@ static int usb_host_set_config(USBHostDevice *s, int config)
     usb_host_release_interfaces(s);
 
     int ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config);
- 
+
     DPRINTF("husb: ctrl set config %d ret %d errno %d\n", config, ret, errno);
-    
-    if (ret < 0)
+
+    if (ret < 0) {
         return ctrl_error();
- 
+    }
     usb_host_claim_interfaces(s, config);
     return 0;
 }
@@ -505,13 +513,13 @@ static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
     si.interface  = iface;
     si.altsetting = alt;
     ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si);
-    
-    DPRINTF("husb: ctrl set iface %d altset %d ret %d errno %d\n", 
-    	iface, alt, ret, errno);
-    
-    if (ret < 0)
-        return ctrl_error();
 
+    DPRINTF("husb: ctrl set iface %d altset %d ret %d errno %d\n",
+            iface, alt, ret, errno);
+
+    if (ret < 0) {
+        return ctrl_error();
+    }
     usb_linux_update_endp_table(s);
     return 0;
 }
@@ -523,7 +531,7 @@ static int usb_host_handle_control(USBHostDevice *s, USBPacket *p)
     int ret, value, index;
     int buffer_len;
 
-    /* 
+    /*
      * Process certain standard device requests.
      * These are infrequent and are processed synchronously.
      */
@@ -531,8 +539,8 @@ static int usb_host_handle_control(USBHostDevice *s, USBPacket *p)
     index = le16_to_cpu(s->ctrl.req.wIndex);
 
     DPRINTF("husb: ctrl type 0x%x req 0x%x val 0x%x index %u len %u\n",
-        s->ctrl.req.bRequestType, s->ctrl.req.bRequest, value, index, 
-        s->ctrl.len);
+            s->ctrl.req.bRequestType, s->ctrl.req.bRequest, value, index,
+            s->ctrl.len);
 
     if (s->ctrl.req.bRequestType == 0) {
         switch (s->ctrl.req.bRequest) {
@@ -545,8 +553,9 @@ static int usb_host_handle_control(USBHostDevice *s, USBPacket *p)
     }
 
     if (s->ctrl.req.bRequestType == 1 &&
-                  s->ctrl.req.bRequest == USB_REQ_SET_INTERFACE)
+                  s->ctrl.req.bRequest == USB_REQ_SET_INTERFACE) {
         return usb_host_set_interface(s, index, value);
+    }
 
     /* The rest are asynchronous */
 
@@ -561,12 +570,12 @@ static int usb_host_handle_control(USBHostDevice *s, USBPacket *p)
     aurb->hdev   = s;
     aurb->packet = p;
 
-    /* 
+    /*
      * Setup ctrl transfer.
      *
      * s->ctrl is layed out such that data buffer immediately follows
      * 'req' struct which is exactly what usbdevfs expects.
-     */ 
+     */
     urb = &aurb->urb;
 
     urb->type     = USBDEVFS_URB_TYPE_CONTROL;
@@ -603,9 +612,10 @@ static int do_token_setup(USBDevice *dev, USBPacket *p)
     USBHostDevice *s = (USBHostDevice *) dev;
     int ret = 0;
 
-    if (p->len != 8)
+    if (p->len != 8) {
         return USB_RET_STALL;
- 
+    }
+
     memcpy(&s->ctrl.req, p->data, 8);
     s->ctrl.len    = le16_to_cpu(s->ctrl.req.wLength);
     s->ctrl.offset = 0;
@@ -613,17 +623,20 @@ static int do_token_setup(USBDevice *dev, USBPacket *p)
 
     if (s->ctrl.req.bRequestType & USB_DIR_IN) {
         ret = usb_host_handle_control(s, p);
-        if (ret < 0)
+        if (ret < 0) {
             return ret;
+        }
 
-        if (ret < s->ctrl.len)
+        if (ret < s->ctrl.len) {
             s->ctrl.len = ret;
+        }
         s->ctrl.state = CTRL_STATE_DATA;
     } else {
-        if (s->ctrl.len == 0)
+        if (s->ctrl.len == 0) {
             s->ctrl.state = CTRL_STATE_ACK;
-        else
+        } else {
             s->ctrl.state = CTRL_STATE_DATA;
+        }
     }
 
     return ret;
@@ -634,16 +647,17 @@ static int do_token_in(USBDevice *dev, USBPacket *p)
     USBHostDevice *s = (USBHostDevice *) dev;
     int ret = 0;
 
-    if (p->devep != 0)
+    if (p->devep != 0) {
         return usb_host_handle_data(s, p);
+    }
 
     switch(s->ctrl.state) {
     case CTRL_STATE_ACK:
         if (!(s->ctrl.req.bRequestType & USB_DIR_IN)) {
             ret = usb_host_handle_control(s, p);
-            if (ret == USB_RET_ASYNC)
+            if (ret == USB_RET_ASYNC) {
                 return USB_RET_ASYNC;
-
+            }
             s->ctrl.state = CTRL_STATE_IDLE;
             return ret > 0 ? 0 : ret;
         }
@@ -653,12 +667,14 @@ static int do_token_in(USBDevice *dev, USBPacket *p)
     case CTRL_STATE_DATA:
         if (s->ctrl.req.bRequestType & USB_DIR_IN) {
             int len = s->ctrl.len - s->ctrl.offset;
-            if (len > p->len)
+            if (len > p->len) {
                 len = p->len;
+            }
             memcpy(p->data, s->ctrl.buffer + s->ctrl.offset, len);
             s->ctrl.offset += len;
-            if (s->ctrl.offset >= s->ctrl.len)
+            if (s->ctrl.offset >= s->ctrl.len) {
                 s->ctrl.state = CTRL_STATE_ACK;
+            }
             return len;
         }
 
@@ -674,8 +690,9 @@ static int do_token_out(USBDevice *dev, USBPacket *p)
 {
     USBHostDevice *s = (USBHostDevice *) dev;
 
-    if (p->devep != 0)
+    if (p->devep != 0) {
         return usb_host_handle_data(s, p);
+    }
 
     switch(s->ctrl.state) {
     case CTRL_STATE_ACK:
@@ -690,12 +707,14 @@ static int do_token_out(USBDevice *dev, USBPacket *p)
     case CTRL_STATE_DATA:
         if (!(s->ctrl.req.bRequestType & USB_DIR_IN)) {
             int len = s->ctrl.len - s->ctrl.offset;
-            if (len > p->len)
+            if (len > p->len) {
                 len = p->len;
+            }
             memcpy(s->ctrl.buffer + s->ctrl.offset, p->data, len);
             s->ctrl.offset += len;
-            if (s->ctrl.offset >= s->ctrl.len)
+            if (s->ctrl.offset >= s->ctrl.len) {
                 s->ctrl.state = CTRL_STATE_ACK;
+            }
             return len;
         }
 
@@ -733,8 +752,9 @@ static int usb_host_handle_packet(USBDevice *s, USBPacket *p)
     }
 
     /* Rest of the PIDs must match our address */
-    if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
+    if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr) {
         return USB_RET_NODEV;
+    }
 
     switch (p->pid) {
     case USB_TOKEN_SETUP:
@@ -745,7 +765,7 @@ static int usb_host_handle_packet(USBDevice *s, USBPacket *p)
 
     case USB_TOKEN_OUT:
         return do_token_out(s, p);
- 
+
     default:
         return USB_RET_STALL;
     }
@@ -774,8 +794,9 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
     }
 
     /* in address state */
-    if (configuration == 0)
+    if (configuration == 0) {
         return 1;
+    }
 
     /* get the desired configuration, interface, and endpoint descriptors
      * from device description */
@@ -821,15 +842,17 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
         }
 
         /* advance to the endpoints */
-        while (i < length && descriptors[i +1] != USB_DT_ENDPOINT)
+        while (i < length && descriptors[i +1] != USB_DT_ENDPOINT) {
             i += descriptors[i];
+        }
 
         if (i >= length)
             break;
 
         while (i < length) {
-            if (descriptors[i + 1] != USB_DT_ENDPOINT)
+            if (descriptors[i + 1] != USB_DT_ENDPOINT) {
                 break;
+            }
 
             devep = descriptors[i + 2];
             switch (descriptors[i + 3] & 0x3) {
@@ -865,9 +888,9 @@ static int usb_host_open(USBHostDevice *dev, int bus_num,
     struct usbdevfs_connectinfo ci;
     char buf[1024];
 
-    if (dev->fd != -1)
+    if (dev->fd != -1) {
         goto fail;
-
+    }
     printf("husb: open device %d.%d\n", bus_num, addr);
 
     if (!usb_host_device_path) {
@@ -898,21 +921,23 @@ static int usb_host_open(USBHostDevice *dev, int bus_num,
     {
         int x;
         printf("=== begin dumping device descriptor data ===\n");
-        for (x = 0; x < dev->descr_len; x++)
+        for (x = 0; x < dev->descr_len; x++) {
             printf("%02x ", dev->descr[x]);
+        }
         printf("\n=== end dumping device descriptor data ===\n");
     }
 #endif
 
 
-    /* 
-     * Initial configuration is -1 which makes us claim first 
+    /*
+     * Initial configuration is -1 which makes us claim first
      * available config. We used to start with 1, which does not
-     * always work. I've seen devices where first config starts 
+     * always work. I've seen devices where first config starts
      * with 2.
      */
-    if (!usb_host_claim_interfaces(dev, -1))
+    if (!usb_host_claim_interfaces(dev, -1)) {
         goto fail;
+    }
 
     ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
     if (ret < 0) {
@@ -923,20 +948,23 @@ static int usb_host_open(USBHostDevice *dev, int bus_num,
     printf("husb: grabbed usb device %d.%d\n", bus_num, addr);
 
     ret = usb_linux_update_endp_table(dev);
-    if (ret)
+    if (ret) {
         goto fail;
+    }
 
-    if (ci.slow)
+    if (ci.slow) {
         dev->dev.speed = USB_SPEED_LOW;
-    else
+    } else {
         dev->dev.speed = USB_SPEED_HIGH;
+    }
 
-    if (!prod_name || prod_name[0] == '\0')
+    if (!prod_name || prod_name[0] == '\0') {
         snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
                  "host:%d.%d", bus_num, addr);
-    else
+    } else {
         pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
                 prod_name);
+    }
 
     /* USB devio uses 'write' flag to check for async completions */
     qemu_set_fd_handler(dev->fd, NULL, async_complete, dev);
@@ -946,15 +974,17 @@ static int usb_host_open(USBHostDevice *dev, int bus_num,
 
 fail:
     dev->fd = -1;
-    if (fd != -1)
+    if (fd != -1) {
         close(fd);
+    }
     return -1;
 }
 
 static int usb_host_close(USBHostDevice *dev)
 {
-    if (dev->fd == -1)
+    if (dev->fd == -1) {
         return -1;
+    }
 
     qemu_set_fd_handler(dev->fd, NULL, NULL, NULL);
     dev->closing = 1;
@@ -1011,8 +1041,9 @@ USBDevice *usb_host_device_open(const char *devname)
     dev = usb_create(NULL /* FIXME */, "usb-host");
 
     if (strstr(devname, "auto:")) {
-        if (parse_filter(devname, &filter) < 0)
+        if (parse_filter(devname, &filter) < 0) {
             goto fail;
+        }
     } else {
         if ((p = strchr(devname, '.'))) {
             filter.bus_num    = strtoul(devname, NULL, 0);
@@ -1048,13 +1079,13 @@ int usb_host_device_close(const char *devname)
     int bus_num, addr;
     USBHostDevice *s;
 
-    if (strstr(devname, "auto:"))
+    if (strstr(devname, "auto:")) {
         return usb_host_auto_del(devname);
-
-    if (usb_host_find_device(&bus_num, &addr, product_name, sizeof(product_name),
-                             devname) < 0)
+    }
+    if (usb_host_find_device(&bus_num, &addr, product_name,
+                                    sizeof(product_name), devname) < 0) {
         return -1;
-
+    }
     s = hostdev_find(bus_num, addr);
     if (s) {
         usb_device_delete_addr(s->bus_num, s->dev.addr);
@@ -1072,15 +1103,18 @@ static int get_tag_value(char *buf, int buf_size,
     const char *p;
     char *q;
     p = strstr(str, tag);
-    if (!p)
+    if (!p) {
         return -1;
+    }
     p += strlen(tag);
-    while (qemu_isspace(*p))
+    while (qemu_isspace(*p)) {
         p++;
+    }
     q = buf;
     while (*p != '\0' && !strchr(stopchars, *p)) {
-        if ((q - buf) < (buf_size - 1))
+        if ((q - buf) < (buf_size - 1)) {
             *q++ = *p;
+        }
         p++;
     }
     *q = '\0';
@@ -1115,51 +1149,62 @@ static int usb_host_scan_dev(void *opaque, USBScanFunc *func)
     device_count = 0;
     bus_num = addr = speed = class_id = product_id = vendor_id = 0;
     for(;;) {
-        if (fgets(line, sizeof(line), f) == NULL)
+        if (fgets(line, sizeof(line), f) == NULL) {
             break;
-        if (strlen(line) > 0)
+        }
+        if (strlen(line) > 0) {
             line[strlen(line) - 1] = '\0';
+        }
         if (line[0] == 'T' && line[1] == ':') {
             if (device_count && (vendor_id || product_id)) {
                 /* New device.  Add the previously discovered device.  */
                 ret = func(opaque, bus_num, addr, class_id, vendor_id,
                            product_id, product_name, speed);
-                if (ret)
+                if (ret) {
                     goto the_end;
+                }
             }
-            if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0)
+            if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0) {
                 goto fail;
+            }
             bus_num = atoi(buf);
-            if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0)
+            if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0) {
                 goto fail;
+            }
             addr = atoi(buf);
-            if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0)
+            if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0) {
                 goto fail;
-            if (!strcmp(buf, "480"))
+            }
+            if (!strcmp(buf, "480")) {
                 speed = USB_SPEED_HIGH;
-            else if (!strcmp(buf, "1.5"))
+            } else if (!strcmp(buf, "1.5")) {
                 speed = USB_SPEED_LOW;
-            else
+            } else {
                 speed = USB_SPEED_FULL;
+            }
             product_name[0] = '\0';
             class_id = 0xff;
             device_count++;
             product_id = 0;
             vendor_id = 0;
         } else if (line[0] == 'P' && line[1] == ':') {
-            if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0)
+            if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0) {
                 goto fail;
+            }
             vendor_id = strtoul(buf, NULL, 16);
-            if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0)
+            if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0) {
                 goto fail;
+            }
             product_id = strtoul(buf, NULL, 16);
         } else if (line[0] == 'S' && line[1] == ':') {
-            if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0)
+            if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0) {
                 goto fail;
+            }
             pstrcpy(product_name, sizeof(product_name), buf);
         } else if (line[0] == 'D' && line[1] == ':') {
-            if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0)
+            if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0) {
                 goto fail;
+            }
             class_id = strtoul(buf, NULL, 16);
         }
     fail: ;
@@ -1170,8 +1215,9 @@ static int usb_host_scan_dev(void *opaque, USBScanFunc *func)
                    product_id, product_name, speed);
     }
  the_end:
-    if (f)
+    if (f) {
         fclose(f);
+    }
     return ret;
 }
 
@@ -1185,7 +1231,8 @@ static int usb_host_scan_dev(void *opaque, USBScanFunc *func)
  *
  * @return 0 failed, 1 succeeded ('line' contains data)
  */
-static int usb_host_read_file(char *line, size_t line_size, const char *device_file, const char *device_name)
+static int usb_host_read_file(char *line, size_t line_size,
+                              const char *device_file, const char *device_name)
 {
     FILE *f;
     int ret = 0;
@@ -1227,59 +1274,71 @@ static int usb_host_scan_sys(void *opaque, USBScanFunc *func)
     while ((de = readdir(dir))) {
         if (de->d_name[0] != '.' && !strchr(de->d_name, ':')) {
             char *tmpstr = de->d_name;
-            if (!strncmp(de->d_name, "usb", 3))
+            if (!strncmp(de->d_name, "usb", 3)) {
                 tmpstr += 3;
+            }
             bus_num = atoi(tmpstr);
 
-            if (!usb_host_read_file(line, sizeof(line), "devnum", de->d_name))
+            if (!usb_host_read_file(line, sizeof(line), "devnum", de->d_name)) {
                 goto the_end;
-            if (sscanf(line, "%d", &addr) != 1)
+            }
+            if (sscanf(line, "%d", &addr) != 1) {
                 goto the_end;
-
+            }
             if (!usb_host_read_file(line, sizeof(line), "bDeviceClass",
-                                    de->d_name))
+                                    de->d_name)) {
                 goto the_end;
-            if (sscanf(line, "%x", &class_id) != 1)
+            }
+            if (sscanf(line, "%x", &class_id) != 1) {
                 goto the_end;
+            }
 
-            if (!usb_host_read_file(line, sizeof(line), "idVendor", de->d_name))
+            if (!usb_host_read_file(line, sizeof(line), "idVendor",
+                                    de->d_name)) {
                 goto the_end;
-            if (sscanf(line, "%x", &vendor_id) != 1)
+            }
+            if (sscanf(line, "%x", &vendor_id) != 1) {
                 goto the_end;
-
+            }
             if (!usb_host_read_file(line, sizeof(line), "idProduct",
-                                    de->d_name))
+                                    de->d_name)) {
                 goto the_end;
-            if (sscanf(line, "%x", &product_id) != 1)
+            }
+            if (sscanf(line, "%x", &product_id) != 1) {
                 goto the_end;
-
+            }
             if (!usb_host_read_file(line, sizeof(line), "product",
                                     de->d_name)) {
                 *product_name = 0;
             } else {
-                if (strlen(line) > 0)
+                if (strlen(line) > 0) {
                     line[strlen(line) - 1] = '\0';
+                }
                 pstrcpy(product_name, sizeof(product_name), line);
             }
 
-            if (!usb_host_read_file(line, sizeof(line), "speed", de->d_name))
+            if (!usb_host_read_file(line, sizeof(line), "speed", de->d_name)) {
                 goto the_end;
-            if (!strcmp(line, "480\n"))
+            }
+            if (!strcmp(line, "480\n")) {
                 speed = USB_SPEED_HIGH;
-            else if (!strcmp(line, "1.5\n"))
+            } else if (!strcmp(line, "1.5\n")) {
                 speed = USB_SPEED_LOW;
-            else
+            } else {
                 speed = USB_SPEED_FULL;
+            }
 
             ret = func(opaque, bus_num, addr, class_id, vendor_id,
                        product_id, product_name, speed);
-            if (ret)
+            if (ret) {
                 goto the_end;
+            }
         }
     }
  the_end:
-    if (dir)
+    if (dir) {
         closedir(dir);
+    }
     return ret;
 }
 
@@ -1328,17 +1387,19 @@ static int usb_host_scan(void *opaque, USBScanFunc *func)
         }
     found_devices:
         if (!usb_fs_type) {
-            if (mon)
+            if (mon) {
                 monitor_printf(mon, "husb: unable to access USB devices\n");
+            }
             return -ENOENT;
         }
 
         /* the module setting (used later for opening devices) */
         usb_host_device_path = qemu_mallocz(strlen(devpath)+1);
         strcpy(usb_host_device_path, devpath);
-        if (mon)
+        if (mon) {
             monitor_printf(mon, "husb: using %s file-system with %s\n",
                            fs_type[usb_fs_type], usb_host_device_path);
+        }
     }
 
     switch (usb_fs_type) {
@@ -1372,27 +1433,29 @@ static int usb_host_auto_scan(void *opaque, int bus_num, int addr,
     QTAILQ_FOREACH(s, &hostdevs, next) {
         f = &s->match;
 
-	if (f->bus_num > 0 && f->bus_num != bus_num)
+        if (f->bus_num > 0 && f->bus_num != bus_num) {
             continue;
-
-	if (f->addr > 0 && f->addr != addr)
+        }
+        if (f->addr > 0 && f->addr != addr) {
             continue;
+        }
 
-	if (f->vendor_id > 0 && f->vendor_id != vendor_id)
+        if (f->vendor_id > 0 && f->vendor_id != vendor_id) {
             continue;
+        }
 
-	if (f->product_id > 0 && f->product_id != product_id)
+        if (f->product_id > 0 && f->product_id != product_id) {
             continue;
-
+        }
         /* We got a match */
 
         /* Already attached ? */
-        if (s->fd != -1)
+        if (s->fd != -1) {
             return 0;
-
+        }
         DPRINTF("husb: auto open: bus_num %d addr %d\n", bus_num, addr);
 
-	usb_host_open(s, bus_num, addr, product_name);
+        usb_host_open(s, bus_num, addr, product_name);
     }
 
     return 0;
@@ -1406,21 +1469,24 @@ static void usb_host_auto_check(void *unused)
     usb_host_scan(NULL, usb_host_auto_scan);
 
     QTAILQ_FOREACH(s, &hostdevs, next) {
-        if (s->fd == -1)
+        if (s->fd == -1) {
             unconnected++;
+        }
     }
 
     if (unconnected == 0) {
         /* nothing to watch */
-        if (usb_auto_timer)
+        if (usb_auto_timer) {
             qemu_del_timer(usb_auto_timer);
+        }
         return;
     }
 
     if (!usb_auto_timer) {
         usb_auto_timer = qemu_new_timer(rt_clock, usb_host_auto_check, NULL);
-        if (!usb_auto_timer)
+        if (!usb_auto_timer) {
             return;
+        }
     }
     qemu_mod_timer(usb_auto_timer, qemu_get_clock(rt_clock) + 2000);
 }
@@ -1450,13 +1516,15 @@ static int parse_filter(const char *spec, struct USBAutoFilter *f)
     f->product_id = 0;
 
     for (i = BUS; i < DONE; i++) {
-    	p = strpbrk(p, ":.");
-    	if (!p) break;
+        p = strpbrk(p, ":.");
+        if (!p) {
+            break;
+        }
         p++;
- 
-    	if (*p == '*')
-            continue;
 
+        if (*p == '*') {
+            continue;
+        }
         switch(i) {
         case BUS: f->bus_num = strtol(p, NULL, 10);    break;
         case DEV: f->addr    = strtol(p, NULL, 10);    break;
@@ -1502,8 +1570,9 @@ static const char *usb_class_str(uint8_t class)
 {
     const struct usb_class_info *p;
     for(p = usb_class_info; p->class != -1; p++) {
-        if (p->class == class)
+        if (p->class == class) {
             break;
+        }
     }
     return p->class_name;
 }
@@ -1533,13 +1602,15 @@ static void usb_info_device(Monitor *mon, int bus_num, int addr, int class_id,
     monitor_printf(mon, "  Device %d.%d, speed %s Mb/s\n",
                 bus_num, addr, speed_str);
     class_str = usb_class_str(class_id);
-    if (class_str)
+    if (class_str) {
         monitor_printf(mon, "    %s:", class_str);
-    else
+    } else {
         monitor_printf(mon, "    Class %02x:", class_id);
+    }
     monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id);
-    if (product_name[0] != '\0')
+    if (product_name[0] != '\0') {
         monitor_printf(mon, ", %s", product_name);
+    }
     monitor_printf(mon, "\n");
 }
 
@@ -1558,18 +1629,20 @@ static int usb_host_info_device(void *opaque, int bus_num, int addr,
 
 static void dec2str(int val, char *str, size_t size)
 {
-    if (val == 0)
+    if (val == 0) {
         snprintf(str, size, "*");
-    else
-        snprintf(str, size, "%d", val); 
+    } else {
+        snprintf(str, size, "%d", val);
+    }
 }
 
 static void hex2str(int val, char *str, size_t size)
 {
-    if (val == 0)
+    if (val == 0) {
         snprintf(str, size, "*");
-    else
+    } else {
         snprintf(str, size, "%04x", val);
+    }
 }
 
 void usb_host_info(Monitor *mon)
@@ -1579,8 +1652,10 @@ void usb_host_info(Monitor *mon)
 
     usb_host_scan(mon, usb_host_info_device);
 
-    if (QTAILQ_EMPTY(&hostdevs))
+    if (QTAILQ_EMPTY(&hostdevs)) {
         return;
+    }
+
     monitor_printf(mon, "  Auto filters:\n");
     QTAILQ_FOREACH(s, &hostdevs, next) {
         char bus[10], addr[10], vid[10], pid[10];
commit 0e1a275bd4a9b0eb6a567f21366074bda4a8d336
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Apr 6 13:31:29 2010 +0200

    Add KVM CFLAGS to vhost build
    
    The configure test of vhost uses KVM CFLAGS, so the build must use them
    as well. Otherwise we specifically miss what --kerneldir provides.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile.target b/Makefile.target
index 7ea753b..c092900 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -33,7 +33,7 @@ PROGS=$(QEMU_PROG)
 
 LIBS+=-lm
 
-kvm.o kvm-all.o: QEMU_CFLAGS+=$(KVM_CFLAGS)
+kvm.o kvm-all.o vhost.o vhost_net.o: QEMU_CFLAGS+=$(KVM_CFLAGS)
 
 config-target.h: config-target.h-timestamp
 config-target.h-timestamp: config-target.mak
commit 6ed2c484f261fd8bd217f855b9e5e5f981e63f0a
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Tue Apr 27 20:35:59 2010 -0300

    QMP: Introduce RESUME event
    
    It's emitted when the Virtual Machine resumes execution.
    
    We currently have the STOP event but don't have the matching
    RESUME one, this means that clients are notified when the VM
    is stopped but don't get anything when it resumes.
    
    Let's fix that as it's already causing some trouble to libvirt.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
index c084a47..01ec85f 100644
--- a/QMP/qmp-events.txt
+++ b/QMP/qmp-events.txt
@@ -38,6 +38,18 @@ Example:
 { "event": "RESET",
     "timestamp": { "seconds": 1267041653, "microseconds": 9518 } }
 
+RESUME
+------
+
+Emitted when the Virtual Machine resumes execution.
+
+Data: None.
+
+Example:
+
+{ "event": "RESUME",
+    "timestamp": { "seconds": 1271770767, "microseconds": 582542 } }
+
 RTC_CHANGE
 ----------
 
diff --git a/monitor.c b/monitor.c
index 754bcc5..bb87479 100644
--- a/monitor.c
+++ b/monitor.c
@@ -423,6 +423,9 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
         case QEVENT_STOP:
             event_name = "STOP";
             break;
+        case QEVENT_RESUME:
+            event_name = "RESUME";
+            break;
         case QEVENT_VNC_CONNECTED:
             event_name = "VNC_CONNECTED";
             break;
diff --git a/monitor.h b/monitor.h
index 5bdeed1..ea15469 100644
--- a/monitor.h
+++ b/monitor.h
@@ -21,6 +21,7 @@ typedef enum MonitorEvent {
     QEVENT_RESET,
     QEVENT_POWERDOWN,
     QEVENT_STOP,
+    QEVENT_RESUME,
     QEVENT_VNC_CONNECTED,
     QEVENT_VNC_INITIALIZED,
     QEVENT_VNC_DISCONNECTED,
diff --git a/vl.c b/vl.c
index 9caf96d..999aac8 100644
--- a/vl.c
+++ b/vl.c
@@ -1689,6 +1689,7 @@ void vm_start(void)
         vm_running = 1;
         vm_state_notify(1, 0);
         resume_all_vcpus();
+        monitor_protocol_event(QEVENT_RESUME, NULL);
     }
 }
 
commit 3d54abc7b7f234685ea48bdd1743ed631cf02ba0
Author: Gautham R Shenoy <ego at in.ibm.com>
Date:   Thu Apr 29 17:45:03 2010 +0530

    virtio-9p: Create a syntactic shortcut for the file-system pass-thru
    
    Currently the commandline to create a virtual-filesystem pass-through between
    the guest and the host is as follows:
    #qemu -fsdev fstype,id=ID,path=path/to/share \
          -device virtio-9p-pci,fsdev=ID,mount_tag=tag \
    
    This patch provides a syntactic short-cut to achieve the same as follows:
    #qemu -virtfs fstype,path=path/to/share,mount_tag=tag
    
    This will be internally expanded as:
    #qemu -fsdev fstype,id=tag,path=path/to/share, \
          -device virtio-9p-pci,fsdev=tag,mount_tag=tag \
    
    Signed-off-by: Gautham R Shenoy <ego at in.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-config.c b/qemu-config.c
index cda5060..d500885 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -169,6 +169,28 @@ QemuOptsList qemu_fsdev_opts = {
 };
 #endif
 
+#ifdef CONFIG_LINUX
+QemuOptsList qemu_virtfs_opts = {
+    .name = "virtfs",
+    .implied_opt_name = "fstype",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_virtfs_opts.head),
+    .desc = {
+        {
+            .name = "fstype",
+            .type = QEMU_OPT_STRING,
+        }, {
+            .name = "path",
+            .type = QEMU_OPT_STRING,
+        }, {
+            .name = "mount_tag",
+            .type = QEMU_OPT_STRING,
+        },
+
+        { /*End of list */ }
+    },
+};
+#endif
+
 QemuOptsList qemu_device_opts = {
     .name = "device",
     .implied_opt_name = "driver",
diff --git a/qemu-config.h b/qemu-config.h
index 5f34803..dca69d4 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -5,6 +5,7 @@ extern QemuOptsList qemu_drive_opts;
 extern QemuOptsList qemu_chardev_opts;
 #ifdef CONFIG_LINUX
 extern QemuOptsList qemu_fsdev_opts;
+extern QemuOptsList qemu_virtfs_opts;
 #endif
 extern QemuOptsList qemu_device_opts;
 extern QemuOptsList qemu_netdev_opts;
diff --git a/qemu-options.hx b/qemu-options.hx
index e754ba1..12f6b51 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -510,6 +510,41 @@ Create a file-system-"device" for local-filesystem.
 ETEXI
 #endif
 
+#ifdef CONFIG_LINUX
+DEFHEADING(Virtual File system pass-through options:)
+
+DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs,
+    "-virtfs local,path=path,mount_tag=tag\n",
+    QEMU_ARCH_ALL)
+
+STEXI
+
+The general form of a Virtual File system pass-through option is:
+ at table @option
+
+ at item -virtfs @var{fstype} [, at var{options}]
+ at findex -virtfs
+Fstype is one of:
+ at option{local},
+The specific Fstype will determine the applicable options.
+
+Options to each backend are described below.
+
+ at item -virtfs local ,path=@var{path} ,mount_tag=@var{mount_tag}
+
+Create a Virtual file-system-pass through for local-filesystem.
+
+ at option{local} is only available on Linux.
+
+ at option{path} specifies the path to be exported. @option{path} is required.
+
+ at option{mount_tag} specifies the tag with which the exported file is mounted.
+ at option{mount_tag} is required.
+
+ at end table
+ETEXI
+#endif
+
 DEFHEADING()
 
 DEF("name", HAS_ARG, QEMU_OPTION_name,
diff --git a/vl.c b/vl.c
index 37f46b6..9caf96d 100644
--- a/vl.c
+++ b/vl.c
@@ -3102,6 +3102,62 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
                 break;
+            case QEMU_OPTION_virtfs: {
+                char *arg_fsdev = NULL;
+                char *arg_9p = NULL;
+                int len = 0;
+
+                opts = qemu_opts_parse(&qemu_virtfs_opts, optarg, 1);
+                if (!opts) {
+                    fprintf(stderr, "parse error: %s\n", optarg);
+                    exit(1);
+                }
+
+                len = strlen(",id=,path=");
+                len += strlen(qemu_opt_get(opts, "fstype"));
+                len += strlen(qemu_opt_get(opts, "mount_tag"));
+                len += strlen(qemu_opt_get(opts, "path"));
+                arg_fsdev = qemu_malloc((len + 1) * sizeof(*arg_fsdev));
+
+                if (!arg_fsdev) {
+                    fprintf(stderr, "No memory to parse -fsdev for %s\n",
+                            optarg);
+                    exit(1);
+                }
+
+                sprintf(arg_fsdev, "%s,id=%s,path=%s",
+                                qemu_opt_get(opts, "fstype"),
+                                qemu_opt_get(opts, "mount_tag"),
+                                qemu_opt_get(opts, "path"));
+
+                len = strlen("virtio-9p-pci,fsdev=,mount_tag=");
+                len += 2*strlen(qemu_opt_get(opts, "mount_tag"));
+                arg_9p = qemu_malloc((len + 1) * sizeof(*arg_9p));
+
+                if (!arg_9p) {
+                    fprintf(stderr, "No memory to parse -device for %s\n",
+                            optarg);
+                    exit(1);
+                }
+
+                sprintf(arg_9p, "virtio-9p-pci,fsdev=%s,mount_tag=%s",
+                                qemu_opt_get(opts, "mount_tag"),
+                                qemu_opt_get(opts, "mount_tag"));
+
+                if (!qemu_opts_parse(&qemu_fsdev_opts, arg_fsdev, 1)) {
+                    fprintf(stderr, "parse error [fsdev]: %s\n", optarg);
+                    exit(1);
+                }
+
+                if (!qemu_opts_parse(&qemu_device_opts, arg_9p, 1)) {
+                    fprintf(stderr, "parse error [device]: %s\n", optarg);
+                    exit(1);
+                }
+
+                qemu_free(arg_fsdev);
+                qemu_free(arg_9p);
+                break;
+            }
 #endif
             case QEMU_OPTION_serial:
                 add_device_config(DEV_SERIAL, optarg);
commit 9c5e9d8970d1822246f73be441c363a17ff1cc2c
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:45:02 2010 +0530

    virtio-9p: Add P9_TFLUSH support
    
    Don't do anything special for flush.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index ca8cf6e..e5d0112 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -932,35 +932,6 @@ static void print_sg(struct iovec *sg, int cnt)
     printf("}\n");
 }
 
-static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
-{
-    /* Note: The following have been added to prevent GCC from complaining
-     * They will be removed in the subsequent patches */
-    (void)pdu_unmarshal;
-    (void) complete_pdu;
-    (void) v9fs_string_init;
-    (void) v9fs_string_free;
-    (void) v9fs_string_null;
-    (void) v9fs_string_sprintf;
-    (void) v9fs_string_copy;
-    (void) v9fs_string_size;
-    (void) v9fs_do_lstat;
-    (void) v9fs_do_setuid;
-    (void) v9fs_do_readlink;
-    (void) v9fs_do_close;
-    (void) v9fs_do_closedir;
-    (void) alloc_fid;
-    (void) free_fid;
-    (void) fid_to_qid;
-    (void) v9mode_to_mode;
-    (void) donttouch_stat;
-    (void) v9fs_stat_free;
-    (void) stat_to_v9stat;
-    (void) adjust_sg;
-    (void) cap_sg;
-    (void) print_sg;
-}
-
 static void v9fs_fix_path(V9fsString *dst, V9fsString *src, int len)
 {
     V9fsString str;
@@ -1959,10 +1930,8 @@ out:
 
 static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)
 {
-    v9fs_dummy(s, pdu);
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
-    }
+    /* A nop call with no return */
+    complete_pdu(s, pdu, 7);
 }
 
 typedef struct V9fsRemoveState {
commit 5bae190082fc24d8881e5db9409fc94f6c46f219
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:45:01 2010 +0530

    virtio-9p: Add P9_TREMOVE support.
    
    Implement P9_TREMOVE support.
    This gets file deletion to work.
    
    [mohan at in.ibm.com: Fix truncate to use the relative path]
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 8ba1927..f84767f 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -34,6 +34,7 @@ typedef struct FileOperations
     int (*mknod)(FsContext *, const char *, mode_t, dev_t);
     int (*mksock)(FsContext *, const char *);
     int (*utime)(FsContext *, const char *, const struct utimbuf *);
+    int (*remove)(FsContext *, const char *);
     int (*symlink)(FsContext *, const char *, const char *);
     int (*link)(FsContext *, const char *, const char *);
     int (*setuid)(FsContext *, uid_t);
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 5a011f3..1afb731 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -252,6 +252,11 @@ static int local_utime(FsContext *ctx, const char *path,
     return utime(rpath(ctx, path), buf);
 }
 
+static int local_remove(FsContext *ctx, const char *path)
+{
+    return remove(rpath(ctx, path));
+}
+
 static int local_fsync(FsContext *ctx, int fd)
 {
     return fsync(fd);
@@ -284,5 +289,6 @@ FileOperations local_ops = {
     .rename = local_rename,
     .chown = local_chown,
     .utime = local_utime,
+    .remove = local_remove,
     .fsync = local_fsync,
 };
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 3288142..ca8cf6e 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -166,6 +166,11 @@ static int v9fs_do_utime(V9fsState *s, V9fsString *path,
     return s->ops->utime(&s->ctx, path->data, buf);
 }
 
+static int v9fs_do_remove(V9fsState *s, V9fsString *path)
+{
+    return s->ops->remove(&s->ctx, path->data);
+}
+
 static int v9fs_do_fsync(V9fsState *s, int fd)
 {
     return s->ops->fsync(&s->ctx, fd);
@@ -1960,11 +1965,52 @@ static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)
     }
 }
 
+typedef struct V9fsRemoveState {
+    V9fsPDU *pdu;
+    size_t offset;
+    V9fsFidState *fidp;
+} V9fsRemoveState;
+
+static void v9fs_remove_post_remove(V9fsState *s, V9fsRemoveState *vs,
+                                                                int err)
+{
+    /* For TREMOVE we need to clunk the fid even on failed remove */
+    err = free_fid(s, vs->fidp->fid);
+    if (err < 0) {
+        goto out;
+    }
+
+    err = vs->offset;
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
 static void v9fs_remove(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int32_t fid;
+    V9fsRemoveState *vs;
+    int err = 0;
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+
+    pdu_unmarshal(vs->pdu, vs->offset, "d", &fid);
+
+    vs->fidp = lookup_fid(s, fid);
+    if (vs->fidp == NULL) {
+        err = -EINVAL;
+        goto out;
     }
+
+    err = v9fs_do_remove(s, &vs->fidp->path);
+    v9fs_remove_post_remove(s, vs, err);
+    return;
+
+out:
+    complete_pdu(s, pdu, err);
+    qemu_free(vs);
 }
 
 typedef struct V9fsWstatState
commit 8cf89e007a37fff75c06e5a4564d530e51c1ec98
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:45:00 2010 +0530

    virtio-9p: Add P9_TWSTAT support
    
    Implement P9_TWSTAT support.
    This gets file and directory creation to work.
    
    [jvrao at linux.vnet.ibm.com: strdup to qemu_strdup conversion]
    [aneesh.kumar at linux.vnet.ibm.com: v9fs_fix_path]
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 5049b2e..8ba1927 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -30,8 +30,10 @@ typedef struct FileOperations
     int (*lstat)(FsContext *, const char *, struct stat *);
     ssize_t (*readlink)(FsContext *, const char *, char *, size_t);
     int (*chmod)(FsContext *, const char *, mode_t);
+    int (*chown)(FsContext *, const char *, uid_t, gid_t);
     int (*mknod)(FsContext *, const char *, mode_t, dev_t);
     int (*mksock)(FsContext *, const char *);
+    int (*utime)(FsContext *, const char *, const struct utimbuf *);
     int (*symlink)(FsContext *, const char *, const char *);
     int (*link)(FsContext *, const char *, const char *);
     int (*setuid)(FsContext *, uid_t);
@@ -49,6 +51,9 @@ typedef struct FileOperations
     off_t (*lseek)(FsContext *, int, off_t, int);
     int (*mkdir)(FsContext *, const char *, mode_t);
     int (*fstat)(FsContext *, int, struct stat *);
+    int (*rename)(FsContext *, const char *, const char *);
+    int (*truncate)(FsContext *, const char *, off_t);
+    int (*fsync)(FsContext *, int);
     void *opaque;
 } FileOperations;
 #endif
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index f6781ca..5a011f3 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -212,6 +212,51 @@ static int local_link(FsContext *ctx, const char *oldpath, const char *newpath)
     return err;
 }
 
+static int local_truncate(FsContext *ctx, const char *path, off_t size)
+{
+    return truncate(rpath(ctx, path), size);
+}
+
+static int local_rename(FsContext *ctx, const char *oldpath,
+                        const char *newpath)
+{
+    char *tmp;
+    int err;
+
+    tmp = qemu_strdup(rpath(ctx, oldpath));
+    if (tmp == NULL) {
+        return -1;
+    }
+
+    err = rename(tmp, rpath(ctx, newpath));
+    if (err == -1) {
+        int serrno = errno;
+        qemu_free(tmp);
+        errno = serrno;
+    } else {
+        qemu_free(tmp);
+    }
+
+    return err;
+
+}
+
+static int local_chown(FsContext *ctx, const char *path, uid_t uid, gid_t gid)
+{
+    return chown(rpath(ctx, path), uid, gid);
+}
+
+static int local_utime(FsContext *ctx, const char *path,
+                        const struct utimbuf *buf)
+{
+    return utime(rpath(ctx, path), buf);
+}
+
+static int local_fsync(FsContext *ctx, int fd)
+{
+    return fsync(fd);
+}
+
 FileOperations local_ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
@@ -235,4 +280,9 @@ FileOperations local_ops = {
     .open2 = local_open2,
     .symlink = local_symlink,
     .link = local_link,
+    .truncate = local_truncate,
+    .rename = local_rename,
+    .chown = local_chown,
+    .utime = local_utime,
+    .fsync = local_fsync,
 };
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index bb2a4ba..3288142 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -144,6 +144,33 @@ static int v9fs_do_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
     return s->ops->link(&s->ctx, oldpath->data, newpath->data);
 }
 
+static int v9fs_do_truncate(V9fsState *s, V9fsString *path, off_t size)
+{
+    return s->ops->truncate(&s->ctx, path->data, size);
+}
+
+static int v9fs_do_rename(V9fsState *s, V9fsString *oldpath,
+                            V9fsString *newpath)
+{
+    return s->ops->rename(&s->ctx, oldpath->data, newpath->data);
+}
+
+static int v9fs_do_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
+{
+    return s->ops->chown(&s->ctx, path->data, uid, gid);
+}
+
+static int v9fs_do_utime(V9fsState *s, V9fsString *path,
+                            const struct utimbuf *buf)
+{
+    return s->ops->utime(&s->ctx, path->data, buf);
+}
+
+static int v9fs_do_fsync(V9fsState *s, int fd)
+{
+    return s->ops->fsync(&s->ctx, fd);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -929,6 +956,15 @@ static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
     (void) print_sg;
 }
 
+static void v9fs_fix_path(V9fsString *dst, V9fsString *src, int len)
+{
+    V9fsString str;
+    v9fs_string_init(&str);
+    v9fs_string_copy(&str, dst);
+    v9fs_string_sprintf(dst, "%s%s", src->data, str.data+len);
+    v9fs_string_free(&str);
+}
+
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
 {
     int32_t msize;
@@ -1931,11 +1967,244 @@ static void v9fs_remove(V9fsState *s, V9fsPDU *pdu)
     }
 }
 
+typedef struct V9fsWstatState
+{
+    V9fsPDU *pdu;
+    size_t offset;
+    int16_t unused;
+    V9fsStat v9stat;
+    V9fsFidState *fidp;
+    struct stat stbuf;
+    V9fsString nname;
+} V9fsWstatState;
+
+static void v9fs_wstat_post_truncate(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    if (err < 0) {
+        goto out;
+    }
+
+    err = vs->offset;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_wstat_post_rename(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    if (err < 0) {
+        goto out;
+    }
+
+    if (vs->v9stat.name.size != 0) {
+        v9fs_string_free(&vs->nname);
+    }
+
+    if (vs->v9stat.length != -1) {
+        if (v9fs_do_truncate(s, &vs->fidp->path, vs->v9stat.length) < 0) {
+            err = -errno;
+        }
+    }
+    v9fs_wstat_post_truncate(s, vs, err);
+    return;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_wstat_post_chown(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    V9fsFidState *fidp;
+    if (err < 0) {
+        goto out;
+    }
+
+    if (vs->v9stat.name.size != 0) {
+        char *old_name, *new_name;
+        char *end;
+
+        old_name = vs->fidp->path.data;
+        end = strrchr(old_name, '/');
+        if (end) {
+            end++;
+        } else {
+            end = old_name;
+        }
+
+        new_name = qemu_malloc(end - old_name + vs->v9stat.name.size + 1);
+
+        memset(new_name, 0, end - old_name + vs->v9stat.name.size + 1);
+        memcpy(new_name, old_name, end - old_name);
+        memcpy(new_name + (end - old_name), vs->v9stat.name.data,
+                vs->v9stat.name.size);
+        vs->nname.data = new_name;
+        vs->nname.size = strlen(new_name);
+
+        if (strcmp(new_name, vs->fidp->path.data) != 0) {
+            if (v9fs_do_rename(s, &vs->fidp->path, &vs->nname)) {
+                err = -errno;
+            } else {
+                /*
+                 * Fixup fid's pointing to the old name to
+                 * start pointing to the new name
+                 */
+                for (fidp = s->fid_list; fidp; fidp = fidp->next) {
+
+                    if (vs->fidp == fidp) {
+                        /*
+                         * we replace name of this fid towards the end
+                         * so that our below strcmp will work
+                         */
+                        continue;
+                    }
+                    if (!strncmp(vs->fidp->path.data, fidp->path.data,
+                                 strlen(vs->fidp->path.data))) {
+                        /* replace the name */
+                        v9fs_fix_path(&fidp->path, &vs->nname,
+                                      strlen(vs->fidp->path.data));
+                    }
+                }
+                v9fs_string_copy(&vs->fidp->path, &vs->nname);
+            }
+        }
+    }
+    v9fs_wstat_post_rename(s, vs, err);
+    return;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_wstat_post_utime(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    if (err < 0) {
+        goto out;
+    }
+
+    if (vs->v9stat.n_gid != -1) {
+        if (v9fs_do_chown(s, &vs->fidp->path, vs->v9stat.n_uid,
+                    vs->v9stat.n_gid)) {
+            err = -errno;
+        }
+    }
+    v9fs_wstat_post_chown(s, vs, err);
+    return;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_wstat_post_chmod(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    if (err < 0) {
+        goto out;
+    }
+
+    if (vs->v9stat.mtime != -1) {
+        struct utimbuf tb;
+        tb.actime = 0;
+        tb.modtime = vs->v9stat.mtime;
+        if (v9fs_do_utime(s, &vs->fidp->path, &tb)) {
+            err = -errno;
+        }
+    }
+
+    v9fs_wstat_post_utime(s, vs, err);
+    return;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_wstat_post_fsync(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    if (err == -1) {
+        err = -errno;
+    }
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_wstat_post_lstat(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    uint32_t v9_mode;
+
+    if (err == -1) {
+        err = -errno;
+        goto out;
+    }
+
+    v9_mode = stat_to_v9mode(&vs->stbuf);
+
+    if ((vs->v9stat.mode & P9_STAT_MODE_TYPE_BITS) !=
+        (v9_mode & P9_STAT_MODE_TYPE_BITS)) {
+            /* Attempting to change the type */
+            err = -EIO;
+            goto out;
+    }
+
+    if (v9fs_do_chmod(s, &vs->fidp->path, v9mode_to_mode(vs->v9stat.mode,
+                    &vs->v9stat.extension))) {
+            err = -errno;
+     }
+    v9fs_wstat_post_chmod(s, vs, err);
+    return;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
 static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int32_t fid;
+    V9fsWstatState *vs;
+    int err = 0;
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+
+    pdu_unmarshal(pdu, vs->offset, "dwS", &fid, &vs->unused, &vs->v9stat);
+
+    vs->fidp = lookup_fid(s, fid);
+    if (vs->fidp == NULL) {
+        err = -EINVAL;
+        goto out;
     }
+
+    /* do we need to sync the file? */
+    if (donttouch_stat(&vs->v9stat)) {
+        err = v9fs_do_fsync(s, vs->fidp->fd);
+        v9fs_wstat_post_fsync(s, vs, err);
+        return;
+    }
+
+    if (vs->v9stat.mode != -1) {
+        err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
+        v9fs_wstat_post_lstat(s, vs, err);
+        return;
+    }
+
+    v9fs_wstat_post_chmod(s, vs, err);
+    return;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
 }
 
 typedef void (pdu_handler_t)(V9fsState *s, V9fsPDU *pdu);
commit c494dd6f28dbacd855bca894c664bf1f9836afe9
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:44:59 2010 +0530

    virtio-9p: Add P9_TCREATE support
    
    Implement P9_TCREATE support.
    [jvrao at linux.vnet.ibm.com: strdup to qemu_strdup conversion]
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 12503c1..5049b2e 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -29,11 +29,17 @@ typedef struct FileOperations
 {
     int (*lstat)(FsContext *, const char *, struct stat *);
     ssize_t (*readlink)(FsContext *, const char *, char *, size_t);
+    int (*chmod)(FsContext *, const char *, mode_t);
+    int (*mknod)(FsContext *, const char *, mode_t, dev_t);
+    int (*mksock)(FsContext *, const char *);
+    int (*symlink)(FsContext *, const char *, const char *);
+    int (*link)(FsContext *, const char *, const char *);
     int (*setuid)(FsContext *, uid_t);
     int (*close)(FsContext *, int);
     int (*closedir)(FsContext *, DIR *);
     DIR *(*opendir)(FsContext *, const char *);
     int (*open)(FsContext *, const char *, int);
+    int (*open2)(FsContext *, const char *, int, mode_t);
     void (*rewinddir)(FsContext *, DIR *);
     off_t (*telldir)(FsContext *, DIR *);
     struct dirent *(*readdir)(FsContext *, DIR *);
@@ -41,6 +47,8 @@ typedef struct FileOperations
     ssize_t (*readv)(FsContext *, int, const struct iovec *, int);
     ssize_t (*writev)(FsContext *, int, const struct iovec *, int);
     off_t (*lseek)(FsContext *, int, off_t, int);
+    int (*mkdir)(FsContext *, const char *, mode_t);
+    int (*fstat)(FsContext *, int, struct stat *);
     void *opaque;
 } FileOperations;
 #endif
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 87aeba8..f6781ca 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -12,8 +12,11 @@
  */
 #include "virtio.h"
 #include "virtio-9p.h"
+#include <arpa/inet.h>
 #include <pwd.h>
 #include <grp.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 
 static const char *rpath(FsContext *ctx, const char *path)
 {
@@ -133,6 +136,82 @@ static ssize_t local_writev(FsContext *ctx, int fd, const struct iovec *iov,
     return writev(fd, iov, iovcnt);
 }
 
+static int local_chmod(FsContext *ctx, const char *path, mode_t mode)
+{
+    return chmod(rpath(ctx, path), mode);
+}
+
+static int local_mknod(FsContext *ctx, const char *path, mode_t mode, dev_t dev)
+{
+    return mknod(rpath(ctx, path), mode, dev);
+}
+
+static int local_mksock(FsContext *ctx2, const char *path)
+{
+    struct sockaddr_un addr;
+    int s;
+
+    addr.sun_family = AF_UNIX;
+    snprintf(addr.sun_path, 108, "%s", rpath(ctx2, path));
+
+    s = socket(PF_UNIX, SOCK_STREAM, 0);
+    if (s == -1) {
+        return -1;
+    }
+
+    if (bind(s, (struct sockaddr *)&addr, sizeof(addr))) {
+        close(s);
+        return -1;
+    }
+
+    close(s);
+    return 0;
+}
+
+static int local_mkdir(FsContext *ctx, const char *path, mode_t mode)
+{
+    return mkdir(rpath(ctx, path), mode);
+}
+
+static int local_fstat(FsContext *ctx, int fd, struct stat *stbuf)
+{
+    return fstat(fd, stbuf);
+}
+
+static int local_open2(FsContext *ctx, const char *path, int flags, mode_t mode)
+{
+    return open(rpath(ctx, path), flags, mode);
+}
+
+static int local_symlink(FsContext *ctx, const char *oldpath,
+                            const char *newpath)
+{
+    return symlink(oldpath, rpath(ctx, newpath));
+}
+
+static int local_link(FsContext *ctx, const char *oldpath, const char *newpath)
+{
+    char *tmp = qemu_strdup(rpath(ctx, oldpath));
+    int err, serrno = 0;
+
+    if (tmp == NULL) {
+        return -ENOMEM;
+    }
+
+    err = link(tmp, rpath(ctx, newpath));
+    if (err == -1) {
+        serrno = errno;
+    }
+
+    qemu_free(tmp);
+
+    if (err == -1) {
+        errno = serrno;
+    }
+
+    return err;
+}
+
 FileOperations local_ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
@@ -148,4 +227,12 @@ FileOperations local_ops = {
     .readv = local_readv,
     .lseek = local_lseek,
     .writev = local_writev,
+    .chmod = local_chmod,
+    .mknod = local_mknod,
+    .mksock = local_mksock,
+    .mkdir = local_mkdir,
+    .fstat = local_fstat,
+    .open2 = local_open2,
+    .symlink = local_symlink,
+    .link = local_link,
 };
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 252eaa9..bb2a4ba 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -103,6 +103,47 @@ static int v9fs_do_writev(V9fsState *s, int fd, const struct iovec *iov,
     return s->ops->writev(&s->ctx, fd, iov, iovcnt);
 }
 
+static int v9fs_do_chmod(V9fsState *s, V9fsString *path, mode_t mode)
+{
+    return s->ops->chmod(&s->ctx, path->data, mode);
+}
+
+static int v9fs_do_mknod(V9fsState *s, V9fsString *path, mode_t mode, dev_t dev)
+{
+    return s->ops->mknod(&s->ctx, path->data, mode, dev);
+}
+
+static int v9fs_do_mksock(V9fsState *s, V9fsString *path)
+{
+    return s->ops->mksock(&s->ctx, path->data);
+}
+
+static int v9fs_do_mkdir(V9fsState *s, V9fsString *path, mode_t mode)
+{
+    return s->ops->mkdir(&s->ctx, path->data, mode);
+}
+
+static int v9fs_do_fstat(V9fsState *s, int fd, struct stat *stbuf)
+{
+    return s->ops->fstat(&s->ctx, fd, stbuf);
+}
+
+static int v9fs_do_open2(V9fsState *s, V9fsString *path, int flags, mode_t mode)
+{
+    return s->ops->open2(&s->ctx, path->data, flags, mode);
+}
+
+static int v9fs_do_symlink(V9fsState *s, V9fsString *oldpath,
+                            V9fsString *newpath)
+{
+    return s->ops->symlink(&s->ctx, oldpath->data, newpath->data);
+}
+
+static int v9fs_do_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
+{
+    return s->ops->link(&s->ctx, oldpath->data, newpath->data);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -1649,11 +1690,230 @@ out:
     qemu_free(vs);
 }
 
+typedef struct V9fsCreateState {
+    V9fsPDU *pdu;
+    size_t offset;
+    V9fsFidState *fidp;
+    V9fsQID qid;
+    int32_t perm;
+    int8_t mode;
+    struct stat stbuf;
+    V9fsString name;
+    V9fsString extension;
+    V9fsString fullname;
+} V9fsCreateState;
+
+static void v9fs_post_create(V9fsState *s, V9fsCreateState *vs, int err)
+{
+    if (err == 0) {
+        v9fs_string_copy(&vs->fidp->path, &vs->fullname);
+        stat_to_qid(&vs->stbuf, &vs->qid);
+
+        vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, 0);
+
+        err = vs->offset;
+    }
+
+    complete_pdu(s, vs->pdu, err);
+    v9fs_string_free(&vs->name);
+    v9fs_string_free(&vs->extension);
+    v9fs_string_free(&vs->fullname);
+    qemu_free(vs);
+}
+
+static void v9fs_create_post_perms(V9fsState *s, V9fsCreateState *vs, int err)
+{
+    if (err) {
+        err = -errno;
+    }
+    v9fs_post_create(s, vs, err);
+}
+
+static void v9fs_create_post_opendir(V9fsState *s, V9fsCreateState *vs,
+                                                                    int err)
+{
+    if (!vs->fidp->dir) {
+        err = -errno;
+    }
+    v9fs_post_create(s, vs, err);
+}
+
+static void v9fs_create_post_dir_lstat(V9fsState *s, V9fsCreateState *vs,
+                                                                    int err)
+{
+    if (err) {
+        err = -errno;
+        goto out;
+    }
+
+    vs->fidp->dir = v9fs_do_opendir(s, &vs->fullname);
+    v9fs_create_post_opendir(s, vs, err);
+    return;
+
+out:
+    v9fs_post_create(s, vs, err);
+}
+
+static void v9fs_create_post_mkdir(V9fsState *s, V9fsCreateState *vs, int err)
+{
+    if (err) {
+        err = -errno;
+        goto out;
+    }
+
+    err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
+    v9fs_create_post_dir_lstat(s, vs, err);
+    return;
+
+out:
+    v9fs_post_create(s, vs, err);
+}
+
+static void v9fs_create_post_mksock(V9fsState *s, V9fsCreateState *vs,
+                                                                int err)
+{
+    if (err) {
+        err = -errno;
+        goto out;
+    }
+
+    err = v9fs_do_chmod(s, &vs->fullname, vs->perm & 0777);
+    v9fs_create_post_perms(s, vs, err);
+    return;
+
+out:
+    v9fs_post_create(s, vs, err);
+}
+
+static void v9fs_create_post_fstat(V9fsState *s, V9fsCreateState *vs, int err)
+{
+    if (err) {
+        vs->fidp->fd = -1;
+        err = -errno;
+    }
+
+    v9fs_post_create(s, vs, err);
+    return;
+}
+
+static void v9fs_create_post_open2(V9fsState *s, V9fsCreateState *vs, int err)
+{
+    if (vs->fidp->fd == -1) {
+        err = -errno;
+        goto out;
+    }
+
+    err = v9fs_do_fstat(s, vs->fidp->fd, &vs->stbuf);
+    v9fs_create_post_fstat(s, vs, err);
+
+    return;
+
+out:
+    v9fs_post_create(s, vs, err);
+
+}
+
+static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
+{
+
+    if (err == 0 || errno != ENOENT) {
+        err = -errno;
+        goto out;
+    }
+
+    if (vs->perm & P9_STAT_MODE_DIR) {
+        err = v9fs_do_mkdir(s, &vs->fullname, vs->perm & 0777);
+        v9fs_create_post_mkdir(s, vs, err);
+    } else if (vs->perm & P9_STAT_MODE_SYMLINK) {
+        err = v9fs_do_symlink(s, &vs->extension, &vs->fullname);
+        v9fs_create_post_perms(s, vs, err);
+    } else if (vs->perm & P9_STAT_MODE_LINK) {
+        int32_t nfid = atoi(vs->extension.data);
+        V9fsFidState *nfidp = lookup_fid(s, nfid);
+        if (nfidp == NULL) {
+            err = -errno;
+            v9fs_post_create(s, vs, err);
+        }
+        err = v9fs_do_link(s, &nfidp->path, &vs->fullname);
+        v9fs_create_post_perms(s, vs, err);
+    } else if (vs->perm & P9_STAT_MODE_DEVICE) {
+        char ctype;
+        uint32_t major, minor;
+        mode_t nmode = 0;
+
+        if (sscanf(vs->extension.data, "%c %u %u", &ctype, &major,
+                                        &minor) != 3) {
+            err = -errno;
+            v9fs_post_create(s, vs, err);
+        }
+
+        switch (ctype) {
+        case 'c':
+            nmode = S_IFCHR;
+            break;
+        case 'b':
+            nmode = S_IFBLK;
+            break;
+        default:
+            err = -EIO;
+            v9fs_post_create(s, vs, err);
+        }
+
+        nmode |= vs->perm & 0777;
+        err = v9fs_do_mknod(s, &vs->fullname, nmode, makedev(major, minor));
+        v9fs_create_post_perms(s, vs, err);
+    } else if (vs->perm & P9_STAT_MODE_NAMED_PIPE) {
+        err = v9fs_do_mknod(s, &vs->fullname, S_IFIFO | (vs->mode & 0777), 0);
+        v9fs_post_create(s, vs, err);
+    } else if (vs->perm & P9_STAT_MODE_SOCKET) {
+        err = v9fs_do_mksock(s, &vs->fullname);
+        v9fs_create_post_mksock(s, vs, err);
+    } else {
+        vs->fidp->fd = v9fs_do_open2(s, &vs->fullname,
+                                omode_to_uflags(vs->mode) | O_CREAT,
+                                vs->perm & 0777);
+        v9fs_create_post_open2(s, vs, err);
+    }
+
+    return;
+
+out:
+    v9fs_post_create(s, vs, err);
+}
+
 static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int32_t fid;
+    V9fsCreateState *vs;
+    int err = 0;
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+
+    v9fs_string_init(&vs->fullname);
+
+    pdu_unmarshal(vs->pdu, vs->offset, "dsdbs", &fid, &vs->name,
+                                &vs->perm, &vs->mode, &vs->extension);
+
+    vs->fidp = lookup_fid(s, fid);
+    if (vs->fidp == NULL) {
+        err = -EINVAL;
+        goto out;
     }
+
+    v9fs_string_sprintf(&vs->fullname, "%s/%s", vs->fidp->path.data,
+                                                        vs->name.data);
+
+    err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf);
+    v9fs_create_post_lstat(s, vs, err);
+    return;
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    v9fs_string_free(&vs->name);
+    v9fs_string_free(&vs->extension);
+    qemu_free(vs);
 }
 
 static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)
commit 8449360cbde906bb36ca2181d3723bae2fd10742
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:44:58 2010 +0530

    virtio-9p: Add P9_TWRITE support
    
    Implement P9_TWRITE support.
    This gets write to file to work
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index c1f5e45..12503c1 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -39,6 +39,7 @@ typedef struct FileOperations
     struct dirent *(*readdir)(FsContext *, DIR *);
     void (*seekdir)(FsContext *, DIR *, off_t);
     ssize_t (*readv)(FsContext *, int, const struct iovec *, int);
+    ssize_t (*writev)(FsContext *, int, const struct iovec *, int);
     off_t (*lseek)(FsContext *, int, off_t, int);
     void *opaque;
 } FileOperations;
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 81d1971..87aeba8 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -127,6 +127,12 @@ static off_t local_lseek(FsContext *ctx, int fd, off_t offset, int whence)
     return lseek(fd, offset, whence);
 }
 
+static ssize_t local_writev(FsContext *ctx, int fd, const struct iovec *iov,
+                            int iovcnt)
+{
+    return writev(fd, iov, iovcnt);
+}
+
 FileOperations local_ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
@@ -141,4 +147,5 @@ FileOperations local_ops = {
     .seekdir = local_seekdir,
     .readv = local_readv,
     .lseek = local_lseek,
+    .writev = local_writev,
 };
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index b9b892c..252eaa9 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -97,6 +97,12 @@ static off_t v9fs_do_lseek(V9fsState *s, int fd, off_t offset, int whence)
     return s->ops->lseek(&s->ctx, fd, offset, whence);
 }
 
+static int v9fs_do_writev(V9fsState *s, int fd, const struct iovec *iov,
+                       int iovcnt)
+{
+    return s->ops->writev(&s->ctx, fd, iov, iovcnt);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -1534,11 +1540,113 @@ out:
     qemu_free(vs);
 }
 
+typedef struct V9fsWriteState {
+    V9fsPDU *pdu;
+    size_t offset;
+    int32_t len;
+    int32_t count;
+    int32_t total;
+    int64_t off;
+    V9fsFidState *fidp;
+    struct iovec iov[128]; /* FIXME: bad, bad, bad */
+    struct iovec *sg;
+    int cnt;
+} V9fsWriteState;
+
+static void v9fs_write_post_writev(V9fsState *s, V9fsWriteState *vs,
+                                   ssize_t err)
+{
+    if (err  < 0) {
+        /* IO error return the error */
+        err = -errno;
+        goto out;
+    }
+    vs->total += vs->len;
+    vs->sg = adjust_sg(vs->sg, vs->len, &vs->cnt);
+    if (vs->total < vs->count && vs->len > 0) {
+        do {
+            if (0) {
+                print_sg(vs->sg, vs->cnt);
+            }
+            vs->len =  v9fs_do_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
+        } while (vs->len == -1 && errno == EINTR);
+        if (vs->len == -1) {
+            err  = -errno;
+        }
+        v9fs_write_post_writev(s, vs, err);
+        return;
+    }
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total);
+
+    err = vs->offset;
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_write_post_lseek(V9fsState *s, V9fsWriteState *vs, ssize_t err)
+{
+    if (err == -1) {
+        err = -errno;
+        goto out;
+    }
+    vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt);
+
+    if (vs->total < vs->count) {
+        do {
+            if (0) {
+                print_sg(vs->sg, vs->cnt);
+            }
+            vs->len = v9fs_do_writev(s, vs->fidp->fd, vs->sg, vs->cnt);
+        } while (vs->len == -1 && errno == EINTR);
+        if (vs->len == -1) {
+            err  = -errno;
+        }
+        v9fs_write_post_writev(s, vs, err);
+        return;
+    }
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
 static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int32_t fid;
+    V9fsWriteState *vs;
+    ssize_t err;
+
+    vs = qemu_malloc(sizeof(*vs));
+
+    vs->pdu = pdu;
+    vs->offset = 7;
+    vs->sg = vs->iov;
+    vs->total = 0;
+    vs->len = 0;
+
+    pdu_unmarshal(vs->pdu, vs->offset, "dqdv", &fid, &vs->off, &vs->count,
+                    vs->sg, &vs->cnt);
+
+    vs->fidp = lookup_fid(s, fid);
+    if (vs->fidp == NULL) {
+        err = -EINVAL;
+        goto out;
     }
+
+    if (vs->fidp->fd == -1) {
+        err = -EINVAL;
+        goto out;
+    }
+
+    err = v9fs_do_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
+
+    v9fs_write_post_lseek(s, vs, err);
+    return;
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
 }
 
 static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
commit bbd5697b8ea7e8795e83d3550cd1a11077c57fd4
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:44:57 2010 +0530

    virtio-9p: Add P9_TCLUNK support
    
    Implement P9_TCLUNK support.
    This patch gets `ls -al` to work.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 96e75d6..b9b892c 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -1311,9 +1311,21 @@ out:
 
 static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int32_t fid;
+    size_t offset = 7;
+    int err;
+
+    pdu_unmarshal(pdu, offset, "d", &fid);
+
+    err = free_fid(s, fid);
+    if (err < 0) {
+        goto out;
     }
+
+    offset = 7;
+    err = offset;
+out:
+    complete_pdu(s, pdu, err);
 }
 
 typedef struct V9fsReadState {
commit a92315553df516a5e3431142aadab93482c6b29f
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:44:56 2010 +0530

    virtio-9p: Add P9_TREAD support
    
    Implement P9_TREAD support.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 715f2d0..c1f5e45 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -34,6 +34,12 @@ typedef struct FileOperations
     int (*closedir)(FsContext *, DIR *);
     DIR *(*opendir)(FsContext *, const char *);
     int (*open)(FsContext *, const char *, int);
+    void (*rewinddir)(FsContext *, DIR *);
+    off_t (*telldir)(FsContext *, DIR *);
+    struct dirent *(*readdir)(FsContext *, DIR *);
+    void (*seekdir)(FsContext *, DIR *, off_t);
+    ssize_t (*readv)(FsContext *, int, const struct iovec *, int);
+    off_t (*lseek)(FsContext *, int, off_t, int);
     void *opaque;
 } FileOperations;
 #endif
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 3788d4e..81d1971 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -96,6 +96,37 @@ static DIR *local_opendir(FsContext *ctx, const char *path)
     return opendir(rpath(ctx, path));
 }
 
+static void local_rewinddir(FsContext *ctx, DIR *dir)
+{
+    return rewinddir(dir);
+}
+
+static off_t local_telldir(FsContext *ctx, DIR *dir)
+{
+    return telldir(dir);
+}
+
+static struct dirent *local_readdir(FsContext *ctx, DIR *dir)
+{
+    return readdir(dir);
+}
+
+static void local_seekdir(FsContext *ctx, DIR *dir, off_t off)
+{
+    return seekdir(dir, off);
+}
+
+static ssize_t local_readv(FsContext *ctx, int fd, const struct iovec *iov,
+                            int iovcnt)
+{
+    return readv(fd, iov, iovcnt);
+}
+
+static off_t local_lseek(FsContext *ctx, int fd, off_t offset, int whence)
+{
+    return lseek(fd, offset, whence);
+}
+
 FileOperations local_ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
@@ -104,4 +135,10 @@ FileOperations local_ops = {
     .closedir = local_closedir,
     .open = local_open,
     .opendir = local_opendir,
+    .rewinddir = local_rewinddir,
+    .telldir = local_telldir,
+    .readdir = local_readdir,
+    .seekdir = local_seekdir,
+    .readv = local_readv,
+    .lseek = local_lseek,
 };
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index e98da1b..96e75d6 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -66,6 +66,37 @@ static DIR *v9fs_do_opendir(V9fsState *s, V9fsString *path)
     return s->ops->opendir(&s->ctx, path->data);
 }
 
+static void v9fs_do_rewinddir(V9fsState *s, DIR *dir)
+{
+    return s->ops->rewinddir(&s->ctx, dir);
+}
+
+static off_t v9fs_do_telldir(V9fsState *s, DIR *dir)
+{
+    return s->ops->telldir(&s->ctx, dir);
+}
+
+static struct dirent *v9fs_do_readdir(V9fsState *s, DIR *dir)
+{
+    return s->ops->readdir(&s->ctx, dir);
+}
+
+static void v9fs_do_seekdir(V9fsState *s, DIR *dir, off_t off)
+{
+    return s->ops->seekdir(&s->ctx, dir, off);
+}
+
+static int v9fs_do_readv(V9fsState *s, int fd, const struct iovec *iov,
+                            int iovcnt)
+{
+    return s->ops->readv(&s->ctx, fd, iov, iovcnt);
+}
+
+static off_t v9fs_do_lseek(V9fsState *s, int fd, off_t offset, int whence)
+{
+    return s->ops->lseek(&s->ctx, fd, offset, whence);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -1285,11 +1316,210 @@ static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
     }
 }
 
+typedef struct V9fsReadState {
+    V9fsPDU *pdu;
+    size_t offset;
+    int32_t count;
+    int32_t total;
+    int64_t off;
+    V9fsFidState *fidp;
+    struct iovec iov[128]; /* FIXME: bad, bad, bad */
+    struct iovec *sg;
+    off_t dir_pos;
+    struct dirent *dent;
+    struct stat stbuf;
+    V9fsString name;
+    V9fsStat v9stat;
+    int32_t len;
+    int32_t cnt;
+    int32_t max_count;
+} V9fsReadState;
+
+static void v9fs_read_post_readdir(V9fsState *, V9fsReadState *, ssize_t);
+
+static void v9fs_read_post_seekdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
+{
+    if (err) {
+        goto out;
+    }
+    v9fs_stat_free(&vs->v9stat);
+    v9fs_string_free(&vs->name);
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count);
+    vs->offset += vs->count;
+    err = vs->offset;
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+    return;
+}
+
+static void v9fs_read_post_dir_lstat(V9fsState *s, V9fsReadState *vs,
+                                    ssize_t err)
+{
+    if (err) {
+        err = -errno;
+        goto out;
+    }
+    err = stat_to_v9stat(s, &vs->name, &vs->stbuf, &vs->v9stat);
+    if (err) {
+        goto out;
+    }
+
+    vs->len = pdu_marshal(vs->pdu, vs->offset + 4 + vs->count, "S",
+                            &vs->v9stat);
+    if ((vs->len != (vs->v9stat.size + 2)) ||
+            ((vs->count + vs->len) > vs->max_count)) {
+        v9fs_do_seekdir(s, vs->fidp->dir, vs->dir_pos);
+        v9fs_read_post_seekdir(s, vs, err);
+        return;
+    }
+    vs->count += vs->len;
+    v9fs_stat_free(&vs->v9stat);
+    v9fs_string_free(&vs->name);
+    vs->dir_pos = vs->dent->d_off;
+    vs->dent = v9fs_do_readdir(s, vs->fidp->dir);
+    v9fs_read_post_readdir(s, vs, err);
+    return;
+out:
+    v9fs_do_seekdir(s, vs->fidp->dir, vs->dir_pos);
+    v9fs_read_post_seekdir(s, vs, err);
+    return;
+
+}
+
+static void v9fs_read_post_readdir(V9fsState *s, V9fsReadState *vs, ssize_t err)
+{
+    if (vs->dent) {
+        memset(&vs->v9stat, 0, sizeof(vs->v9stat));
+        v9fs_string_init(&vs->name);
+        v9fs_string_sprintf(&vs->name, "%s/%s", vs->fidp->path.data,
+                            vs->dent->d_name);
+        err = v9fs_do_lstat(s, &vs->name, &vs->stbuf);
+        v9fs_read_post_dir_lstat(s, vs, err);
+        return;
+    }
+
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count);
+    vs->offset += vs->count;
+    err = vs->offset;
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+    return;
+}
+
+static void v9fs_read_post_telldir(V9fsState *s, V9fsReadState *vs, ssize_t err)
+{
+    vs->dent = v9fs_do_readdir(s, vs->fidp->dir);
+    v9fs_read_post_readdir(s, vs, err);
+    return;
+}
+
+static void v9fs_read_post_rewinddir(V9fsState *s, V9fsReadState *vs,
+                                       ssize_t err)
+{
+    vs->dir_pos = v9fs_do_telldir(s, vs->fidp->dir);
+    v9fs_read_post_telldir(s, vs, err);
+    return;
+}
+
+static void v9fs_read_post_readv(V9fsState *s, V9fsReadState *vs, ssize_t err)
+{
+    if (err  < 0) {
+        /* IO error return the error */
+        err = -errno;
+        goto out;
+    }
+    vs->total += vs->len;
+    vs->sg = adjust_sg(vs->sg, vs->len, &vs->cnt);
+    if (vs->total < vs->count && vs->len > 0) {
+        do {
+            if (0) {
+                print_sg(vs->sg, vs->cnt);
+            }
+            vs->len = v9fs_do_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
+        } while (vs->len == -1 && errno == EINTR);
+        if (vs->len == -1) {
+            err  = -errno;
+        }
+        v9fs_read_post_readv(s, vs, err);
+        return;
+    }
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->total);
+    vs->offset += vs->count;
+    err = vs->offset;
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_read_post_lseek(V9fsState *s, V9fsReadState *vs, ssize_t err)
+{
+    if (err == -1) {
+        err = -errno;
+        goto out;
+    }
+    vs->sg = cap_sg(vs->sg, vs->count, &vs->cnt);
+
+    if (vs->total < vs->count) {
+        do {
+            if (0) {
+                print_sg(vs->sg, vs->cnt);
+            }
+            vs->len = v9fs_do_readv(s, vs->fidp->fd, vs->sg, vs->cnt);
+        } while (vs->len == -1 && errno == EINTR);
+        if (vs->len == -1) {
+            err  = -errno;
+        }
+        v9fs_read_post_readv(s, vs, err);
+        return;
+    }
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
 static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int32_t fid;
+    V9fsReadState *vs;
+    ssize_t err = 0;
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+    vs->total = 0;
+    vs->len = 0;
+    vs->count = 0;
+
+    pdu_unmarshal(vs->pdu, vs->offset, "dqd", &fid, &vs->off, &vs->count);
+
+    vs->fidp = lookup_fid(s, fid);
+    if (vs->fidp == NULL) {
+        err = -EINVAL;
+        goto out;
+    }
+
+    if (vs->fidp->dir) {
+        vs->max_count = vs->count;
+        vs->count = 0;
+        if (vs->off == 0) {
+            v9fs_do_rewinddir(s, vs->fidp->dir);
+        }
+        v9fs_read_post_rewinddir(s, vs, err);
+        return;
+    } else if (vs->fidp->fd != -1) {
+        vs->sg = vs->iov;
+        pdu_marshal(vs->pdu, vs->offset + 4, "v", vs->sg, &vs->cnt);
+        err = v9fs_do_lseek(s, vs->fidp->fd, vs->off, SEEK_SET);
+        v9fs_read_post_lseek(s, vs, err);
+        return;
+    } else {
+        err = -EINVAL;
     }
+out:
+    complete_pdu(s, pdu, err);
+    qemu_free(vs);
 }
 
 static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
commit a6568fe27fdb50a46109b48612128cf712e60130
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:44:55 2010 +0530

    virtio-9p: Add P9_TOPEN support.
    
    Implement P9_TOPEN support.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 461df9e..715f2d0 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -32,6 +32,8 @@ typedef struct FileOperations
     int (*setuid)(FsContext *, uid_t);
     int (*close)(FsContext *, int);
     int (*closedir)(FsContext *, DIR *);
+    DIR *(*opendir)(FsContext *, const char *);
+    int (*open)(FsContext *, const char *, int);
     void *opaque;
 } FileOperations;
 #endif
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 880cd0a..3788d4e 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -86,10 +86,22 @@ static int local_closedir(FsContext *ctx, DIR *dir)
     return closedir(dir);
 }
 
+static int local_open(FsContext *ctx, const char *path, int flags)
+{
+    return open(rpath(ctx, path), flags);
+}
+
+static DIR *local_opendir(FsContext *ctx, const char *path)
+{
+    return opendir(rpath(ctx, path));
+}
+
 FileOperations local_ops = {
     .lstat = local_lstat,
     .setuid = local_setuid,
     .readlink = local_readlink,
     .close = local_close,
     .closedir = local_closedir,
+    .open = local_open,
+    .opendir = local_opendir,
 };
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 18811c3..e98da1b 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -56,6 +56,16 @@ static int v9fs_do_closedir(V9fsState *s, DIR *dir)
     return s->ops->closedir(&s->ctx, dir);
 }
 
+static int v9fs_do_open(V9fsState *s, V9fsString *path, int flags)
+{
+    return s->ops->open(&s->ctx, path->data, flags);
+}
+
+static DIR *v9fs_do_opendir(V9fsState *s, V9fsString *path)
+{
+    return s->ops->opendir(&s->ctx, path->data);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -1129,17 +1139,150 @@ out:
     v9fs_walk_complete(s, vs, err);
 }
 
-static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
+typedef struct V9fsOpenState {
+    V9fsPDU *pdu;
+    size_t offset;
+    int8_t mode;
+    V9fsFidState *fidp;
+    V9fsQID qid;
+    struct stat stbuf;
+
+} V9fsOpenState;
+
+enum {
+    Oread   = 0x00,
+    Owrite  = 0x01,
+    Ordwr   = 0x02,
+    Oexec   = 0x03,
+    Oexcl   = 0x04,
+    Otrunc  = 0x10,
+    Orexec  = 0x20,
+    Orclose = 0x40,
+    Oappend = 0x80,
+};
+
+static int omode_to_uflags(int8_t mode)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int ret = 0;
+
+    switch (mode & 3) {
+    case Oread:
+        ret = O_RDONLY;
+        break;
+    case Ordwr:
+        ret = O_RDWR;
+        break;
+    case Owrite:
+        ret = O_WRONLY;
+        break;
+    case Oexec:
+        ret = O_RDONLY;
+        break;
     }
+
+    if (mode & Otrunc) {
+        ret |= O_TRUNC;
+    }
+
+    if (mode & Oappend) {
+        ret |= O_APPEND;
+    }
+
+    if (mode & Oexcl) {
+        ret |= O_EXCL;
+    }
+
+    return ret;
+}
+
+static void v9fs_open_post_opendir(V9fsState *s, V9fsOpenState *vs, int err)
+{
+    if (vs->fidp->dir == NULL) {
+        err = -errno;
+        goto out;
+    }
+
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, 0);
+    err = vs->offset;
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+
+}
+
+static void v9fs_open_post_open(V9fsState *s, V9fsOpenState *vs, int err)
+{
+    if (vs->fidp->fd == -1) {
+        err = -errno;
+        goto out;
+    }
+
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, 0);
+    err = vs->offset;
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_open_post_lstat(V9fsState *s, V9fsOpenState *vs, int err)
+{
+    if (err) {
+        err = -errno;
+        goto out;
+    }
+
+    stat_to_qid(&vs->stbuf, &vs->qid);
+
+    if (S_ISDIR(vs->stbuf.st_mode)) {
+        vs->fidp->dir = v9fs_do_opendir(s, &vs->fidp->path);
+        v9fs_open_post_opendir(s, vs, err);
+    } else {
+        vs->fidp->fd = v9fs_do_open(s, &vs->fidp->path,
+                                    omode_to_uflags(vs->mode));
+        v9fs_open_post_open(s, vs, err);
+    }
+    return;
+out:
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
 }
 
 static void v9fs_open(V9fsState *s, V9fsPDU *pdu)
-{    if (debug_9p_pdu) {
+{
+    int32_t fid;
+    V9fsOpenState *vs;
+    ssize_t err = 0;
+
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+
+    pdu_unmarshal(vs->pdu, vs->offset, "db", &fid, &vs->mode);
+
+    vs->fidp = lookup_fid(s, fid);
+    if (vs->fidp == NULL) {
+        err = -ENOENT;
+        goto out;
+    }
+
+    BUG_ON(vs->fidp->fd != -1);
+    BUG_ON(vs->fidp->dir);
+
+    err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
+
+    v9fs_open_post_lstat(s, vs, err);
+    return;
+out:
+    complete_pdu(s, pdu, err);
+    qemu_free(vs);
+}
+
+static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
         pprint_pdu(pdu);
-     }
+    }
 }
 
 static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
commit ff5e54c98749ca2e5586cb1cdbb2b97c69c7ee51
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:44:54 2010 +0530

    virtio-9p: Add P9_TWALK support
    
    Implement P9_TWALK support.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index f9d1c55..18811c3 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -953,11 +953,180 @@ out:
     qemu_free(vs);
 }
 
+typedef struct V9fsWalkState {
+    V9fsPDU *pdu;
+    size_t offset;
+    int16_t nwnames;
+    int name_idx;
+    V9fsQID *qids;
+    V9fsFidState *fidp;
+    V9fsFidState *newfidp;
+    V9fsString path;
+    V9fsString *wnames;
+    struct stat stbuf;
+} V9fsWalkState;
+
+static void v9fs_walk_complete(V9fsState *s, V9fsWalkState *vs, int err)
+{
+    complete_pdu(s, vs->pdu, err);
+
+    if (vs->nwnames) {
+        for (vs->name_idx = 0; vs->name_idx < vs->nwnames; vs->name_idx++) {
+            v9fs_string_free(&vs->wnames[vs->name_idx]);
+        }
+
+        qemu_free(vs->wnames);
+        qemu_free(vs->qids);
+    }
+}
+
+static void v9fs_walk_marshal(V9fsWalkState *vs)
+{
+    int i;
+    vs->offset = 7;
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "w", vs->nwnames);
+
+    for (i = 0; i < vs->nwnames; i++) {
+        vs->offset += pdu_marshal(vs->pdu, vs->offset, "Q", &vs->qids[i]);
+    }
+}
+
+static void v9fs_walk_post_newfid_lstat(V9fsState *s, V9fsWalkState *vs,
+                                                                int err)
+{
+    if (err == -1) {
+        free_fid(s, vs->newfidp->fid);
+        v9fs_string_free(&vs->path);
+        err = -ENOENT;
+        goto out;
+    }
+
+    stat_to_qid(&vs->stbuf, &vs->qids[vs->name_idx]);
+
+    vs->name_idx++;
+    if (vs->name_idx < vs->nwnames) {
+        v9fs_string_sprintf(&vs->path, "%s/%s", vs->newfidp->path.data,
+                                            vs->wnames[vs->name_idx].data);
+        v9fs_string_copy(&vs->newfidp->path, &vs->path);
+
+        err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf);
+        v9fs_walk_post_newfid_lstat(s, vs, err);
+        return;
+    }
+
+    v9fs_string_free(&vs->path);
+    v9fs_walk_marshal(vs);
+    err = vs->offset;
+out:
+    v9fs_walk_complete(s, vs, err);
+}
+
+static void v9fs_walk_post_oldfid_lstat(V9fsState *s, V9fsWalkState *vs,
+        int err)
+{
+    if (err == -1) {
+        v9fs_string_free(&vs->path);
+        err = -ENOENT;
+        goto out;
+    }
+
+    stat_to_qid(&vs->stbuf, &vs->qids[vs->name_idx]);
+    vs->name_idx++;
+    if (vs->name_idx < vs->nwnames) {
+
+        v9fs_string_sprintf(&vs->path, "%s/%s",
+                vs->fidp->path.data, vs->wnames[vs->name_idx].data);
+        v9fs_string_copy(&vs->fidp->path, &vs->path);
+
+        err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
+        v9fs_walk_post_oldfid_lstat(s, vs, err);
+        return;
+    }
+
+    v9fs_string_free(&vs->path);
+    v9fs_walk_marshal(vs);
+    err = vs->offset;
+out:
+    v9fs_walk_complete(s, vs, err);
+}
+
 static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int32_t fid, newfid;
+    V9fsWalkState *vs;
+    int err = 0;
+    int i;
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->wnames = NULL;
+    vs->qids = NULL;
+    vs->offset = 7;
+
+    vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "ddw", &fid,
+                                            &newfid, &vs->nwnames);
+
+    if (vs->nwnames) {
+        vs->wnames = qemu_mallocz(sizeof(vs->wnames[0]) * vs->nwnames);
+
+        vs->qids = qemu_mallocz(sizeof(vs->qids[0]) * vs->nwnames);
+
+        for (i = 0; i < vs->nwnames; i++) {
+            vs->offset += pdu_unmarshal(vs->pdu, vs->offset, "s",
+                                            &vs->wnames[i]);
+        }
+    }
+
+    vs->fidp = lookup_fid(s, fid);
+    if (vs->fidp == NULL) {
+        err = -ENOENT;
+        goto out;
+    }
+
+    /* FIXME: is this really valid? */
+    if (fid == newfid) {
+
+        BUG_ON(vs->fidp->fd != -1);
+        BUG_ON(vs->fidp->dir);
+        v9fs_string_init(&vs->path);
+        vs->name_idx = 0;
+
+        if (vs->name_idx < vs->nwnames) {
+            v9fs_string_sprintf(&vs->path, "%s/%s",
+                vs->fidp->path.data, vs->wnames[vs->name_idx].data);
+            v9fs_string_copy(&vs->fidp->path, &vs->path);
+
+            err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
+            v9fs_walk_post_oldfid_lstat(s, vs, err);
+            return;
+        }
+    } else {
+        vs->newfidp = alloc_fid(s, newfid);
+        if (vs->newfidp == NULL) {
+            err = -EINVAL;
+            goto out;
+        }
+
+        vs->newfidp->uid = vs->fidp->uid;
+        v9fs_string_init(&vs->path);
+        vs->name_idx = 0;
+        v9fs_string_copy(&vs->newfidp->path, &vs->fidp->path);
+
+        if (vs->name_idx < vs->nwnames) {
+            v9fs_string_sprintf(&vs->path, "%s/%s", vs->newfidp->path.data,
+                                vs->wnames[vs->name_idx].data);
+            v9fs_string_copy(&vs->newfidp->path, &vs->path);
+
+            err = v9fs_do_lstat(s, &vs->newfidp->path, &vs->stbuf);
+            v9fs_walk_post_newfid_lstat(s, vs, err);
+            return;
+        }
     }
+
+    v9fs_walk_marshal(vs);
+    err = vs->offset;
+out:
+    v9fs_walk_complete(s, vs, err);
 }
 
 static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
commit 4da7d3fa2d9ad02bdf8abfc741bb882f1f5c482a
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:44:53 2010 +0530

    virtio-9p: Add P9_TSTAT support
    
    Implement P9_TSTAT support. This get the mount to work on the guest.
    
    [kiran at linux.vnet.ibm.com: malloc to qemu_malloc conversion]
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 48b5e83..f9d1c55 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -895,11 +895,62 @@ out:
     v9fs_string_free(&aname);
 }
 
+typedef struct V9fsStatState {
+    V9fsPDU *pdu;
+    size_t offset;
+    V9fsStat v9stat;
+    V9fsFidState *fidp;
+    struct stat stbuf;
+} V9fsStatState;
+
+static void v9fs_stat_post_lstat(V9fsState *s, V9fsStatState *vs, int err)
+{
+    if (err == -1) {
+        err = -errno;
+        goto out;
+    }
+
+    err = stat_to_v9stat(s, &vs->fidp->path, &vs->stbuf, &vs->v9stat);
+    if (err) {
+        goto out;
+    }
+    vs->offset += pdu_marshal(vs->pdu, vs->offset, "wS", 0, &vs->v9stat);
+    err = vs->offset;
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    v9fs_stat_free(&vs->v9stat);
+    qemu_free(vs);
+}
+
 static void v9fs_stat(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int32_t fid;
+    V9fsStatState *vs;
+    ssize_t err = 0;
+
+    vs = qemu_malloc(sizeof(*vs));
+    vs->pdu = pdu;
+    vs->offset = 7;
+
+    memset(&vs->v9stat, 0, sizeof(vs->v9stat));
+
+    pdu_unmarshal(vs->pdu, vs->offset, "d", &fid);
+
+    vs->fidp = lookup_fid(s, fid);
+    if (vs->fidp == NULL) {
+        err = -ENOENT;
+        goto out;
     }
+
+    err = v9fs_do_lstat(s, &vs->fidp->path, &vs->stbuf);
+    v9fs_stat_post_lstat(s, vs, err);
+    return;
+
+out:
+    complete_pdu(s, vs->pdu, err);
+    v9fs_stat_free(&vs->v9stat);
+    qemu_free(vs);
 }
 
 static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
commit 955efc47559fb4475d06a37ce0ab3f3ae8c4cd83
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:44:52 2010 +0530

    virtio-9p: Add P9_TATTACH support.
    
    Implement P9_TATTACH support.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index c1c7723..48b5e83 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -861,9 +861,38 @@ static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
 
 static void v9fs_attach(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int32_t fid, afid, n_uname;
+    V9fsString uname, aname;
+    V9fsFidState *fidp;
+    V9fsQID qid;
+    size_t offset = 7;
+    ssize_t err;
+
+    pdu_unmarshal(pdu, offset, "ddssd", &fid, &afid, &uname, &aname, &n_uname);
+
+    fidp = alloc_fid(s, fid);
+    if (fidp == NULL) {
+        err = -EINVAL;
+        goto out;
     }
+
+    fidp->uid = n_uname;
+
+    v9fs_string_sprintf(&fidp->path, "%s", "/");
+    err = fid_to_qid(s, fidp, &qid);
+    if (err) {
+        err = -EINVAL;
+        free_fid(s, fid);
+        goto out;
+    }
+
+    offset += pdu_marshal(pdu, offset, "Q", &qid);
+
+    err = offset;
+out:
+    complete_pdu(s, pdu, err);
+    v9fs_string_free(&uname);
+    v9fs_string_free(&aname);
 }
 
 static void v9fs_stat(V9fsState *s, V9fsPDU *pdu)
commit 92c1ad037a4f3081b07ff945eed10a23087866e2
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:44:51 2010 +0530

    virtio-9p: Add P9_TVERSION support
    
    Implement P9_TVERSION support.
    
    [sripathik at in.ibm.com: Handle unknown 9P versions as per the standards]
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index c31f48c..c1c7723 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -843,9 +843,20 @@ static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
 
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
 {
-    if (debug_9p_pdu) {
-        pprint_pdu(pdu);
+    int32_t msize;
+    V9fsString version;
+    size_t offset = 7;
+
+    pdu_unmarshal(pdu, offset, "ds", &msize, &version);
+
+    if (strcmp(version.data, "9P2000.u")) {
+        v9fs_string_sprintf(&version, "unknown");
     }
+
+    offset += pdu_marshal(pdu, offset, "ds", msize, &version);
+    complete_pdu(s, pdu, offset);
+
+    v9fs_string_free(&version);
 }
 
 static void v9fs_attach(V9fsState *s, V9fsPDU *pdu)
commit 1f5a89bf68193012df13dd3eb188783367e489d5
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:44:50 2010 +0530

    virtio-9p: Add sg helper functions
    
    Add scatter-gather helper functions.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index b37cdf2..c31f48c 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -762,6 +762,56 @@ static int stat_to_v9stat(V9fsState *s, V9fsString *name,
     return 0;
 }
 
+static struct iovec *adjust_sg(struct iovec *sg, int len, int *iovcnt)
+{
+    while (len && *iovcnt) {
+        if (len < sg->iov_len) {
+            sg->iov_len -= len;
+            sg->iov_base += len;
+            len = 0;
+        } else {
+            len -= sg->iov_len;
+            sg++;
+            *iovcnt -= 1;
+        }
+    }
+
+    return sg;
+}
+
+static struct iovec *cap_sg(struct iovec *sg, int cap, int *cnt)
+{
+    int i;
+    int total = 0;
+
+    for (i = 0; i < *cnt; i++) {
+        if ((total + sg[i].iov_len) > cap) {
+            sg[i].iov_len -= ((total + sg[i].iov_len) - cap);
+            i++;
+            break;
+        }
+        total += sg[i].iov_len;
+    }
+
+    *cnt = i;
+
+    return sg;
+}
+
+static void print_sg(struct iovec *sg, int cnt)
+{
+    int i;
+
+    printf("sg[%d]: {", cnt);
+    for (i = 0; i < cnt; i++) {
+        if (i) {
+            printf(", ");
+        }
+        printf("(%p, %zd)", sg[i].iov_base, sg[i].iov_len);
+    }
+    printf("}\n");
+}
+
 static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
 {
     /* Note: The following have been added to prevent GCC from complaining
@@ -786,6 +836,9 @@ static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
     (void) donttouch_stat;
     (void) v9fs_stat_free;
     (void) stat_to_v9stat;
+    (void) adjust_sg;
+    (void) cap_sg;
+    (void) print_sg;
 }
 
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
commit bb9e3216bf32032a08a6f48799991f05203fa54b
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:44:49 2010 +0530

    virtio-9p: Add stat and mode related helper functions.
    
    Add helpers to obtain file stat and mode details.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 4467aea..b37cdf2 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -580,6 +580,188 @@ static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len)
     free_pdu(s, pdu);
 }
 
+static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension)
+{
+    mode_t ret;
+
+    ret = mode & 0777;
+    if (mode & P9_STAT_MODE_DIR) {
+        ret |= S_IFDIR;
+    }
+
+    if (dotu) {
+        if (mode & P9_STAT_MODE_SYMLINK) {
+            ret |= S_IFLNK;
+        }
+        if (mode & P9_STAT_MODE_SOCKET) {
+            ret |= S_IFSOCK;
+        }
+        if (mode & P9_STAT_MODE_NAMED_PIPE) {
+            ret |= S_IFIFO;
+        }
+        if (mode & P9_STAT_MODE_DEVICE) {
+            if (extension && extension->data[0] == 'c') {
+                ret |= S_IFCHR;
+            } else {
+                ret |= S_IFBLK;
+            }
+        }
+    }
+
+    if (!(ret&~0777)) {
+        ret |= S_IFREG;
+    }
+
+    if (mode & P9_STAT_MODE_SETUID) {
+        ret |= S_ISUID;
+    }
+    if (mode & P9_STAT_MODE_SETGID) {
+        ret |= S_ISGID;
+    }
+    if (mode & P9_STAT_MODE_SETVTX) {
+        ret |= S_ISVTX;
+    }
+
+    return ret;
+}
+
+static int donttouch_stat(V9fsStat *stat)
+{
+    if (stat->type == -1 &&
+        stat->dev == -1 &&
+        stat->qid.type == -1 &&
+        stat->qid.version == -1 &&
+        stat->qid.path == -1 &&
+        stat->mode == -1 &&
+        stat->atime == -1 &&
+        stat->mtime == -1 &&
+        stat->length == -1 &&
+        !stat->name.size &&
+        !stat->uid.size &&
+        !stat->gid.size &&
+        !stat->muid.size &&
+        stat->n_uid == -1 &&
+        stat->n_gid == -1 &&
+        stat->n_muid == -1) {
+        return 1;
+    }
+
+    return 0;
+}
+
+static void v9fs_stat_free(V9fsStat *stat)
+{
+    v9fs_string_free(&stat->name);
+    v9fs_string_free(&stat->uid);
+    v9fs_string_free(&stat->gid);
+    v9fs_string_free(&stat->muid);
+    v9fs_string_free(&stat->extension);
+}
+
+static uint32_t stat_to_v9mode(const struct stat *stbuf)
+{
+    uint32_t mode;
+
+    mode = stbuf->st_mode & 0777;
+    if (S_ISDIR(stbuf->st_mode)) {
+        mode |= P9_STAT_MODE_DIR;
+    }
+
+    if (dotu) {
+        if (S_ISLNK(stbuf->st_mode)) {
+            mode |= P9_STAT_MODE_SYMLINK;
+        }
+
+        if (S_ISSOCK(stbuf->st_mode)) {
+            mode |= P9_STAT_MODE_SOCKET;
+        }
+
+        if (S_ISFIFO(stbuf->st_mode)) {
+            mode |= P9_STAT_MODE_NAMED_PIPE;
+        }
+
+        if (S_ISBLK(stbuf->st_mode) || S_ISCHR(stbuf->st_mode)) {
+            mode |= P9_STAT_MODE_DEVICE;
+        }
+
+        if (stbuf->st_mode & S_ISUID) {
+            mode |= P9_STAT_MODE_SETUID;
+        }
+
+        if (stbuf->st_mode & S_ISGID) {
+            mode |= P9_STAT_MODE_SETGID;
+        }
+
+        if (stbuf->st_mode & S_ISVTX) {
+            mode |= P9_STAT_MODE_SETVTX;
+        }
+    }
+
+    return mode;
+}
+
+static int stat_to_v9stat(V9fsState *s, V9fsString *name,
+                            const struct stat *stbuf,
+                            V9fsStat *v9stat)
+{
+    int err;
+    const char *str;
+
+    memset(v9stat, 0, sizeof(*v9stat));
+
+    stat_to_qid(stbuf, &v9stat->qid);
+    v9stat->mode = stat_to_v9mode(stbuf);
+    v9stat->atime = stbuf->st_atime;
+    v9stat->mtime = stbuf->st_mtime;
+    v9stat->length = stbuf->st_size;
+
+    v9fs_string_null(&v9stat->uid);
+    v9fs_string_null(&v9stat->gid);
+    v9fs_string_null(&v9stat->muid);
+
+    if (dotu) {
+        v9stat->n_uid = stbuf->st_uid;
+        v9stat->n_gid = stbuf->st_gid;
+        v9stat->n_muid = 0;
+
+        v9fs_string_null(&v9stat->extension);
+
+        if (v9stat->mode & P9_STAT_MODE_SYMLINK) {
+            err = v9fs_do_readlink(s, name, &v9stat->extension);
+            if (err == -1) {
+                err = -errno;
+                return err;
+            }
+            v9stat->extension.data[err] = 0;
+            v9stat->extension.size = err;
+        } else if (v9stat->mode & P9_STAT_MODE_DEVICE) {
+            v9fs_string_sprintf(&v9stat->extension, "%c %u %u",
+                    S_ISCHR(stbuf->st_mode) ? 'c' : 'b',
+                    major(stbuf->st_rdev), minor(stbuf->st_rdev));
+        } else if (S_ISDIR(stbuf->st_mode) || S_ISREG(stbuf->st_mode)) {
+            v9fs_string_sprintf(&v9stat->extension, "%s %u",
+                    "HARDLINKCOUNT", stbuf->st_nlink);
+        }
+    }
+
+    str = strrchr(name->data, '/');
+    if (str) {
+        str += 1;
+    } else {
+        str = name->data;
+    }
+
+    v9fs_string_sprintf(&v9stat->name, "%s", str);
+
+    v9stat->size = 61 +
+        v9fs_string_size(&v9stat->name) +
+        v9fs_string_size(&v9stat->uid) +
+        v9fs_string_size(&v9stat->gid) +
+        v9fs_string_size(&v9stat->muid) +
+        v9fs_string_size(&v9stat->extension);
+    return 0;
+}
+
 static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
 {
     /* Note: The following have been added to prevent GCC from complaining
@@ -600,6 +782,10 @@ static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
     (void) alloc_fid;
     (void) free_fid;
     (void) fid_to_qid;
+    (void) v9mode_to_mode;
+    (void) donttouch_stat;
+    (void) v9fs_stat_free;
+    (void) stat_to_v9stat;
 }
 
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
commit 286d56526e0ab9b7c9f8b487cbb1ccb280aa5a22
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:44:48 2010 +0530

    virtio-9p: Add fid and qid management support.
    
    Helper APIs for FID and QID management.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 7668e52..4467aea 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -176,6 +176,126 @@ static size_t v9fs_string_size(V9fsString *str)
     return str->size;
 }
 
+static V9fsFidState *lookup_fid(V9fsState *s, int32_t fid)
+{
+    V9fsFidState *f;
+
+    for (f = s->fid_list; f; f = f->next) {
+        if (f->fid == fid) {
+            v9fs_do_setuid(s, f->uid);
+            return f;
+        }
+    }
+
+    return NULL;
+}
+
+static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
+{
+    V9fsFidState *f;
+
+    f = lookup_fid(s, fid);
+    if (f) {
+        return NULL;
+    }
+
+    f = qemu_mallocz(sizeof(V9fsFidState));
+
+    f->fid = fid;
+    f->fd = -1;
+    f->dir = NULL;
+
+    f->next = s->fid_list;
+    s->fid_list = f;
+
+    return f;
+}
+
+static int free_fid(V9fsState *s, int32_t fid)
+{
+    V9fsFidState **fidpp, *fidp;
+
+    for (fidpp = &s->fid_list; *fidpp; fidpp = &(*fidpp)->next) {
+        if ((*fidpp)->fid == fid) {
+            break;
+        }
+    }
+
+    if (*fidpp == NULL) {
+        return -ENOENT;
+    }
+
+    fidp = *fidpp;
+    *fidpp = fidp->next;
+
+    if (fidp->fd != -1) {
+        v9fs_do_close(s, fidp->fd);
+    }
+    if (fidp->dir) {
+        v9fs_do_closedir(s, fidp->dir);
+    }
+    v9fs_string_free(&fidp->path);
+    qemu_free(fidp);
+
+    return 0;
+}
+
+#define P9_QID_TYPE_DIR         0x80
+#define P9_QID_TYPE_SYMLINK     0x02
+
+#define P9_STAT_MODE_DIR        0x80000000
+#define P9_STAT_MODE_APPEND     0x40000000
+#define P9_STAT_MODE_EXCL       0x20000000
+#define P9_STAT_MODE_MOUNT      0x10000000
+#define P9_STAT_MODE_AUTH       0x08000000
+#define P9_STAT_MODE_TMP        0x04000000
+#define P9_STAT_MODE_SYMLINK    0x02000000
+#define P9_STAT_MODE_LINK       0x01000000
+#define P9_STAT_MODE_DEVICE     0x00800000
+#define P9_STAT_MODE_NAMED_PIPE 0x00200000
+#define P9_STAT_MODE_SOCKET     0x00100000
+#define P9_STAT_MODE_SETUID     0x00080000
+#define P9_STAT_MODE_SETGID     0x00040000
+#define P9_STAT_MODE_SETVTX     0x00010000
+
+#define P9_STAT_MODE_TYPE_BITS (P9_STAT_MODE_DIR |          \
+                                P9_STAT_MODE_SYMLINK |      \
+                                P9_STAT_MODE_LINK |         \
+                                P9_STAT_MODE_DEVICE |       \
+                                P9_STAT_MODE_NAMED_PIPE |   \
+                                P9_STAT_MODE_SOCKET)
+
+/* This is the algorithm from ufs in spfs */
+static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp)
+{
+    size_t size;
+
+    size = MIN(sizeof(stbuf->st_ino), sizeof(qidp->path));
+    memcpy(&qidp->path, &stbuf->st_ino, size);
+    qidp->version = stbuf->st_mtime ^ (stbuf->st_size << 8);
+    qidp->type = 0;
+    if (S_ISDIR(stbuf->st_mode)) {
+        qidp->type |= P9_QID_TYPE_DIR;
+    }
+    if (S_ISLNK(stbuf->st_mode)) {
+        qidp->type |= P9_QID_TYPE_SYMLINK;
+    }
+}
+
+static int fid_to_qid(V9fsState *s, V9fsFidState *fidp, V9fsQID *qidp)
+{
+    struct stat stbuf;
+    int err;
+
+    err = v9fs_do_lstat(s, &fidp->path, &stbuf);
+    if (err) {
+        return err;
+    }
+
+    stat_to_qid(&stbuf, qidp);
+    return 0;
+}
+
 static V9fsPDU *alloc_pdu(V9fsState *s)
 {
     V9fsPDU *pdu = NULL;
@@ -477,6 +597,9 @@ static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
     (void) v9fs_do_readlink;
     (void) v9fs_do_close;
     (void) v9fs_do_closedir;
+    (void) alloc_fid;
+    (void) free_fid;
+    (void) fid_to_qid;
 }
 
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
commit 131dcb2521bff704424cdb2ce065dc776fbc89b9
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:44:47 2010 +0530

    virtio-9p: Add minimal set of FileOperations
    
    Add minimal set of FileOperations and the corresponding implementations for
    local fstype. These will be required for the FID management patches later on.
    
    [aneesh.kumar at linux.vnet.ibm.com: rpath fix ]
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 7cde63c..461df9e 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -27,6 +27,11 @@ typedef struct FsContext
 
 typedef struct FileOperations
 {
+    int (*lstat)(FsContext *, const char *, struct stat *);
+    ssize_t (*readlink)(FsContext *, const char *, char *, size_t);
+    int (*setuid)(FsContext *, uid_t);
+    int (*close)(FsContext *, int);
+    int (*closedir)(FsContext *, DIR *);
     void *opaque;
 } FileOperations;
 #endif
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 379af60..880cd0a 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -12,6 +12,84 @@
  */
 #include "virtio.h"
 #include "virtio-9p.h"
+#include <pwd.h>
+#include <grp.h>
+
+static const char *rpath(FsContext *ctx, const char *path)
+{
+    /* FIXME: so wrong... */
+    static char buffer[4096];
+    snprintf(buffer, sizeof(buffer), "%s/%s", ctx->fs_root, path);
+    return buffer;
+}
+
+static int local_lstat(FsContext *ctx, const char *path, struct stat *stbuf)
+{
+    return lstat(rpath(ctx, path), stbuf);
+}
+
+static int local_setuid(FsContext *ctx, uid_t uid)
+{
+    struct passwd *pw;
+    gid_t groups[33];
+    int ngroups;
+    static uid_t cur_uid = -1;
+
+    if (cur_uid == uid) {
+        return 0;
+    }
+
+    if (setreuid(0, 0)) {
+        return -1;
+    }
+
+    pw = getpwuid(uid);
+    if (pw == NULL) {
+        return -1;
+    }
+
+    ngroups = 33;
+    if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups) == -1) {
+        return -1;
+    }
+
+    if (setgroups(ngroups, groups)) {
+        return -1;
+    }
+
+    if (setregid(-1, pw->pw_gid)) {
+        return -1;
+    }
+
+    if (setreuid(-1, uid)) {
+        return -1;
+    }
+
+    cur_uid = uid;
+
+    return 0;
+}
+
+static ssize_t local_readlink(FsContext *ctx, const char *path,
+                                char *buf, size_t bufsz)
+{
+    return readlink(rpath(ctx, path), buf, bufsz);
+}
+
+static int local_close(FsContext *ctx, int fd)
+{
+    return close(fd);
+}
+
+static int local_closedir(FsContext *ctx, DIR *dir)
+{
+    return closedir(dir);
+}
 
 FileOperations local_ops = {
+    .lstat = local_lstat,
+    .setuid = local_setuid,
+    .readlink = local_readlink,
+    .close = local_close,
+    .closedir = local_closedir,
 };
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 97e9b04..7668e52 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -21,6 +21,41 @@
 int dotu = 1;
 int debug_9p_pdu;
 
+static int v9fs_do_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf)
+{
+    return s->ops->lstat(&s->ctx, path->data, stbuf);
+}
+
+static int v9fs_do_setuid(V9fsState *s, uid_t uid)
+{
+    return s->ops->setuid(&s->ctx, uid);
+}
+
+static ssize_t v9fs_do_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
+{
+    ssize_t len;
+
+    buf->data = qemu_malloc(1024);
+
+    len = s->ops->readlink(&s->ctx, path->data, buf->data, 1024 - 1);
+    if (len > -1) {
+        buf->size = len;
+        buf->data[len] = 0;
+    }
+
+    return len;
+}
+
+static int v9fs_do_close(V9fsState *s, int fd)
+{
+    return s->ops->close(&s->ctx, fd);
+}
+
+static int v9fs_do_closedir(V9fsState *s, DIR *dir)
+{
+    return s->ops->closedir(&s->ctx, dir);
+}
+
 static void v9fs_string_init(V9fsString *str)
 {
     str->data = NULL;
@@ -437,9 +472,13 @@ static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
     (void) v9fs_string_sprintf;
     (void) v9fs_string_copy;
     (void) v9fs_string_size;
-
-
+    (void) v9fs_do_lstat;
+    (void) v9fs_do_setuid;
+    (void) v9fs_do_readlink;
+    (void) v9fs_do_close;
+    (void) v9fs_do_closedir;
 }
+
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
 {
     if (debug_9p_pdu) {
commit a03f7874396c909562d35931d03eca79c5c7f708
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:44:46 2010 +0530

    virtio-9p: Add string manipulation support.
    
    Add helpers to do string manipulation.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 10d832a..97e9b04 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -21,6 +21,126 @@
 int dotu = 1;
 int debug_9p_pdu;
 
+static void v9fs_string_init(V9fsString *str)
+{
+    str->data = NULL;
+    str->size = 0;
+}
+
+static void v9fs_string_free(V9fsString *str)
+{
+    qemu_free(str->data);
+    str->data = NULL;
+    str->size = 0;
+}
+
+static void v9fs_string_null(V9fsString *str)
+{
+    v9fs_string_free(str);
+}
+
+static int number_to_string(void *arg, char type)
+{
+    unsigned int ret = 0;
+
+    switch (type) {
+    case 'u': {
+        unsigned int num = *(unsigned int *)arg;
+
+        do {
+            ret++;
+            num = num/10;
+        } while (num);
+        break;
+    }
+    default:
+        printf("Number_to_string: Unknown number format\n");
+        return -1;
+    }
+
+    return ret;
+}
+
+static int v9fs_string_alloc_printf(char **strp, const char *fmt, va_list ap)
+{
+    va_list ap2;
+    char *iter = (char *)fmt;
+    int len = 0;
+    int nr_args = 0;
+    char *arg_char_ptr;
+    unsigned int arg_uint;
+
+    /* Find the number of %'s that denotes an argument */
+    for (iter = strstr(iter, "%"); iter; iter = strstr(iter, "%")) {
+        nr_args++;
+        iter++;
+    }
+
+    len = strlen(fmt) - 2*nr_args;
+
+    if (!nr_args) {
+        goto alloc_print;
+    }
+
+    va_copy(ap2, ap);
+
+    iter = (char *)fmt;
+
+    /* Now parse the format string */
+    for (iter = strstr(iter, "%"); iter; iter = strstr(iter, "%")) {
+        iter++;
+        switch (*iter) {
+        case 'u':
+            arg_uint = va_arg(ap2, unsigned int);
+            len += number_to_string((void *)&arg_uint, 'u');
+            break;
+        case 's':
+            arg_char_ptr = va_arg(ap2, char *);
+            len += strlen(arg_char_ptr);
+            break;
+        case 'c':
+            len += 1;
+            break;
+        default:
+            fprintf(stderr,
+		    "v9fs_string_alloc_printf:Incorrect format %c", *iter);
+            return -1;
+        }
+        iter++;
+    }
+
+alloc_print:
+    *strp = qemu_malloc((len + 1) * sizeof(**strp));
+
+    return vsprintf(*strp, fmt, ap);
+}
+
+static void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
+{
+    va_list ap;
+    int err;
+
+    v9fs_string_free(str);
+
+    va_start(ap, fmt);
+    err = v9fs_string_alloc_printf(&str->data, fmt, ap);
+    BUG_ON(err == -1);
+    va_end(ap);
+
+    str->size = err;
+}
+
+static void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
+{
+    v9fs_string_free(lhs);
+    v9fs_string_sprintf(lhs, "%s", rhs->data);
+}
+
+static size_t v9fs_string_size(V9fsString *str)
+{
+    return str->size;
+}
+
 static V9fsPDU *alloc_pdu(V9fsState *s)
 {
     V9fsPDU *pdu = NULL;
@@ -311,6 +431,13 @@ static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
      * They will be removed in the subsequent patches */
     (void)pdu_unmarshal;
     (void) complete_pdu;
+    (void) v9fs_string_init;
+    (void) v9fs_string_free;
+    (void) v9fs_string_null;
+    (void) v9fs_string_sprintf;
+    (void) v9fs_string_copy;
+    (void) v9fs_string_size;
+
 
 }
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
commit 405a549a160ce632826661902aebee71c2e196bb
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:44:45 2010 +0530

    virtio-9p: pdu processing support.
    
    Add helpers to process the PDUs.
    
    [kiran at linux.vnet.ibm.com: malloc to qemu_malloc coversion]
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-9p-debug.h b/hw/virtio-9p-debug.h
new file mode 100644
index 0000000..0104be5
--- /dev/null
+++ b/hw/virtio-9p-debug.h
@@ -0,0 +1,7 @@
+#ifndef _QEMU_VIRTIO_9P_DEBUG_H
+#define _QEMU_VIRTIO_9P_DEBUG_H
+
+extern int dotu;
+void pprint_pdu(V9fsPDU *pdu);
+
+#endif
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index abd01c1..10d832a 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -71,6 +71,248 @@ size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
     return copied;
 }
 
+static size_t pdu_unpack(void *dst, V9fsPDU *pdu, size_t offset, size_t size)
+{
+    return pdu_packunpack(dst, pdu->elem.out_sg, pdu->elem.out_num,
+                         offset, size, 0);
+}
+
+static size_t pdu_pack(V9fsPDU *pdu, size_t offset, const void *src,
+                        size_t size)
+{
+    return pdu_packunpack((void *)src, pdu->elem.in_sg, pdu->elem.in_num,
+                             offset, size, 1);
+}
+
+static int pdu_copy_sg(V9fsPDU *pdu, size_t offset, int rx, struct iovec *sg)
+{
+    size_t pos = 0;
+    int i, j;
+    struct iovec *src_sg;
+    unsigned int num;
+
+    if (rx) {
+        src_sg = pdu->elem.in_sg;
+        num = pdu->elem.in_num;
+    } else {
+        src_sg = pdu->elem.out_sg;
+        num = pdu->elem.out_num;
+    }
+
+    j = 0;
+    for (i = 0; i < num; i++) {
+        if (offset <= pos) {
+            sg[j].iov_base = src_sg[i].iov_base;
+            sg[j].iov_len = src_sg[i].iov_len;
+            j++;
+        } else if (offset < (src_sg[i].iov_len + pos)) {
+            sg[j].iov_base = src_sg[i].iov_base;
+            sg[j].iov_len = src_sg[i].iov_len;
+            sg[j].iov_base += (offset - pos);
+            sg[j].iov_len -= (offset - pos);
+            j++;
+        }
+        pos += src_sg[i].iov_len;
+    }
+
+    return j;
+}
+
+static size_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
+{
+    size_t old_offset = offset;
+    va_list ap;
+    int i;
+
+    va_start(ap, fmt);
+    for (i = 0; fmt[i]; i++) {
+        switch (fmt[i]) {
+        case 'b': {
+            uint8_t *valp = va_arg(ap, uint8_t *);
+            offset += pdu_unpack(valp, pdu, offset, sizeof(*valp));
+            break;
+        }
+        case 'w': {
+            uint16_t val, *valp;
+            valp = va_arg(ap, uint16_t *);
+            val = le16_to_cpupu(valp);
+            offset += pdu_unpack(&val, pdu, offset, sizeof(val));
+            *valp = val;
+            break;
+        }
+        case 'd': {
+            uint32_t val, *valp;
+            valp = va_arg(ap, uint32_t *);
+            val = le32_to_cpupu(valp);
+            offset += pdu_unpack(&val, pdu, offset, sizeof(val));
+            *valp = val;
+            break;
+        }
+        case 'q': {
+            uint64_t val, *valp;
+            valp = va_arg(ap, uint64_t *);
+            val = le64_to_cpup(valp);
+            offset += pdu_unpack(&val, pdu, offset, sizeof(val));
+            *valp = val;
+            break;
+        }
+        case 'v': {
+            struct iovec *iov = va_arg(ap, struct iovec *);
+            int *iovcnt = va_arg(ap, int *);
+            *iovcnt = pdu_copy_sg(pdu, offset, 0, iov);
+            break;
+        }
+        case 's': {
+            V9fsString *str = va_arg(ap, V9fsString *);
+            offset += pdu_unmarshal(pdu, offset, "w", &str->size);
+            /* FIXME: sanity check str->size */
+            str->data = qemu_malloc(str->size + 1);
+            offset += pdu_unpack(str->data, pdu, offset, str->size);
+            str->data[str->size] = 0;
+            break;
+        }
+        case 'Q': {
+            V9fsQID *qidp = va_arg(ap, V9fsQID *);
+            offset += pdu_unmarshal(pdu, offset, "bdq",
+                        &qidp->type, &qidp->version, &qidp->path);
+            break;
+        }
+        case 'S': {
+            V9fsStat *statp = va_arg(ap, V9fsStat *);
+            offset += pdu_unmarshal(pdu, offset, "wwdQdddqsssssddd",
+                        &statp->size, &statp->type, &statp->dev,
+                        &statp->qid, &statp->mode, &statp->atime,
+                        &statp->mtime, &statp->length,
+                        &statp->name, &statp->uid, &statp->gid,
+                        &statp->muid, &statp->extension,
+                        &statp->n_uid, &statp->n_gid,
+                        &statp->n_muid);
+            break;
+        }
+        default:
+            break;
+        }
+    }
+
+    va_end(ap);
+
+    return offset - old_offset;
+}
+
+static size_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
+{
+    size_t old_offset = offset;
+    va_list ap;
+    int i;
+
+    va_start(ap, fmt);
+    for (i = 0; fmt[i]; i++) {
+        switch (fmt[i]) {
+        case 'b': {
+            uint8_t val = va_arg(ap, int);
+            offset += pdu_pack(pdu, offset, &val, sizeof(val));
+            break;
+        }
+        case 'w': {
+            uint16_t val;
+            cpu_to_le16w(&val, va_arg(ap, int));
+            offset += pdu_pack(pdu, offset, &val, sizeof(val));
+            break;
+        }
+        case 'd': {
+            uint32_t val;
+            cpu_to_le32w(&val, va_arg(ap, uint32_t));
+            offset += pdu_pack(pdu, offset, &val, sizeof(val));
+            break;
+        }
+        case 'q': {
+            uint64_t val;
+            cpu_to_le64w(&val, va_arg(ap, uint64_t));
+            offset += pdu_pack(pdu, offset, &val, sizeof(val));
+            break;
+        }
+        case 'v': {
+            struct iovec *iov = va_arg(ap, struct iovec *);
+            int *iovcnt = va_arg(ap, int *);
+            *iovcnt = pdu_copy_sg(pdu, offset, 1, iov);
+            break;
+        }
+        case 's': {
+            V9fsString *str = va_arg(ap, V9fsString *);
+            offset += pdu_marshal(pdu, offset, "w", str->size);
+            offset += pdu_pack(pdu, offset, str->data, str->size);
+            break;
+        }
+        case 'Q': {
+            V9fsQID *qidp = va_arg(ap, V9fsQID *);
+            offset += pdu_marshal(pdu, offset, "bdq",
+                        qidp->type, qidp->version, qidp->path);
+            break;
+        }
+        case 'S': {
+            V9fsStat *statp = va_arg(ap, V9fsStat *);
+            offset += pdu_marshal(pdu, offset, "wwdQdddqsssssddd",
+                        statp->size, statp->type, statp->dev,
+                        &statp->qid, statp->mode, statp->atime,
+                        statp->mtime, statp->length, &statp->name,
+                        &statp->uid, &statp->gid, &statp->muid,
+                        &statp->extension, statp->n_uid,
+                        statp->n_gid, statp->n_muid);
+            break;
+        }
+        default:
+            break;
+        }
+    }
+    va_end(ap);
+
+    return offset - old_offset;
+}
+
+static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len)
+{
+    int8_t id = pdu->id + 1; /* Response */
+
+    if (len < 0) {
+        V9fsString str;
+        int err = -len;
+
+        str.data = strerror(err);
+        str.size = strlen(str.data);
+
+        len = 7;
+        len += pdu_marshal(pdu, len, "s", &str);
+        if (dotu) {
+            len += pdu_marshal(pdu, len, "d", err);
+        }
+
+        id = P9_RERROR;
+    }
+
+    /* fill out the header */
+    pdu_marshal(pdu, 0, "dbw", (int32_t)len, id, pdu->tag);
+
+    /* keep these in sync */
+    pdu->size = len;
+    pdu->id = id;
+
+    /* push onto queue and notify */
+    virtqueue_push(s->vq, &pdu->elem, len);
+
+    /* FIXME: we should batch these completions */
+    virtio_notify(&s->vdev, s->vq);
+
+    free_pdu(s, pdu);
+}
+
+static void v9fs_dummy(V9fsState *s, V9fsPDU *pdu)
+{
+    /* Note: The following have been added to prevent GCC from complaining
+     * They will be removed in the subsequent patches */
+    (void)pdu_unmarshal;
+    (void) complete_pdu;
+
+}
 static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
 {
     if (debug_9p_pdu) {
@@ -135,6 +377,7 @@ static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
 
 static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)
 {
+    v9fs_dummy(s, pdu);
     if (debug_9p_pdu) {
         pprint_pdu(pdu);
     }
commit 9f10751365b26b13b8a9b67e0e90536ae3d282df
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 29 17:44:44 2010 +0530

    virtio-9p: Add a virtio 9p device to qemu
    
    This patch doesn't implement the 9p protocol handling
    code. It adds a simple device which dump the protocol data.
    
    [jvrao at linux.vnet.ibm.com: Little-Endian to host format conversion]
    [aneesh.kumar at linux.vnet.ibm.com: Multiple-mounts support]
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile.target b/Makefile.target
index 65beed5..7ea753b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -168,6 +168,7 @@ obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
 obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
 obj-y += vhost_net.o
 obj-$(CONFIG_VHOST_NET) += vhost.o
+obj-$(CONFIG_LINUX) += virtio-9p.o virtio-9p-debug.o virtio-9p-local.o
 obj-y += rwhandler.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index 48bbfd9..813e1f7 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -21,7 +21,7 @@ static QTAILQ_HEAD(FsTypeEntry_head, FsTypeListEntry) fstype_entries =
     QTAILQ_HEAD_INITIALIZER(fstype_entries);
 
 static FsTypeTable FsTypes[] = {
-    { .name = "local", .ops = NULL},
+    { .name = "local", .ops = &local_ops},
 };
 
 int qemu_fsdev_add(QemuOpts *opts)
diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h
index 7fa4f60..b50fbe0 100644
--- a/fsdev/qemu-fsdev.h
+++ b/fsdev/qemu-fsdev.h
@@ -50,4 +50,5 @@ typedef struct FsTypeListEntry {
 
 extern int qemu_fsdev_add(QemuOpts *opts);
 extern FsTypeEntry *get_fsdev_fsentry(char *id);
+extern FileOperations local_ops;
 #endif
diff --git a/hw/9p.h b/hw/9p.h
new file mode 100644
index 0000000..5fdd770
--- /dev/null
+++ b/hw/9p.h
@@ -0,0 +1,26 @@
+/*
+ * Virtio 9p
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_9P_H
+#define QEMU_9P_H
+
+#include <stdbool.h>
+
+typedef struct V9fsConf
+{
+    /* tag name for the device */
+    char *tag;
+    char *fsdev_id;
+} V9fsConf;
+
+#endif
diff --git a/hw/virtio-9p-debug.c b/hw/virtio-9p-debug.c
new file mode 100644
index 0000000..2fb2673
--- /dev/null
+++ b/hw/virtio-9p-debug.c
@@ -0,0 +1,484 @@
+/*
+ * Virtio 9p PDU debug
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#include "virtio.h"
+#include "pc.h"
+#include "virtio-9p.h"
+#include "virtio-9p-debug.h"
+
+#define BUG_ON(cond) assert(!(cond))
+
+static FILE *llogfile;
+
+static struct iovec *get_sg(V9fsPDU *pdu, int rx)
+{
+    if (rx) {
+        return pdu->elem.in_sg;
+    }
+    return pdu->elem.out_sg;
+}
+
+static int get_sg_count(V9fsPDU *pdu, int rx)
+{
+    if (rx) {
+        return pdu->elem.in_num;
+    }
+    return pdu->elem.out_num;
+
+}
+
+static void pprint_int8(V9fsPDU *pdu, int rx, size_t *offsetp,
+                        const char *name)
+{
+    size_t copied;
+    int count = get_sg_count(pdu, rx);
+    size_t offset = *offsetp;
+    struct iovec *sg = get_sg(pdu, rx);
+    int8_t value;
+
+    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
+
+    BUG_ON(copied != sizeof(value));
+    offset += sizeof(value);
+    fprintf(llogfile, "%s=0x%x", name, value);
+    *offsetp = offset;
+}
+
+static void pprint_int16(V9fsPDU *pdu, int rx, size_t *offsetp,
+                        const char *name)
+{
+    size_t copied;
+    int count = get_sg_count(pdu, rx);
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    int16_t value;
+
+
+    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
+
+    BUG_ON(copied != sizeof(value));
+    offset += sizeof(value);
+    fprintf(llogfile, "%s=0x%x", name, value);
+    *offsetp = offset;
+}
+
+static void pprint_int32(V9fsPDU *pdu, int rx, size_t *offsetp,
+                        const char *name)
+{
+    size_t copied;
+    int count = get_sg_count(pdu, rx);
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    int32_t value;
+
+
+    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
+
+    BUG_ON(copied != sizeof(value));
+    offset += sizeof(value);
+    fprintf(llogfile, "%s=0x%x", name, value);
+    *offsetp = offset;
+}
+
+static void pprint_int64(V9fsPDU *pdu, int rx, size_t *offsetp,
+                        const char *name)
+{
+    size_t copied;
+    int count = get_sg_count(pdu, rx);
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    int64_t value;
+
+
+    copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
+
+    BUG_ON(copied != sizeof(value));
+    offset += sizeof(value);
+    fprintf(llogfile, "%s=0x%" PRIx64, name, value);
+    *offsetp = offset;
+}
+
+static void pprint_str(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    int sg_count = get_sg_count(pdu, rx);
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    uint16_t tmp_size, size;
+    size_t result;
+    size_t copied = 0;
+    int i = 0;
+
+    /* get the size */
+    copied = do_pdu_unpack(&tmp_size, sg, sg_count, offset, sizeof(tmp_size));
+    BUG_ON(copied != sizeof(tmp_size));
+    size = le16_to_cpupu(&tmp_size);
+    offset += copied;
+
+    fprintf(llogfile, "%s=", name);
+    for (i = 0; size && i < sg_count; i++) {
+        size_t len;
+        if (offset >= sg[i].iov_len) {
+            /* skip this sg */
+            offset -= sg[i].iov_len;
+            continue;
+        } else {
+            len = MIN(sg[i].iov_len - offset, size);
+            result = fwrite(sg[i].iov_base + offset, 1, len, llogfile);
+            BUG_ON(result != len);
+            size -= len;
+            copied += len;
+            if (size) {
+                offset = 0;
+                continue;
+            }
+        }
+    }
+    *offsetp += copied;
+}
+
+static void pprint_qid(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    fprintf(llogfile, "%s={", name);
+    pprint_int8(pdu, rx, offsetp, "type");
+    pprint_int32(pdu, rx, offsetp, ", version");
+    pprint_int64(pdu, rx, offsetp, ", path");
+    fprintf(llogfile, "}");
+}
+
+static void pprint_stat(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    fprintf(llogfile, "%s={", name);
+    pprint_int16(pdu, rx, offsetp, "size");
+    pprint_int16(pdu, rx, offsetp, ", type");
+    pprint_int32(pdu, rx, offsetp, ", dev");
+    pprint_qid(pdu, rx, offsetp, ", qid");
+    pprint_int32(pdu, rx, offsetp, ", mode");
+    pprint_int32(pdu, rx, offsetp, ", atime");
+    pprint_int32(pdu, rx, offsetp, ", mtime");
+    pprint_int64(pdu, rx, offsetp, ", length");
+    pprint_str(pdu, rx, offsetp, ", name");
+    pprint_str(pdu, rx, offsetp, ", uid");
+    pprint_str(pdu, rx, offsetp, ", gid");
+    pprint_str(pdu, rx, offsetp, ", muid");
+    if (dotu) {
+        pprint_str(pdu, rx, offsetp, ", extension");
+        pprint_int32(pdu, rx, offsetp, ", uid");
+        pprint_int32(pdu, rx, offsetp, ", gid");
+        pprint_int32(pdu, rx, offsetp, ", muid");
+    }
+    fprintf(llogfile, "}");
+}
+
+static void pprint_strs(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    int sg_count = get_sg_count(pdu, rx);
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    uint16_t tmp_count, count, i;
+    size_t copied = 0;
+
+    fprintf(llogfile, "%s={", name);
+
+    /* Get the count */
+    copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
+    BUG_ON(copied != sizeof(tmp_count));
+    count = le16_to_cpupu(&tmp_count);
+    offset += copied;
+
+    for (i = 0; i < count; i++) {
+        char str[512];
+        if (i) {
+            fprintf(llogfile, ", ");
+        }
+        snprintf(str, sizeof(str), "[%d]", i);
+        pprint_str(pdu, rx, &offset, str);
+    }
+
+    fprintf(llogfile, "}");
+
+    *offsetp = offset;
+}
+
+static void pprint_qids(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    int sg_count = get_sg_count(pdu, rx);
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    uint16_t tmp_count, count, i;
+    size_t copied = 0;
+
+    fprintf(llogfile, "%s={", name);
+
+    copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
+    BUG_ON(copied != sizeof(tmp_count));
+    count = le16_to_cpupu(&tmp_count);
+    offset += copied;
+
+    for (i = 0; i < count; i++) {
+        char str[512];
+        if (i) {
+            fprintf(llogfile, ", ");
+        }
+        snprintf(str, sizeof(str), "[%d]", i);
+        pprint_qid(pdu, rx, &offset, str);
+    }
+
+    fprintf(llogfile, "}");
+
+    *offsetp = offset;
+}
+
+static void pprint_sg(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    struct iovec *sg = get_sg(pdu, rx);
+    unsigned int count;
+    int i;
+
+    if (rx) {
+        count = pdu->elem.in_num;
+    } else {
+        count = pdu->elem.out_num;
+    }
+
+    fprintf(llogfile, "%s={", name);
+    for (i = 0; i < count; i++) {
+        if (i) {
+            fprintf(llogfile, ", ");
+        }
+        fprintf(llogfile, "(%p, 0x%zx)", sg[i].iov_base, sg[i].iov_len);
+    }
+    fprintf(llogfile, "}");
+}
+
+/* FIXME: read from a directory fid returns serialized stat_t's */
+#ifdef DEBUG_DATA
+static void pprint_data(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
+{
+    struct iovec *sg = get_sg(pdu, rx);
+    size_t offset = *offsetp;
+    unsigned int count;
+    int32_t size;
+    int total, i, j;
+    ssize_t len;
+
+    if (rx) {
+        count = pdu->elem.in_num;
+    } else
+        count = pdu->elem.out_num;
+    }
+
+    BUG_ON((offset + sizeof(size)) > sg[0].iov_len);
+
+    memcpy(&size, sg[0].iov_base + offset, sizeof(size));
+    offset += sizeof(size);
+
+    fprintf(llogfile, "size: %x\n", size);
+
+    sg[0].iov_base += 11; /* skip header */
+    sg[0].iov_len -= 11;
+
+    total = 0;
+    for (i = 0; i < count; i++) {
+        total += sg[i].iov_len;
+        if (total >= size) {
+            /* trim sg list so writev does the right thing */
+            sg[i].iov_len -= (total - size);
+            i++;
+            break;
+        }
+    }
+
+    fprintf(llogfile, "%s={\"", name);
+    fflush(llogfile);
+    for (j = 0; j < i; j++) {
+        if (j) {
+            fprintf(llogfile, "\", \"");
+            fflush(llogfile);
+        }
+
+        do {
+            len = writev(fileno(llogfile), &sg[j], 1);
+        } while (len == -1 && errno == EINTR);
+        fprintf(llogfile, "len == %ld: %m\n", len);
+        BUG_ON(len != sg[j].iov_len);
+    }
+    fprintf(llogfile, "\"}");
+
+    sg[0].iov_base -= 11;
+    sg[0].iov_len += 11;
+
+}
+#endif
+
+void pprint_pdu(V9fsPDU *pdu)
+{
+    size_t offset = 7;
+
+    if (llogfile == NULL) {
+        llogfile = fopen("/tmp/pdu.log", "w");
+    }
+
+    switch (pdu->id) {
+    case P9_TVERSION:
+        fprintf(llogfile, "TVERSION: (");
+        pprint_int32(pdu, 0, &offset, "msize");
+        pprint_str(pdu, 0, &offset, ", version");
+        break;
+    case P9_RVERSION:
+        fprintf(llogfile, "RVERSION: (");
+        pprint_int32(pdu, 1, &offset, "msize");
+        pprint_str(pdu, 1, &offset, ", version");
+        break;
+    case P9_TAUTH:
+        fprintf(llogfile, "TAUTH: (");
+        pprint_int32(pdu, 0, &offset, "afid");
+        pprint_str(pdu, 0, &offset, ", uname");
+        pprint_str(pdu, 0, &offset, ", aname");
+        if (dotu) {
+            pprint_int32(pdu, 0, &offset, ", n_uname");
+        }
+        break;
+    case P9_RAUTH:
+        fprintf(llogfile, "RAUTH: (");
+        pprint_qid(pdu, 1, &offset, "qid");
+        break;
+    case P9_TATTACH:
+        fprintf(llogfile, "TATTACH: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        pprint_int32(pdu, 0, &offset, ", afid");
+        pprint_str(pdu, 0, &offset, ", uname");
+        pprint_str(pdu, 0, &offset, ", aname");
+        if (dotu) {
+            pprint_int32(pdu, 0, &offset, ", n_uname");
+        }
+        break;
+    case P9_RATTACH:
+        fprintf(llogfile, "RATTACH: (");
+        pprint_qid(pdu, 1, &offset, "qid");
+        break;
+    case P9_TERROR:
+        fprintf(llogfile, "TERROR: (");
+        break;
+    case P9_RERROR:
+        fprintf(llogfile, "RERROR: (");
+        pprint_str(pdu, 1, &offset, "ename");
+        if (dotu) {
+            pprint_int32(pdu, 1, &offset, ", ecode");
+        }
+        break;
+    case P9_TFLUSH:
+        fprintf(llogfile, "TFLUSH: (");
+        pprint_int16(pdu, 0, &offset, "oldtag");
+        break;
+    case P9_RFLUSH:
+        fprintf(llogfile, "RFLUSH: (");
+        break;
+    case P9_TWALK:
+        fprintf(llogfile, "TWALK: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        pprint_int32(pdu, 0, &offset, ", newfid");
+        pprint_strs(pdu, 0, &offset, ", wnames");
+        break;
+    case P9_RWALK:
+        fprintf(llogfile, "RWALK: (");
+        pprint_qids(pdu, 1, &offset, "wqids");
+        break;
+    case P9_TOPEN:
+        fprintf(llogfile, "TOPEN: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        pprint_int8(pdu, 0, &offset, ", mode");
+        break;
+    case P9_ROPEN:
+        fprintf(llogfile, "ROPEN: (");
+        pprint_qid(pdu, 1, &offset, "qid");
+        pprint_int32(pdu, 1, &offset, ", iounit");
+        break;
+    case P9_TCREATE:
+        fprintf(llogfile, "TCREATE: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        pprint_str(pdu, 0, &offset, ", name");
+        pprint_int32(pdu, 0, &offset, ", perm");
+        pprint_int8(pdu, 0, &offset, ", mode");
+        if (dotu) {
+            pprint_str(pdu, 0, &offset, ", extension");
+        }
+        break;
+    case P9_RCREATE:
+        fprintf(llogfile, "RCREATE: (");
+        pprint_qid(pdu, 1, &offset, "qid");
+        pprint_int32(pdu, 1, &offset, ", iounit");
+        break;
+    case P9_TREAD:
+        fprintf(llogfile, "TREAD: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        pprint_int64(pdu, 0, &offset, ", offset");
+        pprint_int32(pdu, 0, &offset, ", count");
+        pprint_sg(pdu, 0, &offset, ", sg");
+        break;
+    case P9_RREAD:
+        fprintf(llogfile, "RREAD: (");
+        pprint_int32(pdu, 1, &offset, "count");
+        pprint_sg(pdu, 1, &offset, ", sg");
+        offset = 7;
+#ifdef DEBUG_DATA
+        pprint_data(pdu, 1, &offset, ", data");
+#endif
+        break;
+    case P9_TWRITE:
+        fprintf(llogfile, "TWRITE: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        pprint_int64(pdu, 0, &offset, ", offset");
+        pprint_int32(pdu, 0, &offset, ", count");
+        break;
+    case P9_RWRITE:
+        fprintf(llogfile, "RWRITE: (");
+        pprint_int32(pdu, 1, &offset, "count");
+        break;
+    case P9_TCLUNK:
+        fprintf(llogfile, "TCLUNK: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        break;
+    case P9_RCLUNK:
+        fprintf(llogfile, "RCLUNK: (");
+        break;
+    case P9_TREMOVE:
+        fprintf(llogfile, "TREMOVE: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        break;
+    case P9_RREMOVE:
+        fprintf(llogfile, "RREMOVE: (");
+        break;
+    case P9_TSTAT:
+        fprintf(llogfile, "TSTAT: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        break;
+    case P9_RSTAT:
+        fprintf(llogfile, "RSTAT: (");
+        offset += 2; /* ignored */
+        pprint_stat(pdu, 1, &offset, "stat");
+        break;
+    case P9_TWSTAT:
+        fprintf(llogfile, "TWSTAT: (");
+        pprint_int32(pdu, 0, &offset, "fid");
+        offset += 2; /* ignored */
+        pprint_stat(pdu, 0, &offset, ", stat");
+        break;
+    case P9_RWSTAT:
+        fprintf(llogfile, "RWSTAT: (");
+        break;
+    default:
+        fprintf(llogfile, "unknown(%d): (", pdu->id);
+        break;
+    }
+
+    fprintf(llogfile, ")\n");
+}
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
new file mode 100644
index 0000000..379af60
--- /dev/null
+++ b/hw/virtio-9p-local.c
@@ -0,0 +1,17 @@
+/*
+ * Virtio 9p Posix callback
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#include "virtio.h"
+#include "virtio-9p.h"
+
+FileOperations local_ops = {
+};
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
new file mode 100644
index 0000000..abd01c1
--- /dev/null
+++ b/hw/virtio-9p.c
@@ -0,0 +1,307 @@
+/*
+ * Virtio 9p backend
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "virtio.h"
+#include "pc.h"
+#include "qemu_socket.h"
+#include "virtio-9p.h"
+#include "fsdev/qemu-fsdev.h"
+#include "virtio-9p-debug.h"
+
+int dotu = 1;
+int debug_9p_pdu;
+
+static V9fsPDU *alloc_pdu(V9fsState *s)
+{
+    V9fsPDU *pdu = NULL;
+
+    if (!QLIST_EMPTY(&s->free_list)) {
+	pdu = QLIST_FIRST(&s->free_list);
+	QLIST_REMOVE(pdu, next);
+    }
+    return pdu;
+}
+
+static void free_pdu(V9fsState *s, V9fsPDU *pdu)
+{
+    if (pdu) {
+	QLIST_INSERT_HEAD(&s->free_list, pdu, next);
+    }
+}
+
+size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
+                        size_t offset, size_t size, int pack)
+{
+    int i = 0;
+    size_t copied = 0;
+
+    for (i = 0; size && i < sg_count; i++) {
+        size_t len;
+        if (offset >= sg[i].iov_len) {
+            /* skip this sg */
+            offset -= sg[i].iov_len;
+            continue;
+        } else {
+            len = MIN(sg[i].iov_len - offset, size);
+            if (pack) {
+                memcpy(sg[i].iov_base + offset, addr, len);
+            } else {
+                memcpy(addr, sg[i].iov_base + offset, len);
+            }
+            size -= len;
+            copied += len;
+            addr += len;
+            if (size) {
+                offset = 0;
+                continue;
+            }
+        }
+    }
+
+    return copied;
+}
+
+static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_attach(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_stat(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_walk(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_open(V9fsState *s, V9fsPDU *pdu)
+{    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+     }
+}
+
+static void v9fs_read(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_write(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_create(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_flush(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_remove(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
+{
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+}
+
+typedef void (pdu_handler_t)(V9fsState *s, V9fsPDU *pdu);
+
+static pdu_handler_t *pdu_handlers[] = {
+    [P9_TVERSION] = v9fs_version,
+    [P9_TATTACH] = v9fs_attach,
+    [P9_TSTAT] = v9fs_stat,
+    [P9_TWALK] = v9fs_walk,
+    [P9_TCLUNK] = v9fs_clunk,
+    [P9_TOPEN] = v9fs_open,
+    [P9_TREAD] = v9fs_read,
+#if 0
+    [P9_TAUTH] = v9fs_auth,
+#endif
+    [P9_TFLUSH] = v9fs_flush,
+    [P9_TCREATE] = v9fs_create,
+    [P9_TWRITE] = v9fs_write,
+    [P9_TWSTAT] = v9fs_wstat,
+    [P9_TREMOVE] = v9fs_remove,
+};
+
+static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
+{
+    pdu_handler_t *handler;
+
+    if (debug_9p_pdu) {
+        pprint_pdu(pdu);
+    }
+
+    BUG_ON(pdu->id >= ARRAY_SIZE(pdu_handlers));
+
+    handler = pdu_handlers[pdu->id];
+    BUG_ON(handler == NULL);
+
+    handler(s, pdu);
+}
+
+static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+    V9fsState *s = (V9fsState *)vdev;
+    V9fsPDU *pdu;
+    ssize_t len;
+
+    while ((pdu = alloc_pdu(s)) &&
+            (len = virtqueue_pop(vq, &pdu->elem)) != 0) {
+        uint8_t *ptr;
+
+        BUG_ON(pdu->elem.out_num == 0 || pdu->elem.in_num == 0);
+        BUG_ON(pdu->elem.out_sg[0].iov_len < 7);
+
+        ptr = pdu->elem.out_sg[0].iov_base;
+
+        memcpy(&pdu->size, ptr, 4);
+        pdu->id = ptr[4];
+        memcpy(&pdu->tag, ptr + 5, 2);
+
+        submit_pdu(s, pdu);
+    }
+
+    free_pdu(s, pdu);
+}
+
+static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features)
+{
+    features |= 1 << VIRTIO_9P_MOUNT_TAG;
+    return features;
+}
+
+static V9fsState *to_virtio_9p(VirtIODevice *vdev)
+{
+    return (V9fsState *)vdev;
+}
+
+static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
+{
+    struct virtio_9p_config *cfg;
+    V9fsState *s = to_virtio_9p(vdev);
+
+    cfg = qemu_mallocz(sizeof(struct virtio_9p_config) +
+                        s->tag_len);
+    stw_raw(&cfg->tag_len, s->tag_len);
+    memcpy(cfg->tag, s->tag, s->tag_len);
+    memcpy(config, cfg, s->config_size);
+    qemu_free(cfg);
+}
+
+VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
+ {
+    V9fsState *s;
+    int i, len;
+    struct stat stat;
+    FsTypeEntry *fse;
+
+
+    s = (V9fsState *)virtio_common_init("virtio-9p",
+                                    VIRTIO_ID_9P,
+                                    sizeof(struct virtio_9p_config)+
+                                    MAX_TAG_LEN,
+                                    sizeof(V9fsState));
+
+    /* initialize pdu allocator */
+    QLIST_INIT(&s->free_list);
+    for (i = 0; i < (MAX_REQ - 1); i++) {
+	QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next);
+    }
+
+    s->vq = virtio_add_queue(&s->vdev, MAX_REQ, handle_9p_output);
+
+    fse = get_fsdev_fsentry(conf->fsdev_id);
+
+    if (!fse) {
+        /* We don't have a fsdev identified by fsdev_id */
+        fprintf(stderr, "Virtio-9p device couldn't find fsdev "
+                    "with the id %s\n", conf->fsdev_id);
+        exit(1);
+    }
+
+    if (!fse->path || !conf->tag) {
+        /* we haven't specified a mount_tag or the path */
+        fprintf(stderr, "fsdev with id %s needs path "
+                "and Virtio-9p device needs mount_tag arguments\n",
+                conf->fsdev_id);
+        exit(1);
+    }
+
+    if (lstat(fse->path, &stat)) {
+        fprintf(stderr, "share path %s does not exist\n", fse->path);
+        exit(1);
+    } else if (!S_ISDIR(stat.st_mode)) {
+        fprintf(stderr, "share path %s is not a directory \n", fse->path);
+        exit(1);
+    }
+
+    s->ctx.fs_root = qemu_strdup(fse->path);
+    len = strlen(conf->tag);
+    if (len > MAX_TAG_LEN) {
+        len = MAX_TAG_LEN;
+    }
+    /* s->tag is non-NULL terminated string */
+    s->tag = qemu_malloc(len);
+    memcpy(s->tag, conf->tag, len);
+    s->tag_len = len;
+    s->ctx.uid = -1;
+
+    s->ops = fse->ops;
+    s->vdev.get_features = virtio_9p_get_features;
+    s->config_size = sizeof(struct virtio_9p_config) +
+                        s->tag_len;
+    s->vdev.get_config = virtio_9p_get_config;
+
+    return &s->vdev;
+}
diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h
new file mode 100644
index 0000000..b95dbe4
--- /dev/null
+++ b/hw/virtio-9p.h
@@ -0,0 +1,166 @@
+#ifndef _QEMU_VIRTIO_9P_H
+#define _QEMU_VIRTIO_9P_H
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/time.h>
+#include <utime.h>
+
+#include "file-op-9p.h"
+
+/* The feature bitmap for virtio 9P */
+/* The mount point is specified in a config variable */
+#define VIRTIO_9P_MOUNT_TAG 0
+
+enum {
+    P9_TVERSION = 100,
+    P9_RVERSION,
+    P9_TAUTH = 102,
+    P9_RAUTH,
+    P9_TATTACH = 104,
+    P9_RATTACH,
+    P9_TERROR = 106,
+    P9_RERROR,
+    P9_TFLUSH = 108,
+    P9_RFLUSH,
+    P9_TWALK = 110,
+    P9_RWALK,
+    P9_TOPEN = 112,
+    P9_ROPEN,
+    P9_TCREATE = 114,
+    P9_RCREATE,
+    P9_TREAD = 116,
+    P9_RREAD,
+    P9_TWRITE = 118,
+    P9_RWRITE,
+    P9_TCLUNK = 120,
+    P9_RCLUNK,
+    P9_TREMOVE = 122,
+    P9_RREMOVE,
+    P9_TSTAT = 124,
+    P9_RSTAT,
+    P9_TWSTAT = 126,
+    P9_RWSTAT,
+};
+
+
+/* qid.types */
+enum {
+    P9_QTDIR = 0x80,
+    P9_QTAPPEND = 0x40,
+    P9_QTEXCL = 0x20,
+    P9_QTMOUNT = 0x10,
+    P9_QTAUTH = 0x08,
+    P9_QTTMP = 0x04,
+    P9_QTSYMLINK = 0x02,
+    P9_QTLINK = 0x01,
+    P9_QTFILE = 0x00,
+};
+
+#define P9_NOTAG    (u16)(~0)
+#define P9_NOFID    (u32)(~0)
+#define P9_MAXWELEM 16
+
+typedef struct V9fsPDU V9fsPDU;
+
+struct V9fsPDU
+{
+    uint32_t size;
+    uint16_t tag;
+    uint8_t id;
+    VirtQueueElement elem;
+    QLIST_ENTRY(V9fsPDU) next;
+};
+
+
+/* FIXME
+ * 1) change user needs to set groups and stuff
+ */
+
+/* from Linux's linux/virtio_9p.h */
+
+/* The ID for virtio console */
+#define VIRTIO_ID_9P    9
+#define MAX_REQ         128
+#define MAX_TAG_LEN     32
+
+#define BUG_ON(cond) assert(!(cond))
+
+typedef struct V9fsFidState V9fsFidState;
+
+typedef struct V9fsString
+{
+    int16_t size;
+    char *data;
+} V9fsString;
+
+typedef struct V9fsQID
+{
+    int8_t type;
+    int32_t version;
+    int64_t path;
+} V9fsQID;
+
+typedef struct V9fsStat
+{
+    int16_t size;
+    int16_t type;
+    int32_t dev;
+    V9fsQID qid;
+    int32_t mode;
+    int32_t atime;
+    int32_t mtime;
+    int64_t length;
+    V9fsString name;
+    V9fsString uid;
+    V9fsString gid;
+    V9fsString muid;
+    /* 9p2000.u */
+    V9fsString extension;
+   int32_t n_uid;
+    int32_t n_gid;
+    int32_t n_muid;
+} V9fsStat;
+
+struct V9fsFidState
+{
+    int32_t fid;
+    V9fsString path;
+    int fd;
+    DIR *dir;
+    uid_t uid;
+    V9fsFidState *next;
+};
+
+typedef struct V9fsState
+{
+    VirtIODevice vdev;
+    VirtQueue *vq;
+    V9fsPDU pdus[MAX_REQ];
+    QLIST_HEAD(, V9fsPDU) free_list;
+    V9fsFidState *fid_list;
+    FileOperations *ops;
+    FsContext ctx;
+    uint16_t tag_len;
+    uint8_t *tag;
+    size_t config_size;
+} V9fsState;
+
+struct virtio_9p_config
+{
+    /* number of characters in tag */
+    uint16_t tag_len;
+    /* Variable size tag name */
+    uint8_t tag[0];
+} __attribute__((packed));
+
+extern size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
+                            size_t offset, size_t size, int pack);
+
+static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
+                        size_t offset, size_t size)
+{
+    return pdu_packunpack(dst, sg, sg_count, offset, size, 0);
+}
+
+#endif
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 7ce526f..7ddf612 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -102,6 +102,9 @@ typedef struct {
     BlockConf block;
     NICConf nic;
     uint32_t host_features;
+#ifdef CONFIG_LINUX
+    V9fsConf fsconf;
+#endif
     /* Max. number of ports we can have for a the virtio-serial device */
     uint32_t max_virtserial_ports;
 } VirtIOPCIProxy;
@@ -639,6 +642,23 @@ static int virtio_balloon_init_pci(PCIDevice *pci_dev)
     return 0;
 }
 
+#ifdef CONFIG_LINUX
+static int virtio_9p_init_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+    VirtIODevice *vdev;
+
+    vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
+    virtio_init_pci(proxy, vdev,
+                    PCI_VENDOR_ID_REDHAT_QUMRANET,
+                    0x1009,
+                    0x2,
+                    0x00);
+
+    return 0;
+}
+#endif
+
 static PCIDeviceInfo virtio_info[] = {
     {
         .qdev.name = "virtio-blk-pci",
@@ -693,6 +713,18 @@ static PCIDeviceInfo virtio_info[] = {
         },
         .qdev.reset = virtio_pci_reset,
     },{
+#ifdef CONFIG_LINUX
+        .qdev.name = "virtio-9p-pci",
+        .qdev.size = sizeof(VirtIOPCIProxy),
+        .init      = virtio_9p_init_pci,
+        .qdev.props = (Property[]) {
+            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+            DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
+            DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
+            DEFINE_PROP_END_OF_LIST(),
+        },
+    }, {
+#endif
         /* end of list */
     }
 };
diff --git a/hw/virtio.h b/hw/virtio.h
index f885f1b..e4306cd 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -20,6 +20,9 @@
 #include "sysemu.h"
 #include "block_int.h"
 #include "event_notifier.h"
+#ifdef CONFIG_LINUX
+#include "9p.h"
+#endif
 
 /* from Linux's linux/virtio_config.h */
 
@@ -185,6 +188,10 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf);
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf);
 VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports);
 VirtIODevice *virtio_balloon_init(DeviceState *dev);
+#ifdef CONFIG_LINUX
+VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
+#endif
+
 
 void virtio_net_exit(VirtIODevice *vdev);
 
commit 74db920c32cea5b52a91b81f2bfd467fc070e942
Author: Gautham R Shenoy <ego at in.ibm.com>
Date:   Thu Apr 29 17:44:43 2010 +0530

    virtio-9p: Create a commandline option -fsdev
    
    This patch creates a new command line option named -fsdev to hold any file
    system specific information.
    
    The option will currently hold the following attributes:
    -fsdev fstype id=id,path=path_to_share
    where
    fstype: Type of the file system.
    id:     Identifier used to refer to this fsdev
    path:   The path on the host that is identified by this fsdev.
    
    [aneesh.kumar at linux.vnet.ibm.com: Abstraction using FsContext]
    Signed-off-by: Gautham R Shenoy <ego at in.ibm.com>
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile.objs b/Makefile.objs
index 603a8d7..ecdd53e 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -35,6 +35,9 @@ net-nested-$(CONFIG_SLIRP) += slirp.o
 net-nested-$(CONFIG_VDE) += vde.o
 net-obj-y += $(addprefix net/, $(net-nested-y))
 
+fsdev-nested-$(CONFIG_LINUX) = qemu-fsdev.o
+fsdev-obj-$(CONFIG_LINUX) += $(addprefix fsdev/, $(fsdev-nested-y))
+
 ######################################################################
 # libqemu_common.a: Target independent part of system emulation. The
 # long term path is to suppress *all* target specific code in case of
@@ -44,8 +47,8 @@ net-obj-y += $(addprefix net/, $(net-nested-y))
 common-obj-y = $(block-obj-y)
 common-obj-y += $(net-obj-y)
 common-obj-y += $(qobject-obj-y)
+common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
 common-obj-y += readline.o console.o async.o qemu-error.o
-
 common-obj-y += tcg-runtime.o host-utils.o
 common-obj-y += irq.o ioport.o input.o
 common-obj-$(CONFIG_PTIMER) += ptimer.o
diff --git a/configure b/configure
index 172b7cf..87942f4 100755
--- a/configure
+++ b/configure
@@ -2757,6 +2757,7 @@ done # for target in $targets
 if test "$source_path_used" = "yes" ; then
     DIRS="tests tests/cris slirp audio block net pc-bios/optionrom"
     DIRS="$DIRS roms/seabios roms/vgabios"
+    DIRS="$DIRS fsdev"
     FILES="Makefile tests/Makefile"
     FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
     FILES="$FILES tests/test-mmap.c"
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
new file mode 100644
index 0000000..48bbfd9
--- /dev/null
+++ b/fsdev/qemu-fsdev.c
@@ -0,0 +1,70 @@
+/*
+ * Virtio 9p
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Gautham R Shenoy <ego at in.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include "qemu-fsdev.h"
+#include "qemu-queue.h"
+#include "osdep.h"
+#include "qemu-common.h"
+
+static QTAILQ_HEAD(FsTypeEntry_head, FsTypeListEntry) fstype_entries =
+    QTAILQ_HEAD_INITIALIZER(fstype_entries);
+
+static FsTypeTable FsTypes[] = {
+    { .name = "local", .ops = NULL},
+};
+
+int qemu_fsdev_add(QemuOpts *opts)
+{
+    struct FsTypeListEntry *fsle;
+    int i;
+
+    if (qemu_opts_id(opts) == NULL) {
+        fprintf(stderr, "fsdev: No id specified\n");
+        return -1;
+    }
+
+     for (i = 0; i < ARRAY_SIZE(FsTypes); i++) {
+        if (strcmp(FsTypes[i].name, qemu_opt_get(opts, "fstype")) == 0) {
+            break;
+        }
+    }
+
+    if (i == ARRAY_SIZE(FsTypes)) {
+        fprintf(stderr, "fsdev: fstype %s not found\n",
+                    qemu_opt_get(opts, "fstype"));
+        return -1;
+    }
+
+    fsle = qemu_malloc(sizeof(*fsle));
+
+    fsle->fse.fsdev_id = qemu_strdup(qemu_opts_id(opts));
+    fsle->fse.path = qemu_strdup(qemu_opt_get(opts, "path"));
+    fsle->fse.ops = FsTypes[i].ops;
+
+    QTAILQ_INSERT_TAIL(&fstype_entries, fsle, next);
+    return 0;
+
+}
+
+FsTypeEntry *get_fsdev_fsentry(char *id)
+{
+    struct FsTypeListEntry *fsle;
+
+    QTAILQ_FOREACH(fsle, &fstype_entries, next) {
+        if (strcmp(fsle->fse.fsdev_id, id) == 0) {
+            return &fsle->fse;
+        }
+    }
+    return NULL;
+}
diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h
new file mode 100644
index 0000000..7fa4f60
--- /dev/null
+++ b/fsdev/qemu-fsdev.h
@@ -0,0 +1,53 @@
+/*
+ * Virtio 9p
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Gautham R Shenoy <ego at in.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#ifndef QEMU_FSDEV_H
+#define QEMU_FSDEV_H
+#include "qemu-option.h"
+#include "hw/file-op-9p.h"
+
+
+/*
+ * A table to store the various file systems and their callback operations.
+ * -----------------
+ * fstype | ops
+ * -----------------
+ *  local | local_ops
+ *  .     |
+ *  .     |
+ *  .     |
+ *  .     |
+ * -----------------
+ *  etc
+ */
+typedef struct FsTypeTable {
+    const char *name;
+    FileOperations *ops;
+} FsTypeTable;
+
+/*
+ * Structure to store the various fsdev's passed through command line.
+ */
+typedef struct FsTypeEntry {
+    char *fsdev_id;
+    char *path;
+    FileOperations *ops;
+} FsTypeEntry;
+
+typedef struct FsTypeListEntry {
+    FsTypeEntry fse;
+    QTAILQ_ENTRY(FsTypeListEntry) next;
+} FsTypeListEntry;
+
+extern int qemu_fsdev_add(QemuOpts *opts);
+extern FsTypeEntry *get_fsdev_fsentry(char *id);
+#endif
diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
new file mode 100644
index 0000000..7cde63c
--- /dev/null
+++ b/hw/file-op-9p.h
@@ -0,0 +1,32 @@
+/*
+ * Virtio 9p
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#ifndef _FILEOP_H
+#define _FILEOP_H
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/time.h>
+#include <utime.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+
+typedef struct FsContext
+{
+    char *fs_root;
+    uid_t uid;
+} FsContext;
+
+typedef struct FileOperations
+{
+    void *opaque;
+} FileOperations;
+#endif
diff --git a/qemu-config.c b/qemu-config.c
index 9f0f143..cda5060 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -151,6 +151,24 @@ QemuOptsList qemu_chardev_opts = {
     },
 };
 
+#ifdef CONFIG_LINUX
+QemuOptsList qemu_fsdev_opts = {
+    .name = "fsdev",
+    .implied_opt_name = "fstype",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_fsdev_opts.head),
+    .desc = {
+        {
+            .name = "fstype",
+            .type = QEMU_OPT_STRING,
+        }, {
+            .name = "path",
+            .type = QEMU_OPT_STRING,
+        },
+        { /*End of list */ }
+    },
+};
+#endif
+
 QemuOptsList qemu_device_opts = {
     .name = "device",
     .implied_opt_name = "driver",
diff --git a/qemu-config.h b/qemu-config.h
index dd299c2..5f34803 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -3,6 +3,9 @@
 
 extern QemuOptsList qemu_drive_opts;
 extern QemuOptsList qemu_chardev_opts;
+#ifdef CONFIG_LINUX
+extern QemuOptsList qemu_fsdev_opts;
+#endif
 extern QemuOptsList qemu_device_opts;
 extern QemuOptsList qemu_netdev_opts;
 extern QemuOptsList qemu_net_opts;
diff --git a/qemu-options.hx b/qemu-options.hx
index 83b54c3..e754ba1 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -478,6 +478,40 @@ To get a help on possible @var{driver}s, @var{option}s or @var{value}s, use
 @code{-device @var{driver}, at var{option}=?}. 
 ETEXI
 
+#ifdef CONFIG_LINUX
+DEFHEADING(File system options:)
+
+DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
+    "-fsdev local,id=id,path=path\n",
+    QEMU_ARCH_ALL)
+
+STEXI
+
+The general form of a File system device option is:
+ at table @option
+
+ at item -fsdev @var{fstype} ,id=@var{id} [, at var{options}]
+ at findex -fsdev
+Fstype is one of:
+ at option{local},
+The specific Fstype will determine the applicable options.
+
+Options to each backend are described below.
+
+ at item -fsdev local ,id=@var{id} ,path=@var{path}
+
+Create a file-system-"device" for local-filesystem.
+
+ at option{local} is only available on Linux.
+
+ at option{path} specifies the path to be exported. @option{path} is required.
+
+ at end table
+ETEXI
+#endif
+
+DEFHEADING()
+
 DEF("name", HAS_ARG, QEMU_OPTION_name,
     "-name string1[,process=string2]\n"
     "                set the name of the guest\n"
diff --git a/vl.c b/vl.c
index 53ea698..37f46b6 100644
--- a/vl.c
+++ b/vl.c
@@ -149,6 +149,9 @@ int main(int argc, char **argv)
 #include "qemu-option.h"
 #include "qemu-config.h"
 #include "qemu-objects.h"
+#ifdef CONFIG_LINUX
+#include "fsdev/qemu-fsdev.h"
+#endif
 
 #include "disas.h"
 
@@ -2310,6 +2313,16 @@ static int chardev_init_func(QemuOpts *opts, void *opaque)
     return 0;
 }
 
+#ifdef CONFIG_LINUX
+static int fsdev_init_func(QemuOpts *opts, void *opaque)
+{
+    int ret;
+    ret = qemu_fsdev_add(opts);
+
+    return ret;
+}
+#endif
+
 static int mon_init_func(QemuOpts *opts, void *opaque)
 {
     CharDriverState *chr;
@@ -3081,6 +3094,15 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
                 break;
+#ifdef CONFIG_LINUX
+            case QEMU_OPTION_fsdev:
+                opts = qemu_opts_parse(&qemu_fsdev_opts, optarg, 1);
+                if (!opts) {
+                    fprintf(stderr, "parse error: %s\n", optarg);
+                    exit(1);
+                }
+                break;
+#endif
             case QEMU_OPTION_serial:
                 add_device_config(DEV_SERIAL, optarg);
                 default_serial = 0;
@@ -3437,6 +3459,11 @@ int main(int argc, char **argv, char **envp)
 
     if (qemu_opts_foreach(&qemu_chardev_opts, chardev_init_func, NULL, 1) != 0)
         exit(1);
+#ifdef CONFIG_LINUX
+    if (qemu_opts_foreach(&qemu_fsdev_opts, fsdev_init_func, NULL, 1) != 0) {
+        exit(1);
+    }
+#endif
 
 #ifndef _WIN32
     if (daemonize) {
commit a1c5975270f2335e1d7129c084a6e562d7b99bdd
Author: Amit Shah <amit.shah at redhat.com>
Date:   Fri Apr 30 16:43:55 2010 +0530

    virtio-serial: Fix check for 'assert'; prevent NULL derefs
    
    In the flush_queued_data() function, we expect port to be valid. Assert
    only for port and not port || discard.
    
    Reported-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 97694d5..3ce95e8 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -137,7 +137,7 @@ static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
 
 static void flush_queued_data(VirtIOSerialPort *port, bool discard)
 {
-    assert(port || discard);
+    assert(port);
 
     do_flush_queued_data(port, port->ovq, &port->vser->vdev, discard);
 }
commit f8778a7785d530515b0db395606f327fd5f94a92
Author: Stefan Berger <stefanb at us.ibm.com>
Date:   Sat Apr 24 08:54:07 2010 -0400

    Fix the RARP protocol ID
    
    The packet(s) sent out after migration are supposed to be RAPR type of
    packets. If they are supposed to go anywhere useful, the RAPR ethernet
    identifier needs to be fix.
    
    Also see http://www.iana.org/assignments/ethernet-numbers for 0x8035 for
    RARP.
    
    Signed-off-by: Stefan Berger <stefanb at us.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/savevm.c b/savevm.c
index 086c92a..31a419c 100644
--- a/savevm.c
+++ b/savevm.c
@@ -89,7 +89,7 @@ static BlockDriverState *bs_snapshots;
 #define SELF_ANNOUNCE_ROUNDS 5
 
 #ifndef ETH_P_RARP
-#define ETH_P_RARP 0x0835
+#define ETH_P_RARP 0x8035
 #endif
 #define ARP_HTYPE_ETH 0x0001
 #define ARP_PTYPE_IP 0x0800
commit d510c5cf343eabd4d3a301f5730af724747b7055
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Thu Apr 29 18:24:43 2010 +0200

    Fix tiny leak in qemu_opts_parse
    
    qemu_opts_create duplicates the id we pass in case it shall be stored in
    the opts. So we do not need to dup it in qemu_opts_parse, leaking a few
    bytes this way.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-option.c b/qemu-option.c
index 1ffc497..076dddf 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -763,10 +763,10 @@ QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
 
     if (strncmp(params, "id=", 3) == 0) {
         get_opt_value(value, sizeof(value), params+3);
-        id = qemu_strdup(value);
+        id = value;
     } else if ((p = strstr(params, ",id=")) != NULL) {
         get_opt_value(value, sizeof(value), p+4);
-        id = qemu_strdup(value);
+        id = value;
     }
     opts = qemu_opts_create(list, id, 1);
     if (opts == NULL)
commit 54eefd72bfc0ad7cd5cbedba8ef4368bd2bc3329
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Apr 30 14:06:13 2010 +0200

    lsi: Properly initialize controller state on reset
    
    The LSI controller was lacking a system reset handler. Simply invoke the
    existing soft reset handler in this case. This also allows to drop its
    explicit invocation during init.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index ad23ece..85eea15 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -2007,6 +2007,13 @@ static void lsi_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
     cpu_register_physical_memory(addr + 0, 0x400, s->mmio_io_addr);
 }
 
+static void lsi_scsi_reset(DeviceState *dev)
+{
+    LSIState *s = DO_UPCAST(LSIState, dev.qdev, dev);
+
+    lsi_soft_reset(s);
+}
+
 static void lsi_pre_save(void *opaque)
 {
     LSIState *s = opaque;
@@ -2147,8 +2154,6 @@ static int lsi_scsi_init(PCIDevice *dev)
                            PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_ram_mapfunc);
     QTAILQ_INIT(&s->queue);
 
-    lsi_soft_reset(s);
-
     scsi_bus_new(&s->bus, &dev->qdev, 1, LSI_MAX_DEVS, lsi_command_complete);
     if (!dev->qdev.hotplugged) {
         scsi_bus_legacy_handle_cmdline(&s->bus);
@@ -2160,6 +2165,7 @@ static PCIDeviceInfo lsi_info = {
     .qdev.name  = "lsi53c895a",
     .qdev.alias = "lsi",
     .qdev.size  = sizeof(LSIState),
+    .qdev.reset = lsi_scsi_reset,
     .qdev.vmsd  = &vmstate_lsi_scsi,
     .init       = lsi_scsi_init,
     .exit       = lsi_scsi_uninit,
commit 51336214da6f2eaa7baaa8efa1823377252c1496
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Apr 30 14:06:12 2010 +0200

    lsi: Purge request queue on soft reset
    
    Avoid keeping zombie requests across controller reset by purging the
    queue and also dropping the currently active request.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 98b7f54..ad23ece 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -283,6 +283,8 @@ static inline int lsi_irq_on_rsl(LSIState *s)
 
 static void lsi_soft_reset(LSIState *s)
 {
+    lsi_request *p;
+
     DPRINTF("Reset\n");
     s->carry = 0;
 
@@ -345,6 +347,15 @@ static void lsi_soft_reset(LSIState *s)
     s->sbc = 0;
     s->csbc = 0;
     s->sbr = 0;
+    while (!QTAILQ_EMPTY(&s->queue)) {
+        p = QTAILQ_FIRST(&s->queue);
+        QTAILQ_REMOVE(&s->queue, p, next);
+        qemu_free(p);
+    }
+    if (s->current) {
+        qemu_free(s->current);
+        s->current = NULL;
+    }
 }
 
 static int lsi_dma_40bit(LSIState *s)
commit 37905d6ae53d8a9f0744867a8cf2dad6e7ae3674
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Fri Apr 30 15:21:11 2010 -0600

    Fix boot once option
    
    The boot once options seems to have gotten broken since it originally
    went in.  We need to wait until the second time restore_boot_devices()
    gets called before restoring the standard boot order and removing itself
    from the reset list.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    --
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index 5e03b72..53ea698 100644
--- a/vl.c
+++ b/vl.c
@@ -1193,6 +1193,13 @@ static void validate_bootdevices(char *devices)
 static void restore_boot_devices(void *opaque)
 {
     char *standard_boot_devices = opaque;
+    static int first = 1;
+
+    /* Restore boot order and remove ourselves after the first boot */
+    if (first) {
+        first = 0;
+        return;
+    }
 
     qemu_boot_set(standard_boot_devices);
 
commit 70a4568fe0c5a64adaa3da5030b7109e5199e692
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Mon May 3 14:31:34 2010 +0200

    vnc: split encoding in specific files
    
    This will allow to implement new encodings (tight, zrle, ..)
    in a cleaner way. This may hurt performances, because some
    functions like vnc_convert_pixel are not static anymore, but
    should not be a problem with gcc 4.5 and the new -flto.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index 18e7368..eb9e02b 100644
--- a/Makefile
+++ b/Makefile
@@ -120,6 +120,10 @@ vnc-auth-vencrypt.o: vnc-auth-vencrypt.c vnc.h
 
 vnc-auth-sasl.o: vnc-auth-sasl.c vnc.h
 
+vnc-encoding-zlib.o: vnc.h
+
+vnc-encoding-hextile.o: vnc.h
+
 curses.o: curses.c keymaps.h curses_keys.h
 
 bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
diff --git a/Makefile.objs b/Makefile.objs
index 4f65bfb..603a8d7 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -100,6 +100,7 @@ common-obj-y += keymaps.o
 common-obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o
 common-obj-$(CONFIG_CURSES) += curses.o
 common-obj-y += vnc.o acl.o d3des.o
+common-obj-y += vnc-encoding-zlib.o vnc-encoding-hextile.o
 common-obj-y += iov.o
 common-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
 common-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
diff --git a/vnc-encoding-hextile.c b/vnc-encoding-hextile.c
new file mode 100644
index 0000000..a01c5e2
--- /dev/null
+++ b/vnc-encoding-hextile.c
@@ -0,0 +1,115 @@
+/*
+ * QEMU VNC display driver: hextile encoding
+ *
+ * Copyright (C) 2006 Anthony Liguori <anthony at codemonkey.ws>
+ * Copyright (C) 2006 Fabrice Bellard
+ * Copyright (C) 2009 Red Hat, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vnc.h"
+
+static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
+{
+    ptr[0] = ((x & 0x0F) << 4) | (y & 0x0F);
+    ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F);
+}
+
+#define BPP 8
+#include "vnchextile.h"
+#undef BPP
+
+#define BPP 16
+#include "vnchextile.h"
+#undef BPP
+
+#define BPP 32
+#include "vnchextile.h"
+#undef BPP
+
+#define GENERIC
+#define BPP 8
+#include "vnchextile.h"
+#undef BPP
+#undef GENERIC
+
+#define GENERIC
+#define BPP 16
+#include "vnchextile.h"
+#undef BPP
+#undef GENERIC
+
+#define GENERIC
+#define BPP 32
+#include "vnchextile.h"
+#undef BPP
+#undef GENERIC
+
+void vnc_hextile_send_framebuffer_update(VncState *vs, int x,
+                                         int y, int w, int h)
+{
+    int i, j;
+    int has_fg, has_bg;
+    uint8_t *last_fg, *last_bg;
+    VncDisplay *vd = vs->vd;
+
+    last_fg = (uint8_t *) qemu_malloc(vd->server->pf.bytes_per_pixel);
+    last_bg = (uint8_t *) qemu_malloc(vd->server->pf.bytes_per_pixel);
+    has_fg = has_bg = 0;
+    for (j = y; j < (y + h); j += 16) {
+        for (i = x; i < (x + w); i += 16) {
+            vs->send_hextile_tile(vs, i, j,
+                                  MIN(16, x + w - i), MIN(16, y + h - j),
+                                  last_bg, last_fg, &has_bg, &has_fg);
+        }
+    }
+    free(last_fg);
+    free(last_bg);
+
+}
+
+void vnc_hextile_set_pixel_conversion(VncState *vs, int generic)
+{
+    if (!generic) {
+        switch (vs->ds->surface->pf.bits_per_pixel) {
+            case 8:
+                vs->send_hextile_tile = send_hextile_tile_8;
+                break;
+            case 16:
+                vs->send_hextile_tile = send_hextile_tile_16;
+                break;
+            case 32:
+                vs->send_hextile_tile = send_hextile_tile_32;
+                break;
+        }
+    } else {
+        switch (vs->ds->surface->pf.bits_per_pixel) {
+            case 8:
+                vs->send_hextile_tile = send_hextile_tile_generic_8;
+                break;
+            case 16:
+                vs->send_hextile_tile = send_hextile_tile_generic_16;
+                break;
+            case 32:
+                vs->send_hextile_tile = send_hextile_tile_generic_32;
+                break;
+        }
+    }
+}
diff --git a/vnc-encoding-zlib.c b/vnc-encoding-zlib.c
new file mode 100644
index 0000000..4a495ad
--- /dev/null
+++ b/vnc-encoding-zlib.c
@@ -0,0 +1,142 @@
+/*
+ * QEMU VNC display driver: zlib encoding
+ *
+ * Copyright (C) 2006 Anthony Liguori <anthony at codemonkey.ws>
+ * Copyright (C) 2006 Fabrice Bellard
+ * Copyright (C) 2009 Red Hat, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vnc.h"
+
+#define ZALLOC_ALIGNMENT 16
+
+static void *zalloc(void *x, unsigned items, unsigned size)
+{
+    void *p;
+
+    size *= items;
+    size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
+
+    p = qemu_mallocz(size);
+
+    return (p);
+}
+
+static void zfree(void *x, void *addr)
+{
+    qemu_free(addr);
+}
+
+static void vnc_zlib_start(VncState *vs)
+{
+    buffer_reset(&vs->zlib);
+
+    // make the output buffer be the zlib buffer, so we can compress it later
+    vs->zlib_tmp = vs->output;
+    vs->output = vs->zlib;
+}
+
+static int vnc_zlib_stop(VncState *vs, int stream_id)
+{
+    z_streamp zstream = &vs->zlib_stream[stream_id];
+    int previous_out;
+
+    // switch back to normal output/zlib buffers
+    vs->zlib = vs->output;
+    vs->output = vs->zlib_tmp;
+
+    // compress the zlib buffer
+
+    // initialize the stream
+    // XXX need one stream per session
+    if (zstream->opaque != vs) {
+        int err;
+
+        VNC_DEBUG("VNC: initializing zlib stream %d\n", stream_id);
+        VNC_DEBUG("VNC: opaque = %p | vs = %p\n", zstream->opaque, vs);
+        zstream->zalloc = zalloc;
+        zstream->zfree = zfree;
+
+        err = deflateInit2(zstream, vs->tight_compression, Z_DEFLATED, MAX_WBITS,
+                           MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
+
+        if (err != Z_OK) {
+            fprintf(stderr, "VNC: error initializing zlib\n");
+            return -1;
+        }
+
+        zstream->opaque = vs;
+    }
+
+    // XXX what to do if tight_compression changed in between?
+
+    // reserve memory in output buffer
+    buffer_reserve(&vs->output, vs->zlib.offset + 64);
+
+    // set pointers
+    zstream->next_in = vs->zlib.buffer;
+    zstream->avail_in = vs->zlib.offset;
+    zstream->next_out = vs->output.buffer + vs->output.offset;
+    zstream->avail_out = vs->output.capacity - vs->output.offset;
+    zstream->data_type = Z_BINARY;
+    previous_out = zstream->total_out;
+
+    // start encoding
+    if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) {
+        fprintf(stderr, "VNC: error during zlib compression\n");
+        return -1;
+    }
+
+    vs->output.offset = vs->output.capacity - zstream->avail_out;
+    return zstream->total_out - previous_out;
+}
+
+void vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
+{
+    int old_offset, new_offset, bytes_written;
+
+    vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_ZLIB);
+
+    // remember where we put in the follow-up size
+    old_offset = vs->output.offset;
+    vnc_write_s32(vs, 0);
+
+    // compress the stream
+    vnc_zlib_start(vs);
+    vnc_raw_send_framebuffer_update(vs, x, y, w, h);
+    bytes_written = vnc_zlib_stop(vs, 0);
+
+    if (bytes_written == -1)
+        return;
+
+    // hack in the size
+    new_offset = vs->output.offset;
+    vs->output.offset = old_offset;
+    vnc_write_u32(vs, bytes_written);
+    vs->output.offset = new_offset;
+}
+
+void vnc_zlib_init(VncState *vs)
+{
+    int i;
+    for (i=0; i<(sizeof(vs->zlib_stream) / sizeof(z_stream)); i++)
+        vs->zlib_stream[i].opaque = NULL;
+}
diff --git a/vnc.c b/vnc.c
index d332099..5241a6a 100644
--- a/vnc.c
+++ b/vnc.c
@@ -468,8 +468,8 @@ static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
             vnc_set_bit(s->dirty[y], (x + i) / 16);
 }
 
-static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
-                                   int32_t encoding)
+void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
+                            int32_t encoding)
 {
     vnc_write_u16(vs, x);
     vnc_write_u16(vs, y);
@@ -560,7 +560,7 @@ static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
 }
 
 /* slowest but generic code. */
-static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
+void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
 {
     uint8_t r, g, b;
     VncDisplay *vd = vs->vd;
@@ -638,7 +638,7 @@ static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
     }
 }
 
-static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h)
+void vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
 {
     int i;
     uint8_t *row;
@@ -651,192 +651,19 @@ static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h
     }
 }
 
-static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
-{
-    ptr[0] = ((x & 0x0F) << 4) | (y & 0x0F);
-    ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F);
-}
-
-#define BPP 8
-#include "vnchextile.h"
-#undef BPP
-
-#define BPP 16
-#include "vnchextile.h"
-#undef BPP
-
-#define BPP 32
-#include "vnchextile.h"
-#undef BPP
-
-#define GENERIC
-#define BPP 8
-#include "vnchextile.h"
-#undef BPP
-#undef GENERIC
-
-#define GENERIC
-#define BPP 16
-#include "vnchextile.h"
-#undef BPP
-#undef GENERIC
-
-#define GENERIC
-#define BPP 32
-#include "vnchextile.h"
-#undef BPP
-#undef GENERIC
-
-static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, int h)
-{
-    int i, j;
-    int has_fg, has_bg;
-    uint8_t *last_fg, *last_bg;
-    VncDisplay *vd = vs->vd;
-
-    last_fg = (uint8_t *) qemu_malloc(vd->server->pf.bytes_per_pixel);
-    last_bg = (uint8_t *) qemu_malloc(vd->server->pf.bytes_per_pixel);
-    has_fg = has_bg = 0;
-    for (j = y; j < (y + h); j += 16) {
-        for (i = x; i < (x + w); i += 16) {
-            vs->send_hextile_tile(vs, i, j,
-                                  MIN(16, x + w - i), MIN(16, y + h - j),
-                                  last_bg, last_fg, &has_bg, &has_fg);
-        }
-    }
-    free(last_fg);
-    free(last_bg);
-
-}
-
-#define ZALLOC_ALIGNMENT 16
-
-static void *zalloc(void *x, unsigned items, unsigned size)
-{
-    void *p;
-
-    size *= items;
-    size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
-
-    p = qemu_mallocz(size);
-
-    return (p);
-}
-
-static void zfree(void *x, void *addr)
-{
-    qemu_free(addr);
-}
-
-static void vnc_zlib_init(VncState *vs)
-{
-    int i;
-    for (i=0; i<(sizeof(vs->zlib_stream) / sizeof(z_stream)); i++)
-        vs->zlib_stream[i].opaque = NULL;
-}
-
-static void vnc_zlib_start(VncState *vs)
-{
-    buffer_reset(&vs->zlib);
-
-    // make the output buffer be the zlib buffer, so we can compress it later
-    vs->zlib_tmp = vs->output;
-    vs->output = vs->zlib;
-}
-
-static int vnc_zlib_stop(VncState *vs, int stream_id)
-{
-    z_streamp zstream = &vs->zlib_stream[stream_id];
-    int previous_out;
-
-    // switch back to normal output/zlib buffers
-    vs->zlib = vs->output;
-    vs->output = vs->zlib_tmp;
-
-    // compress the zlib buffer
-
-    // initialize the stream
-    // XXX need one stream per session
-    if (zstream->opaque != vs) {
-        int err;
-
-        VNC_DEBUG("VNC: initializing zlib stream %d\n", stream_id);
-        VNC_DEBUG("VNC: opaque = %p | vs = %p\n", zstream->opaque, vs);
-        zstream->zalloc = zalloc;
-        zstream->zfree = zfree;
-
-        err = deflateInit2(zstream, vs->tight_compression, Z_DEFLATED, MAX_WBITS,
-                           MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
-
-        if (err != Z_OK) {
-            fprintf(stderr, "VNC: error initializing zlib\n");
-            return -1;
-        }
-
-        zstream->opaque = vs;
-    }
-
-    // XXX what to do if tight_compression changed in between?
-
-    // reserve memory in output buffer
-    buffer_reserve(&vs->output, vs->zlib.offset + 64);
-
-    // set pointers
-    zstream->next_in = vs->zlib.buffer;
-    zstream->avail_in = vs->zlib.offset;
-    zstream->next_out = vs->output.buffer + vs->output.offset;
-    zstream->avail_out = vs->output.capacity - vs->output.offset;
-    zstream->data_type = Z_BINARY;
-    previous_out = zstream->total_out;
-
-    // start encoding
-    if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) {
-        fprintf(stderr, "VNC: error during zlib compression\n");
-        return -1;
-    }
-
-    vs->output.offset = vs->output.capacity - zstream->avail_out;
-    return zstream->total_out - previous_out;
-}
-
-static void send_framebuffer_update_zlib(VncState *vs, int x, int y, int w, int h)
-{
-    int old_offset, new_offset, bytes_written;
-
-    vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_ZLIB);
-
-    // remember where we put in the follow-up size
-    old_offset = vs->output.offset;
-    vnc_write_s32(vs, 0);
-
-    // compress the stream
-    vnc_zlib_start(vs);
-    send_framebuffer_update_raw(vs, x, y, w, h);
-    bytes_written = vnc_zlib_stop(vs, 0);
-
-    if (bytes_written == -1)
-        return;
-
-    // hack in the size
-    new_offset = vs->output.offset;
-    vs->output.offset = old_offset;
-    vnc_write_u32(vs, bytes_written);
-    vs->output.offset = new_offset;
-}
-
 static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
 {
     switch(vs->vnc_encoding) {
         case VNC_ENCODING_ZLIB:
-            send_framebuffer_update_zlib(vs, x, y, w, h);
+            vnc_hextile_send_framebuffer_update(vs, x, y, w, h);
             break;
         case VNC_ENCODING_HEXTILE:
             vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE);
-            send_framebuffer_update_hextile(vs, x, y, w, h);
+            vnc_hextile_send_framebuffer_update(vs, x, y, w, h);
             break;
         default:
             vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW);
-            send_framebuffer_update_raw(vs, x, y, w, h);
+            vnc_raw_send_framebuffer_update(vs, x, y, w, h);
             break;
     }
 }
@@ -1823,30 +1650,10 @@ static void set_pixel_conversion(VncState *vs)
         (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) && 
         !memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) {
         vs->write_pixels = vnc_write_pixels_copy;
-        switch (vs->ds->surface->pf.bits_per_pixel) {
-            case 8:
-                vs->send_hextile_tile = send_hextile_tile_8;
-                break;
-            case 16:
-                vs->send_hextile_tile = send_hextile_tile_16;
-                break;
-            case 32:
-                vs->send_hextile_tile = send_hextile_tile_32;
-                break;
-        }
+        vnc_hextile_set_pixel_conversion(vs, 0);
     } else {
         vs->write_pixels = vnc_write_pixels_generic;
-        switch (vs->ds->surface->pf.bits_per_pixel) {
-            case 8:
-                vs->send_hextile_tile = send_hextile_tile_generic_8;
-                break;
-            case 16:
-                vs->send_hextile_tile = send_hextile_tile_generic_16;
-                break;
-            case 32:
-                vs->send_hextile_tile = send_hextile_tile_generic_32;
-                break;
-        }
+        vnc_hextile_set_pixel_conversion(vs, 1);
     }
 }
 
@@ -1903,12 +1710,9 @@ static void pixel_format_message (VncState *vs) {
     vnc_write_u8(vs, vs->ds->surface->pf.rshift);    /* red-shift */
     vnc_write_u8(vs, vs->ds->surface->pf.gshift);    /* green-shift */
     vnc_write_u8(vs, vs->ds->surface->pf.bshift);    /* blue-shift */
-    if (vs->ds->surface->pf.bits_per_pixel == 32)
-        vs->send_hextile_tile = send_hextile_tile_32;
-    else if (vs->ds->surface->pf.bits_per_pixel == 16)
-        vs->send_hextile_tile = send_hextile_tile_16;
-    else if (vs->ds->surface->pf.bits_per_pixel == 8)
-        vs->send_hextile_tile = send_hextile_tile_8;
+
+    vnc_hextile_set_pixel_conversion(vs, 0);
+
     vs->clientds = *(vs->ds->surface);
     vs->clientds.flags &= ~QEMU_ALLOCATED_FLAG;
     vs->write_pixels = vnc_write_pixels_copy;
diff --git a/vnc.h b/vnc.h
index b593608..1aa71b0 100644
--- a/vnc.h
+++ b/vnc.h
@@ -132,8 +132,6 @@ struct VncState
     int last_y;
 
     uint32_t vnc_encoding;
-    uint8_t tight_quality;
-    uint8_t tight_compression;
 
     int major;
     int minor;
@@ -152,7 +150,6 @@ struct VncState
     Buffer input;
     /* current output mode information */
     VncWritePixels *write_pixels;
-    VncSendHextileTile *send_hextile_tile;
     DisplaySurface clientds;
 
     CaptureVoiceOut *audio_cap;
@@ -164,6 +161,16 @@ struct VncState
     uint8_t modifiers_state[256];
     QEMUPutLEDEntry *led;
 
+    /* Encoding specific */
+
+    /* Tight */
+    uint8_t tight_quality;
+    uint8_t tight_compression;
+
+    /* Hextile */
+    VncSendHextileTile *send_hextile_tile;
+
+    /* Zlib */
     Buffer zlib;
     Buffer zlib_tmp;
     z_stream zlib_stream[4];
@@ -376,4 +383,20 @@ void buffer_append(Buffer *buffer, const void *data, size_t len);
 char *vnc_socket_local_addr(const char *format, int fd);
 char *vnc_socket_remote_addr(const char *format, int fd);
 
+/* Framebuffer */
+void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
+                            int32_t encoding);
+
+void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v);
+
+/* Encodings */
+void vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
+
+void vnc_hextile_send_framebuffer_update(VncState *vs, int x,
+                                         int y, int w, int h);
+void vnc_hextile_set_pixel_conversion(VncState *vs, int generic);
+
+void vnc_zlib_init(VncState *vs);
+void vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
+
 #endif /* __QEMU_VNC_H */
commit bc47d201d6868a6ad51a5d2f7f946d0e6b33c5ab
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Mon May 3 14:31:18 2010 +0200

    vnc: Fix compile error on x86_64 with -D_VNC_DEBUG=1
    
    cc1: warnings being treated as errors
    vnc-auth-sasl.c: In function ‘vnc_client_write_sasl’:
    vnc-auth-sasl.c:50: error: format ‘%d’ expects type ‘int’, but argument 4 has type ‘size_t’
    vnc-auth-sasl.c:50: error: format ‘%d’ expects type ‘int’, but argument 5 has type ‘size_t’
    make: *** [vnc-auth-sasl.o] Error 1
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vnc-auth-sasl.c b/vnc-auth-sasl.c
index acaac0c..a51ddc8 100644
--- a/vnc-auth-sasl.c
+++ b/vnc-auth-sasl.c
@@ -47,7 +47,8 @@ long vnc_client_write_sasl(VncState *vs)
 {
     long ret;
 
-    VNC_DEBUG("Write SASL: Pending output %p size %d offset %d Encoded: %p size %d offset %d\n",
+    VNC_DEBUG("Write SASL: Pending output %p size %zd offset %zd "
+              "Encoded: %p size %d offset %d\n",
               vs->output.buffer, vs->output.capacity, vs->output.offset,
               vs->sasl.encoded, vs->sasl.encodedLength, vs->sasl.encodedOffset);
 
commit 72375c2290ef696f49b4fe81da55b8761608f524
Merge: a6dac6a... d748768...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon May 3 07:31:51 2010 -0500

    Merge remote branch 'kwolf/for-anthony' into HEAD

commit a6dac6a9ab81b1052e052876a67b9fc483b8b337
Merge: ace22f6... 8369e01...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon May 3 07:31:37 2010 -0500

    Merge remote branch 'qemu-kvm/uq/master' into HEAD

commit d748768c09b1f93bea90f660ab0b4063d5e9d88d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Thu Apr 29 18:24:50 2010 +0200

    block: Release allocated options after bdrv_open
    
    They aren't used afterwards nor supposed to be stored by a bdrv_create
    handler.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index f463ec4..48305b7 100644
--- a/block.c
+++ b/block.c
@@ -540,6 +540,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
         }
 
         ret = bdrv_create(bdrv_qcow2, tmp_filename, options);
+        free_option_parameters(options);
         if (ret < 0) {
             return ret;
         }
commit cc60e327c0988a5e5288cf7bb78cd9848db800ab
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Apr 29 14:47:48 2010 +0200

    qemu-img rebase: Fix output image corruption
    
    qemu-img rebase must always give clusters in the COW file priority over those
    in the backing file. As it failed to use number of non-allocated clusters but
    assumed the maximum, it was possible that allocated clusters were taken from
    the backing file instead, leading to a corrupted output image.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-img.c b/qemu-img.c
index c21d999..d3c30a7 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1136,7 +1136,7 @@ static int img_rebase(int argc, char **argv)
     if (!unsafe) {
         uint64_t num_sectors;
         uint64_t sector;
-        int n, n1;
+        int n;
         uint8_t * buf_old;
         uint8_t * buf_new;
 
@@ -1155,8 +1155,8 @@ static int img_rebase(int argc, char **argv)
             }
 
             /* If the cluster is allocated, we don't need to take action */
-            if (bdrv_is_allocated(bs, sector, n, &n1)) {
-                n = n1;
+            ret = bdrv_is_allocated(bs, sector, n, &n);
+            if (ret) {
                 continue;
             }
 
commit 294cc35f3db84017e0c176c15dd9a1b711e8354d
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Apr 28 14:34:01 2010 +0200

    block: Add wr_highest_sector blockstat
    
    This adds the wr_highest_sector blockstat which implements what is generally
    known as the high watermark. It is the highest offset of a sector written to
    the respective BlockDriverState since it has been opened.
    
    The query-blockstat QMP command is extended to add this value to the result,
    and also to add the statistics of the underlying protocol in a new "parent"
    field. Note that to get the "high watermark" of a qcow2 image, you need to look
    into the wr_highest_sector field of the parent (which can be a file, a
    host_device, ...). The wr_highest_sector of the qcow2 BlockDriverState itself
    is the highest offset on the _virtual_ disk that the guest has written to.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 91fecab..f463ec4 100644
--- a/block.c
+++ b/block.c
@@ -880,6 +880,10 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
         set_dirty_bitmap(bs, sector_num, nb_sectors, 1);
     }
 
+    if (bs->wr_highest_sector < sector_num + nb_sectors - 1) {
+        bs->wr_highest_sector = sector_num + nb_sectors - 1;
+    }
+
     return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
 }
 
@@ -1530,6 +1534,35 @@ void bdrv_stats_print(Monitor *mon, const QObject *data)
     qlist_iter(qobject_to_qlist(data), bdrv_stats_iter, mon);
 }
 
+static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
+{
+    QObject *res;
+    QDict *dict;
+
+    res = qobject_from_jsonf("{ 'stats': {"
+                             "'rd_bytes': %" PRId64 ","
+                             "'wr_bytes': %" PRId64 ","
+                             "'rd_operations': %" PRId64 ","
+                             "'wr_operations': %" PRId64 ","
+                             "'wr_highest_offset': %" PRId64
+                             "} }",
+                             bs->rd_bytes, bs->wr_bytes,
+                             bs->rd_ops, bs->wr_ops,
+                             bs->wr_highest_sector * 512);
+    dict  = qobject_to_qdict(res);
+
+    if (*bs->device_name) {
+        qdict_put(dict, "device", qstring_from_str(bs->device_name));
+    }
+
+    if (bs->file) {
+        QObject *parent = bdrv_info_stats_bs(bs->file);
+        qdict_put_obj(dict, "parent", parent);
+    }
+
+    return res;
+}
+
 /**
  * bdrv_info_stats(): show block device statistics
  *
@@ -1544,19 +1577,34 @@ void bdrv_stats_print(Monitor *mon, const QObject *data)
  *     - "wr_bytes": bytes written
  *     - "rd_operations": read operations
  *     - "wr_operations": write operations
- * 
+ *     - "wr_highest_offset": Highest offset of a sector written since the
+ *       BlockDriverState has been opened
+ *     - "parent": Contains recursively the statistics of the underlying
+ *       protocol (e.g. the host file for a qcow2 image). If there is no
+ *       underlying protocol, this field is omitted.
+ *
  * Example:
  *
  * [ { "device": "ide0-hd0",
  *               "stats": { "rd_bytes": 512,
  *                          "wr_bytes": 0,
  *                          "rd_operations": 1,
- *                          "wr_operations": 0 } },
+ *                          "wr_operations": 0,
+ *                          "wr_highest_offset": 0,
+ *                          "parent": {
+ *                              "stats": { "rd_bytes": 1024,
+ *                                         "wr_bytes": 0,
+ *                                         "rd_operations": 2,
+ *                                         "wr_operations": 0,
+ *                                         "wr_highest_offset": 0,
+ *                              }
+ *                          } } },
  *   { "device": "ide1-cd0",
  *               "stats": { "rd_bytes": 0,
  *                          "wr_bytes": 0,
  *                          "rd_operations": 0,
- *                          "wr_operations": 0 } } ]
+ *                          "wr_operations": 0,
+ *                          "wr_highest_offset": 0 } },
  */
 void bdrv_info_stats(Monitor *mon, QObject **ret_data)
 {
@@ -1567,15 +1615,7 @@ void bdrv_info_stats(Monitor *mon, QObject **ret_data)
     devices = qlist_new();
 
     QTAILQ_FOREACH(bs, &bdrv_states, list) {
-        obj = qobject_from_jsonf("{ 'device': %s, 'stats': {"
-                                 "'rd_bytes': %" PRId64 ","
-                                 "'wr_bytes': %" PRId64 ","
-                                 "'rd_operations': %" PRId64 ","
-                                 "'wr_operations': %" PRId64
-                                 "} }",
-                                 bs->device_name,
-                                 bs->rd_bytes, bs->wr_bytes,
-                                 bs->rd_ops, bs->wr_ops);
+        obj = bdrv_info_stats_bs(bs);
         qlist_append_obj(devices, obj);
     }
 
@@ -1834,9 +1874,12 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
                                cb, opaque);
 
     if (ret) {
-	/* Update stats even though technically transfer has not happened. */
-	bs->wr_bytes += (unsigned) nb_sectors * BDRV_SECTOR_SIZE;
-	bs->wr_ops ++;
+        /* Update stats even though technically transfer has not happened. */
+        bs->wr_bytes += (unsigned) nb_sectors * BDRV_SECTOR_SIZE;
+        bs->wr_ops ++;
+        if (bs->wr_highest_sector < sector_num + nb_sectors - 1) {
+            bs->wr_highest_sector = sector_num + nb_sectors - 1;
+        }
     }
 
     return ret;
diff --git a/block_int.h b/block_int.h
index a3afe63..1a7240c 100644
--- a/block_int.h
+++ b/block_int.h
@@ -167,6 +167,7 @@ struct BlockDriverState {
     uint64_t wr_bytes;
     uint64_t rd_ops;
     uint64_t wr_ops;
+    uint64_t wr_highest_sector;
 
     /* Whether the disk can expand beyond total_sectors */
     int growable;
commit 419b19d9b427fad5ff2fa886d8cc217f7acee18c
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Apr 28 11:36:11 2010 +0100

    qcow2: Implement bdrv_truncate() for growing images
    
    This patch adds the ability to grow qcow2 images in-place using
    bdrv_truncate().  This enables qemu-img resize command support for
    qcow2.
    
    Snapshots are not supported and bdrv_truncate() will return -ENOTSUP.
    The notion of resizing an image with snapshots could lead to confusion:
    users may expect snapshots to remain unchanged, but this is not possible
    with the current qcow2 on-disk format where the header.size field is
    global instead of per-snapshot.  Others may expect snapshots to change
    size along with the current image data.  I think it is safest to not
    support snapshots and perhaps add behavior later if there is a
    consensus.
    
    Backing images continue to work.  If the image is now larger than its
    backing image, zeroes are read when accessing beyond the end of the
    backing image.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 4fa3ff9..21ed6f8 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -140,7 +140,7 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
 static int qcow_open(BlockDriverState *bs, int flags)
 {
     BDRVQcowState *s = bs->opaque;
-    int len, i, shift;
+    int len, i;
     QCowHeader header;
     uint64_t ext_end;
 
@@ -188,8 +188,7 @@ static int qcow_open(BlockDriverState *bs, int flags)
 
     /* read the level 1 table */
     s->l1_size = header.l1_size;
-    shift = s->cluster_bits + s->l2_bits;
-    s->l1_vm_state_index = (header.size + (1LL << shift) - 1) >> shift;
+    s->l1_vm_state_index = size_to_l1(s, header.size);
     /* the L1 table must contain at least enough entries to put
        header.size bytes */
     if (s->l1_size < s->l1_vm_state_index)
@@ -851,6 +850,43 @@ static int qcow_make_empty(BlockDriverState *bs)
     return 0;
 }
 
+static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
+{
+    BDRVQcowState *s = bs->opaque;
+    int ret, new_l1_size;
+
+    if (offset & 511) {
+        return -EINVAL;
+    }
+
+    /* cannot proceed if image has snapshots */
+    if (s->nb_snapshots) {
+        return -ENOTSUP;
+    }
+
+    /* shrinking is currently not supported */
+    if (offset < bs->total_sectors * 512) {
+        return -ENOTSUP;
+    }
+
+    new_l1_size = size_to_l1(s, offset);
+    ret = qcow2_grow_l1_table(bs, new_l1_size);
+    if (ret < 0) {
+        return ret;
+    }
+
+    /* write updated header.size */
+    offset = cpu_to_be64(offset);
+    ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, size),
+                      &offset, sizeof(uint64_t));
+    if (ret < 0) {
+        return ret;
+    }
+
+    s->l1_vm_state_index = new_l1_size;
+    return 0;
+}
+
 /* XXX: put compressed sectors first, then all the cluster aligned
    tables to avoid losing bytes in alignment */
 static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
@@ -1050,7 +1086,9 @@ static BlockDriver bdrv_qcow2 = {
     .bdrv_aio_readv	= qcow_aio_readv,
     .bdrv_aio_writev	= qcow_aio_writev,
     .bdrv_aio_flush	= qcow_aio_flush,
-    .bdrv_write_compressed = qcow_write_compressed,
+
+    .bdrv_truncate          = qcow2_truncate,
+    .bdrv_write_compressed  = qcow_write_compressed,
 
     .bdrv_snapshot_create   = qcow2_snapshot_create,
     .bdrv_snapshot_goto     = qcow2_snapshot_goto,
diff --git a/block/qcow2.h b/block/qcow2.h
index 5bd08db..01053b7 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -150,6 +150,12 @@ static inline int size_to_clusters(BDRVQcowState *s, int64_t size)
     return (size + (s->cluster_size - 1)) >> s->cluster_bits;
 }
 
+static inline int size_to_l1(BDRVQcowState *s, int64_t size)
+{
+    int shift = s->cluster_bits + s->l2_bits;
+    return (size + (1ULL << shift) - 1) >> shift;
+}
+
 static inline int64_t align_offset(int64_t offset, int n)
 {
     offset = (offset + n - 1) & ~(n - 1);
commit 003fad6e2cae5311d3aea996388c90e3ab17de90
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Apr 21 11:37:52 2010 +0200

    qcow2: Remove abort on free_clusters failure
    
    While it's true that during regular operation free_clusters failure would be a
    bug, an I/O error can always happen. There's no need to kill the VM, the worst
    thing that can happen (and it will) is that we leak some clusters.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 95491d3..744107c 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -638,7 +638,7 @@ void qcow2_free_clusters(BlockDriverState *bs,
     ret = update_refcount(bs, offset, size, -1);
     if (ret < 0) {
         fprintf(stderr, "qcow2_free_clusters failed: %s\n", strerror(-ret));
-        abort();
+        /* TODO Remember the clusters to free them later and avoid leaking */
     }
 }
 
commit ae6b0ed6d4d4a41e77584f44d2888303645fa845
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Sat Apr 24 09:12:12 2010 +0100

    qemu-img: Add 'resize' command to grow/shrink disk images
    
    This patch adds a 'resize' command to grow/shrink disk images.  This
    allows changing the size of disk images without copying to a new image
    file.  Currently only raw files support resize.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index f96876a..c079019 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -49,5 +49,11 @@ DEF("rebase", img_rebase,
     "rebase [-f fmt] [-u] -b backing_file [-F backing_fmt] filename")
 STEXI
 @item rebase [-f @var{fmt}] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
+ETEXI
+
+DEF("resize", img_resize,
+    "resize filename [+ | -]size")
+STEXI
+ at item rebase @var{filename} [+ | -]@var{size}
 @end table
 ETEXI
diff --git a/qemu-img.c b/qemu-img.c
index 74311a5..c21d999 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1225,6 +1225,98 @@ static int img_rebase(int argc, char **argv)
     return 0;
 }
 
+static int img_resize(int argc, char **argv)
+{
+    int c, ret, relative;
+    const char *filename, *fmt, *size;
+    int64_t n, total_size;
+    BlockDriverState *bs;
+    QEMUOptionParameter *param;
+    QEMUOptionParameter resize_options[] = {
+        {
+            .name = BLOCK_OPT_SIZE,
+            .type = OPT_SIZE,
+            .help = "Virtual disk size"
+        },
+        { NULL }
+    };
+
+    fmt = NULL;
+    for(;;) {
+        c = getopt(argc, argv, "f:h");
+        if (c == -1) {
+            break;
+        }
+        switch(c) {
+        case 'h':
+            help();
+            break;
+        case 'f':
+            fmt = optarg;
+            break;
+        }
+    }
+    if (optind + 1 >= argc) {
+        help();
+    }
+    filename = argv[optind++];
+    size = argv[optind++];
+
+    /* Choose grow, shrink, or absolute resize mode */
+    switch (size[0]) {
+    case '+':
+        relative = 1;
+        size++;
+        break;
+    case '-':
+        relative = -1;
+        size++;
+        break;
+    default:
+        relative = 0;
+        break;
+    }
+
+    /* Parse size */
+    param = parse_option_parameters("", resize_options, NULL);
+    if (set_option_parameter(param, BLOCK_OPT_SIZE, size)) {
+        /* Error message already printed when size parsing fails */
+        exit(1);
+    }
+    n = get_option_parameter(param, BLOCK_OPT_SIZE)->value.n;
+    free_option_parameters(param);
+
+    bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
+
+    if (relative) {
+        total_size = bdrv_getlength(bs) + n * relative;
+    } else {
+        total_size = n;
+    }
+    if (total_size <= 0) {
+        error("New image size must be positive");
+    }
+
+    ret = bdrv_truncate(bs, total_size);
+    switch (ret) {
+    case 0:
+        printf("Image resized.\n");
+        break;
+    case -ENOTSUP:
+        error("This image format does not support resize");
+        break;
+    case -EACCES:
+        error("Image is read-only");
+        break;
+    default:
+        error("Error resizing image (%d)", -ret);
+        break;
+    }
+
+    bdrv_delete(bs);
+    return 0;
+}
+
 static const img_cmd_t img_cmds[] = {
 #define DEF(option, callback, arg_string)        \
     { option, callback },
diff --git a/qemu-img.texi b/qemu-img.texi
index ac97854..c1b1f27 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -106,6 +106,18 @@ they are displayed too.
 @item snapshot [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot} ] @var{filename}
 
 List, apply, create or delete snapshots in image @var{filename}.
+
+ at item resize @var{filename} [+ | -]@var{size}
+
+Change the disk image as if it had been created with @var{size}.
+
+Before using this command to shrink a disk image, you MUST use file system and
+partitioning tools inside the VM to reduce allocated file systems and partition
+sizes accordingly.  Failure to do so will result in data loss!
+
+After using this command to grow a disk image, you must use file system and
+partitioning tools inside the VM to actually begin using the new space on the
+device.
 @end table
 
 Supported image file formats:
commit 51762288b41f59d027073c404a29256fc4d4540e
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Apr 19 16:56:41 2010 +0100

    block: Cache total_sectors to reduce bdrv_getlength calls
    
    The BlockDriver bdrv_getlength function is called from the I/O code path
    when checking that the request falls within the device.  Unfortunately
    this involves an lseek system call in the raw protocol; every read or
    write request will incur this lseek cost.
    
    Jan Kiszka <jan.kiszka at siemens.com> identified this issue and its
    latency overhead.  This patch caches device length in the existing
    total_sectors variable so lseek calls can be avoided for fixed size
    devices.
    
    Growable devices fall back to the full bdrv_getlength code path because
    I have not added logic to detect extending the size of the device in a
    write.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index b318355..91fecab 100644
--- a/block.c
+++ b/block.c
@@ -352,6 +352,26 @@ static BlockDriver *find_image_format(const char *filename)
     return drv;
 }
 
+/**
+ * Set the current 'total_sectors' value
+ */
+static int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
+{
+    BlockDriver *drv = bs->drv;
+
+    /* query actual device if possible, otherwise just trust the hint */
+    if (drv->bdrv_getlength) {
+        int64_t length = drv->bdrv_getlength(bs);
+        if (length < 0) {
+            return length;
+        }
+        hint = length >> BDRV_SECTOR_BITS;
+    }
+
+    bs->total_sectors = hint;
+    return 0;
+}
+
 /*
  * Common part for opening disk images and files
  */
@@ -363,6 +383,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
     assert(drv != NULL);
 
     bs->file = NULL;
+    bs->total_sectors = 0;
     bs->is_temporary = 0;
     bs->encrypted = 0;
     bs->valid_key = 0;
@@ -416,9 +437,12 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
     }
 
     bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR);
-    if (drv->bdrv_getlength) {
-        bs->total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
+
+    ret = refresh_total_sectors(bs, bs->total_sectors);
+    if (ret < 0) {
+        goto free_and_fail;
     }
+
 #ifndef _WIN32
     if (bs->is_temporary) {
         unlink(filename);
@@ -959,13 +983,18 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
 int bdrv_truncate(BlockDriverState *bs, int64_t offset)
 {
     BlockDriver *drv = bs->drv;
+    int ret;
     if (!drv)
         return -ENOMEDIUM;
     if (!drv->bdrv_truncate)
         return -ENOTSUP;
     if (bs->read_only)
         return -EACCES;
-    return drv->bdrv_truncate(bs, offset);
+    ret = drv->bdrv_truncate(bs, offset);
+    if (ret == 0) {
+        ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
+    }
+    return ret;
 }
 
 /**
@@ -976,8 +1005,12 @@ int64_t bdrv_getlength(BlockDriverState *bs)
     BlockDriver *drv = bs->drv;
     if (!drv)
         return -ENOMEDIUM;
-    if (!drv->bdrv_getlength) {
-        /* legacy mode */
+
+    /* Fixed size devices use the total_sectors value for speed instead of
+       issuing a length query (like lseek) on each call.  Also, legacy block
+       drivers don't provide a bdrv_getlength function and must use
+       total_sectors. */
+    if (!bs->growable || !drv->bdrv_getlength) {
         return bs->total_sectors * BDRV_SECTOR_SIZE;
     }
     return drv->bdrv_getlength(bs);
commit 4899d10d142e97eea8f64141a3507b2ee1a64f52
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Apr 19 13:34:11 2010 +0100

    raw-posix: Use pread/pwrite instead of lseek+read/write
    
    This patch combines the lseek+read/write calls to use pread/pwrite
    instead.  This will result in fewer system calls and is already used by
    AIO.
    
    Thanks to Jan Kiszka <jan.kiszka at siemens.com> for identifying excessive
    lseek and Christoph Hellwig <hch at lst.de> for confirming that this
    approach should work.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/raw-posix.c b/block/raw-posix.c
index 598ea19..7541ed2 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -105,7 +105,6 @@
 typedef struct BDRVRawState {
     int fd;
     int type;
-    unsigned int lseek_err_cnt;
     int open_flags;
 #if defined(__linux__)
     /* linux floppy specific */
@@ -134,8 +133,6 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
     BDRVRawState *s = bs->opaque;
     int fd, ret;
 
-    s->lseek_err_cnt = 0;
-
     s->open_flags = open_flags | O_BINARY;
     s->open_flags &= ~O_ACCMODE;
     if (bdrv_flags & BDRV_O_RDWR) {
@@ -243,19 +240,7 @@ static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
     if (ret < 0)
         return ret;
 
-    if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
-        ++(s->lseek_err_cnt);
-        if(s->lseek_err_cnt <= 10) {
-            DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
-                              "] lseek failed : %d = %s\n",
-                              s->fd, bs->filename, offset, buf, count,
-                              bs->total_sectors, errno, strerror(errno));
-        }
-        return -1;
-    }
-    s->lseek_err_cnt=0;
-
-    ret = read(s->fd, buf, count);
+    ret = pread(s->fd, buf, count, offset);
     if (ret == count)
         goto label__raw_read__success;
 
@@ -276,12 +261,10 @@ static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
 
     /* Try harder for CDrom. */
     if (bs->type == BDRV_TYPE_CDROM) {
-        lseek(s->fd, offset, SEEK_SET);
-        ret = read(s->fd, buf, count);
+        ret = pread(s->fd, buf, count, offset);
         if (ret == count)
             goto label__raw_read__success;
-        lseek(s->fd, offset, SEEK_SET);
-        ret = read(s->fd, buf, count);
+        ret = pread(s->fd, buf, count, offset);
         if (ret == count)
             goto label__raw_read__success;
 
@@ -313,19 +296,7 @@ static int raw_pwrite_aligned(BlockDriverState *bs, int64_t offset,
     if (ret < 0)
         return -errno;
 
-    if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
-        ++(s->lseek_err_cnt);
-        if(s->lseek_err_cnt) {
-            DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
-                              PRId64 "] lseek failed : %d = %s\n",
-                              s->fd, bs->filename, offset, buf, count,
-                              bs->total_sectors, errno, strerror(errno));
-        }
-        return -EIO;
-    }
-    s->lseek_err_cnt = 0;
-
-    ret = write(s->fd, buf, count);
+    ret = pwrite(s->fd, buf, count, offset);
     if (ret == count)
         goto label__raw_write__success;
 
commit 508e0893686794be55cfaa336fea584b16a471d9
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Sat Apr 17 10:49:07 2010 +0100

    qcow2: Avoid shadowing variable in alloc_clusters_noref()
    
    The i loop iterator is shadowed by the next free cluster index.  Both
    using the variable name 'i' makes the code harder to read.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 2661493..95491d3 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -556,8 +556,8 @@ static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size)
     nb_clusters = size_to_clusters(s, size);
 retry:
     for(i = 0; i < nb_clusters; i++) {
-        int64_t i = s->free_cluster_index++;
-        if (get_refcount(bs, i) != 0)
+        int64_t next_cluster_index = s->free_cluster_index++;
+        if (get_refcount(bs, next_cluster_index) != 0)
             goto retry;
     }
 #ifdef DEBUG_ALLOC2
commit 557df6aca2e389ef631b283ca1522b1fdf121eff
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Sat Apr 17 10:49:06 2010 +0100

    block: Set backing_hd to NULL after deleting it
    
    It is safer to set backing_hd to NULL after deleting it so that any use
    after deletion is obvious during development.  Happy segfaulting!
    
    This patch should be applied after Kevin Wolf's "vmdk: Convert to
    bdrv_open" so that vmdk does not segfault on close.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 56835af..b318355 100644
--- a/block.c
+++ b/block.c
@@ -589,8 +589,10 @@ unlink_and_fail:
 void bdrv_close(BlockDriverState *bs)
 {
     if (bs->drv) {
-        if (bs->backing_hd)
+        if (bs->backing_hd) {
             bdrv_delete(bs->backing_hd);
+            bs->backing_hd = NULL;
+        }
         bs->drv->bdrv_close(bs);
         qemu_free(bs->opaque);
 #ifdef _WIN32
commit 6511ef77375100ecf9134f85f08cef31fd196cdf
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Apr 16 21:27:51 2010 +0200

    vmdk: Convert to bdrv_open
    
    It's a format driver, so implement bdrv_open instead of bdrv_file_open.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index e44769b..e659908 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -108,14 +108,13 @@ static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
 
 static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
 {
-    BDRVVmdkState *s = bs->opaque;
     char desc[DESC_SIZE];
     uint32_t cid;
     const char *p_name, *cid_str;
     size_t cid_str_size;
 
     /* the descriptor offset = 0x200 */
-    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+    if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE)
         return 0;
 
     if (parent) {
@@ -136,12 +135,11 @@ static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
 
 static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
 {
-    BDRVVmdkState *s = bs->opaque;
     char desc[DESC_SIZE], tmp_desc[DESC_SIZE];
     char *p_name, *tmp_str;
 
     /* the descriptor offset = 0x200 */
-    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+    if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE)
         return -1;
 
     tmp_str = strstr(desc,"parentCID");
@@ -152,7 +150,7 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
         pstrcat(desc, sizeof(desc), tmp_desc);
     }
 
-    if (bdrv_pwrite(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+    if (bdrv_pwrite(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE)
         return -1;
     return 0;
 }
@@ -339,12 +337,11 @@ fail:
 
 static int vmdk_parent_open(BlockDriverState *bs)
 {
-    BDRVVmdkState *s = bs->opaque;
     char *p_name;
     char desc[DESC_SIZE];
 
     /* the descriptor offset = 0x200 */
-    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+    if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE)
         return -1;
 
     if ((p_name = strstr(desc,"parentFileNameHint")) != NULL) {
@@ -362,23 +359,20 @@ static int vmdk_parent_open(BlockDriverState *bs)
     return 0;
 }
 
-static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
+static int vmdk_open(BlockDriverState *bs, int flags)
 {
     BDRVVmdkState *s = bs->opaque;
     uint32_t magic;
-    int l1_size, i, ret;
+    int l1_size, i;
 
-    ret = bdrv_file_open(&s->hd, filename, flags);
-    if (ret < 0)
-        return ret;
-    if (bdrv_pread(s->hd, 0, &magic, sizeof(magic)) != sizeof(magic))
+    if (bdrv_pread(bs->file, 0, &magic, sizeof(magic)) != sizeof(magic))
         goto fail;
 
     magic = be32_to_cpu(magic);
     if (magic == VMDK3_MAGIC) {
         VMDK3Header header;
 
-        if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))
+        if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)) != sizeof(header))
             goto fail;
         s->cluster_sectors = le32_to_cpu(header.granularity);
         s->l2_size = 1 << 9;
@@ -390,7 +384,7 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
     } else if (magic == VMDK4_MAGIC) {
         VMDK4Header header;
 
-        if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))
+        if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)) != sizeof(header))
             goto fail;
         bs->total_sectors = le64_to_cpu(header.capacity);
         s->cluster_sectors = le64_to_cpu(header.granularity);
@@ -415,7 +409,7 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
     /* read the L1 table */
     l1_size = s->l1_size * sizeof(uint32_t);
     s->l1_table = qemu_malloc(l1_size);
-    if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, l1_size) != l1_size)
+    if (bdrv_pread(bs->file, s->l1_table_offset, s->l1_table, l1_size) != l1_size)
         goto fail;
     for(i = 0; i < s->l1_size; i++) {
         le32_to_cpus(&s->l1_table[i]);
@@ -423,7 +417,7 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
 
     if (s->l1_backup_table_offset) {
         s->l1_backup_table = qemu_malloc(l1_size);
-        if (bdrv_pread(s->hd, s->l1_backup_table_offset, s->l1_backup_table, l1_size) != l1_size)
+        if (bdrv_pread(bs->file, s->l1_backup_table_offset, s->l1_backup_table, l1_size) != l1_size)
             goto fail;
         for(i = 0; i < s->l1_size; i++) {
             le32_to_cpus(&s->l1_backup_table[i]);
@@ -436,7 +430,6 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
     qemu_free(s->l1_backup_table);
     qemu_free(s->l1_table);
     qemu_free(s->l2_cache);
-    bdrv_delete(s->hd);
     return -1;
 }
 
@@ -464,7 +457,7 @@ static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
         }
 
         //Write grain only into the active image
-        ret = bdrv_write(s->hd, cluster_offset, whole_grain,
+        ret = bdrv_write(bs->file, cluster_offset, whole_grain,
             s->cluster_sectors);
         if (ret < 0) {
             return -1;
@@ -478,13 +471,13 @@ static int vmdk_L2update(BlockDriverState *bs, VmdkMetaData *m_data)
     BDRVVmdkState *s = bs->opaque;
 
     /* update L2 table */
-    if (bdrv_pwrite(s->hd, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
+    if (bdrv_pwrite(bs->file, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
                     &(m_data->offset), sizeof(m_data->offset)) != sizeof(m_data->offset))
         return -1;
     /* update backup L2 table */
     if (s->l1_backup_table_offset != 0) {
         m_data->l2_offset = s->l1_backup_table[m_data->l1_index];
-        if (bdrv_pwrite(s->hd, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
+        if (bdrv_pwrite(bs->file, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
                         &(m_data->offset), sizeof(m_data->offset)) != sizeof(m_data->offset))
             return -1;
     }
@@ -532,7 +525,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
         }
     }
     l2_table = s->l2_cache + (min_index * s->l2_size);
-    if (bdrv_pread(s->hd, (int64_t)l2_offset * 512, l2_table, s->l2_size * sizeof(uint32_t)) !=
+    if (bdrv_pread(bs->file, (int64_t)l2_offset * 512, l2_table, s->l2_size * sizeof(uint32_t)) !=
                                                                         s->l2_size * sizeof(uint32_t))
         return 0;
 
@@ -547,8 +540,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
             return 0;
 
         // Avoid the L2 tables update for the images that have snapshots.
-        cluster_offset = bdrv_getlength(s->hd);
-        bdrv_truncate(s->hd, cluster_offset + (s->cluster_sectors << 9));
+        cluster_offset = bdrv_getlength(bs->file);
+        bdrv_truncate(bs->file, cluster_offset + (s->cluster_sectors << 9));
 
         cluster_offset >>= 9;
         tmp = cpu_to_le32(cluster_offset);
@@ -615,7 +608,7 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
                 memset(buf, 0, 512 * n);
             }
         } else {
-            if(bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
+            if(bdrv_pread(bs->file, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
                 return -1;
         }
         nb_sectors -= n;
@@ -651,7 +644,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
         if (!cluster_offset)
             return -1;
 
-        if (bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
+        if (bdrv_pwrite(bs->file, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
             return -1;
         if (m_data.valid) {
             /* update L2 tables */
@@ -828,13 +821,11 @@ static void vmdk_close(BlockDriverState *bs)
 
     qemu_free(s->l1_table);
     qemu_free(s->l2_cache);
-    bdrv_delete(s->hd);
 }
 
 static void vmdk_flush(BlockDriverState *bs)
 {
-    BDRVVmdkState *s = bs->opaque;
-    bdrv_flush(s->hd);
+    bdrv_flush(bs->file);
 }
 
 
@@ -861,7 +852,7 @@ static BlockDriver bdrv_vmdk = {
     .format_name	= "vmdk",
     .instance_size	= sizeof(BDRVVmdkState),
     .bdrv_probe		= vmdk_probe,
-    .bdrv_file_open	= vmdk_open,
+    .bdrv_open      = vmdk_open,
     .bdrv_read		= vmdk_read,
     .bdrv_write		= vmdk_write,
     .bdrv_close		= vmdk_close,
commit 9949f97e84c8040fde6116cb438f2999c52f023a
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Apr 16 21:07:19 2010 +0200

    vmdk: Clean up backing file handling
    
    VMDK is doing interesting things when it needs to open a backing file. This
    patch changes that part to look more like in other drivers. The nice side
    effect is that the file name isn't needed any more in the open function.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index ae34121..e44769b 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -76,7 +76,6 @@ typedef struct BDRVVmdkState {
 
     unsigned int cluster_sectors;
     uint32_t parent_cid;
-    int is_parent;
 } BDRVVmdkState;
 
 typedef struct VmdkMetaData {
@@ -338,19 +337,11 @@ fail:
     return ret;
 }
 
-static void vmdk_parent_close(BlockDriverState *bs)
-{
-    if (bs->backing_hd)
-        bdrv_close(bs->backing_hd);
-}
-
-static int parent_open = 0;
-static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
+static int vmdk_parent_open(BlockDriverState *bs)
 {
     BDRVVmdkState *s = bs->opaque;
     char *p_name;
     char desc[DESC_SIZE];
-    char parent_img_name[1024];
 
     /* the descriptor offset = 0x200 */
     if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
@@ -358,7 +349,6 @@ static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
 
     if ((p_name = strstr(desc,"parentFileNameHint")) != NULL) {
         char *end_name;
-        struct stat file_buf;
 
         p_name += sizeof("parentFileNameHint") + 1;
         if ((end_name = strchr(p_name,'\"')) == NULL)
@@ -367,24 +357,6 @@ static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
             return -1;
 
         pstrcpy(bs->backing_file, end_name - p_name + 1, p_name);
-        if (stat(bs->backing_file, &file_buf) != 0) {
-            path_combine(parent_img_name, sizeof(parent_img_name),
-                         filename, bs->backing_file);
-        } else {
-            pstrcpy(parent_img_name, sizeof(parent_img_name),
-                    bs->backing_file);
-        }
-
-        bs->backing_hd = bdrv_new("");
-        if (!bs->backing_hd) {
-            failure:
-            bdrv_close(s->hd);
-            return -1;
-        }
-        parent_open = 1;
-        if (bdrv_open(bs->backing_hd, parent_img_name, 0, NULL) < 0)
-            goto failure;
-        parent_open = 0;
     }
 
     return 0;
@@ -396,11 +368,6 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
     uint32_t magic;
     int l1_size, i, ret;
 
-    if (parent_open) {
-        /* Parent must be opened as RO, no RDWR. */
-        flags = 0;
-    }
-
     ret = bdrv_file_open(&s->hd, filename, flags);
     if (ret < 0)
         return ret;
@@ -436,13 +403,8 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
         s->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9;
         s->l1_backup_table_offset = le64_to_cpu(header.gd_offset) << 9;
 
-        if (parent_open)
-            s->is_parent = 1;
-        else
-            s->is_parent = 0;
-
         // try to open parent images, if exist
-        if (vmdk_parent_open(bs, filename) != 0)
+        if (vmdk_parent_open(bs) != 0)
             goto fail;
         // write the CID once after the image creation
         s->parent_cid = vmdk_read_cid(bs,1);
@@ -583,15 +545,15 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
     if (!cluster_offset) {
         if (!allocate)
             return 0;
+
         // Avoid the L2 tables update for the images that have snapshots.
-        if (!s->is_parent) {
-            cluster_offset = bdrv_getlength(s->hd);
-            bdrv_truncate(s->hd, cluster_offset + (s->cluster_sectors << 9));
+        cluster_offset = bdrv_getlength(s->hd);
+        bdrv_truncate(s->hd, cluster_offset + (s->cluster_sectors << 9));
+
+        cluster_offset >>= 9;
+        tmp = cpu_to_le32(cluster_offset);
+        l2_table[l2_index] = tmp;
 
-            cluster_offset >>= 9;
-            tmp = cpu_to_le32(cluster_offset);
-            l2_table[l2_index] = tmp;
-        }
         /* First of all we write grain itself, to avoid race condition
          * that may to corrupt the image.
          * This problem may occur because of insufficient space on host disk
@@ -866,8 +828,6 @@ static void vmdk_close(BlockDriverState *bs)
 
     qemu_free(s->l1_table);
     qemu_free(s->l2_cache);
-    // try to close parent image, if exist
-    vmdk_parent_close(s->hd);
     bdrv_delete(s->hd);
 }
 
commit c336500df5bf08492f4e7796b2193cd4976f3548
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Apr 16 19:28:14 2010 +0200

    vmdk: Fix COW
    
    When trying to do COW, VMDK wrote the data back to the backing file. This
    problem was revealed by the patch that made backing files read-only. This patch
    does not only fix the problem, but also simplifies the VMDK code a bit.
    
    This fixes the backing file qemu-iotests cases for VMDK.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index 5ef4375..ae34121 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -87,14 +87,6 @@ typedef struct VmdkMetaData {
     int valid;
 } VmdkMetaData;
 
-typedef struct ActiveBDRVState{
-    BlockDriverState *hd;            // active image handler
-    uint64_t cluster_offset;         // current write offset
-}ActiveBDRVState;
-
-static ActiveBDRVState activeBDRV;
-
-
 static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
 {
     uint32_t magic;
@@ -492,30 +484,28 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
 static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
                              uint64_t offset, int allocate)
 {
-    uint64_t parent_cluster_offset;
     BDRVVmdkState *s = bs->opaque;
     uint8_t  whole_grain[s->cluster_sectors*512];        // 128 sectors * 512 bytes each = grain size 64KB
 
     // we will be here if it's first write on non-exist grain(cluster).
     // try to read from parent image, if exist
     if (bs->backing_hd) {
-        BDRVVmdkState *ps = bs->backing_hd->opaque;
+        int ret;
 
         if (!vmdk_is_cid_valid(bs))
             return -1;
 
-        parent_cluster_offset = get_cluster_offset(bs->backing_hd, NULL,
-            offset, allocate);
-
-        if (parent_cluster_offset) {
-            BDRVVmdkState *act_s = activeBDRV.hd->opaque;
-
-            if (bdrv_pread(ps->hd, parent_cluster_offset, whole_grain, ps->cluster_sectors*512) != ps->cluster_sectors*512)
-                return -1;
+        ret = bdrv_read(bs->backing_hd, offset >> 9, whole_grain,
+            s->cluster_sectors);
+        if (ret < 0) {
+            return -1;
+        }
 
-            //Write grain only into the active image
-            if (bdrv_pwrite(act_s->hd, activeBDRV.cluster_offset << 9, whole_grain, sizeof(whole_grain)) != sizeof(whole_grain))
-                return -1;
+        //Write grain only into the active image
+        ret = bdrv_write(s->hd, cluster_offset, whole_grain,
+            s->cluster_sectors);
+        if (ret < 0) {
+            return -1;
         }
     }
     return 0;
@@ -601,9 +591,6 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
             cluster_offset >>= 9;
             tmp = cpu_to_le32(cluster_offset);
             l2_table[l2_index] = tmp;
-            // Save the active image state
-            activeBDRV.cluster_offset = cluster_offset;
-            activeBDRV.hd = bs;
         }
         /* First of all we write grain itself, to avoid race condition
          * that may to corrupt the image.
commit f2feebbd93c251ec0098a9ccf808f7cb1da7f67c
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Apr 14 17:30:35 2010 +0200

    block: bdrv_has_zero_init
    
    This fixes the problem that qemu-img's use of no_zero_init only considered the
    no_zero_init flag of the format driver, but not of the underlying protocols.
    
    Between the raw/file split and this fix, converting to host devices is broken.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index eb1d562..56835af 100644
--- a/block.c
+++ b/block.c
@@ -1282,6 +1282,19 @@ void bdrv_flush_all(void)
     }
 }
 
+int bdrv_has_zero_init(BlockDriverState *bs)
+{
+    assert(bs->drv);
+
+    if (bs->drv->no_zero_init) {
+        return 0;
+    } else if (bs->file) {
+        return bdrv_has_zero_init(bs->file);
+    }
+
+    return 1;
+}
+
 /*
  * Returns true iff the specified sector is present in the disk image. Drivers
  * not implementing the functionality are assumed to not support backing files,
diff --git a/block.h b/block.h
index f58edf1..f87d24e 100644
--- a/block.h
+++ b/block.h
@@ -122,6 +122,7 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
 void bdrv_flush(BlockDriverState *bs);
 void bdrv_flush_all(void);
 
+int bdrv_has_zero_init(BlockDriverState *bs);
 int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
 	int *pnum);
 
diff --git a/qemu-img.c b/qemu-img.c
index 7203b8b..74311a5 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -732,6 +732,8 @@ static int img_convert(int argc, char **argv)
         /* signal EOF to align */
         bdrv_write_compressed(out_bs, 0, NULL, 0);
     } else {
+        int has_zero_init = bdrv_has_zero_init(out_bs);
+
         sector_num = 0; // total number of sectors converted so far
         for(;;) {
             nb_sectors = total_sectors - sector_num;
@@ -755,7 +757,7 @@ static int img_convert(int argc, char **argv)
             if (n > bs_offset + bs_sectors - sector_num)
                 n = bs_offset + bs_sectors - sector_num;
 
-            if (!drv->no_zero_init) {
+            if (has_zero_init) {
                 /* If the output image is being created as a copy on write image,
                    assume that sectors which are unallocated in the input image
                    are present in both the output's and input's base images (no
@@ -788,7 +790,7 @@ static int img_convert(int argc, char **argv)
                    If the output is to a host device, we also write out
                    sectors that are entirely 0, since whatever data was
                    already there is garbage, not 0s. */
-                if (drv->no_zero_init || out_baseimg ||
+                if (!has_zero_init || out_baseimg ||
                     is_allocated_sectors(buf1, n, &n1)) {
                     if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
                         error("error while writing");
commit 66f82ceed6781261c09e65fb440ca76842fd0500
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Apr 14 14:17:38 2010 +0200

    block: Open the underlying image file in generic code
    
    Format drivers shouldn't need to bother with things like file names, but rather
    just get an open BlockDriverState for the underlying protocol. This patch
    introduces this behaviour for bdrv_open implementation. For protocols which
    need to access the filename to open their file/device/connection/... a new
    callback bdrv_file_open is introduced which doesn't get an underlying file
    opened.
    
    For now, also some of the more obscure formats use bdrv_file_open because they
    open() the file themselves instead of using the block.c functions. They need to
    be fixed in later patches.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index f9b5e53..eb1d562 100644
--- a/block.c
+++ b/block.c
@@ -288,6 +288,8 @@ static BlockDriver *find_protocol(const char *filename)
     int len;
     const char *p;
 
+    /* TODO Drivers without bdrv_file_open must be specified explicitly */
+
 #ifdef _WIN32
     if (is_windows_drive(filename) ||
         is_windows_drive_prefix(filename))
@@ -360,6 +362,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
 
     assert(drv != NULL);
 
+    bs->file = NULL;
     bs->is_temporary = 0;
     bs->encrypted = 0;
     bs->valid_key = 0;
@@ -398,7 +401,16 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
         open_flags |= BDRV_O_RDWR;
     }
 
-    ret = drv->bdrv_open(bs, filename, open_flags);
+    /* Open the image, either directly or using a protocol */
+    if (drv->bdrv_file_open) {
+        ret = drv->bdrv_file_open(bs, filename, open_flags);
+    } else {
+        ret = bdrv_file_open(&bs->file, filename, open_flags);
+        if (ret >= 0) {
+            ret = drv->bdrv_open(bs, open_flags);
+        }
+    }
+
     if (ret < 0) {
         goto free_and_fail;
     }
@@ -415,6 +427,10 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
     return 0;
 
 free_and_fail:
+    if (bs->file) {
+        bdrv_delete(bs->file);
+        bs->file = NULL;
+    }
     qemu_free(bs->opaque);
     bs->opaque = NULL;
     bs->drv = NULL;
@@ -585,6 +601,10 @@ void bdrv_close(BlockDriverState *bs)
         bs->opaque = NULL;
         bs->drv = NULL;
 
+        if (bs->file != NULL) {
+            bdrv_close(bs->file);
+        }
+
         /* call the change callback */
         bs->media_changed = 1;
         if (bs->change_cb)
@@ -600,6 +620,10 @@ void bdrv_delete(BlockDriverState *bs)
     }
 
     bdrv_close(bs);
+    if (bs->file != NULL) {
+        bdrv_delete(bs->file);
+    }
+
     qemu_free(bs);
 }
 
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 643c397..bb4a91a 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -44,7 +44,6 @@ typedef struct BlkdebugVars {
 } BlkdebugVars;
 
 typedef struct BDRVBlkdebugState {
-    BlockDriverState *hd;
     BlkdebugVars vars;
     QLIST_HEAD(list, BlkdebugRule) rules[BLKDBG_EVENT_MAX];
 } BDRVBlkdebugState;
@@ -303,7 +302,7 @@ static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags)
     filename = c + 1;
 
     /* Open the backing file */
-    ret = bdrv_file_open(&s->hd, filename, flags);
+    ret = bdrv_file_open(&bs->file, filename, flags);
     if (ret < 0) {
         return ret;
     }
@@ -362,7 +361,7 @@ static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
     }
 
     BlockDriverAIOCB *acb =
-        bdrv_aio_readv(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
+        bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
     return acb;
 }
 
@@ -377,7 +376,7 @@ static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
     }
 
     BlockDriverAIOCB *acb =
-        bdrv_aio_writev(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
+        bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
     return acb;
 }
 
@@ -393,21 +392,17 @@ static void blkdebug_close(BlockDriverState *bs)
             qemu_free(rule);
         }
     }
-
-    bdrv_delete(s->hd);
 }
 
 static void blkdebug_flush(BlockDriverState *bs)
 {
-    BDRVBlkdebugState *s = bs->opaque;
-    bdrv_flush(s->hd);
+    bdrv_flush(bs->file);
 }
 
 static BlockDriverAIOCB *blkdebug_aio_flush(BlockDriverState *bs,
     BlockDriverCompletionFunc *cb, void *opaque)
 {
-    BDRVBlkdebugState *s = bs->opaque;
-    return bdrv_aio_flush(s->hd, cb, opaque);
+    return bdrv_aio_flush(bs->file, cb, opaque);
 }
 
 static void process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
@@ -456,7 +451,7 @@ static BlockDriver bdrv_blkdebug = {
 
     .instance_size      = sizeof(BDRVBlkdebugState),
 
-    .bdrv_open          = blkdebug_open,
+    .bdrv_file_open     = blkdebug_open,
     .bdrv_close         = blkdebug_close,
     .bdrv_flush         = blkdebug_flush,
 
diff --git a/block/bochs.c b/block/bochs.c
index fb83594..e952670 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -252,7 +252,7 @@ static BlockDriver bdrv_bochs = {
     .format_name	= "bochs",
     .instance_size	= sizeof(BDRVBochsState),
     .bdrv_probe		= bochs_probe,
-    .bdrv_open		= bochs_open,
+    .bdrv_file_open	= bochs_open,
     .bdrv_read		= bochs_read,
     .bdrv_close		= bochs_close,
 };
diff --git a/block/cloop.c b/block/cloop.c
index 06c687e..e4f995b 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -158,7 +158,7 @@ static BlockDriver bdrv_cloop = {
     .format_name	= "cloop",
     .instance_size	= sizeof(BDRVCloopState),
     .bdrv_probe		= cloop_probe,
-    .bdrv_open		= cloop_open,
+    .bdrv_file_open	= cloop_open,
     .bdrv_read		= cloop_read,
     .bdrv_close		= cloop_close,
 };
diff --git a/block/cow.c b/block/cow.c
index 97e9745..fde066e 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -291,7 +291,7 @@ static BlockDriver bdrv_cow = {
     .format_name	= "cow",
     .instance_size	= sizeof(BDRVCowState),
     .bdrv_probe		= cow_probe,
-    .bdrv_open		= cow_open,
+    .bdrv_file_open	= cow_open,
     .bdrv_read		= cow_read,
     .bdrv_write		= cow_write,
     .bdrv_close		= cow_close,
diff --git a/block/curl.c b/block/curl.c
index 2cf72cb..b944740 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -495,7 +495,7 @@ static BlockDriver bdrv_http = {
     .protocol_name   = "http",
 
     .instance_size   = sizeof(BDRVCURLState),
-    .bdrv_open       = curl_open,
+    .bdrv_file_open  = curl_open,
     .bdrv_close      = curl_close,
     .bdrv_getlength  = curl_getlength,
 
@@ -507,7 +507,7 @@ static BlockDriver bdrv_https = {
     .protocol_name   = "https",
 
     .instance_size   = sizeof(BDRVCURLState),
-    .bdrv_open       = curl_open,
+    .bdrv_file_open  = curl_open,
     .bdrv_close      = curl_close,
     .bdrv_getlength  = curl_getlength,
 
@@ -519,7 +519,7 @@ static BlockDriver bdrv_ftp = {
     .protocol_name   = "ftp",
 
     .instance_size   = sizeof(BDRVCURLState),
-    .bdrv_open       = curl_open,
+    .bdrv_file_open  = curl_open,
     .bdrv_close      = curl_close,
     .bdrv_getlength  = curl_getlength,
 
@@ -531,7 +531,7 @@ static BlockDriver bdrv_ftps = {
     .protocol_name   = "ftps",
 
     .instance_size   = sizeof(BDRVCURLState),
-    .bdrv_open       = curl_open,
+    .bdrv_file_open  = curl_open,
     .bdrv_close      = curl_close,
     .bdrv_getlength  = curl_getlength,
 
@@ -543,7 +543,7 @@ static BlockDriver bdrv_tftp = {
     .protocol_name   = "tftp",
 
     .instance_size   = sizeof(BDRVCURLState),
-    .bdrv_open       = curl_open,
+    .bdrv_file_open  = curl_open,
     .bdrv_close      = curl_close,
     .bdrv_getlength  = curl_getlength,
 
diff --git a/block/dmg.c b/block/dmg.c
index f4c01c7..d5c1a68 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -288,7 +288,7 @@ static BlockDriver bdrv_dmg = {
     .format_name	= "dmg",
     .instance_size	= sizeof(BDRVDMGState),
     .bdrv_probe		= dmg_probe,
-    .bdrv_open		= dmg_open,
+    .bdrv_file_open	= dmg_open,
     .bdrv_read		= dmg_read,
     .bdrv_close		= dmg_close,
 };
diff --git a/block/nbd.c b/block/nbd.c
index 7bac38d..a1ec123 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -177,7 +177,7 @@ static int64_t nbd_getlength(BlockDriverState *bs)
 static BlockDriver bdrv_nbd = {
     .format_name	= "nbd",
     .instance_size	= sizeof(BDRVNBDState),
-    .bdrv_open		= nbd_open,
+    .bdrv_file_open	= nbd_open,
     .bdrv_read		= nbd_read,
     .bdrv_write		= nbd_write,
     .bdrv_close		= nbd_close,
diff --git a/block/parallels.c b/block/parallels.c
index 41b3a7c..b217101 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -167,7 +167,7 @@ static BlockDriver bdrv_parallels = {
     .format_name	= "parallels",
     .instance_size	= sizeof(BDRVParallelsState),
     .bdrv_probe		= parallels_probe,
-    .bdrv_open		= parallels_open,
+    .bdrv_file_open	= parallels_open,
     .bdrv_read		= parallels_read,
     .bdrv_close		= parallels_close,
 };
diff --git a/block/qcow.c b/block/qcow.c
index c619984..2883c40 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -76,7 +76,7 @@ typedef struct BDRVQcowState {
     AES_KEY aes_decrypt_key;
 } BDRVQcowState;
 
-static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset);
+static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
 
 static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
 {
@@ -90,16 +90,13 @@ static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
         return 0;
 }
 
-static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
+static int qcow_open(BlockDriverState *bs, int flags)
 {
     BDRVQcowState *s = bs->opaque;
-    int len, i, shift, ret;
+    int len, i, shift;
     QCowHeader header;
 
-    ret = bdrv_file_open(&s->hd, filename, flags);
-    if (ret < 0)
-        return ret;
-    if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
+    if (bdrv_pread(bs->file, 0, &header, sizeof(header)) != sizeof(header))
         goto fail;
     be32_to_cpus(&header.magic);
     be32_to_cpus(&header.version);
@@ -135,7 +132,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
     s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
     if (!s->l1_table)
         goto fail;
-    if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
+    if (bdrv_pread(bs->file, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
         s->l1_size * sizeof(uint64_t))
         goto fail;
     for(i = 0;i < s->l1_size; i++) {
@@ -158,7 +155,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
         len = header.backing_file_size;
         if (len > 1023)
             len = 1023;
-        if (bdrv_pread(s->hd, header.backing_file_offset, bs->backing_file, len) != len)
+        if (bdrv_pread(bs->file, header.backing_file_offset, bs->backing_file, len) != len)
             goto fail;
         bs->backing_file[len] = '\0';
     }
@@ -169,7 +166,6 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
     qemu_free(s->l2_cache);
     qemu_free(s->cluster_cache);
     qemu_free(s->cluster_data);
-    bdrv_delete(s->hd);
     return -1;
 }
 
@@ -271,13 +267,13 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
         if (!allocate)
             return 0;
         /* allocate a new l2 entry */
-        l2_offset = bdrv_getlength(s->hd);
+        l2_offset = bdrv_getlength(bs->file);
         /* round to cluster size */
         l2_offset = (l2_offset + s->cluster_size - 1) & ~(s->cluster_size - 1);
         /* update the L1 entry */
         s->l1_table[l1_index] = l2_offset;
         tmp = cpu_to_be64(l2_offset);
-        if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp),
+        if (bdrv_pwrite(bs->file, s->l1_table_offset + l1_index * sizeof(tmp),
                         &tmp, sizeof(tmp)) != sizeof(tmp))
             return 0;
         new_l2_table = 1;
@@ -306,11 +302,11 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
     l2_table = s->l2_cache + (min_index << s->l2_bits);
     if (new_l2_table) {
         memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
-        if (bdrv_pwrite(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
+        if (bdrv_pwrite(bs->file, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
             s->l2_size * sizeof(uint64_t))
             return 0;
     } else {
-        if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
+        if (bdrv_pread(bs->file, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
             s->l2_size * sizeof(uint64_t))
             return 0;
     }
@@ -329,22 +325,22 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
             /* if the cluster is already compressed, we must
                decompress it in the case it is not completely
                overwritten */
-            if (decompress_cluster(s, cluster_offset) < 0)
+            if (decompress_cluster(bs, cluster_offset) < 0)
                 return 0;
-            cluster_offset = bdrv_getlength(s->hd);
+            cluster_offset = bdrv_getlength(bs->file);
             cluster_offset = (cluster_offset + s->cluster_size - 1) &
                 ~(s->cluster_size - 1);
             /* write the cluster content */
-            if (bdrv_pwrite(s->hd, cluster_offset, s->cluster_cache, s->cluster_size) !=
+            if (bdrv_pwrite(bs->file, cluster_offset, s->cluster_cache, s->cluster_size) !=
                 s->cluster_size)
                 return -1;
         } else {
-            cluster_offset = bdrv_getlength(s->hd);
+            cluster_offset = bdrv_getlength(bs->file);
             if (allocate == 1) {
                 /* round to cluster size */
                 cluster_offset = (cluster_offset + s->cluster_size - 1) &
                     ~(s->cluster_size - 1);
-                bdrv_truncate(s->hd, cluster_offset + s->cluster_size);
+                bdrv_truncate(bs->file, cluster_offset + s->cluster_size);
                 /* if encrypted, we must initialize the cluster
                    content which won't be written */
                 if (s->crypt_method &&
@@ -358,7 +354,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
                                             s->cluster_data,
                                             s->cluster_data + 512, 1, 1,
                                             &s->aes_encrypt_key);
-                            if (bdrv_pwrite(s->hd, cluster_offset + i * 512,
+                            if (bdrv_pwrite(bs->file, cluster_offset + i * 512,
                                             s->cluster_data, 512) != 512)
                                 return -1;
                         }
@@ -372,7 +368,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
         /* update L2 table */
         tmp = cpu_to_be64(cluster_offset);
         l2_table[l2_index] = tmp;
-        if (bdrv_pwrite(s->hd,
+        if (bdrv_pwrite(bs->file,
                         l2_offset + l2_index * sizeof(tmp), &tmp, sizeof(tmp)) != sizeof(tmp))
             return 0;
     }
@@ -422,8 +418,9 @@ static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
     return 0;
 }
 
-static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
+static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
 {
+    BDRVQcowState *s = bs->opaque;
     int ret, csize;
     uint64_t coffset;
 
@@ -431,7 +428,7 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
     if (s->cluster_cache_offset != coffset) {
         csize = cluster_offset >> (63 - s->cluster_bits);
         csize &= (s->cluster_size - 1);
-        ret = bdrv_pread(s->hd, coffset, s->cluster_data, csize);
+        ret = bdrv_pread(bs->file, coffset, s->cluster_data, csize);
         if (ret != csize)
             return -1;
         if (decompress_buffer(s->cluster_cache, s->cluster_size,
@@ -468,11 +465,11 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
                 memset(buf, 0, 512 * n);
             }
         } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
-            if (decompress_cluster(s, cluster_offset) < 0)
+            if (decompress_cluster(bs, cluster_offset) < 0)
                 return -1;
             memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
         } else {
-            ret = bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
+            ret = bdrv_pread(bs->file, cluster_offset + index_in_cluster * 512, buf, n * 512);
             if (ret != n * 512)
                 return -1;
             if (s->crypt_method) {
@@ -601,7 +598,7 @@ static void qcow_aio_read_cb(void *opaque, int ret)
         }
     } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
         /* add AIO support for compressed blocks ? */
-        if (decompress_cluster(s, acb->cluster_offset) < 0)
+        if (decompress_cluster(bs, acb->cluster_offset) < 0)
             goto done;
         memcpy(acb->buf,
                s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
@@ -614,7 +611,7 @@ static void qcow_aio_read_cb(void *opaque, int ret)
         acb->hd_iov.iov_base = (void *)acb->buf;
         acb->hd_iov.iov_len = acb->n * 512;
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        acb->hd_aiocb = bdrv_aio_readv(s->hd,
+        acb->hd_aiocb = bdrv_aio_readv(bs->file,
                             (acb->cluster_offset >> 9) + index_in_cluster,
                             &acb->hd_qiov, acb->n, qcow_aio_read_cb, acb);
         if (acb->hd_aiocb == NULL)
@@ -699,7 +696,7 @@ static void qcow_aio_write_cb(void *opaque, int ret)
     acb->hd_iov.iov_base = (void *)src_buf;
     acb->hd_iov.iov_len = acb->n * 512;
     qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-    acb->hd_aiocb = bdrv_aio_writev(s->hd,
+    acb->hd_aiocb = bdrv_aio_writev(bs->file,
                                     (cluster_offset >> 9) + index_in_cluster,
                                     &acb->hd_qiov, acb->n,
                                     qcow_aio_write_cb, acb);
@@ -739,7 +736,6 @@ static void qcow_close(BlockDriverState *bs)
     qemu_free(s->l2_cache);
     qemu_free(s->cluster_cache);
     qemu_free(s->cluster_data);
-    bdrv_delete(s->hd);
 }
 
 static int qcow_create(const char *filename, QEMUOptionParameter *options)
@@ -839,9 +835,9 @@ static int qcow_make_empty(BlockDriverState *bs)
     int ret;
 
     memset(s->l1_table, 0, l1_length);
-    if (bdrv_pwrite(s->hd, s->l1_table_offset, s->l1_table, l1_length) < 0)
+    if (bdrv_pwrite(bs->file, s->l1_table_offset, s->l1_table, l1_length) < 0)
 	return -1;
-    ret = bdrv_truncate(s->hd, s->l1_table_offset + l1_length);
+    ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length);
     if (ret < 0)
         return ret;
 
@@ -902,7 +898,7 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
         cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
                                             out_len, 0, 0);
         cluster_offset &= s->cluster_offset_mask;
-        if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
+        if (bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len) != out_len) {
             qemu_free(out_buf);
             return -1;
         }
@@ -914,16 +910,13 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
 
 static void qcow_flush(BlockDriverState *bs)
 {
-    BDRVQcowState *s = bs->opaque;
-    bdrv_flush(s->hd);
+    bdrv_flush(bs->file);
 }
 
 static BlockDriverAIOCB *qcow_aio_flush(BlockDriverState *bs,
         BlockDriverCompletionFunc *cb, void *opaque)
 {
-    BDRVQcowState *s = bs->opaque;
-
-    return bdrv_aio_flush(s->hd, cb, opaque);
+    return bdrv_aio_flush(bs->file, cb, opaque);
 }
 
 static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 639e05e..c11680d 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -54,27 +54,27 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
     memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
 
     /* write new table (align to cluster) */
-    BLKDBG_EVENT(s->hd, BLKDBG_L1_GROW_ALLOC_TABLE);
+    BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ALLOC_TABLE);
     new_l1_table_offset = qcow2_alloc_clusters(bs, new_l1_size2);
     if (new_l1_table_offset < 0) {
         qemu_free(new_l1_table);
         return new_l1_table_offset;
     }
 
-    BLKDBG_EVENT(s->hd, BLKDBG_L1_GROW_WRITE_TABLE);
+    BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_WRITE_TABLE);
     for(i = 0; i < s->l1_size; i++)
         new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
-    ret = bdrv_pwrite(s->hd, new_l1_table_offset, new_l1_table, new_l1_size2);
+    ret = bdrv_pwrite(bs->file, new_l1_table_offset, new_l1_table, new_l1_size2);
     if (ret != new_l1_size2)
         goto fail;
     for(i = 0; i < s->l1_size; i++)
         new_l1_table[i] = be64_to_cpu(new_l1_table[i]);
 
     /* set new table */
-    BLKDBG_EVENT(s->hd, BLKDBG_L1_GROW_ACTIVATE_TABLE);
+    BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ACTIVATE_TABLE);
     cpu_to_be32w((uint32_t*)data, new_l1_size);
     cpu_to_be64w((uint64_t*)(data + 4), new_l1_table_offset);
-    ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size), data,sizeof(data));
+    ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, l1_size), data,sizeof(data));
     if (ret != sizeof(data)) {
         goto fail;
     }
@@ -174,8 +174,8 @@ static uint64_t *l2_load(BlockDriverState *bs, uint64_t l2_offset)
     min_index = l2_cache_new_entry(bs);
     l2_table = s->l2_cache + (min_index << s->l2_bits);
 
-    BLKDBG_EVENT(s->hd, BLKDBG_L2_LOAD);
-    if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
+    BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
+    if (bdrv_pread(bs->file, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
         s->l2_size * sizeof(uint64_t))
         return NULL;
     s->l2_cache_offsets[min_index] = l2_offset;
@@ -189,8 +189,9 @@ static uint64_t *l2_load(BlockDriverState *bs, uint64_t l2_offset)
  * and we really don't want bdrv_pread to perform a read-modify-write)
  */
 #define L1_ENTRIES_PER_SECTOR (512 / 8)
-static int write_l1_entry(BDRVQcowState *s, int l1_index)
+static int write_l1_entry(BlockDriverState *bs, int l1_index)
 {
+    BDRVQcowState *s = bs->opaque;
     uint64_t buf[L1_ENTRIES_PER_SECTOR];
     int l1_start_index;
     int i, ret;
@@ -200,8 +201,8 @@ static int write_l1_entry(BDRVQcowState *s, int l1_index)
         buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]);
     }
 
-    BLKDBG_EVENT(s->hd, BLKDBG_L1_UPDATE);
-    ret = bdrv_pwrite(s->hd, s->l1_table_offset + 8 * l1_start_index,
+    BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE);
+    ret = bdrv_pwrite(bs->file, s->l1_table_offset + 8 * l1_start_index,
         buf, sizeof(buf));
     if (ret < 0) {
         return ret;
@@ -241,7 +242,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
     /* update the L1 entry */
 
     s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
-    ret = write_l1_entry(s, l1_index);
+    ret = write_l1_entry(bs, l1_index);
     if (ret < 0) {
         return ret;
     }
@@ -256,16 +257,16 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
         memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
     } else {
         /* if there was an old l2 table, read it from the disk */
-        BLKDBG_EVENT(s->hd, BLKDBG_L2_ALLOC_COW_READ);
-        ret = bdrv_pread(s->hd, old_l2_offset, l2_table,
+        BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_COW_READ);
+        ret = bdrv_pread(bs->file, old_l2_offset, l2_table,
             s->l2_size * sizeof(uint64_t));
         if (ret < 0) {
             return ret;
         }
     }
     /* write the l2 table to the file */
-    BLKDBG_EVENT(s->hd, BLKDBG_L2_ALLOC_WRITE);
-    ret = bdrv_pwrite(s->hd, l2_offset, l2_table,
+    BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_WRITE);
+    ret = bdrv_pwrite(bs->file, l2_offset, l2_table,
         s->l2_size * sizeof(uint64_t));
     if (ret < 0) {
         return ret;
@@ -348,7 +349,7 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
                 /* read from the base image */
                 n1 = qcow2_backing_read1(bs->backing_hd, sector_num, buf, n);
                 if (n1 > 0) {
-                    BLKDBG_EVENT(s->hd, BLKDBG_READ_BACKING);
+                    BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING);
                     ret = bdrv_read(bs->backing_hd, sector_num, buf, n1);
                     if (ret < 0)
                         return -1;
@@ -357,12 +358,12 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
                 memset(buf, 0, 512 * n);
             }
         } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
-            if (qcow2_decompress_cluster(s, cluster_offset) < 0)
+            if (qcow2_decompress_cluster(bs, cluster_offset) < 0)
                 return -1;
             memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
         } else {
-            BLKDBG_EVENT(s->hd, BLKDBG_READ);
-            ret = bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
+            BLKDBG_EVENT(bs->file, BLKDBG_READ);
+            ret = bdrv_pread(bs->file, cluster_offset + index_in_cluster * 512, buf, n * 512);
             if (ret != n * 512)
                 return -1;
             if (s->crypt_method) {
@@ -386,7 +387,7 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
     n = n_end - n_start;
     if (n <= 0)
         return 0;
-    BLKDBG_EVENT(s->hd, BLKDBG_COW_READ);
+    BLKDBG_EVENT(bs->file, BLKDBG_COW_READ);
     ret = qcow_read(bs, start_sect + n_start, s->cluster_data, n);
     if (ret < 0)
         return ret;
@@ -396,8 +397,8 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
                         s->cluster_data, n, 1,
                         &s->aes_encrypt_key);
     }
-    BLKDBG_EVENT(s->hd, BLKDBG_COW_WRITE);
-    ret = bdrv_write(s->hd, (cluster_offset >> 9) + n_start,
+    BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE);
+    ret = bdrv_write(bs->file, (cluster_offset >> 9) + n_start,
                      s->cluster_data, n);
     if (ret < 0)
         return ret;
@@ -610,9 +611,9 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
 
     /* compressed clusters never have the copied flag */
 
-    BLKDBG_EVENT(s->hd, BLKDBG_L2_UPDATE_COMPRESSED);
+    BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED);
     l2_table[l2_index] = cpu_to_be64(cluster_offset);
-    if (bdrv_pwrite(s->hd,
+    if (bdrv_pwrite(bs->file,
                     l2_offset + l2_index * sizeof(uint64_t),
                     l2_table + l2_index,
                     sizeof(uint64_t)) != sizeof(uint64_t))
@@ -626,7 +627,7 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
  * read-modify-write in bdrv_pwrite
  */
 #define L2_ENTRIES_PER_SECTOR (512 / 8)
-static int write_l2_entries(BDRVQcowState *s, uint64_t *l2_table,
+static int write_l2_entries(BlockDriverState *bs, uint64_t *l2_table,
     uint64_t l2_offset, int l2_index, int num)
 {
     int l2_start_index = l2_index & ~(L1_ENTRIES_PER_SECTOR - 1);
@@ -635,8 +636,8 @@ static int write_l2_entries(BDRVQcowState *s, uint64_t *l2_table,
     size_t len = end_offset - start_offset;
     int ret;
 
-    BLKDBG_EVENT(s->hd, BLKDBG_L2_UPDATE);
-    ret = bdrv_pwrite(s->hd, l2_offset + start_offset,
+    BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
+    ret = bdrv_pwrite(bs->file, l2_offset + start_offset,
         &l2_table[l2_start_index], len);
     if (ret < 0) {
         return ret;
@@ -693,7 +694,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
                     (i << s->cluster_bits)) | QCOW_OFLAG_COPIED);
      }
 
-    ret = write_l2_entries(s, l2_table, l2_offset, l2_index, m->nb_clusters);
+    ret = write_l2_entries(bs, l2_table, l2_offset, l2_index, m->nb_clusters);
     if (ret < 0) {
         goto err;
     }
@@ -877,8 +878,9 @@ static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
     return 0;
 }
 
-int qcow2_decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
+int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
 {
+    BDRVQcowState *s = bs->opaque;
     int ret, csize, nb_csectors, sector_offset;
     uint64_t coffset;
 
@@ -887,8 +889,8 @@ int qcow2_decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
         nb_csectors = ((cluster_offset >> s->csize_shift) & s->csize_mask) + 1;
         sector_offset = coffset & 511;
         csize = nb_csectors * 512 - sector_offset;
-        BLKDBG_EVENT(s->hd, BLKDBG_READ_COMPRESSED);
-        ret = bdrv_read(s->hd, coffset >> 9, s->cluster_data, nb_csectors);
+        BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
+        ret = bdrv_read(bs->file, coffset >> 9, s->cluster_data, nb_csectors);
         if (ret < 0) {
             return -1;
         }
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 47c9978..2661493 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -34,16 +34,17 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
 
 static int cache_refcount_updates = 0;
 
-static int write_refcount_block(BDRVQcowState *s)
+static int write_refcount_block(BlockDriverState *bs)
 {
+    BDRVQcowState *s = bs->opaque;
     size_t size = s->cluster_size;
 
     if (s->refcount_block_cache_offset == 0) {
         return 0;
     }
 
-    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_UPDATE);
-    if (bdrv_pwrite(s->hd, s->refcount_block_cache_offset,
+    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE);
+    if (bdrv_pwrite(bs->file, s->refcount_block_cache_offset,
             s->refcount_block_cache, size) != size)
     {
         return -EIO;
@@ -64,8 +65,8 @@ int qcow2_refcount_init(BlockDriverState *bs)
     refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t);
     s->refcount_table = qemu_malloc(refcount_table_size2);
     if (s->refcount_table_size > 0) {
-        BLKDBG_EVENT(s->hd, BLKDBG_REFTABLE_LOAD);
-        ret = bdrv_pread(s->hd, s->refcount_table_offset,
+        BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_LOAD);
+        ret = bdrv_pread(bs->file, s->refcount_table_offset,
                          s->refcount_table, refcount_table_size2);
         if (ret != refcount_table_size2)
             goto fail;
@@ -92,11 +93,11 @@ static int load_refcount_block(BlockDriverState *bs,
     int ret;
 
     if (cache_refcount_updates) {
-        write_refcount_block(s);
+        write_refcount_block(bs);
     }
 
-    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_LOAD);
-    ret = bdrv_pread(s->hd, refcount_block_offset, s->refcount_block_cache,
+    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_LOAD);
+    ret = bdrv_pread(bs->file, refcount_block_offset, s->refcount_block_cache,
                      s->cluster_size);
     if (ret != s->cluster_size)
         return -EIO;
@@ -167,7 +168,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
     unsigned int refcount_table_index;
     int ret;
 
-    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC);
+    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC);
 
     /* Find the refcount block for the given cluster */
     refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
@@ -212,7 +213,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
      */
 
     if (cache_refcount_updates) {
-        ret = write_refcount_block(s);
+        ret = write_refcount_block(bs);
         if (ret < 0) {
             return ret;
         }
@@ -244,8 +245,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
     }
 
     /* Now the new refcount block needs to be written to disk */
-    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC_WRITE);
-    ret = bdrv_pwrite(s->hd, new_block, s->refcount_block_cache,
+    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE);
+    ret = bdrv_pwrite(bs->file, new_block, s->refcount_block_cache,
         s->cluster_size);
     if (ret < 0) {
         goto fail_block;
@@ -254,8 +255,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
     /* If the refcount table is big enough, just hook the block up there */
     if (refcount_table_index < s->refcount_table_size) {
         uint64_t data64 = cpu_to_be64(new_block);
-        BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC_HOOKUP);
-        ret = bdrv_pwrite(s->hd,
+        BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_HOOKUP);
+        ret = bdrv_pwrite(bs->file,
             s->refcount_table_offset + refcount_table_index * sizeof(uint64_t),
             &data64, sizeof(data64));
         if (ret < 0) {
@@ -277,7 +278,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
      * refcount table at once without producing an inconsistent state in
      * between.
      */
-    BLKDBG_EVENT(s->hd, BLKDBG_REFTABLE_GROW);
+    BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_GROW);
 
     /* Calculate the number of refcount blocks needed so far */
     uint64_t refcount_block_clusters = 1 << (s->cluster_bits - REFCOUNT_SHIFT);
@@ -334,8 +335,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
     }
 
     /* Write refcount blocks to disk */
-    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS);
-    ret = bdrv_pwrite(s->hd, meta_offset, new_blocks,
+    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS);
+    ret = bdrv_pwrite(bs->file, meta_offset, new_blocks,
         blocks_clusters * s->cluster_size);
     qemu_free(new_blocks);
     if (ret < 0) {
@@ -347,8 +348,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
         cpu_to_be64s(&new_table[i]);
     }
 
-    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE);
-    ret = bdrv_pwrite(s->hd, table_offset, new_table,
+    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE);
+    ret = bdrv_pwrite(bs->file, table_offset, new_table,
         table_size * sizeof(uint64_t));
     if (ret < 0) {
         goto fail_table;
@@ -362,8 +363,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
     uint8_t data[12];
     cpu_to_be64w((uint64_t*)data, table_offset);
     cpu_to_be32w((uint32_t*)(data + 8), table_clusters);
-    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE);
-    ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),
+    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE);
+    ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, refcount_table_offset),
         data, sizeof(data));
     if (ret < 0) {
         goto fail_table;
@@ -398,9 +399,10 @@ fail_block:
 }
 
 #define REFCOUNTS_PER_SECTOR (512 >> REFCOUNT_SHIFT)
-static int write_refcount_block_entries(BDRVQcowState *s,
+static int write_refcount_block_entries(BlockDriverState *bs,
     int64_t refcount_block_offset, int first_index, int last_index)
 {
+    BDRVQcowState *s = bs->opaque;
     size_t size;
 
     if (cache_refcount_updates) {
@@ -412,8 +414,8 @@ static int write_refcount_block_entries(BDRVQcowState *s,
         & ~(REFCOUNTS_PER_SECTOR - 1);
 
     size = (last_index - first_index) << REFCOUNT_SHIFT;
-    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_UPDATE_PART);
-    if (bdrv_pwrite(s->hd,
+    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE_PART);
+    if (bdrv_pwrite(bs->file,
         refcount_block_offset + (first_index << REFCOUNT_SHIFT),
         &s->refcount_block_cache[first_index], size) != size)
     {
@@ -458,7 +460,7 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
         table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
         if ((old_table_index >= 0) && (table_index != old_table_index)) {
 
-            if (write_refcount_block_entries(s, refcount_block_offset,
+            if (write_refcount_block_entries(bs, refcount_block_offset,
                 first_index, last_index) < 0)
             {
                 return -EIO;
@@ -503,7 +505,7 @@ fail:
 
     /* Write last changed block to disk */
     if (refcount_block_offset != 0) {
-        if (write_refcount_block_entries(s, refcount_block_offset,
+        if (write_refcount_block_entries(bs, refcount_block_offset,
             first_index, last_index) < 0)
         {
             return ret < 0 ? ret : -EIO;
@@ -568,11 +570,10 @@ retry:
 
 int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size)
 {
-    BDRVQcowState *s = bs->opaque;
     int64_t offset;
     int ret;
 
-    BLKDBG_EVENT(s->hd, BLKDBG_CLUSTER_ALLOC);
+    BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC);
     offset = alloc_clusters_noref(bs, size);
     ret = update_refcount(bs, offset, size, 1);
     if (ret < 0) {
@@ -589,7 +590,7 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
     int64_t offset, cluster_offset;
     int free_in_cluster;
 
-    BLKDBG_EVENT(s->hd, BLKDBG_CLUSTER_ALLOC_BYTES);
+    BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC_BYTES);
     assert(size > 0 && size <= s->cluster_size);
     if (s->free_byte_offset == 0) {
         s->free_byte_offset = qcow2_alloc_clusters(bs, s->cluster_size);
@@ -631,10 +632,9 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
 void qcow2_free_clusters(BlockDriverState *bs,
                           int64_t offset, int64_t size)
 {
-    BDRVQcowState *s = bs->opaque;
     int ret;
 
-    BLKDBG_EVENT(s->hd, BLKDBG_CLUSTER_FREE);
+    BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_FREE);
     ret = update_refcount(bs, offset, size, -1);
     if (ret < 0) {
         fprintf(stderr, "qcow2_free_clusters failed: %s\n", strerror(-ret));
@@ -718,7 +718,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
             l1_table = NULL;
         }
         l1_allocated = 1;
-        if (bdrv_pread(s->hd, l1_table_offset,
+        if (bdrv_pread(bs->file, l1_table_offset,
                        l1_table, l1_size2) != l1_size2)
             goto fail;
         for(i = 0;i < l1_size; i++)
@@ -738,7 +738,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
             old_l2_offset = l2_offset;
             l2_offset &= ~QCOW_OFLAG_COPIED;
             l2_modified = 0;
-            if (bdrv_pread(s->hd, l2_offset, l2_table, l2_size) != l2_size)
+            if (bdrv_pread(bs->file, l2_offset, l2_table, l2_size) != l2_size)
                 goto fail;
             for(j = 0; j < s->l2_size; j++) {
                 offset = be64_to_cpu(l2_table[j]);
@@ -777,7 +777,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
                 }
             }
             if (l2_modified) {
-                if (bdrv_pwrite(s->hd,
+                if (bdrv_pwrite(bs->file,
                                 l2_offset, l2_table, l2_size) != l2_size)
                     goto fail;
             }
@@ -799,7 +799,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
     if (l1_modified) {
         for(i = 0; i < l1_size; i++)
             cpu_to_be64s(&l1_table[i]);
-        if (bdrv_pwrite(s->hd, l1_table_offset, l1_table,
+        if (bdrv_pwrite(bs->file, l1_table_offset, l1_table,
                         l1_size2) != l1_size2)
             goto fail;
         for(i = 0; i < l1_size; i++)
@@ -809,14 +809,14 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
         qemu_free(l1_table);
     qemu_free(l2_table);
     cache_refcount_updates = 0;
-    write_refcount_block(s);
+    write_refcount_block(bs);
     return 0;
  fail:
     if (l1_allocated)
         qemu_free(l1_table);
     qemu_free(l2_table);
     cache_refcount_updates = 0;
-    write_refcount_block(s);
+    write_refcount_block(bs);
     return -EIO;
 }
 
@@ -890,7 +890,7 @@ static int check_refcounts_l2(BlockDriverState *bs,
     l2_size = s->l2_size * sizeof(uint64_t);
     l2_table = qemu_malloc(l2_size);
 
-    if (bdrv_pread(s->hd, l2_offset, l2_table, l2_size) != l2_size)
+    if (bdrv_pread(bs->file, l2_offset, l2_table, l2_size) != l2_size)
         goto fail;
 
     /* Do the actual checks */
@@ -982,7 +982,7 @@ static int check_refcounts_l1(BlockDriverState *bs,
         l1_table = NULL;
     } else {
         l1_table = qemu_malloc(l1_size2);
-        if (bdrv_pread(s->hd, l1_table_offset,
+        if (bdrv_pread(bs->file, l1_table_offset,
                        l1_table, l1_size2) != l1_size2)
             goto fail;
         for(i = 0;i < l1_size; i++)
@@ -1051,7 +1051,7 @@ int qcow2_check_refcounts(BlockDriverState *bs)
     uint16_t *refcount_table;
     int ret, errors = 0;
 
-    size = bdrv_getlength(s->hd);
+    size = bdrv_getlength(bs->file);
     nb_clusters = size_to_clusters(s, size);
     refcount_table = qemu_mallocz(nb_clusters * sizeof(uint16_t));
 
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 8ddaea2..2a21c17 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -79,7 +79,7 @@ int qcow2_read_snapshots(BlockDriverState *bs)
     s->snapshots = qemu_mallocz(s->nb_snapshots * sizeof(QCowSnapshot));
     for(i = 0; i < s->nb_snapshots; i++) {
         offset = align_offset(offset, 8);
-        if (bdrv_pread(s->hd, offset, &h, sizeof(h)) != sizeof(h))
+        if (bdrv_pread(bs->file, offset, &h, sizeof(h)) != sizeof(h))
             goto fail;
         offset += sizeof(h);
         sn = s->snapshots + i;
@@ -97,13 +97,13 @@ int qcow2_read_snapshots(BlockDriverState *bs)
         offset += extra_data_size;
 
         sn->id_str = qemu_malloc(id_str_size + 1);
-        if (bdrv_pread(s->hd, offset, sn->id_str, id_str_size) != id_str_size)
+        if (bdrv_pread(bs->file, offset, sn->id_str, id_str_size) != id_str_size)
             goto fail;
         offset += id_str_size;
         sn->id_str[id_str_size] = '\0';
 
         sn->name = qemu_malloc(name_size + 1);
-        if (bdrv_pread(s->hd, offset, sn->name, name_size) != name_size)
+        if (bdrv_pread(bs->file, offset, sn->name, name_size) != name_size)
             goto fail;
         offset += name_size;
         sn->name[name_size] = '\0';
@@ -158,24 +158,24 @@ static int qcow_write_snapshots(BlockDriverState *bs)
         h.id_str_size = cpu_to_be16(id_str_size);
         h.name_size = cpu_to_be16(name_size);
         offset = align_offset(offset, 8);
-        if (bdrv_pwrite(s->hd, offset, &h, sizeof(h)) != sizeof(h))
+        if (bdrv_pwrite(bs->file, offset, &h, sizeof(h)) != sizeof(h))
             goto fail;
         offset += sizeof(h);
-        if (bdrv_pwrite(s->hd, offset, sn->id_str, id_str_size) != id_str_size)
+        if (bdrv_pwrite(bs->file, offset, sn->id_str, id_str_size) != id_str_size)
             goto fail;
         offset += id_str_size;
-        if (bdrv_pwrite(s->hd, offset, sn->name, name_size) != name_size)
+        if (bdrv_pwrite(bs->file, offset, sn->name, name_size) != name_size)
             goto fail;
         offset += name_size;
     }
 
     /* update the various header fields */
     data64 = cpu_to_be64(snapshots_offset);
-    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, snapshots_offset),
+    if (bdrv_pwrite(bs->file, offsetof(QCowHeader, snapshots_offset),
                     &data64, sizeof(data64)) != sizeof(data64))
         goto fail;
     data32 = cpu_to_be32(s->nb_snapshots);
-    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, nb_snapshots),
+    if (bdrv_pwrite(bs->file, offsetof(QCowHeader, nb_snapshots),
                     &data32, sizeof(data32)) != sizeof(data32))
         goto fail;
 
@@ -284,7 +284,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     for(i = 0; i < s->l1_size; i++) {
         l1_table[i] = cpu_to_be64(s->l1_table[i]);
     }
-    if (bdrv_pwrite(s->hd, sn->l1_table_offset,
+    if (bdrv_pwrite(bs->file, sn->l1_table_offset,
                     l1_table, s->l1_size * sizeof(uint64_t)) !=
         (s->l1_size * sizeof(uint64_t)))
         goto fail;
@@ -332,10 +332,10 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
     s->l1_size = sn->l1_size;
     l1_size2 = s->l1_size * sizeof(uint64_t);
     /* copy the snapshot l1 table to the current l1 table */
-    if (bdrv_pread(s->hd, sn->l1_table_offset,
+    if (bdrv_pread(bs->file, sn->l1_table_offset,
                    s->l1_table, l1_size2) != l1_size2)
         goto fail;
-    if (bdrv_pwrite(s->hd, s->l1_table_offset,
+    if (bdrv_pwrite(bs->file, s->l1_table_offset,
                     s->l1_table, l1_size2) != l1_size2)
         goto fail;
     for(i = 0;i < s->l1_size; i++) {
diff --git a/block/qcow2.c b/block/qcow2.c
index 5436fec..4fa3ff9 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -77,7 +77,6 @@ static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
 static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
                                 uint64_t end_offset)
 {
-    BDRVQcowState *s = bs->opaque;
     QCowExtension ext;
     uint64_t offset;
 
@@ -95,7 +94,7 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
         printf("attemting to read extended header in offset %lu\n", offset);
 #endif
 
-        if (bdrv_pread(s->hd, offset, &ext, sizeof(ext)) != sizeof(ext)) {
+        if (bdrv_pread(bs->file, offset, &ext, sizeof(ext)) != sizeof(ext)) {
             fprintf(stderr, "qcow_handle_extension: ERROR: pread fail from offset %llu\n",
                     (unsigned long long)offset);
             return 1;
@@ -117,7 +116,7 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
                         ext.len, sizeof(bs->backing_format));
                 return 2;
             }
-            if (bdrv_pread(s->hd, offset , bs->backing_format,
+            if (bdrv_pread(bs->file, offset , bs->backing_format,
                            ext.len) != ext.len)
                 return 3;
             bs->backing_format[ext.len] = '\0';
@@ -138,17 +137,14 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
 }
 
 
-static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
+static int qcow_open(BlockDriverState *bs, int flags)
 {
     BDRVQcowState *s = bs->opaque;
-    int len, i, shift, ret;
+    int len, i, shift;
     QCowHeader header;
     uint64_t ext_end;
 
-    ret = bdrv_file_open(&s->hd, filename, flags);
-    if (ret < 0)
-        return ret;
-    if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
+    if (bdrv_pread(bs->file, 0, &header, sizeof(header)) != sizeof(header))
         goto fail;
     be32_to_cpus(&header.magic);
     be32_to_cpus(&header.version);
@@ -202,7 +198,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
     if (s->l1_size > 0) {
         s->l1_table = qemu_mallocz(
             align_offset(s->l1_size * sizeof(uint64_t), 512));
-        if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
+        if (bdrv_pread(bs->file, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
             s->l1_size * sizeof(uint64_t))
             goto fail;
         for(i = 0;i < s->l1_size; i++) {
@@ -235,7 +231,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
         len = header.backing_file_size;
         if (len > 1023)
             len = 1023;
-        if (bdrv_pread(s->hd, header.backing_file_offset, bs->backing_file, len) != len)
+        if (bdrv_pread(bs->file, header.backing_file_offset, bs->backing_file, len) != len)
             goto fail;
         bs->backing_file[len] = '\0';
     }
@@ -254,7 +250,6 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
     qemu_free(s->l2_cache);
     qemu_free(s->cluster_cache);
     qemu_free(s->cluster_data);
-    bdrv_delete(s->hd);
     return -1;
 }
 
@@ -429,7 +424,7 @@ static void qcow_aio_read_cb(void *opaque, int ret)
                 acb->hd_iov.iov_base = (void *)acb->buf;
                 acb->hd_iov.iov_len = acb->cur_nr_sectors * 512;
                 qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-                BLKDBG_EVENT(s->hd, BLKDBG_READ_BACKING_AIO);
+                BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
                 acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num,
                                     &acb->hd_qiov, acb->cur_nr_sectors,
 				    qcow_aio_read_cb, acb);
@@ -449,7 +444,7 @@ static void qcow_aio_read_cb(void *opaque, int ret)
         }
     } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
         /* add AIO support for compressed blocks ? */
-        if (qcow2_decompress_cluster(s, acb->cluster_offset) < 0)
+        if (qcow2_decompress_cluster(bs, acb->cluster_offset) < 0)
             goto done;
         memcpy(acb->buf, s->cluster_cache + index_in_cluster * 512,
                512 * acb->cur_nr_sectors);
@@ -465,8 +460,8 @@ static void qcow_aio_read_cb(void *opaque, int ret)
         acb->hd_iov.iov_base = (void *)acb->buf;
         acb->hd_iov.iov_len = acb->cur_nr_sectors * 512;
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        BLKDBG_EVENT(s->hd, BLKDBG_READ_AIO);
-        acb->hd_aiocb = bdrv_aio_readv(s->hd,
+        BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
+        acb->hd_aiocb = bdrv_aio_readv(bs->file,
                             (acb->cluster_offset >> 9) + index_in_cluster,
                             &acb->hd_qiov, acb->cur_nr_sectors,
                             qcow_aio_read_cb, acb);
@@ -615,8 +610,8 @@ static void qcow_aio_write_cb(void *opaque, int ret)
     acb->hd_iov.iov_base = (void *)src_buf;
     acb->hd_iov.iov_len = acb->cur_nr_sectors * 512;
     qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-    BLKDBG_EVENT(s->hd, BLKDBG_WRITE_AIO);
-    acb->hd_aiocb = bdrv_aio_writev(s->hd,
+    BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
+    acb->hd_aiocb = bdrv_aio_writev(bs->file,
                                     (acb->cluster_offset >> 9) + index_in_cluster,
                                     &acb->hd_qiov, acb->cur_nr_sectors,
                                     qcow_aio_write_cb, acb);
@@ -663,7 +658,6 @@ static void qcow_close(BlockDriverState *bs)
     qemu_free(s->cluster_cache);
     qemu_free(s->cluster_data);
     qcow2_refcount_close(bs);
-    bdrv_delete(s->hd);
 }
 
 /*
@@ -733,7 +727,7 @@ static int qcow2_update_ext_header(BlockDriverState *bs,
         backing_file_offset = sizeof(QCowHeader) + offset;
     }
 
-    ret = bdrv_pwrite(s->hd, sizeof(QCowHeader), buf, ext_size);
+    ret = bdrv_pwrite(bs->file, sizeof(QCowHeader), buf, ext_size);
     if (ret < 0) {
         goto fail;
     }
@@ -742,13 +736,13 @@ static int qcow2_update_ext_header(BlockDriverState *bs,
     uint64_t be_backing_file_offset = cpu_to_be64(backing_file_offset);
     uint32_t be_backing_file_size = cpu_to_be32(backing_file_len);
 
-    ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, backing_file_offset),
+    ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, backing_file_offset),
         &be_backing_file_offset, sizeof(uint64_t));
     if (ret < 0) {
         goto fail;
     }
 
-    ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, backing_file_size),
+    ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, backing_file_size),
         &be_backing_file_size, sizeof(uint32_t));
     if (ret < 0) {
         goto fail;
@@ -789,7 +783,6 @@ static int get_bits_from_size(size_t size)
 
 static int preallocate(BlockDriverState *bs)
 {
-    BDRVQcowState *s = bs->opaque;
     uint64_t nb_sectors;
     uint64_t offset;
     int num;
@@ -832,7 +825,7 @@ static int preallocate(BlockDriverState *bs)
     if (meta.cluster_offset != 0) {
         uint8_t buf[512];
         memset(buf, 0, 512);
-        bdrv_write(s->hd, (meta.cluster_offset >> 9) + num - 1, buf, 1);
+        bdrv_write(bs->file, (meta.cluster_offset >> 9) + num - 1, buf, 1);
     }
 
     return 0;
@@ -847,9 +840,9 @@ static int qcow_make_empty(BlockDriverState *bs)
     int ret;
 
     memset(s->l1_table, 0, l1_length);
-    if (bdrv_pwrite(s->hd, s->l1_table_offset, s->l1_table, l1_length) < 0)
+    if (bdrv_pwrite(bs->file, s->l1_table_offset, s->l1_table, l1_length) < 0)
         return -1;
-    ret = bdrv_truncate(s->hd, s->l1_table_offset + l1_length);
+    ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length);
     if (ret < 0)
         return ret;
 
@@ -872,9 +865,9 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
     if (nb_sectors == 0) {
         /* align end of file to a sector boundary to ease reading with
            sector based I/Os */
-        cluster_offset = bdrv_getlength(s->hd);
+        cluster_offset = bdrv_getlength(bs->file);
         cluster_offset = (cluster_offset + 511) & ~511;
-        bdrv_truncate(s->hd, cluster_offset);
+        bdrv_truncate(bs->file, cluster_offset);
         return 0;
     }
 
@@ -917,8 +910,8 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
         if (!cluster_offset)
             return -1;
         cluster_offset &= s->cluster_offset_mask;
-        BLKDBG_EVENT(s->hd, BLKDBG_WRITE_COMPRESSED);
-        if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
+        BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);
+        if (bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len) != out_len) {
             qemu_free(out_buf);
             return -1;
         }
@@ -930,16 +923,13 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
 
 static void qcow_flush(BlockDriverState *bs)
 {
-    BDRVQcowState *s = bs->opaque;
-    bdrv_flush(s->hd);
+    bdrv_flush(bs->file);
 }
 
 static BlockDriverAIOCB *qcow_aio_flush(BlockDriverState *bs,
          BlockDriverCompletionFunc *cb, void *opaque)
 {
-     BDRVQcowState *s = bs->opaque;
-
-     return bdrv_aio_flush(s->hd, cb, opaque);
+    return bdrv_aio_flush(bs->file, cb, opaque);
 }
 
 static int64_t qcow_vm_state_offset(BDRVQcowState *s)
@@ -968,7 +958,7 @@ static void dump_refcounts(BlockDriverState *bs)
     int64_t nb_clusters, k, k1, size;
     int refcount;
 
-    size = bdrv_getlength(s->hd);
+    size = bdrv_getlength(bs->file);
     nb_clusters = size_to_clusters(s, size);
     for(k = 0; k < nb_clusters;) {
         k1 = k;
@@ -988,7 +978,7 @@ static int qcow_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
     int growable = bs->growable;
     int ret;
 
-    BLKDBG_EVENT(s->hd, BLKDBG_VMSTATE_SAVE);
+    BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_SAVE);
     bs->growable = 1;
     ret = bdrv_pwrite(bs, qcow_vm_state_offset(s) + pos, buf, size);
     bs->growable = growable;
@@ -1003,7 +993,7 @@ static int qcow_load_vmstate(BlockDriverState *bs, uint8_t *buf,
     int growable = bs->growable;
     int ret;
 
-    BLKDBG_EVENT(s->hd, BLKDBG_VMSTATE_LOAD);
+    BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_LOAD);
     bs->growable = 1;
     ret = bdrv_pread(bs, qcow_vm_state_offset(s) + pos, buf, size);
     bs->growable = growable;
diff --git a/block/qcow2.h b/block/qcow2.h
index de9397a..5bd08db 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -184,7 +184,7 @@ int qcow2_check_refcounts(BlockDriverState *bs);
 /* qcow2-cluster.c functions */
 int qcow2_grow_l1_table(BlockDriverState *bs, int min_size);
 void qcow2_l2_cache_reset(BlockDriverState *bs);
-int qcow2_decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset);
+int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
 void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
                      uint8_t *out_buf, const uint8_t *in_buf,
                      int nb_sectors, int enc,
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 8f57ab0..598ea19 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -773,7 +773,7 @@ static BlockDriver bdrv_file = {
     .protocol_name = "file",
     .instance_size = sizeof(BDRVRawState),
     .bdrv_probe = NULL, /* no probe for protocols */
-    .bdrv_open = raw_open,
+    .bdrv_file_open = raw_open,
     .bdrv_read = raw_read,
     .bdrv_write = raw_write,
     .bdrv_close = raw_close,
@@ -1030,7 +1030,7 @@ static BlockDriver bdrv_host_device = {
     .protocol_name        = "host_device",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device  = hdev_probe_device,
-    .bdrv_open          = hdev_open,
+    .bdrv_file_open     = hdev_open,
     .bdrv_close         = raw_close,
     .bdrv_create        = hdev_create,
     .create_options     = raw_create_options,
@@ -1145,7 +1145,7 @@ static BlockDriver bdrv_host_floppy = {
     .protocol_name      = "host_floppy",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device	= floppy_probe_device,
-    .bdrv_open          = floppy_open,
+    .bdrv_file_open     = floppy_open,
     .bdrv_close         = raw_close,
     .bdrv_create        = hdev_create,
     .create_options     = raw_create_options,
@@ -1245,7 +1245,7 @@ static BlockDriver bdrv_host_cdrom = {
     .protocol_name      = "host_cdrom",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device	= cdrom_probe_device,
-    .bdrv_open          = cdrom_open,
+    .bdrv_file_open     = cdrom_open,
     .bdrv_close         = raw_close,
     .bdrv_create        = hdev_create,
     .create_options     = raw_create_options,
@@ -1368,7 +1368,7 @@ static BlockDriver bdrv_host_cdrom = {
     .protocol_name      = "host_cdrom",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device	= cdrom_probe_device,
-    .bdrv_open          = cdrom_open,
+    .bdrv_file_open     = cdrom_open,
     .bdrv_close         = raw_close,
     .bdrv_create        = hdev_create,
     .create_options     = raw_create_options,
diff --git a/block/raw-win32.c b/block/raw-win32.c
index eadebeb..745bbde 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -242,7 +242,7 @@ static BlockDriver bdrv_file = {
     .format_name	= "file",
     .protocol_name	= "file",
     .instance_size	= sizeof(BDRVRawState),
-    .bdrv_open		= raw_open,
+    .bdrv_file_open	= raw_open,
     .bdrv_close		= raw_close,
     .bdrv_create	= raw_create,
     .bdrv_flush		= raw_flush,
@@ -399,7 +399,7 @@ static BlockDriver bdrv_host_device = {
     .protocol_name	= "host_device",
     .instance_size	= sizeof(BDRVRawState),
     .bdrv_probe_device	= hdev_probe_device,
-    .bdrv_open		= hdev_open,
+    .bdrv_file_open	= hdev_open,
     .bdrv_close		= raw_close,
     .bdrv_flush		= raw_flush,
 
diff --git a/block/raw.c b/block/raw.c
index 953e285..4406b8c 100644
--- a/block/raw.c
+++ b/block/raw.c
@@ -3,84 +3,61 @@
 #include "block_int.h"
 #include "module.h"
 
-typedef struct RAWState {
-    BlockDriverState *hd;
-} RAWState;
-
-static int raw_open(BlockDriverState *bs, const char *filename, int flags)
+static int raw_open(BlockDriverState *bs, int flags)
 {
-    RAWState *s = bs->opaque;
-    int ret;
-
-    ret = bdrv_file_open(&s->hd, filename, flags);
-    if (!ret) {
-        bs->sg = s->hd->sg;
-    }
-
-    return ret;
+    bs->sg = bs->file->sg;
+    return 0;
 }
 
 static int raw_read(BlockDriverState *bs, int64_t sector_num,
                     uint8_t *buf, int nb_sectors)
 {
-    RAWState *s = bs->opaque;
-    return bdrv_read(s->hd, sector_num, buf, nb_sectors);
+    return bdrv_read(bs->file, sector_num, buf, nb_sectors);
 }
 
 static int raw_write(BlockDriverState *bs, int64_t sector_num,
                      const uint8_t *buf, int nb_sectors)
 {
-    RAWState *s = bs->opaque;
-    return bdrv_write(s->hd, sector_num, buf, nb_sectors);
+    return bdrv_write(bs->file, sector_num, buf, nb_sectors);
 }
 
 static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
     int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
     BlockDriverCompletionFunc *cb, void *opaque)
 {
-    RAWState *s = bs->opaque;
-
-    return bdrv_aio_readv(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
+    return bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
 }
 
 static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
     int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
     BlockDriverCompletionFunc *cb, void *opaque)
 {
-    RAWState *s = bs->opaque;
-
-    return bdrv_aio_writev(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
+    return bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
 }
 
 static void raw_close(BlockDriverState *bs)
 {
-    RAWState *s = bs->opaque;
-    bdrv_delete(s->hd);
 }
 
 static void raw_flush(BlockDriverState *bs)
 {
-    RAWState *s = bs->opaque;
-    bdrv_flush(s->hd);
+    bdrv_flush(bs->file);
 }
 
 static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
     BlockDriverCompletionFunc *cb, void *opaque)
 {
-    RAWState *s = bs->opaque;
-    return bdrv_aio_flush(s->hd, cb, opaque);
+    return bdrv_aio_flush(bs->file, cb, opaque);
 }
 
 static int64_t raw_getlength(BlockDriverState *bs)
 {
-    RAWState *s = bs->opaque;
-    return bdrv_getlength(s->hd);
+    return bdrv_getlength(bs->file);
 }
 
 static int raw_truncate(BlockDriverState *bs, int64_t offset)
 {
-    RAWState *s = bs->opaque;
-    return bdrv_truncate(s->hd, offset);
+    return bdrv_truncate(bs->file, offset);
 }
 
 static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
@@ -90,35 +67,30 @@ static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
 
 static int raw_is_inserted(BlockDriverState *bs)
 {
-    RAWState *s = bs->opaque;
-    return bdrv_is_inserted(s->hd);
+    return bdrv_is_inserted(bs->file);
 }
 
 static int raw_eject(BlockDriverState *bs, int eject_flag)
 {
-    RAWState *s = bs->opaque;
-    return bdrv_eject(s->hd, eject_flag);
+    return bdrv_eject(bs->file, eject_flag);
 }
 
 static int raw_set_locked(BlockDriverState *bs, int locked)
 {
-    RAWState *s = bs->opaque;
-    bdrv_set_locked(s->hd, locked);
+    bdrv_set_locked(bs->file, locked);
     return 0;
 }
 
 static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
 {
-   RAWState *s = bs->opaque;
-   return bdrv_ioctl(s->hd, req, buf);
+   return bdrv_ioctl(bs->file, req, buf);
 }
 
 static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
         unsigned long int req, void *buf,
         BlockDriverCompletionFunc *cb, void *opaque)
 {
-   RAWState *s = bs->opaque;
-   return bdrv_aio_ioctl(s->hd, req, buf, cb, opaque);
+   return bdrv_aio_ioctl(bs->file, req, buf, cb, opaque);
 }
 
 static int raw_create(const char *filename, QEMUOptionParameter *options)
@@ -138,7 +110,8 @@ static QEMUOptionParameter raw_create_options[] = {
 static BlockDriver bdrv_raw = {
     .format_name        = "raw",
 
-    .instance_size      = sizeof(RAWState),
+    /* It's really 0, but we need to make qemu_malloc() happy */
+    .instance_size      = 1,
 
     .bdrv_open          = raw_open,
     .bdrv_close         = raw_close,
diff --git a/block/vdi.c b/block/vdi.c
index c91961a..1d257b4 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -376,21 +376,15 @@ static int vdi_probe(const uint8_t *buf, int buf_size, const char *filename)
     return result;
 }
 
-static int vdi_open(BlockDriverState *bs, const char *filename, int flags)
+static int vdi_open(BlockDriverState *bs, int flags)
 {
     BDRVVdiState *s = bs->opaque;
     VdiHeader header;
     size_t bmap_size;
-    int ret;
 
     logout("\n");
 
-    ret = bdrv_file_open(&s->hd, filename, flags);
-    if (ret < 0) {
-        return ret;
-    }
-
-    if (bdrv_read(s->hd, 0, (uint8_t *)&header, 1) < 0) {
+    if (bdrv_read(bs->file, 0, (uint8_t *)&header, 1) < 0) {
         goto fail;
     }
 
@@ -442,7 +436,7 @@ static int vdi_open(BlockDriverState *bs, const char *filename, int flags)
     bmap_size = header.blocks_in_image * sizeof(uint32_t);
     bmap_size = (bmap_size + SECTOR_SIZE - 1) / SECTOR_SIZE;
     s->bmap = qemu_malloc(bmap_size * SECTOR_SIZE);
-    if (bdrv_read(s->hd, s->bmap_sector, (uint8_t *)s->bmap, bmap_size) < 0) {
+    if (bdrv_read(bs->file, s->bmap_sector, (uint8_t *)s->bmap, bmap_size) < 0) {
         goto fail_free_bmap;
     }
 
@@ -452,7 +446,6 @@ static int vdi_open(BlockDriverState *bs, const char *filename, int flags)
     qemu_free(s->bmap);
 
  fail:
-    bdrv_delete(s->hd);
     return -1;
 }
 
@@ -607,7 +600,7 @@ static void vdi_aio_read_cb(void *opaque, int ret)
         acb->hd_iov.iov_base = (void *)acb->buf;
         acb->hd_iov.iov_len = n_sectors * SECTOR_SIZE;
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        acb->hd_aiocb = bdrv_aio_readv(s->hd, offset, &acb->hd_qiov,
+        acb->hd_aiocb = bdrv_aio_readv(bs->file, offset, &acb->hd_qiov,
                                        n_sectors, vdi_aio_read_cb, acb);
         if (acb->hd_aiocb == NULL) {
             goto done;
@@ -670,7 +663,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
             acb->hd_iov.iov_base = acb->block_buffer;
             acb->hd_iov.iov_len = SECTOR_SIZE;
             qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-            acb->hd_aiocb = bdrv_aio_writev(s->hd, 0, &acb->hd_qiov, 1,
+            acb->hd_aiocb = bdrv_aio_writev(bs->file, 0, &acb->hd_qiov, 1,
                                             vdi_aio_write_cb, acb);
             if (acb->hd_aiocb == NULL) {
                 goto done;
@@ -699,7 +692,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
             qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
             logout("will write %u block map sectors starting from entry %u\n",
                    n_sectors, bmap_first);
-            acb->hd_aiocb = bdrv_aio_writev(s->hd, offset, &acb->hd_qiov,
+            acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov,
                                             n_sectors, vdi_aio_write_cb, acb);
             if (acb->hd_aiocb == NULL) {
                 goto done;
@@ -748,7 +741,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
         acb->hd_iov.iov_base = (void *)block;
         acb->hd_iov.iov_len = s->block_size;
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        acb->hd_aiocb = bdrv_aio_writev(s->hd, offset,
+        acb->hd_aiocb = bdrv_aio_writev(bs->file, offset,
                                         &acb->hd_qiov, s->block_sectors,
                                         vdi_aio_write_cb, acb);
         if (acb->hd_aiocb == NULL) {
@@ -761,7 +754,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
         acb->hd_iov.iov_base = (void *)acb->buf;
         acb->hd_iov.iov_len = n_sectors * SECTOR_SIZE;
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        acb->hd_aiocb = bdrv_aio_writev(s->hd, offset, &acb->hd_qiov,
+        acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov,
                                         n_sectors, vdi_aio_write_cb, acb);
         if (acb->hd_aiocb == NULL) {
             goto done;
@@ -891,16 +884,12 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
 
 static void vdi_close(BlockDriverState *bs)
 {
-    BDRVVdiState *s = bs->opaque;
-    logout("\n");
-    bdrv_delete(s->hd);
 }
 
 static void vdi_flush(BlockDriverState *bs)
 {
-    BDRVVdiState *s = bs->opaque;
     logout("\n");
-    bdrv_flush(s->hd);
+    bdrv_flush(bs->file);
 }
 
 
diff --git a/block/vmdk.c b/block/vmdk.c
index 6fdea1d..5ef4375 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -914,7 +914,7 @@ static BlockDriver bdrv_vmdk = {
     .format_name	= "vmdk",
     .instance_size	= sizeof(BDRVVmdkState),
     .bdrv_probe		= vmdk_probe,
-    .bdrv_open		= vmdk_open,
+    .bdrv_file_open	= vmdk_open,
     .bdrv_read		= vmdk_read,
     .bdrv_write		= vmdk_write,
     .bdrv_close		= vmdk_close,
diff --git a/block/vpc.c b/block/vpc.c
index 950ad58..f94e469 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -150,20 +150,16 @@ static int vpc_probe(const uint8_t *buf, int buf_size, const char *filename)
     return 0;
 }
 
-static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
+static int vpc_open(BlockDriverState *bs, int flags)
 {
     BDRVVPCState *s = bs->opaque;
-    int ret, i;
+    int i;
     struct vhd_footer* footer;
     struct vhd_dyndisk_header* dyndisk_header;
     uint8_t buf[HEADER_SIZE];
     uint32_t checksum;
 
-    ret = bdrv_file_open(&s->hd, filename, flags);
-    if (ret < 0)
-        return ret;
-
-    if (bdrv_pread(s->hd, 0, s->footer_buf, HEADER_SIZE) != HEADER_SIZE)
+    if (bdrv_pread(bs->file, 0, s->footer_buf, HEADER_SIZE) != HEADER_SIZE)
         goto fail;
 
     footer = (struct vhd_footer*) s->footer_buf;
@@ -174,7 +170,7 @@ static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
     footer->checksum = 0;
     if (vpc_checksum(s->footer_buf, HEADER_SIZE) != checksum)
         fprintf(stderr, "block-vpc: The header checksum of '%s' is "
-            "incorrect.\n", filename);
+            "incorrect.\n", bs->filename);
 
     // The visible size of a image in Virtual PC depends on the geometry
     // rather than on the size stored in the footer (the size in the footer
@@ -182,7 +178,7 @@ static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
     bs->total_sectors = (int64_t)
         be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl;
 
-    if (bdrv_pread(s->hd, be64_to_cpu(footer->data_offset), buf, HEADER_SIZE)
+    if (bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), buf, HEADER_SIZE)
             != HEADER_SIZE)
         goto fail;
 
@@ -199,7 +195,7 @@ static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
     s->pagetable = qemu_malloc(s->max_table_entries * 4);
 
     s->bat_offset = be64_to_cpu(dyndisk_header->table_offset);
-    if (bdrv_pread(s->hd, s->bat_offset, s->pagetable,
+    if (bdrv_pread(bs->file, s->bat_offset, s->pagetable,
             s->max_table_entries * 4) != s->max_table_entries * 4)
 	    goto fail;
 
@@ -228,7 +224,6 @@ static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
 
     return 0;
  fail:
-    bdrv_delete(s->hd);
     return -1;
 }
 
@@ -266,7 +261,7 @@ static inline int64_t get_sector_offset(BlockDriverState *bs,
 
         s->last_bitmap_offset = bitmap_offset;
         memset(bitmap, 0xff, s->bitmap_size);
-        bdrv_pwrite(s->hd, bitmap_offset, bitmap, s->bitmap_size);
+        bdrv_pwrite(bs->file, bitmap_offset, bitmap, s->bitmap_size);
     }
 
 //    printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n",
@@ -316,7 +311,7 @@ static int rewrite_footer(BlockDriverState* bs)
     BDRVVPCState *s = bs->opaque;
     int64_t offset = s->free_data_block_offset;
 
-    ret = bdrv_pwrite(s->hd, offset, s->footer_buf, HEADER_SIZE);
+    ret = bdrv_pwrite(bs->file, offset, s->footer_buf, HEADER_SIZE);
     if (ret < 0)
         return ret;
 
@@ -351,7 +346,7 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num)
 
     // Initialize the block's bitmap
     memset(bitmap, 0xff, s->bitmap_size);
-    bdrv_pwrite(s->hd, s->free_data_block_offset, bitmap, s->bitmap_size);
+    bdrv_pwrite(bs->file, s->free_data_block_offset, bitmap, s->bitmap_size);
 
     // Write new footer (the old one will be overwritten)
     s->free_data_block_offset += s->block_size + s->bitmap_size;
@@ -362,7 +357,7 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num)
     // Write BAT entry to disk
     bat_offset = s->bat_offset + (4 * index);
     bat_value = be32_to_cpu(s->pagetable[index]);
-    ret = bdrv_pwrite(s->hd, bat_offset, &bat_value, 4);
+    ret = bdrv_pwrite(bs->file, bat_offset, &bat_value, 4);
     if (ret < 0)
         goto fail;
 
@@ -376,7 +371,6 @@ fail:
 static int vpc_read(BlockDriverState *bs, int64_t sector_num,
                     uint8_t *buf, int nb_sectors)
 {
-    BDRVVPCState *s = bs->opaque;
     int ret;
     int64_t offset;
 
@@ -386,7 +380,7 @@ static int vpc_read(BlockDriverState *bs, int64_t sector_num,
         if (offset == -1) {
             memset(buf, 0, 512);
         } else {
-            ret = bdrv_pread(s->hd, offset, buf, 512);
+            ret = bdrv_pread(bs->file, offset, buf, 512);
             if (ret != 512)
                 return -1;
         }
@@ -401,7 +395,6 @@ static int vpc_read(BlockDriverState *bs, int64_t sector_num,
 static int vpc_write(BlockDriverState *bs, int64_t sector_num,
     const uint8_t *buf, int nb_sectors)
 {
-    BDRVVPCState *s = bs->opaque;
     int64_t offset;
     int ret;
 
@@ -414,7 +407,7 @@ static int vpc_write(BlockDriverState *bs, int64_t sector_num,
                 return -1;
         }
 
-        ret = bdrv_pwrite(s->hd, offset, buf, 512);
+        ret = bdrv_pwrite(bs->file, offset, buf, 512);
         if (ret != 512)
             return -1;
 
@@ -590,7 +583,6 @@ static void vpc_close(BlockDriverState *bs)
 #ifdef CACHE
     qemu_free(s->pageentry_u8);
 #endif
-    bdrv_delete(s->hd);
 }
 
 static QEMUOptionParameter vpc_create_options[] = {
diff --git a/block/vvfat.c b/block/vvfat.c
index 66259b4..ce16bbd 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -2827,7 +2827,7 @@ static void vvfat_close(BlockDriverState *bs)
 static BlockDriver bdrv_vvfat = {
     .format_name	= "vvfat",
     .instance_size	= sizeof(BDRVVVFATState),
-    .bdrv_open		= vvfat_open,
+    .bdrv_file_open	= vvfat_open,
     .bdrv_read		= vvfat_read,
     .bdrv_write		= vvfat_write,
     .bdrv_close		= vvfat_close,
diff --git a/block_int.h b/block_int.h
index d4067ff..a3afe63 100644
--- a/block_int.h
+++ b/block_int.h
@@ -51,7 +51,8 @@ struct BlockDriver {
     int instance_size;
     int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
     int (*bdrv_probe_device)(const char *filename);
-    int (*bdrv_open)(BlockDriverState *bs, const char *filename, int flags);
+    int (*bdrv_open)(BlockDriverState *bs, int flags);
+    int (*bdrv_file_open)(BlockDriverState *bs, const char *filename, int flags);
     int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
                      uint8_t *buf, int nb_sectors);
     int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
@@ -155,6 +156,8 @@ struct BlockDriverState {
     int media_changed;
 
     BlockDriverState *backing_hd;
+    BlockDriverState *file;
+
     /* async read/write emulation */
 
     void *sync_aiocb;
commit 579153325158d944be544ced96c6218e7d48802a
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Apr 14 15:24:50 2010 +0200

    block: Avoid forward declaration of bdrv_open_common
    
    Move bdrv_open_common so it's defined before its callers and remove the forward
    declaration.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 6efc2b3..f9b5e53 100644
--- a/block.c
+++ b/block.c
@@ -42,9 +42,6 @@
 #include <windows.h>
 #endif
 
-static int bdrv_open_common(BlockDriverState *bs, const char *filename,
-    int flags, BlockDriver *drv);
-
 static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
         BlockDriverCompletionFunc *cb, void *opaque);
@@ -354,6 +351,77 @@ static BlockDriver *find_image_format(const char *filename)
 }
 
 /*
+ * Common part for opening disk images and files
+ */
+static int bdrv_open_common(BlockDriverState *bs, const char *filename,
+    int flags, BlockDriver *drv)
+{
+    int ret, open_flags;
+
+    assert(drv != NULL);
+
+    bs->is_temporary = 0;
+    bs->encrypted = 0;
+    bs->valid_key = 0;
+    bs->open_flags = flags;
+    /* buffer_alignment defaulted to 512, drivers can change this value */
+    bs->buffer_alignment = 512;
+
+    pstrcpy(bs->filename, sizeof(bs->filename), filename);
+
+    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
+        return -ENOTSUP;
+    }
+
+    bs->drv = drv;
+    bs->opaque = qemu_mallocz(drv->instance_size);
+
+    /*
+     * Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a
+     * write cache to the guest.  We do need the fdatasync to flush
+     * out transactions for block allocations, and we maybe have a
+     * volatile write cache in our backing device to deal with.
+     */
+    if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE))
+        bs->enable_write_cache = 1;
+
+    /*
+     * Clear flags that are internal to the block layer before opening the
+     * image.
+     */
+    open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
+
+    /*
+     * Snapshots should be writeable.
+     */
+    if (bs->is_temporary) {
+        open_flags |= BDRV_O_RDWR;
+    }
+
+    ret = drv->bdrv_open(bs, filename, open_flags);
+    if (ret < 0) {
+        goto free_and_fail;
+    }
+
+    bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR);
+    if (drv->bdrv_getlength) {
+        bs->total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
+    }
+#ifndef _WIN32
+    if (bs->is_temporary) {
+        unlink(filename);
+    }
+#endif
+    return 0;
+
+free_and_fail:
+    qemu_free(bs->opaque);
+    bs->opaque = NULL;
+    bs->drv = NULL;
+    return ret;
+}
+
+/*
  * Opens a file using a protocol (file, host_device, nbd, ...)
  */
 int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
@@ -502,77 +570,6 @@ unlink_and_fail:
     return ret;
 }
 
-/*
- * Common part for opening disk images and files
- */
-static int bdrv_open_common(BlockDriverState *bs, const char *filename,
-    int flags, BlockDriver *drv)
-{
-    int ret, open_flags;
-
-    assert(drv != NULL);
-
-    bs->is_temporary = 0;
-    bs->encrypted = 0;
-    bs->valid_key = 0;
-    bs->open_flags = flags;
-    /* buffer_alignment defaulted to 512, drivers can change this value */
-    bs->buffer_alignment = 512;
-
-    pstrcpy(bs->filename, sizeof(bs->filename), filename);
-
-    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
-        return -ENOTSUP;
-    }
-
-    bs->drv = drv;
-    bs->opaque = qemu_mallocz(drv->instance_size);
-
-    /*
-     * Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a
-     * write cache to the guest.  We do need the fdatasync to flush
-     * out transactions for block allocations, and we maybe have a
-     * volatile write cache in our backing device to deal with.
-     */
-    if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE))
-        bs->enable_write_cache = 1;
-
-    /*
-     * Clear flags that are internal to the block layer before opening the
-     * image.
-     */
-    open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
-
-    /*
-     * Snapshots should be writeable.
-     */
-    if (bs->is_temporary) {
-        open_flags |= BDRV_O_RDWR;
-    }
-
-    ret = drv->bdrv_open(bs, filename, open_flags);
-    if (ret < 0) {
-        goto free_and_fail;
-    }
-
-    bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR);
-    if (drv->bdrv_getlength) {
-        bs->total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
-    }
-#ifndef _WIN32
-    if (bs->is_temporary) {
-        unlink(filename);
-    }
-#endif
-    return 0;
-
-free_and_fail:
-    qemu_free(bs->opaque);
-    bs->opaque = NULL;
-    bs->drv = NULL;
-    return ret;
-}
-
 void bdrv_close(BlockDriverState *bs)
 {
     if (bs->drv) {
commit b6ce07aa83bdee3cfd2610f270a0ce304e78df95
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Apr 12 16:37:13 2010 +0200

    block: Split bdrv_open
    
    bdrv_open contains quite some code that is only useful for opening images (as
    opposed to opening files by a protocol), for example snapshots.
    
    This patch splits the code so that we have bdrv_open_file() for files (uses
    protocols), bdrv_open() for images (uses format drivers) and bdrv_open_common()
    for the code common for opening both images and files.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index ad681db..6efc2b3 100644
--- a/block.c
+++ b/block.c
@@ -42,6 +42,9 @@
 #include <windows.h>
 #endif
 
+static int bdrv_open_common(BlockDriverState *bs, const char *filename,
+    int flags, BlockDriver *drv);
+
 static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
         BlockDriverCompletionFunc *cb, void *opaque);
@@ -350,6 +353,9 @@ static BlockDriver *find_image_format(const char *filename)
     return drv;
 }
 
+/*
+ * Opens a file using a protocol (file, host_device, nbd, ...)
+ */
 int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
 {
     BlockDriverState *bs;
@@ -362,7 +368,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
     }
 
     bs = bdrv_new("");
-    ret = bdrv_open(bs, filename, flags, drv);
+    ret = bdrv_open_common(bs, filename, flags, drv);
     if (ret < 0) {
         bdrv_delete(bs);
         return ret;
@@ -372,19 +378,13 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
     return 0;
 }
 
+/*
+ * Opens a disk image (raw, qcow2, vmdk, ...)
+ */
 int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
               BlockDriver *drv)
 {
-    int ret, open_flags;
-    char tmp_filename[PATH_MAX];
-    char backing_filename[PATH_MAX];
-
-    bs->is_temporary = 0;
-    bs->encrypted = 0;
-    bs->valid_key = 0;
-    bs->open_flags = flags;
-    /* buffer_alignment defaulted to 512, drivers can change this value */
-    bs->buffer_alignment = 512;
+    int ret;
 
     if (flags & BDRV_O_SNAPSHOT) {
         BlockDriverState *bs1;
@@ -392,6 +392,8 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
         int is_protocol = 0;
         BlockDriver *bdrv_qcow2;
         QEMUOptionParameter *options;
+        char tmp_filename[PATH_MAX];
+        char backing_filename[PATH_MAX];
 
         /* if snapshot, we create a temporary backing file and open it
            instead of opening 'filename' directly */
@@ -439,8 +441,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
         bs->is_temporary = 1;
     }
 
-    pstrcpy(bs->filename, sizeof(bs->filename), filename);
-
+    /* Find the right image format driver */
     if (!drv) {
         drv = find_image_format(filename);
     }
@@ -449,11 +450,81 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
         ret = -ENOENT;
         goto unlink_and_fail;
     }
-    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
-        ret = -ENOTSUP;
+
+    /* Open the image */
+    ret = bdrv_open_common(bs, filename, flags, drv);
+    if (ret < 0) {
         goto unlink_and_fail;
     }
 
+    /* If there is a backing file, use it */
+    if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') {
+        char backing_filename[PATH_MAX];
+        int back_flags;
+        BlockDriver *back_drv = NULL;
+
+        bs->backing_hd = bdrv_new("");
+        path_combine(backing_filename, sizeof(backing_filename),
+                     filename, bs->backing_file);
+        if (bs->backing_format[0] != '\0')
+            back_drv = bdrv_find_format(bs->backing_format);
+
+        /* backing files always opened read-only */
+        back_flags =
+            flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
+
+        ret = bdrv_open(bs->backing_hd, backing_filename, back_flags, back_drv);
+        if (ret < 0) {
+            bdrv_close(bs);
+            return ret;
+        }
+        if (bs->is_temporary) {
+            bs->backing_hd->keep_read_only = !(flags & BDRV_O_RDWR);
+        } else {
+            /* base image inherits from "parent" */
+            bs->backing_hd->keep_read_only = bs->keep_read_only;
+        }
+    }
+
+    if (!bdrv_key_required(bs)) {
+        /* call the change callback */
+        bs->media_changed = 1;
+        if (bs->change_cb)
+            bs->change_cb(bs->change_opaque);
+    }
+
+    return 0;
+
+unlink_and_fail:
+    if (bs->is_temporary) {
+        unlink(filename);
+    }
+    return ret;
+}
+
+/*
+ * Common part for opening disk images and files
+ */
+static int bdrv_open_common(BlockDriverState *bs, const char *filename,
+    int flags, BlockDriver *drv)
+{
+    int ret, open_flags;
+
+    assert(drv != NULL);
+
+    bs->is_temporary = 0;
+    bs->encrypted = 0;
+    bs->valid_key = 0;
+    bs->open_flags = flags;
+    /* buffer_alignment defaulted to 512, drivers can change this value */
+    bs->buffer_alignment = 512;
+
+    pstrcpy(bs->filename, sizeof(bs->filename), filename);
+
+    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
+        return -ENOTSUP;
+    }
+
     bs->drv = drv;
     bs->opaque = qemu_mallocz(drv->instance_size);
 
@@ -493,46 +564,12 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
         unlink(filename);
     }
 #endif
-    if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') {
-        /* if there is a backing file, use it */
-        BlockDriver *back_drv = NULL;
-        bs->backing_hd = bdrv_new("");
-        path_combine(backing_filename, sizeof(backing_filename),
-                     filename, bs->backing_file);
-        if (bs->backing_format[0] != '\0')
-            back_drv = bdrv_find_format(bs->backing_format);
-
-        /* backing files always opened read-only */
-        open_flags &= ~BDRV_O_RDWR;
-
-        ret = bdrv_open(bs->backing_hd, backing_filename, open_flags, back_drv);
-        if (ret < 0) {
-            bdrv_close(bs);
-            return ret;
-        }
-        if (bs->is_temporary) {
-            bs->backing_hd->keep_read_only = !(flags & BDRV_O_RDWR);
-        } else {
-            /* base image inherits from "parent" */
-            bs->backing_hd->keep_read_only = bs->keep_read_only;
-        }
-    }
-
-    if (!bdrv_key_required(bs)) {
-        /* call the change callback */
-        bs->media_changed = 1;
-        if (bs->change_cb)
-            bs->change_cb(bs->change_opaque);
-    }
     return 0;
 
 free_and_fail:
     qemu_free(bs->opaque);
     bs->opaque = NULL;
     bs->drv = NULL;
-unlink_and_fail:
-    if (bs->is_temporary)
-        unlink(filename);
     return ret;
 }
 
commit 84a12e6648444f517055138a7d7f25a22d7e1029
Author: Christoph Hellwig <hch at lst.de>
Date:   Wed Apr 7 22:30:24 2010 +0200

    block: separate raw images from the file protocol
    
    We're running into various problems because the "raw" file access, which
    is used internally by the various image formats is entangled with the
    "raw" image format, which maps the VM view 1:1 to a file system.
    
    This patch renames the raw file backends to the file protocol which
    is treated like other protocols (e.g. nbd and http) and adds a new
    "raw" image format which is just a wrapper around calls to the underlying
    protocol.
    
    The patch is surprisingly simple, besides changing the probing logical
    in block.c to only look for image formats when using bdrv_open and
    renaming of the old raw protocols to file there's almost nothing in there.
    
    For creating images, a new bdrv_create_file is introduced which guesses the
    protocol to use. This allows using qemu-img create -f raw (or just using the
    default) for both files and host devices. Converting the other format drivers
    to use this function to create their images is left for later patches.
    
    The only issues still open are in the handling of the host devices.
    Firstly in current qemu we can specifiy the host* format names
    on various command line acceping images, but the new code can't
    do that without adding some translation.  Second the layering breaks
    the no_zero_init flag in the BlockDriver used by qemu-img.  I'm not
    happy how this is done per-driver instead of per-state so I'll
    prepare a separate patch to clean this up.
    
    There's some more cleanup opportunity after this patch, e.g. using
    separate lists and registration functions for image formats vs
    protocols and maybe even host drivers, but this can be done at a
    later stage.
    
    Also there's a check for protocol in bdrv_open for the BDRV_O_SNAPSHOT
    case that I don't quite understand, but which I fear won't work as
    expected - possibly even before this patch.
    
    Note that this patch requires various recent block patches from Kevin
    and me, which should all be in his block queue.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 1c7c64b..4f65bfb 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -12,7 +12,7 @@ block-obj-y += nbd.o block.o aio.o aes.o osdep.o qemu-config.o
 block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 
-block-nested-y += cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
+block-nested-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
 block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o
 block-nested-y += parallels.o nbd.o blkdebug.o
 block-nested-$(CONFIG_WIN32) += raw-win32.o
diff --git a/block.c b/block.c
index 7974215..ad681db 100644
--- a/block.c
+++ b/block.c
@@ -54,6 +54,7 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
                         uint8_t *buf, int nb_sectors);
 static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
                          const uint8_t *buf, int nb_sectors);
+static BlockDriver *find_protocol(const char *filename);
 
 static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
     QTAILQ_HEAD_INITIALIZER(bdrv_states);
@@ -203,6 +204,18 @@ int bdrv_create(BlockDriver *drv, const char* filename,
     return drv->bdrv_create(filename, options);
 }
 
+int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
+{
+    BlockDriver *drv;
+
+    drv = find_protocol(filename);
+    if (drv == NULL) {
+        drv = bdrv_find_format("file");
+    }
+
+    return bdrv_create(drv, filename, options);
+}
+
 #ifdef _WIN32
 void get_tmp_filename(char *filename, int size)
 {
@@ -246,6 +259,28 @@ int is_windows_drive(const char *filename)
 }
 #endif
 
+/*
+ * Detect host devices. By convention, /dev/cdrom[N] is always
+ * recognized as a host CDROM.
+ */
+static BlockDriver *find_hdev_driver(const char *filename)
+{
+    int score_max = 0, score;
+    BlockDriver *drv = NULL, *d;
+
+    QLIST_FOREACH(d, &bdrv_drivers, list) {
+        if (d->bdrv_probe_device) {
+            score = d->bdrv_probe_device(filename);
+            if (score > score_max) {
+                score_max = score;
+                drv = d;
+            }
+        }
+    }
+
+    return drv;
+}
+
 static BlockDriver *find_protocol(const char *filename)
 {
     BlockDriver *drv1;
@@ -256,11 +291,16 @@ static BlockDriver *find_protocol(const char *filename)
 #ifdef _WIN32
     if (is_windows_drive(filename) ||
         is_windows_drive_prefix(filename))
-        return bdrv_find_format("raw");
+        return bdrv_find_format("file");
 #endif
     p = strchr(filename, ':');
-    if (!p)
-        return bdrv_find_format("raw");
+    if (!p) {
+        drv1 = find_hdev_driver(filename);
+        if (!drv1) {
+            drv1 = bdrv_find_format("file");
+        }
+        return drv1;
+    }
     len = p - filename;
     if (len > sizeof(protocol) - 1)
         len = sizeof(protocol) - 1;
@@ -275,28 +315,6 @@ static BlockDriver *find_protocol(const char *filename)
     return NULL;
 }
 
-/*
- * Detect host devices. By convention, /dev/cdrom[N] is always
- * recognized as a host CDROM.
- */
-static BlockDriver *find_hdev_driver(const char *filename)
-{
-    int score_max = 0, score;
-    BlockDriver *drv = NULL, *d;
-
-    QLIST_FOREACH(d, &bdrv_drivers, list) {
-        if (d->bdrv_probe_device) {
-            score = d->bdrv_probe_device(filename);
-            if (score > score_max) {
-                score_max = score;
-                drv = d;
-            }
-        }
-    }
-
-    return drv;
-}
-
 static BlockDriver *find_image_format(const char *filename)
 {
     int ret, score, score_max;
@@ -319,6 +337,7 @@ static BlockDriver *find_image_format(const char *filename)
     }
 
     score_max = 0;
+    drv = NULL;
     QLIST_FOREACH(drv1, &bdrv_drivers, list) {
         if (drv1->bdrv_probe) {
             score = drv1->bdrv_probe(buf, ret, filename);
@@ -423,10 +442,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
     pstrcpy(bs->filename, sizeof(bs->filename), filename);
 
     if (!drv) {
-        drv = find_hdev_driver(filename);
-        if (!drv) {
-            drv = find_image_format(filename);
-        }
+        drv = find_image_format(filename);
     }
 
     if (!drv) {
diff --git a/block.h b/block.h
index 05ad572..f58edf1 100644
--- a/block.h
+++ b/block.h
@@ -57,6 +57,7 @@ BlockDriver *bdrv_find_format(const char *format_name);
 BlockDriver *bdrv_find_whitelisted_format(const char *format_name);
 int bdrv_create(BlockDriver *drv, const char* filename,
     QEMUOptionParameter *options);
+int bdrv_create_file(const char* filename, QEMUOptionParameter *options);
 BlockDriverState *bdrv_new(const char *device_name);
 void bdrv_delete(BlockDriverState *bs);
 int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 4cda9c1..8f57ab0 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -768,8 +768,9 @@ static QEMUOptionParameter raw_create_options[] = {
     { NULL }
 };
 
-static BlockDriver bdrv_raw = {
-    .format_name = "raw",
+static BlockDriver bdrv_file = {
+    .format_name = "file",
+    .protocol_name = "file",
     .instance_size = sizeof(BDRVRawState),
     .bdrv_probe = NULL, /* no probe for protocols */
     .bdrv_open = raw_open,
@@ -1026,6 +1027,7 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options)
 
 static BlockDriver bdrv_host_device = {
     .format_name        = "host_device",
+    .protocol_name        = "host_device",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device  = hdev_probe_device,
     .bdrv_open          = hdev_open,
@@ -1140,6 +1142,7 @@ static int floppy_eject(BlockDriverState *bs, int eject_flag)
 
 static BlockDriver bdrv_host_floppy = {
     .format_name        = "host_floppy",
+    .protocol_name      = "host_floppy",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device	= floppy_probe_device,
     .bdrv_open          = floppy_open,
@@ -1239,6 +1242,7 @@ static int cdrom_set_locked(BlockDriverState *bs, int locked)
 
 static BlockDriver bdrv_host_cdrom = {
     .format_name        = "host_cdrom",
+    .protocol_name      = "host_cdrom",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device	= cdrom_probe_device,
     .bdrv_open          = cdrom_open,
@@ -1361,6 +1365,7 @@ static int cdrom_set_locked(BlockDriverState *bs, int locked)
 
 static BlockDriver bdrv_host_cdrom = {
     .format_name        = "host_cdrom",
+    .protocol_name      = "host_cdrom",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device	= cdrom_probe_device,
     .bdrv_open          = cdrom_open,
@@ -1385,13 +1390,13 @@ static BlockDriver bdrv_host_cdrom = {
 };
 #endif /* __FreeBSD__ */
 
-static void bdrv_raw_init(void)
+static void bdrv_file_init(void)
 {
     /*
      * Register all the drivers.  Note that order is important, the driver
      * registered last will get probed first.
      */
-    bdrv_register(&bdrv_raw);
+    bdrv_register(&bdrv_file);
     bdrv_register(&bdrv_host_device);
 #ifdef __linux__
     bdrv_register(&bdrv_host_floppy);
@@ -1402,4 +1407,4 @@ static void bdrv_raw_init(void)
 #endif
 }
 
-block_init(bdrv_raw_init);
+block_init(bdrv_file_init);
diff --git a/block/raw-win32.c b/block/raw-win32.c
index 526764f..eadebeb 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -238,8 +238,9 @@ static QEMUOptionParameter raw_create_options[] = {
     { NULL }
 };
 
-static BlockDriver bdrv_raw = {
-    .format_name	= "raw",
+static BlockDriver bdrv_file = {
+    .format_name	= "file",
+    .protocol_name	= "file",
     .instance_size	= sizeof(BDRVRawState),
     .bdrv_open		= raw_open,
     .bdrv_close		= raw_close,
@@ -395,6 +396,7 @@ static int raw_set_locked(BlockDriverState *bs, int locked)
 
 static BlockDriver bdrv_host_device = {
     .format_name	= "host_device",
+    .protocol_name	= "host_device",
     .instance_size	= sizeof(BDRVRawState),
     .bdrv_probe_device	= hdev_probe_device,
     .bdrv_open		= hdev_open,
@@ -406,10 +408,10 @@ static BlockDriver bdrv_host_device = {
     .bdrv_getlength	= raw_getlength,
 };
 
-static void bdrv_raw_init(void)
+static void bdrv_file_init(void)
 {
-    bdrv_register(&bdrv_raw);
+    bdrv_register(&bdrv_file);
     bdrv_register(&bdrv_host_device);
 }
 
-block_init(bdrv_raw_init);
+block_init(bdrv_file_init);
diff --git a/block/raw.c b/block/raw.c
new file mode 100644
index 0000000..953e285
--- /dev/null
+++ b/block/raw.c
@@ -0,0 +1,171 @@
+
+#include "qemu-common.h"
+#include "block_int.h"
+#include "module.h"
+
+typedef struct RAWState {
+    BlockDriverState *hd;
+} RAWState;
+
+static int raw_open(BlockDriverState *bs, const char *filename, int flags)
+{
+    RAWState *s = bs->opaque;
+    int ret;
+
+    ret = bdrv_file_open(&s->hd, filename, flags);
+    if (!ret) {
+        bs->sg = s->hd->sg;
+    }
+
+    return ret;
+}
+
+static int raw_read(BlockDriverState *bs, int64_t sector_num,
+                    uint8_t *buf, int nb_sectors)
+{
+    RAWState *s = bs->opaque;
+    return bdrv_read(s->hd, sector_num, buf, nb_sectors);
+}
+
+static int raw_write(BlockDriverState *bs, int64_t sector_num,
+                     const uint8_t *buf, int nb_sectors)
+{
+    RAWState *s = bs->opaque;
+    return bdrv_write(s->hd, sector_num, buf, nb_sectors);
+}
+
+static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
+    int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+    BlockDriverCompletionFunc *cb, void *opaque)
+{
+    RAWState *s = bs->opaque;
+
+    return bdrv_aio_readv(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
+}
+
+static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
+    int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+    BlockDriverCompletionFunc *cb, void *opaque)
+{
+    RAWState *s = bs->opaque;
+
+    return bdrv_aio_writev(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
+}
+
+static void raw_close(BlockDriverState *bs)
+{
+    RAWState *s = bs->opaque;
+    bdrv_delete(s->hd);
+}
+
+static void raw_flush(BlockDriverState *bs)
+{
+    RAWState *s = bs->opaque;
+    bdrv_flush(s->hd);
+}
+
+static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
+    BlockDriverCompletionFunc *cb, void *opaque)
+{
+    RAWState *s = bs->opaque;
+    return bdrv_aio_flush(s->hd, cb, opaque);
+}
+
+static int64_t raw_getlength(BlockDriverState *bs)
+{
+    RAWState *s = bs->opaque;
+    return bdrv_getlength(s->hd);
+}
+
+static int raw_truncate(BlockDriverState *bs, int64_t offset)
+{
+    RAWState *s = bs->opaque;
+    return bdrv_truncate(s->hd, offset);
+}
+
+static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
+{
+   return 1; /* everything can be opened as raw image */
+}
+
+static int raw_is_inserted(BlockDriverState *bs)
+{
+    RAWState *s = bs->opaque;
+    return bdrv_is_inserted(s->hd);
+}
+
+static int raw_eject(BlockDriverState *bs, int eject_flag)
+{
+    RAWState *s = bs->opaque;
+    return bdrv_eject(s->hd, eject_flag);
+}
+
+static int raw_set_locked(BlockDriverState *bs, int locked)
+{
+    RAWState *s = bs->opaque;
+    bdrv_set_locked(s->hd, locked);
+    return 0;
+}
+
+static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
+{
+   RAWState *s = bs->opaque;
+   return bdrv_ioctl(s->hd, req, buf);
+}
+
+static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
+        unsigned long int req, void *buf,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+   RAWState *s = bs->opaque;
+   return bdrv_aio_ioctl(s->hd, req, buf, cb, opaque);
+}
+
+static int raw_create(const char *filename, QEMUOptionParameter *options)
+{
+    return bdrv_create_file(filename, options);
+}
+
+static QEMUOptionParameter raw_create_options[] = {
+    {
+        .name = BLOCK_OPT_SIZE,
+        .type = OPT_SIZE,
+        .help = "Virtual disk size"
+    },
+    { NULL }
+};
+
+static BlockDriver bdrv_raw = {
+    .format_name        = "raw",
+
+    .instance_size      = sizeof(RAWState),
+
+    .bdrv_open          = raw_open,
+    .bdrv_close         = raw_close,
+    .bdrv_read          = raw_read,
+    .bdrv_write         = raw_write,
+    .bdrv_flush         = raw_flush,
+    .bdrv_probe         = raw_probe,
+    .bdrv_getlength     = raw_getlength,
+    .bdrv_truncate      = raw_truncate,
+
+    .bdrv_aio_readv     = raw_aio_readv,
+    .bdrv_aio_writev    = raw_aio_writev,
+    .bdrv_aio_flush     = raw_aio_flush,
+
+    .bdrv_is_inserted   = raw_is_inserted,
+    .bdrv_eject         = raw_eject,
+    .bdrv_set_locked    = raw_set_locked,
+    .bdrv_ioctl         = raw_ioctl,
+    .bdrv_aio_ioctl     = raw_aio_ioctl,
+
+    .bdrv_create        = raw_create,
+    .create_options     = raw_create_options,
+};
+
+static void bdrv_raw_init(void)
+{
+    bdrv_register(&bdrv_raw);
+}
+
+block_init(bdrv_raw_init);
commit ace22f6917849de28d8ba96b7426a0ea64f95369
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun May 2 18:38:10 2010 +0000

    Fix missing '|' in '|=', spotted by clang analyzer
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index 3360808..9f09ef4 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -197,10 +197,10 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
     case 0xd18: case 0xd1c: case 0xd20: /* System Handler Priority.  */
         irq = offset - 0xd14;
         val = 0;
-        val = s->gic.priority1[irq++][0];
-        val = s->gic.priority1[irq++][0] << 8;
-        val = s->gic.priority1[irq++][0] << 16;
-        val = s->gic.priority1[irq][0] << 24;
+        val |= s->gic.priority1[irq++][0];
+        val |= s->gic.priority1[irq++][0] << 8;
+        val |= s->gic.priority1[irq++][0] << 16;
+        val |= s->gic.priority1[irq][0] << 24;
         return val;
     case 0xd24: /* System Handler Status.  */
         val = 0;
commit f75ca1ae205f24dae296c82d534c37746f87232f
Author: Thomas Monjalon <thomas at monjalon.net>
Date:   Wed Apr 28 14:42:01 2010 +0200

    fix old typos in help header
    
    1) Qemu is not only a PC emulator.
    2) "image image" has already been changed to "disk image" in qemu-doc.texi
    
    Signed-off-by: Thomas Monjalon <thomas at monjalon.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/vl.c b/vl.c
index a485c58..5e03b72 100644
--- a/vl.c
+++ b/vl.c
@@ -2001,7 +2001,7 @@ static void main_loop(void)
 
 static void version(void)
 {
-    printf("QEMU PC emulator version " QEMU_VERSION QEMU_PKGVERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n");
+    printf("QEMU emulator version " QEMU_VERSION QEMU_PKGVERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n");
 }
 
 static void help(int exitcode)
@@ -2018,7 +2018,7 @@ static void help(int exitcode)
     version();
     printf("usage: %s [options] [disk_image]\n"
            "\n"
-           "'disk_image' is a raw hard image image for IDE hard disk 0\n"
+           "'disk_image' is a raw hard disk image for IDE hard disk 0\n"
            "\n"
            "%s\n"
            "During emulation, the following keys are useful:\n"
commit 4d0e4ac703745e366d15ea5e174ae5e25c384461
Author: Stuart Brady <sdb at zubnet.me.uk>
Date:   Tue Apr 27 22:23:35 2010 +0100

    Clean up definition of MAX_OPC_PARAM
    
    MAX_OPC_PARAM is intended to refer to the maximum number of entries used
    in gen_opparam_buf[] for any single helper call.  It is currently defined
    as 10, but for 32-bit archs, the correct value (with a maximum for four
    helper arguments) is 14, and for 64-bit archs, only 9 entries are needed.
    
    tcg_gen_callN() fills four entries with the function address, flags,
    number of args, etc. and on 32-bit archs uses a further two entries per
    argument (with a maximum of four helper arguments), plus two more for the
    return value.  On 64-bit archs, only half as many entries are used for the
    args and the return value.
    
    In reality, TBs tend not to consist purely of helper calls exceeding the
    stated 10 gen_opparam_buf[] entries, so this would never actually be a
    problem on 32-bit archs, but the definition is still rather confusing.
    
    Signed-off-by: Stuart Brady <sdb at zubnet.me.uk>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/exec-all.h b/exec-all.h
index 4bae1e2..1016de2 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -44,8 +44,20 @@ typedef struct TranslationBlock TranslationBlock;
 
 /* XXX: make safe guess about sizes */
 #define MAX_OP_PER_INSTR 96
-/* A Call op needs up to 6 + 2N parameters (N = number of arguments).  */
-#define MAX_OPC_PARAM 10
+
+#if HOST_LONG_BITS == 32
+#define MAX_OPC_PARAM_PER_ARG 2
+#else
+#define MAX_OPC_PARAM_PER_ARG 1
+#endif
+#define MAX_OPC_PARAM_IARGS 4
+#define MAX_OPC_PARAM_OARGS 1
+#define MAX_OPC_PARAM_ARGS (MAX_OPC_PARAM_IARGS + MAX_OPC_PARAM_OARGS)
+
+/* A Call op needs up to 4 + 2N parameters on 32-bit archs,
+ * and up to 4 + N parameters on 64-bit archs
+ * (N = number of input arguments + output arguments).  */
+#define MAX_OPC_PARAM (4 + (MAX_OPC_PARAM_PER_ARG * MAX_OPC_PARAM_ARGS))
 #define OPC_BUF_SIZE 640
 #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
 
commit 50a480946b980c2000fc3b13bda174d57b45fbdd
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date:   Fri Apr 23 01:54:50 2010 +0400

    cmd646: fix abort due to changed opaque pointer for ioport read
    
    We cannot install different opaque pointer for read and write
    of the same i/o address.
    
    - handle zero address in bmdma_writeb_common and install
      the same opaque pointer for both read and write access.
    
    Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index c6ed0b7..cdcc9bf 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -123,6 +123,9 @@ static void bmdma_writeb_common(PCIIDEState *pci_dev, BMDMAState *bm,
     printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val);
 #endif
     switch(addr & 3) {
+    case 0:
+        bmdma_cmd_writeb(bm, addr, val);
+        break;
     case 1:
         pci_dev->dev.config[MRDMODE] =
             (pci_dev->dev.config[MRDMODE] & ~0x30) | (val & 0x30);
@@ -168,13 +171,11 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
         bm->bus = d->bus+i;
         qemu_add_vm_change_state_handler(ide_dma_restart_cb, bm);
 
-        register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm);
-
         if (i == 0) {
-            register_ioport_write(addr + 1, 3, 1, bmdma_writeb_0, d);
+            register_ioport_write(addr, 4, 1, bmdma_writeb_0, d);
             register_ioport_read(addr, 4, 1, bmdma_readb_0, d);
         } else {
-            register_ioport_write(addr + 1, 3, 1, bmdma_writeb_1, d);
+            register_ioport_write(addr, 4, 1, bmdma_writeb_1, d);
             register_ioport_read(addr, 4, 1, bmdma_readb_1, d);
         }
 
commit 70ae65f5d91462e1905a53236179fde21cda3a2f
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date:   Fri Apr 23 01:54:45 2010 +0400

    cmd646: pass pci_dev as it needs it
    
    Instead of doing tricks to get the pci_dev, just pass it in the 1st
    place.  Patch is a bit longer that reverting the pci_dev field, but it
    states more clearly (IMHO) what we are doing.
    
    It also fixes the bm test, now that you told me that ->unit is not
    always valid.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 0875de4..c6ed0b7 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -68,15 +68,9 @@ static void ide_map(PCIDevice *pci_dev, int region_num,
     }
 }
 
-static PCIIDEState *pci_from_bm(BMDMAState *bm)
+static uint32_t bmdma_readb_common(PCIIDEState *pci_dev, BMDMAState *bm,
+                                   uint32_t addr)
 {
-    return bm->pci_dev;
-}
-
-static uint32_t bmdma_readb(void *opaque, uint32_t addr)
-{
-    BMDMAState *bm = opaque;
-    PCIIDEState *pci_dev = pci_from_bm(bm);
     uint32_t val;
 
     switch(addr & 3) {
@@ -90,7 +84,7 @@ static uint32_t bmdma_readb(void *opaque, uint32_t addr)
         val = bm->status;
         break;
     case 3:
-        if (bm->unit == 0) {
+        if (bm == &pci_dev->bmdma[0]) {
             val = pci_dev->dev.config[UDIDETCR0];
         } else {
             val = pci_dev->dev.config[UDIDETCR1];
@@ -106,10 +100,25 @@ static uint32_t bmdma_readb(void *opaque, uint32_t addr)
     return val;
 }
 
-static void bmdma_writeb(void *opaque, uint32_t addr, uint32_t val)
+static uint32_t bmdma_readb_0(void *opaque, uint32_t addr)
+{
+    PCIIDEState *pci_dev = opaque;
+    BMDMAState *bm = &pci_dev->bmdma[0];
+
+    return bmdma_readb_common(pci_dev, bm, addr);
+}
+
+static uint32_t bmdma_readb_1(void *opaque, uint32_t addr)
+{
+    PCIIDEState *pci_dev = opaque;
+    BMDMAState *bm = &pci_dev->bmdma[1];
+
+    return bmdma_readb_common(pci_dev, bm, addr);
+}
+
+static void bmdma_writeb_common(PCIIDEState *pci_dev, BMDMAState *bm,
+                                uint32_t addr, uint32_t val)
 {
-    BMDMAState *bm = opaque;
-    PCIIDEState *pci_dev = pci_from_bm(bm);
 #ifdef DEBUG_IDE
     printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val);
 #endif
@@ -123,7 +132,7 @@ static void bmdma_writeb(void *opaque, uint32_t addr, uint32_t val)
         bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06);
         break;
     case 3:
-        if (bm->unit == 0)
+        if (bm == &pci_dev->bmdma[0])
             pci_dev->dev.config[UDIDETCR0] = val;
         else
             pci_dev->dev.config[UDIDETCR1] = val;
@@ -131,6 +140,22 @@ static void bmdma_writeb(void *opaque, uint32_t addr, uint32_t val)
     }
 }
 
+static void bmdma_writeb_0(void *opaque, uint32_t addr, uint32_t val)
+{
+    PCIIDEState *pci_dev = opaque;
+    BMDMAState *bm = &pci_dev->bmdma[0];
+
+    bmdma_writeb_common(pci_dev, bm, addr, val);
+}
+
+static void bmdma_writeb_1(void *opaque, uint32_t addr, uint32_t val)
+{
+    PCIIDEState *pci_dev = opaque;
+    BMDMAState *bm = &pci_dev->bmdma[1];
+
+    bmdma_writeb_common(pci_dev, bm, addr, val);
+}
+
 static void bmdma_map(PCIDevice *pci_dev, int region_num,
                     pcibus_t addr, pcibus_t size, int type)
 {
@@ -141,13 +166,17 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
         BMDMAState *bm = &d->bmdma[i];
         d->bus[i].bmdma = bm;
         bm->bus = d->bus+i;
-        bm->pci_dev = d;
         qemu_add_vm_change_state_handler(ide_dma_restart_cb, bm);
 
         register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm);
 
-        register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm);
-        register_ioport_read(addr, 4, 1, bmdma_readb, bm);
+        if (i == 0) {
+            register_ioport_write(addr + 1, 3, 1, bmdma_writeb_0, d);
+            register_ioport_read(addr, 4, 1, bmdma_readb_0, d);
+        } else {
+            register_ioport_write(addr + 1, 3, 1, bmdma_writeb_1, d);
+            register_ioport_read(addr, 4, 1, bmdma_readb_1, d);
+        }
 
         register_ioport_write(addr + 4, 4, 1, bmdma_addr_writeb, bm);
         register_ioport_read(addr + 4, 4, 1, bmdma_addr_readb, bm);
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 027029e..2efc784 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -483,7 +483,6 @@ struct BMDMAState {
     uint8_t status;
     uint32_t addr;
 
-    struct PCIIDEState *pci_dev;
     IDEBus *bus;
     /* current transfer state */
     uint32_t cur_addr;
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 295a93d..4fa3851 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -78,7 +78,6 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
         BMDMAState *bm = &d->bmdma[i];
         d->bus[i].bmdma = bm;
         bm->bus = d->bus+i;
-        bm->pci_dev = d;
         qemu_add_vm_change_state_handler(ide_dma_restart_cb, bm);
 
         register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm);
commit 8369e01ce418edb26a6e1f65406cac650563b3da
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Fri Apr 23 14:04:14 2010 -0300

    kvm: port qemu-kvm's bitmap scanning
    
    Which is significantly faster.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 9c8aa7d..6962b2b 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -26,6 +26,7 @@
 #include "hw/hw.h"
 #include "gdbstub.h"
 #include "kvm.h"
+#include "bswap.h"
 
 /* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */
 #define PAGE_SIZE TARGET_PAGE_SIZE
@@ -283,11 +284,41 @@ static int kvm_set_migration_log(int enable)
     return 0;
 }
 
-static int test_le_bit(unsigned long nr, unsigned char *addr)
+/* get kvm's dirty pages bitmap and update qemu's */
+static int kvm_get_dirty_pages_log_range(unsigned long start_addr,
+                                         unsigned long *bitmap,
+                                         unsigned long offset,
+                                         unsigned long mem_size)
 {
-    return (addr[nr >> 3] >> (nr & 7)) & 1;
+    unsigned int i, j;
+    unsigned long page_number, addr, addr1, c;
+    ram_addr_t ram_addr;
+    unsigned int len = ((mem_size / TARGET_PAGE_SIZE) + HOST_LONG_BITS - 1) /
+        HOST_LONG_BITS;
+
+    /*
+     * bitmap-traveling is faster than memory-traveling (for addr...)
+     * especially when most of the memory is not dirty.
+     */
+    for (i = 0; i < len; i++) {
+        if (bitmap[i] != 0) {
+            c = leul_to_cpu(bitmap[i]);
+            do {
+                j = ffsl(c) - 1;
+                c &= ~(1ul << j);
+                page_number = i * HOST_LONG_BITS + j;
+                addr1 = page_number * TARGET_PAGE_SIZE;
+                addr = offset + addr1;
+                ram_addr = cpu_get_physical_page_desc(addr);
+                cpu_physical_memory_set_dirty(ram_addr);
+            } while (c != 0);
+        }
+    }
+    return 0;
 }
 
+#define ALIGN(x, y)  (((x)+(y)-1) & ~((y)-1))
+
 /**
  * kvm_physical_sync_dirty_bitmap - Grab dirty bitmap from kernel space
  * This function updates qemu's dirty bitmap using cpu_physical_memory_set_dirty().
@@ -301,8 +332,6 @@ static int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
 {
     KVMState *s = kvm_state;
     unsigned long size, allocated_size = 0;
-    target_phys_addr_t phys_addr;
-    ram_addr_t addr;
     KVMDirtyLog d;
     KVMSlot *mem;
     int ret = 0;
@@ -314,7 +343,7 @@ static int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
             break;
         }
 
-        size = ((mem->memory_size >> TARGET_PAGE_BITS) + 7) / 8;
+        size = ALIGN(((mem->memory_size) >> TARGET_PAGE_BITS), HOST_LONG_BITS) / 8;
         if (!d.dirty_bitmap) {
             d.dirty_bitmap = qemu_malloc(size);
         } else if (size > allocated_size) {
@@ -331,17 +360,9 @@ static int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
             break;
         }
 
-        for (phys_addr = mem->start_addr, addr = mem->phys_offset;
-             phys_addr < mem->start_addr + mem->memory_size;
-             phys_addr += TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
-            unsigned char *bitmap = (unsigned char *)d.dirty_bitmap;
-            unsigned nr = (phys_addr - mem->start_addr) >> TARGET_PAGE_BITS;
-
-            if (test_le_bit(nr, bitmap)) {
-                cpu_physical_memory_set_dirty(addr);
-            }
-        }
-        start_addr = phys_addr;
+        kvm_get_dirty_pages_log_range(mem->start_addr, d.dirty_bitmap,
+                                      mem->start_addr, mem->memory_size);
+        start_addr = mem->start_addr + mem->memory_size;
     }
     qemu_free(d.dirty_bitmap);
 
commit 213acd2ec24f86cdbfe3391c8776987fd6d5e373
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Fri Apr 23 14:04:13 2010 -0300

    introduce leul_to_cpu
    
    To be used by next patch.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/bswap.h b/bswap.h
index aace9b7..956f3fa 100644
--- a/bswap.h
+++ b/bswap.h
@@ -205,8 +205,10 @@ static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
 
 #ifdef HOST_WORDS_BIGENDIAN
 #define cpu_to_32wu cpu_to_be32wu
+#define leul_to_cpu(v) le ## HOST_LONG_BITS ## _to_cpu(v)
 #else
 #define cpu_to_32wu cpu_to_le32wu
+#define leul_to_cpu(v) (v)
 #endif
 
 #undef le_bswap
commit cce83b7d625d71b8708c869403d1b8781af6f9b4
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Fri Apr 23 14:04:11 2010 -0300

    vga: fix typo in length passed to kvm_log_stop
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/hw/vga.c b/hw/vga.c
index 845dbcc..db72115 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1618,8 +1618,8 @@ void vga_dirty_log_stop(VGACommonState *s)
 	kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
 
     if (kvm_enabled() && s->lfb_vram_mapped) {
-	kvm_log_stop(isa_mem_base + 0xa0000, 0x80000);
-	kvm_log_stop(isa_mem_base + 0xa8000, 0x80000);
+	kvm_log_stop(isa_mem_base + 0xa0000, 0x8000);
+	kvm_log_stop(isa_mem_base + 0xa8000, 0x8000);
     }
 
 #ifdef CONFIG_BOCHS_VBE
commit 9ed7b059ef776a3921cfd085e891f45076922542
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:04:11 2010 +0530

    virtio-serial: Implement flow control for individual ports
    
    Individual ports can now signal to the virtio-serial core to stop
    sending data if the ports cannot immediately handle new data.  When a
    port later unthrottles, any data queued up in the virtqueue are sent to
    the port.
    
    Disable throttling once a port is closed (and we discard all the
    unconsumed buffers in the vq).
    
    The guest kernel can reclaim the buffers when it receives the port close
    event or when a port is being removed. Ensure we free up the buffers
    before we send out any events to the guest.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 8d07152..97694d5 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -111,14 +111,14 @@ static size_t write_to_port(VirtIOSerialPort *port,
     return offset;
 }
 
-static void flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
-                              VirtIODevice *vdev, bool discard)
+static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
+                                 VirtIODevice *vdev, bool discard)
 {
     VirtQueueElement elem;
 
     assert(port || discard);
 
-    while (virtqueue_pop(vq, &elem)) {
+    while ((discard || !port->throttled) && virtqueue_pop(vq, &elem)) {
         uint8_t *buf;
         size_t ret, buf_size;
 
@@ -135,6 +135,13 @@ static void flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
     virtio_notify(vdev, vq);
 }
 
+static void flush_queued_data(VirtIOSerialPort *port, bool discard)
+{
+    assert(port || discard);
+
+    do_flush_queued_data(port, port->ovq, &port->vser->vdev, discard);
+}
+
 static size_t send_control_msg(VirtIOSerialPort *port, void *buf, size_t len)
 {
     VirtQueueElement elem;
@@ -186,6 +193,13 @@ int virtio_serial_open(VirtIOSerialPort *port)
 int virtio_serial_close(VirtIOSerialPort *port)
 {
     port->host_connected = false;
+    /*
+     * If there's any data the guest sent which the app didn't
+     * consume, reset the throttling flag and discard the data.
+     */
+    port->throttled = false;
+    flush_queued_data(port, true);
+
     send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
 
     return 0;
@@ -227,6 +241,20 @@ size_t virtio_serial_guest_ready(VirtIOSerialPort *port)
     return 0;
 }
 
+void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle)
+{
+    if (!port) {
+        return;
+    }
+
+    port->throttled = throttle;
+    if (throttle) {
+        return;
+    }
+
+    flush_queued_data(port, false);
+}
+
 /* Guest wants to notify us of some event */
 static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
 {
@@ -380,7 +408,11 @@ static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
         discard = true;
     }
 
-    flush_queued_data(port, vq, vdev, discard);
+    if (!discard && port->throttled) {
+        return;
+    }
+
+    do_flush_queued_data(port, vq, vdev, discard);
 }
 
 static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
@@ -555,6 +587,8 @@ static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
                    indent, "", port->guest_connected);
     monitor_printf(mon, "%*s dev-prop-int: host_connected: %d\n",
                    indent, "", port->host_connected);
+    monitor_printf(mon, "%*s dev-prop-int: throttled: %d\n",
+                   indent, "", port->throttled);
 }
 
 /* This function is only used if a port id is not provided by the user */
@@ -592,13 +626,17 @@ static void add_port(VirtIOSerial *vser, uint32_t port_id)
 
 static void remove_port(VirtIOSerial *vser, uint32_t port_id)
 {
+    VirtIOSerialPort *port;
     unsigned int i;
 
     i = port_id / 32;
     vser->ports_map[i] &= ~(1U << (port_id % 32));
 
-    send_control_event(find_port_by_id(vser, port_id),
-                       VIRTIO_CONSOLE_PORT_REMOVE, 1);
+    port = find_port_by_id(vser, port_id);
+    /* Flush out any unconsumed buffers first */
+    flush_queued_data(port, true);
+
+    send_control_event(port, VIRTIO_CONSOLE_PORT_REMOVE, 1);
 }
 
 static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index 62d76a2..a93b545 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -110,6 +110,8 @@ struct VirtIOSerialPort {
     bool guest_connected;
     /* Is this device open for IO on the host? */
     bool host_connected;
+    /* Do apps not want to receive data? */
+    bool throttled;
 };
 
 struct VirtIOSerialPortInfo {
@@ -173,4 +175,11 @@ ssize_t virtio_serial_write(VirtIOSerialPort *port, const uint8_t *buf,
  */
 size_t virtio_serial_guest_ready(VirtIOSerialPort *port);
 
+/*
+ * Flow control: Ports can signal to the virtio-serial core to stop
+ * sending data or re-start sending data, depending on the 'throttle'
+ * value here.
+ */
+void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle);
+
 #endif
commit a69c76008597ccdffae7a933686ab856ca85e87c
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:04:10 2010 +0530

    virtio-serial: Discard data that guest sends us when ports aren't connected
    
    Before the earlier patch, we relied on incorrect virtio api usage to
    signal to the guest that a particular buffer wasn't consumed by the
    host.
    
    After fixing that, we now just discard the data the guest sends us while
    a host port is disconnected or doesn't have a handler registered for
    consuming data.
    
    This commit really doesn't change anything from the current behaviour,
    just makes the code slightly better by spinning off data handling to
    ports in another function.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index ad44127..8d07152 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -111,6 +111,30 @@ static size_t write_to_port(VirtIOSerialPort *port,
     return offset;
 }
 
+static void flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
+                              VirtIODevice *vdev, bool discard)
+{
+    VirtQueueElement elem;
+
+    assert(port || discard);
+
+    while (virtqueue_pop(vq, &elem)) {
+        uint8_t *buf;
+        size_t ret, buf_size;
+
+        if (!discard) {
+            buf_size = iov_size(elem.out_sg, elem.out_num);
+            buf = qemu_malloc(buf_size);
+            ret = iov_to_buf(elem.out_sg, elem.out_num, buf, 0, buf_size);
+
+            port->info->have_data(port, buf, ret);
+            qemu_free(buf);
+        }
+        virtqueue_push(vq, &elem, 0);
+    }
+    virtio_notify(vdev, vq);
+}
+
 static size_t send_control_msg(VirtIOSerialPort *port, void *buf, size_t len)
 {
     VirtQueueElement elem;
@@ -345,47 +369,18 @@ static void control_out(VirtIODevice *vdev, VirtQueue *vq)
 static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
 {
     VirtIOSerial *vser;
-    VirtQueueElement elem;
+    VirtIOSerialPort *port;
+    bool discard;
 
     vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
+    port = find_port_by_vq(vser, vq);
 
-    while (virtqueue_pop(vq, &elem)) {
-        VirtIOSerialPort *port;
-        uint8_t *buf;
-        size_t ret, buf_size;
-
-        port = find_port_by_vq(vser, vq);
-        if (!port) {
-            ret = 0;
-            goto next_buf;
-        }
-
-	if (!port->host_connected) {
-            ret = 0;
-            goto next_buf;
-        }
-
-        /*
-         * A port may not have any handler registered for consuming the
-         * data that the guest sends or it may not have a chardev associated
-         * with it. Just ignore the data in that case.
-         */
-        if (!port->info->have_data) {
-            ret = 0;
-            goto next_buf;
-        }
-
-        buf_size = iov_size(elem.out_sg, elem.out_num);
-        buf = qemu_malloc(buf_size);
-        ret = iov_to_buf(elem.out_sg, elem.out_num, buf, 0, buf_size);
-
-        port->info->have_data(port, buf, ret);
-        qemu_free(buf);
-
-    next_buf:
-        virtqueue_push(vq, &elem, 0);
+    discard = false;
+    if (!port || !port->host_connected || !port->info->have_data) {
+        discard = true;
     }
-    virtio_notify(vdev, vq);
+
+    flush_queued_data(port, vq, vdev, discard);
 }
 
 static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
commit 1e4476aa03b70e78b0dbc21cebd6e9f9c6835067
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:04:09 2010 +0530

    virtio-serial: Apps should consume all data that guest sends out / Fix virtio api abuse
    
    We cannot indicate to the guest how much data was consumed by an app for
    out_bufs.  So we just have to assume the apps will consume all the data
    that are handed over to them.
    
    Fix the virtio api abuse in control_out() and handle_output().
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index bbbb6b8..caea11f 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -20,14 +20,11 @@ typedef struct VirtConsole {
 
 
 /* Callback function that's called when the guest sends us data */
-static size_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
+static void flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
 {
     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
-    ssize_t ret;
 
-    ret = qemu_chr_write(vcon->chr, buf, len);
-
-    return ret < 0 ? 0 : ret;
+    qemu_chr_write(vcon->chr, buf, len);
 }
 
 /* Readiness of the guest to accept data on a port */
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 3053a35..ad44127 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -335,7 +335,7 @@ static void control_out(VirtIODevice *vdev, VirtQueue *vq)
         copied = iov_to_buf(elem.out_sg, elem.out_num, buf, 0, len);
 
         handle_control_message(vser, buf, copied);
-        virtqueue_push(vq, &elem, copied);
+        virtqueue_push(vq, &elem, 0);
     }
     qemu_free(buf);
     virtio_notify(vdev, vq);
@@ -379,11 +379,11 @@ static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
         buf = qemu_malloc(buf_size);
         ret = iov_to_buf(elem.out_sg, elem.out_num, buf, 0, buf_size);
 
-        ret = port->info->have_data(port, buf, ret);
+        port->info->have_data(port, buf, ret);
         qemu_free(buf);
 
     next_buf:
-        virtqueue_push(vq, &elem, ret);
+        virtqueue_push(vq, &elem, 0);
     }
     virtio_notify(vdev, vq);
 }
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index f023873..62d76a2 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -136,10 +136,10 @@ struct VirtIOSerialPortInfo {
 
     /*
      * Guest wrote some data to the port. This data is handed over to
-     * the app via this callback. The app should return the number of
-     * bytes it successfully consumed.
+     * the app via this callback.  The app is supposed to consume all
+     * the data that is presented to it.
      */
-    size_t (*have_data)(VirtIOSerialPort *port, const uint8_t *buf, size_t len);
+    void (*have_data)(VirtIOSerialPort *port, const uint8_t *buf, size_t len);
 };
 
 /* Interface to the virtio-serial bus */
commit e85ba9b2dce43d706e21135fc1bf21a30601c2cf
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:04:08 2010 +0530

    virtio-serial: Handle scatter/gather input from the guest
    
    Current guests don't send more than one iov but it can change later.
    Ensure we handle that case.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    CC: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index b8410c3..3053a35 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -351,7 +351,8 @@ static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
 
     while (virtqueue_pop(vq, &elem)) {
         VirtIOSerialPort *port;
-        size_t ret;
+        uint8_t *buf;
+        size_t ret, buf_size;
 
         port = find_port_by_vq(vser, vq);
         if (!port) {
@@ -374,9 +375,12 @@ static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
             goto next_buf;
         }
 
-        /* The guest always sends only one sg */
-        ret = port->info->have_data(port, elem.out_sg[0].iov_base,
-                                    elem.out_sg[0].iov_len);
+        buf_size = iov_size(elem.out_sg, elem.out_num);
+        buf = qemu_malloc(buf_size);
+        ret = iov_to_buf(elem.out_sg, elem.out_num, buf, 0, buf_size);
+
+        ret = port->info->have_data(port, buf, ret);
+        qemu_free(buf);
 
     next_buf:
         virtqueue_push(vq, &elem, ret);
commit e61da14d60ba1cceacad8396adcb9662c7f690af
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:04:07 2010 +0530

    virtio-serial: Handle scatter-gather buffers for control messages
    
    Current control messages are small enough to not be split into multiple
    buffers but we could run into such a situation in the future or a
    malicious guest could cause such a situation.
    
    So handle the entire iov request for control messages.
    
    Also ensure the size of the control request is >= what we expect
    otherwise we risk accessing memory that we don't own.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    CC: Avi Kivity <avi at redhat.com>
    Reported-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index a72b6b5..b8410c3 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -204,7 +204,7 @@ size_t virtio_serial_guest_ready(VirtIOSerialPort *port)
 }
 
 /* Guest wants to notify us of some event */
-static void handle_control_message(VirtIOSerial *vser, void *buf)
+static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
 {
     struct VirtIOSerialPort *port;
     struct virtio_console_control cpkt, *gcpkt;
@@ -213,6 +213,11 @@ static void handle_control_message(VirtIOSerial *vser, void *buf)
 
     gcpkt = buf;
 
+    if (len < sizeof(cpkt)) {
+        /* The guest sent an invalid control packet */
+        return;
+    }
+
     cpkt.event = lduw_p(&gcpkt->event);
     cpkt.value = lduw_p(&gcpkt->value);
 
@@ -306,13 +311,33 @@ static void control_out(VirtIODevice *vdev, VirtQueue *vq)
 {
     VirtQueueElement elem;
     VirtIOSerial *vser;
+    uint8_t *buf;
+    size_t len;
 
     vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
 
+    len = 0;
+    buf = NULL;
     while (virtqueue_pop(vq, &elem)) {
-        handle_control_message(vser, elem.out_sg[0].iov_base);
-        virtqueue_push(vq, &elem, elem.out_sg[0].iov_len);
+        size_t cur_len, copied;
+
+        cur_len = iov_size(elem.out_sg, elem.out_num);
+        /*
+         * Allocate a new buf only if we didn't have one previously or
+         * if the size of the buf differs
+         */
+        if (cur_len > len) {
+            qemu_free(buf);
+
+            buf = qemu_malloc(cur_len);
+            len = cur_len;
+        }
+        copied = iov_to_buf(elem.out_sg, elem.out_num, buf, 0, len);
+
+        handle_control_message(vser, buf, copied);
+        virtqueue_push(vq, &elem, copied);
     }
+    qemu_free(buf);
     virtio_notify(vdev, vq);
 }
 
commit fa6111f215736e44f0ac4fc50947e6c407588c28
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:04:06 2010 +0530

    iov: Add iov_to_buf and iov_size helpers
    
    iov_to_buf() puts the buffer contents in the iov in a linearized buffer.
    
    iov_size() gets the length of the contents in the iov.
    
    The iov_to_buf() function is the memcpy_to_iovec() function that was
    used in virtio-ballon.c.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/iov.c b/hw/iov.c
index 07bd499..588cd04 100644
--- a/hw/iov.c
+++ b/hw/iov.c
@@ -31,3 +31,40 @@ size_t iov_from_buf(struct iovec *iov, unsigned int iovcnt,
     }
     return offset;
 }
+
+size_t iov_to_buf(const struct iovec *iov, const unsigned int iovcnt,
+                  void *buf, size_t offset, size_t size)
+{
+    uint8_t *ptr;
+    size_t iov_off, buf_off;
+    unsigned int i;
+
+    ptr = buf;
+    iov_off = 0;
+    buf_off = 0;
+    for (i = 0; i < iovcnt && size; i++) {
+        if (offset < (iov_off + iov[i].iov_len)) {
+            size_t len = MIN((iov_off + iov[i].iov_len) - offset , size);
+
+            memcpy(ptr + buf_off, iov[i].iov_base + (offset - iov_off), len);
+
+            buf_off += len;
+            offset += len;
+            size -= len;
+        }
+        iov_off += iov[i].iov_len;
+    }
+    return buf_off;
+}
+
+size_t iov_size(const struct iovec *iov, const unsigned int iovcnt)
+{
+    size_t len;
+    unsigned int i;
+
+    len = 0;
+    for (i = 0; i < iovcnt; i++) {
+        len += iov[i].iov_len;
+    }
+    return len;
+}
diff --git a/hw/iov.h b/hw/iov.h
index 5e3e541..60a8547 100644
--- a/hw/iov.h
+++ b/hw/iov.h
@@ -14,3 +14,6 @@
 
 size_t iov_from_buf(struct iovec *iov, unsigned int iovcnt,
                     const void *buf, size_t size);
+size_t iov_to_buf(const struct iovec *iov, const unsigned int iovcnt,
+                  void *buf, size_t offset, size_t size);
+size_t iov_size(const struct iovec *iov, const unsigned int iovcnt);
diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index f55f7ec..152af80 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -11,6 +11,7 @@
  *
  */
 
+#include "iov.h"
 #include "qemu-common.h"
 #include "virtio.h"
 #include "pc.h"
@@ -92,33 +93,6 @@ static QObject *get_stats_qobject(VirtIOBalloon *dev)
     return QOBJECT(dict);
 }
 
-/* FIXME: once we do a virtio refactoring, this will get subsumed into common
- * code */
-static size_t memcpy_from_iovector(void *data, size_t offset, size_t size,
-                                   struct iovec *iov, int iovlen)
-{
-    int i;
-    uint8_t *ptr = data;
-    size_t iov_off = 0;
-    size_t data_off = 0;
-
-    for (i = 0; i < iovlen && size; i++) {
-        if (offset < (iov_off + iov[i].iov_len)) {
-            size_t len = MIN((iov_off + iov[i].iov_len) - offset , size);
-
-            memcpy(ptr + data_off, iov[i].iov_base + (offset - iov_off), len);
-
-            data_off += len;
-            offset += len;
-            size -= len;
-        }
-
-        iov_off += iov[i].iov_len;
-    }
-
-    return data_off;
-}
-
 static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
 {
     VirtIOBalloon *s = to_virtio_balloon(vdev);
@@ -128,8 +102,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
         size_t offset = 0;
         uint32_t pfn;
 
-        while (memcpy_from_iovector(&pfn, offset, 4,
-                                    elem.out_sg, elem.out_num) == 4) {
+        while (iov_to_buf(elem.out_sg, elem.out_num, &pfn, offset, 4) == 4) {
             ram_addr_t pa;
             ram_addr_t addr;
 
@@ -181,8 +154,8 @@ static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
      */
     reset_stats(s);
 
-    while (memcpy_from_iovector(&stat, offset, sizeof(stat), elem->out_sg,
-                                elem->out_num) == sizeof(stat)) {
+    while (iov_to_buf(elem->out_sg, elem->out_num, &stat, offset, sizeof(stat))
+           == sizeof(stat)) {
         uint16_t tag = tswap16(stat.tag);
         uint64_t val = tswap64(stat.val);
 
commit e4d5639dbb6181ebbfdb554f2594721b2d63882b
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:04:05 2010 +0530

    iov: Introduce a new file for helpers around iovs, add iov_from_buf()
    
    The virtio-net code uses iov_fill() which fills an iov from a linear
    buffer. The virtio-serial-bus code does something similar in an
    open-coded function.
    
    Create a new iov.c file that has iov_from_buf().
    
    Convert virtio-net and virtio-serial-bus over to use this functionality.
    virtio-net used ints to hold sizes, the new function is going to use
    size_t types.
    
    Later commits will add the opposite functionality -- going from an iov
    to a linear buffer.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index a404fda..18e7368 100644
--- a/Makefile
+++ b/Makefile
@@ -124,6 +124,8 @@ curses.o: curses.c keymaps.h curses_keys.h
 
 bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
 
+iov.o: iov.c iov.h
+
 ######################################################################
 
 qemu-img.o: qemu-img-cmds.h
diff --git a/Makefile.objs b/Makefile.objs
index 69d6879..1c7c64b 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -100,6 +100,7 @@ common-obj-y += keymaps.o
 common-obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o
 common-obj-$(CONFIG_CURSES) += curses.o
 common-obj-y += vnc.o acl.o d3des.o
+common-obj-y += iov.o
 common-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
 common-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
 common-obj-$(CONFIG_COCOA) += cocoa.o
diff --git a/hw/iov.c b/hw/iov.c
new file mode 100644
index 0000000..07bd499
--- /dev/null
+++ b/hw/iov.c
@@ -0,0 +1,33 @@
+/*
+ * Helpers for getting linearized buffers from iov / filling buffers into iovs
+ *
+ * Copyright IBM, Corp. 2007, 2008
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * Author(s):
+ *  Anthony Liguori <aliguori at us.ibm.com>
+ *  Amit Shah <amit.shah at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "iov.h"
+
+size_t iov_from_buf(struct iovec *iov, unsigned int iovcnt,
+                    const void *buf, size_t size)
+{
+    size_t offset;
+    unsigned int i;
+
+    offset = 0;
+    for (i = 0; offset < size && i < iovcnt; i++) {
+        size_t len;
+
+        len = MIN(iov[i].iov_len, size - offset);
+
+        memcpy(iov[i].iov_base, buf + offset, len);
+        offset += len;
+    }
+    return offset;
+}
diff --git a/hw/iov.h b/hw/iov.h
new file mode 100644
index 0000000..5e3e541
--- /dev/null
+++ b/hw/iov.h
@@ -0,0 +1,16 @@
+/*
+ * Helpers for getting linearized buffers from iov / filling buffers into iovs
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * Author(s):
+ *  Amit Shah <amit.shah at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "qemu-common.h"
+
+size_t iov_from_buf(struct iovec *iov, unsigned int iovcnt,
+                    const void *buf, size_t size);
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index acb3cec..d602c56 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -11,6 +11,7 @@
  *
  */
 
+#include "iov.h"
 #include "virtio.h"
 #include "net.h"
 #include "net/checksum.h"
@@ -445,21 +446,6 @@ static void work_around_broken_dhclient(struct virtio_net_hdr *hdr,
     }
 }
 
-static int iov_fill(struct iovec *iov, int iovcnt, const void *buf, int count)
-{
-    int offset, i;
-
-    offset = i = 0;
-    while (offset < count && i < iovcnt) {
-        int len = MIN(iov[i].iov_len, count - offset);
-        memcpy(iov[i].iov_base, buf + offset, len);
-        offset += len;
-        i++;
-    }
-
-    return offset;
-}
-
 static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt,
                           const void *buf, size_t size, size_t hdr_len)
 {
@@ -595,8 +581,8 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
         }
 
         /* copy in packet.  ugh */
-        len = iov_fill(sg, elem.in_num,
-                       buf + offset, size - offset);
+        len = iov_from_buf(sg, elem.in_num,
+                           buf + offset, size - offset);
         total += len;
 
         /* signal other side */
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 6befd4d..a72b6b5 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -15,6 +15,7 @@
  * the COPYING file in the top-level directory.
  */
 
+#include "iov.h"
 #include "monitor.h"
 #include "qemu-queue.h"
 #include "sysbus.h"
@@ -84,27 +85,25 @@ static size_t write_to_port(VirtIOSerialPort *port,
 {
     VirtQueueElement elem;
     VirtQueue *vq;
-    size_t offset = 0;
-    size_t len = 0;
+    size_t offset;
 
     vq = port->ivq;
     if (!virtio_queue_ready(vq)) {
         return 0;
     }
 
+    offset = 0;
     while (offset < size) {
-        int i;
+        size_t len;
 
         if (!virtqueue_pop(vq, &elem)) {
             break;
         }
 
-        for (i = 0; offset < size && i < elem.in_num; i++) {
-            len = MIN(elem.in_sg[i].iov_len, size - offset);
+        len = iov_from_buf(elem.in_sg, elem.in_num,
+                           buf + offset, size - offset);
+        offset += len;
 
-            memcpy(elem.in_sg[i].iov_base, buf + offset, len);
-            offset += len;
-        }
         virtqueue_push(vq, &elem, len);
     }
 
commit 3ecb45f893d09a97b8f24399b5e40808a708261f
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:04:04 2010 +0530

    virtio-serial: Send out guest data to ports only if port is opened
    
    Data should be written only when ports are open.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 3a09f0d..6befd4d 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -335,6 +335,11 @@ static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
             goto next_buf;
         }
 
+	if (!port->host_connected) {
+            ret = 0;
+            goto next_buf;
+        }
+
         /*
          * A port may not have any handler registered for consuming the
          * data that the guest sends or it may not have a chardev associated
commit 4048c7c321d3029e8c41863a9f54dc39054c57ca
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:04:03 2010 +0530

    virtio-serial: Propagate errors in initialising ports / devices in guest
    
    If adding of ports or devices in the guest fails we can send out a QMP
    event so that management software can deal with it.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index c77ea4f..3a09f0d 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -223,6 +223,11 @@ static void handle_control_message(VirtIOSerial *vser, void *buf)
 
     switch(cpkt.event) {
     case VIRTIO_CONSOLE_DEVICE_READY:
+        if (!cpkt.value) {
+            error_report("virtio-serial-bus: Guest failure in adding device %s\n",
+                         vser->bus->qbus.name);
+            break;
+        }
         /*
          * The device is up, we can now tell the device about all the
          * ports we have here.
@@ -233,6 +238,11 @@ static void handle_control_message(VirtIOSerial *vser, void *buf)
         break;
 
     case VIRTIO_CONSOLE_PORT_READY:
+        if (!cpkt.value) {
+            error_report("virtio-serial-bus: Guest failure in adding port %u for device %s\n",
+                         port->id, vser->bus->qbus.name);
+            break;
+        }
         /*
          * Now that we know the guest asked for the port name, we're
          * sure the guest has initialised whatever state is necessary
commit 71c092e92b45e7ebc762c8736089c074097548d3
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:04:02 2010 +0530

    virtio-serial: Update copyright year to 2010
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index 17b221d..bbbb6b8 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -1,7 +1,7 @@
 /*
  * Virtio Console and Generic Serial Port Devices
  *
- * Copyright Red Hat, Inc. 2009
+ * Copyright Red Hat, Inc. 2009, 2010
  *
  * Authors:
  *  Amit Shah <amit.shah at redhat.com>
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index c1d9851..c77ea4f 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -1,7 +1,7 @@
 /*
  * A bus for connecting virtio serial and console ports
  *
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright (C) 2009, 2010 Red Hat, Inc.
  *
  * Author(s):
  *  Amit Shah <amit.shah at redhat.com>
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index 0548689..f023873 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -2,7 +2,7 @@
  * Virtio Serial / Console Support
  *
  * Copyright IBM, Corp. 2008
- * Copyright Red Hat, Inc. 2009
+ * Copyright Red Hat, Inc. 2009, 2010
  *
  * Authors:
  *  Christian Ehrhardt <ehrhardt at linux.vnet.ibm.com>
commit e30f328c7429d4e891ce6da26af95c607f392739
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:04:01 2010 +0530

    virtio-serial: Remove redundant check for 0-sized write request
    
    The check for a 0-sized write request to a guest port is not necessary;
    the while loop below won't be executed in this case and all will be
    fine.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 8efba0b..c1d9851 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -91,9 +91,6 @@ static size_t write_to_port(VirtIOSerialPort *port,
     if (!virtio_queue_ready(vq)) {
         return 0;
     }
-    if (!size) {
-        return 0;
-    }
 
     while (offset < size) {
         int i;
commit 306eb457fd057b7d0185145530a98f236b1c9aa4
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:04:00 2010 +0530

    virtio-serial: whitespace: match surrounding code
    
    The virtio-serial code doesn't mix declarations and definitions, so
    separate them out on different lines.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index bb11a9b..8efba0b 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -354,7 +354,10 @@ static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
 
 static uint32_t get_features(VirtIODevice *vdev, uint32_t features)
 {
-    VirtIOSerial *vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
+    VirtIOSerial *vser;
+
+    vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
+
     if (vser->bus->max_nr_ports > 1) {
         features |= (1 << VIRTIO_CONSOLE_F_MULTIPORT);
     }
commit 055b889f942b063bd1901a316b34017f2b699b12
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:03:59 2010 +0530

    virtio-serial: Use control messages to notify guest of new ports
    
    Allow the port 'id's to be set by a user on the command line. This is
    needed by management apps that will want a stable port numbering scheme
    for hot-plug/unplug and migration.
    
    Since the port numbers are shared with the guest (to identify ports in
    control messages), we just send a control message to the guest
    indicating addition of new ports (hot-plug) or notifying the guest of
    the available ports when the guest sends us a DEVICE_READY control
    message.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index bd44ec6..17b221d 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -99,6 +99,7 @@ static VirtIOSerialPortInfo virtconsole_info = {
     .exit          = virtconsole_exitfn,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT8("is_console", VirtConsole, port.is_console, 1),
+        DEFINE_PROP_UINT32("nr", VirtConsole, port.id, VIRTIO_CONSOLE_BAD_ID),
         DEFINE_PROP_CHR("chardev", VirtConsole, chr),
         DEFINE_PROP_STRING("name", VirtConsole, port.name),
         DEFINE_PROP_END_OF_LIST(),
@@ -133,6 +134,7 @@ static VirtIOSerialPortInfo virtserialport_info = {
     .init          = virtserialport_initfn,
     .exit          = virtconsole_exitfn,
     .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("nr", VirtConsole, port.id, VIRTIO_CONSOLE_BAD_ID),
         DEFINE_PROP_CHR("chardev", VirtConsole, chr),
         DEFINE_PROP_STRING("name", VirtConsole, port.name),
         DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 484dc94..bb11a9b 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -41,6 +41,10 @@ struct VirtIOSerial {
     VirtIOSerialBus *bus;
 
     QTAILQ_HEAD(, VirtIOSerialPort) ports;
+
+    /* bitmap for identifying active ports */
+    uint32_t *ports_map;
+
     struct virtio_console_config config;
 };
 
@@ -48,6 +52,10 @@ static VirtIOSerialPort *find_port_by_id(VirtIOSerial *vser, uint32_t id)
 {
     VirtIOSerialPort *port;
 
+    if (id == VIRTIO_CONSOLE_BAD_ID) {
+        return NULL;
+    }
+
     QTAILQ_FOREACH(port, &vser->ports, next) {
         if (port->id == id)
             return port;
@@ -208,14 +216,25 @@ static void handle_control_message(VirtIOSerial *vser, void *buf)
     size_t buffer_len;
 
     gcpkt = buf;
-    port = find_port_by_id(vser, ldl_p(&gcpkt->id));
-    if (!port)
-        return;
 
     cpkt.event = lduw_p(&gcpkt->event);
     cpkt.value = lduw_p(&gcpkt->value);
 
+    port = find_port_by_id(vser, ldl_p(&gcpkt->id));
+    if (!port && cpkt.event != VIRTIO_CONSOLE_DEVICE_READY)
+        return;
+
     switch(cpkt.event) {
+    case VIRTIO_CONSOLE_DEVICE_READY:
+        /*
+         * The device is up, we can now tell the device about all the
+         * ports we have here.
+         */
+        QTAILQ_FOREACH(port, &vser->ports, next) {
+            send_control_event(port, VIRTIO_CONSOLE_PORT_ADD, 1);
+        }
+        break;
+
     case VIRTIO_CONSOLE_PORT_READY:
         /*
          * Now that we know the guest asked for the port name, we're
@@ -363,6 +382,7 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
     VirtIOSerial *s = opaque;
     VirtIOSerialPort *port;
     uint32_t nr_active_ports;
+    unsigned int i;
 
     /* The virtio device */
     virtio_save(&s->vdev, f);
@@ -370,13 +390,17 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
     /* The config space */
     qemu_put_be16s(f, &s->config.cols);
     qemu_put_be16s(f, &s->config.rows);
-    qemu_put_be32s(f, &s->config.nr_ports);
 
-    /* Items in struct VirtIOSerial */
+    qemu_put_be32s(f, &s->config.max_nr_ports);
+
+    /* The ports map */
+
+    for (i = 0; i < (s->config.max_nr_ports + 31) / 32; i++) {
+        qemu_put_be32s(f, &s->ports_map[i]);
+    }
 
-    qemu_put_be32s(f, &s->bus->max_nr_ports);
+    /* Ports */
 
-    /* Do this because we might have hot-unplugged some ports */
     nr_active_ports = 0;
     QTAILQ_FOREACH(port, &s->ports, next) {
         nr_active_ports++;
@@ -388,11 +412,6 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
      * Items in struct VirtIOSerialPort.
      */
     QTAILQ_FOREACH(port, &s->ports, next) {
-        /*
-         * We put the port number because we may not have an active
-         * port at id 0 that's reserved for a console port, or in case
-         * of ports that might have gotten unplugged
-         */
         qemu_put_be32s(f, &port->id);
         qemu_put_byte(f, port->guest_connected);
         qemu_put_byte(f, port->host_connected);
@@ -403,7 +422,8 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
 {
     VirtIOSerial *s = opaque;
     VirtIOSerialPort *port;
-    uint32_t max_nr_ports, nr_active_ports, nr_ports;
+    size_t ports_map_size;
+    uint32_t max_nr_ports, nr_active_ports, *ports_map;
     unsigned int i;
 
     if (version_id > 2) {
@@ -420,29 +440,29 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
     /* The config space */
     qemu_get_be16s(f, &s->config.cols);
     qemu_get_be16s(f, &s->config.rows);
-    nr_ports = qemu_get_be32(f);
 
-    if (nr_ports != s->config.nr_ports) {
-        /*
-         * Source hot-plugged/unplugged ports and we don't have all of
-         * them here.
-         *
-         * Note: This condition cannot check for all hotplug/unplug
-         * events: eg, if one port was hot-plugged and one was
-         * unplugged, the nr_ports remains the same but the port id's
-         * would have changed and we won't catch it here. A later
-         * check for !find_port_by_id() will confirm if this happened.
-         */
+    qemu_get_be32s(f, &max_nr_ports);
+    if (max_nr_ports > s->config.max_nr_ports) {
+        /* Source could have had more ports than us. Fail migration. */
         return -EINVAL;
     }
 
-    /* Items in struct VirtIOSerial */
+    ports_map_size = sizeof(uint32_t) * (max_nr_ports + 31) / 32;
+    ports_map = qemu_malloc(ports_map_size);
 
-    qemu_get_be32s(f, &max_nr_ports);
-    if (max_nr_ports > s->bus->max_nr_ports) {
-        /* Source could have more ports than us. Fail migration. */
-        return -EINVAL;
+    for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
+        qemu_get_be32s(f, &ports_map[i]);
+
+        if (ports_map[i] != s->ports_map[i]) {
+            /*
+             * Ports active on source and destination don't
+             * match. Fail migration.
+             */
+            qemu_free(ports_map);
+            return -EINVAL;
+        }
     }
+    qemu_free(ports_map);
 
     qemu_get_be32s(f, &nr_active_ports);
 
@@ -453,13 +473,6 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
 
         id = qemu_get_be32(f);
         port = find_port_by_id(s, id);
-        if (!port) {
-            /*
-             * The requested port was hot-plugged on the source but we
-             * don't have it
-             */
-            return -EINVAL;
-        }
 
         port->guest_connected = qemu_get_byte(f);
         host_connected = qemu_get_byte(f);
@@ -472,7 +485,6 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
                                port->host_connected);
         }
     }
-
     return 0;
 }
 
@@ -507,6 +519,50 @@ static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
                    indent, "", port->host_connected);
 }
 
+/* This function is only used if a port id is not provided by the user */
+static uint32_t find_free_port_id(VirtIOSerial *vser)
+{
+    unsigned int i;
+
+    for (i = 0; i < (vser->config.max_nr_ports + 31) / 32; i++) {
+        uint32_t map, bit;
+
+        map = vser->ports_map[i];
+        bit = ffs(~map);
+        if (bit) {
+            return (bit - 1) + i * 32;
+        }
+    }
+    return VIRTIO_CONSOLE_BAD_ID;
+}
+
+static void mark_port_added(VirtIOSerial *vser, uint32_t port_id)
+{
+    unsigned int i;
+
+    i = port_id / 32;
+    vser->ports_map[i] |= 1U << (port_id % 32);
+}
+
+static void add_port(VirtIOSerial *vser, uint32_t port_id)
+{
+    mark_port_added(vser, port_id);
+
+    send_control_event(find_port_by_id(vser, port_id),
+                       VIRTIO_CONSOLE_PORT_ADD, 1);
+}
+
+static void remove_port(VirtIOSerial *vser, uint32_t port_id)
+{
+    unsigned int i;
+
+    i = port_id / 32;
+    vser->ports_map[i] &= ~(1U << (port_id % 32));
+
+    send_control_event(find_port_by_id(vser, port_id),
+                       VIRTIO_CONSOLE_PORT_REMOVE, 1);
+}
+
 static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
 {
     VirtIOSerialDevice *dev = DO_UPCAST(VirtIOSerialDevice, qdev, qdev);
@@ -525,19 +581,36 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
      */
     plugging_port0 = port->is_console && !find_port_by_id(port->vser, 0);
 
-    if (port->vser->config.nr_ports == bus->max_nr_ports && !plugging_port0) {
-        error_report("virtio-serial-bus: Maximum device limit reached");
+    if (find_port_by_id(port->vser, port->id)) {
+        error_report("virtio-serial-bus: A port already exists at id %u\n",
+                     port->id);
         return -1;
     }
-    dev->info = info;
 
+    if (port->id == VIRTIO_CONSOLE_BAD_ID) {
+        if (plugging_port0) {
+            port->id = 0;
+        } else {
+            port->id = find_free_port_id(port->vser);
+            if (port->id == VIRTIO_CONSOLE_BAD_ID) {
+                error_report("virtio-serial-bus: Maximum port limit for this device reached\n");
+                return -1;
+            }
+        }
+    }
+
+    if (port->id >= port->vser->config.max_nr_ports) {
+        error_report("virtio-serial-bus: Out-of-range port id specified, max. allowed: %u\n",
+                     port->vser->config.max_nr_ports - 1);
+        return -1;
+    }
+
+    dev->info = info;
     ret = info->init(dev);
     if (ret) {
         return ret;
     }
 
-    port->id = plugging_port0 ? 0 : port->vser->config.nr_ports++;
-
     if (!use_multiport(port->vser)) {
         /*
          * Allow writes to guest in this case; we have no way of
@@ -550,6 +623,8 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
     port->ivq = port->vser->ivqs[port->id];
     port->ovq = port->vser->ovqs[port->id];
 
+    add_port(port->vser, port->id);
+
     /* Send an update to the guest about this new port added */
     virtio_notify_config(&port->vser->vdev);
 
@@ -562,26 +637,8 @@ static int virtser_port_qdev_exit(DeviceState *qdev)
     VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
     VirtIOSerial *vser = port->vser;
 
-    send_control_event(port, VIRTIO_CONSOLE_PORT_REMOVE, 1);
+    remove_port(port->vser, port->id);
 
-    /*
-     * Don't decrement nr_ports here; thus we keep a linearly
-     * increasing port id. Not utilising an id again saves us a couple
-     * of complications:
-     *
-     * - Not having to bother about sending the port id to the guest
-     *   kernel on hotplug or on addition of new ports; the guest can
-     *   also linearly increment the port number. This is preferable
-     *   because the config space won't have the need to store a
-     *   ports_map.
-     *
-     * - Extra state to be stored for all the "holes" that got created
-     *   so that we keep filling in the ids from the least available
-     *   index.
-     *
-     * When such a functionality is desired, a control message to add
-     * a port can be introduced.
-     */
     QTAILQ_REMOVE(&vser->ports, port, next);
 
     if (port->info->exit)
@@ -641,11 +698,12 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
     }
 
     vser->config.max_nr_ports = max_nr_ports;
+    vser->ports_map = qemu_mallocz((max_nr_ports + 31) / 32);
     /*
      * Reserve location 0 for a console port for backward compat
      * (old kernel, new qemu)
      */
-    vser->config.nr_ports = 1;
+    mark_port_added(vser, 0);
 
     vser->vdev.get_features = get_features;
     vser->vdev.get_config = get_config;
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index f297b00..0548689 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -27,6 +27,8 @@
 /* Features supported */
 #define VIRTIO_CONSOLE_F_MULTIPORT	1
 
+#define VIRTIO_CONSOLE_BAD_ID           (~(uint32_t)0)
+
 struct virtio_console_config {
     /*
      * These two fields are used by VIRTIO_CONSOLE_F_SIZE which
@@ -36,7 +38,6 @@ struct virtio_console_config {
     uint16_t rows;
 
     uint32_t max_nr_ports;
-    uint32_t nr_ports;
 } __attribute__((packed));
 
 struct virtio_console_control {
@@ -46,12 +47,14 @@ struct virtio_console_control {
 };
 
 /* Some events for the internal messages (control packets) */
-#define VIRTIO_CONSOLE_PORT_READY	0
-#define VIRTIO_CONSOLE_CONSOLE_PORT	1
-#define VIRTIO_CONSOLE_RESIZE		2
-#define VIRTIO_CONSOLE_PORT_OPEN	3
-#define VIRTIO_CONSOLE_PORT_NAME	4
-#define VIRTIO_CONSOLE_PORT_REMOVE	5
+#define VIRTIO_CONSOLE_DEVICE_READY	0
+#define VIRTIO_CONSOLE_PORT_ADD		1
+#define VIRTIO_CONSOLE_PORT_REMOVE	2
+#define VIRTIO_CONSOLE_PORT_READY	3
+#define VIRTIO_CONSOLE_CONSOLE_PORT	4
+#define VIRTIO_CONSOLE_RESIZE		5
+#define VIRTIO_CONSOLE_PORT_OPEN	6
+#define VIRTIO_CONSOLE_PORT_NAME	7
 
 /* == In-qemu interface == */
 
commit 31abe21f4f026171128e6fbafb40062ae1872bd5
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:03:58 2010 +0530

    virtio-serial: save/load: Send target host connection status if different
    
    If the host connection to a port is closed on the destination machine
    after migration, whereas the connection was open on the source, the
    guest has to be informed of that.
    
    Similar for a host connection open on the destination.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 5316ef6..484dc94 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -395,6 +395,7 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
          */
         qemu_put_be32s(f, &port->id);
         qemu_put_byte(f, port->guest_connected);
+        qemu_put_byte(f, port->host_connected);
     }
 }
 
@@ -448,6 +449,7 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
     /* Items in struct VirtIOSerialPort */
     for (i = 0; i < nr_active_ports; i++) {
         uint32_t id;
+        bool host_connected;
 
         id = qemu_get_be32(f);
         port = find_port_by_id(s, id);
@@ -460,6 +462,15 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
         }
 
         port->guest_connected = qemu_get_byte(f);
+        host_connected = qemu_get_byte(f);
+        if (host_connected != port->host_connected) {
+            /*
+             * We have to let the guest know of the host connection
+             * status change
+             */
+            send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN,
+                               port->host_connected);
+        }
     }
 
     return 0;
commit 16af2e3c35990cb7aceb37ffe5827a28fd4614d0
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:03:57 2010 +0530

    virtio-serial: save/load: Ensure we have hot-plugged ports instantiated
    
    If some ports that were hot-plugged on the source are not available on
    the destination, fail migration instead of trying to deref a NULL
    pointer.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Reported-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index d31e62d..5316ef6 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -451,6 +451,13 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
 
         id = qemu_get_be32(f);
         port = find_port_by_id(s, id);
+        if (!port) {
+            /*
+             * The requested port was hot-plugged on the source but we
+             * don't have it
+             */
+            return -EINVAL;
+        }
 
         port->guest_connected = qemu_get_byte(f);
     }
commit 295587f747c7747e37208540a7a7f4d13a6ba4de
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:03:56 2010 +0530

    virtio-serial: save/load: Ensure nr_ports on src and dest are same.
    
    The number of ports on the source as well as the destination machines
    should match. If they don't, it means some ports that got hotplugged on
    the source aren't instantiated on the destination. Or that ports that
    were hot-unplugged on the source are created on the destination.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Reported-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 9a7f0c1..d31e62d 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -402,7 +402,7 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
 {
     VirtIOSerial *s = opaque;
     VirtIOSerialPort *port;
-    uint32_t max_nr_ports, nr_active_ports;
+    uint32_t max_nr_ports, nr_active_ports, nr_ports;
     unsigned int i;
 
     if (version_id > 2) {
@@ -419,7 +419,21 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
     /* The config space */
     qemu_get_be16s(f, &s->config.cols);
     qemu_get_be16s(f, &s->config.rows);
-    s->config.nr_ports = qemu_get_be32(f);
+    nr_ports = qemu_get_be32(f);
+
+    if (nr_ports != s->config.nr_ports) {
+        /*
+         * Source hot-plugged/unplugged ports and we don't have all of
+         * them here.
+         *
+         * Note: This condition cannot check for all hotplug/unplug
+         * events: eg, if one port was hot-plugged and one was
+         * unplugged, the nr_ports remains the same but the port id's
+         * would have changed and we won't catch it here. A later
+         * check for !find_port_by_id() will confirm if this happened.
+         */
+        return -EINVAL;
+    }
 
     /* Items in struct VirtIOSerial */
 
commit e245795b50e97250ee63f86580457cf35f29f3ca
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Apr 27 18:03:55 2010 +0530

    virtio-serial: save/load: Ensure target has enough ports
    
    The target could be started with max_nr_ports for a virtio-serial device
    lesser than what was available on the source machine. Fail the migration
    in such a case.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Reported-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 17c1ec1..9a7f0c1 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -374,10 +374,13 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
 
     /* Items in struct VirtIOSerial */
 
+    qemu_put_be32s(f, &s->bus->max_nr_ports);
+
     /* Do this because we might have hot-unplugged some ports */
     nr_active_ports = 0;
-    QTAILQ_FOREACH(port, &s->ports, next)
+    QTAILQ_FOREACH(port, &s->ports, next) {
         nr_active_ports++;
+    }
 
     qemu_put_be32s(f, &nr_active_ports);
 
@@ -399,7 +402,7 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
 {
     VirtIOSerial *s = opaque;
     VirtIOSerialPort *port;
-    uint32_t nr_active_ports;
+    uint32_t max_nr_ports, nr_active_ports;
     unsigned int i;
 
     if (version_id > 2) {
@@ -420,6 +423,12 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
 
     /* Items in struct VirtIOSerial */
 
+    qemu_get_be32s(f, &max_nr_ports);
+    if (max_nr_ports > s->bus->max_nr_ports) {
+        /* Source could have more ports than us. Fail migration. */
+        return -EINVAL;
+    }
+
     qemu_get_be32s(f, &nr_active_ports);
 
     /* Items in struct VirtIOSerialPort */
commit aacf4563878cac2afbbdc9818d810d2a3b075c6a
Author: Thomas Monjalon <thomas at monjalon.net>
Date:   Tue Apr 27 15:27:09 2010 +0200

    microblaze: fix custom fprintf
    
    Using GCC-4.2.4-1ubuntu4, there is a warning:
    	microblaze-dis.c:792: warning: unused variable 'fprintf'
    
    Indeed, fprintf() is shadowed by a custom redefinition but is not used because
    of FORTIFY_SOURCE option which replace calls to fprintf() by fprintf_chk().
    So, fprintf refers to the libc implementation instead of the qemu one.
    It's a bug.
    
    It is fixed by renaming the variable to something different of "fprintf".
    It prevents from hazardous shadowing.
    
    Signed-off-by: Thomas Monjalon <thomas at monjalon.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/microblaze-dis.c b/microblaze-dis.c
index 9235fd8..7694a43 100644
--- a/microblaze-dis.c
+++ b/microblaze-dis.c
@@ -789,7 +789,7 @@ read_insn_microblaze (bfd_vma memaddr,
 int 
 print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
 {
-  fprintf_ftype       fprintf = info->fprintf_func;
+  fprintf_ftype       fprintf_func = info->fprintf_func;
   void *              stream = info->stream;
   unsigned long       inst, prev_inst;
   struct op_code_struct * op, *pop;
@@ -826,19 +826,19 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
   prev_insn_vma = curr_insn_vma;
 
   if (op->name == 0) {
-    fprintf (stream, ".short 0x%04lx", inst);
+    fprintf_func (stream, ".short 0x%04lx", inst);
   }
   else
     {
-      fprintf (stream, "%s", op->name);
+      fprintf_func (stream, "%s", op->name);
       
       switch (op->inst_type)
 	{
   case INST_TYPE_RD_R1_R2:
-     fprintf(stream, "\t%s, %s, %s", get_field_rd(inst), get_field_r1(inst), get_field_r2(inst));
+     fprintf_func(stream, "\t%s, %s, %s", get_field_rd(inst), get_field_r1(inst), get_field_r2(inst));
      break;
         case INST_TYPE_RD_R1_IMM:
-	  fprintf(stream, "\t%s, %s, %s", get_field_rd(inst), get_field_r1(inst), get_field_imm(inst));
+	  fprintf_func(stream, "\t%s, %s, %s", get_field_rd(inst), get_field_r1(inst), get_field_imm(inst));
 	  if (info->print_address_func && get_int_field_r1(inst) == 0 && info->symbol_at_address_func) {
 	    if (immfound)
 	      immval |= (get_int_field_imm(inst) & 0x0000ffff);
@@ -848,34 +848,34 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
 		immval |= 0xFFFF0000;
 	    }
 	    if (immval > 0 && info->symbol_at_address_func(immval, info)) {
-	      fprintf (stream, "\t// ");
+	      fprintf_func (stream, "\t// ");
 	      info->print_address_func (immval, info);
 	    }
 	  }
 	  break;
 	case INST_TYPE_RD_R1_IMM5:
-	  fprintf(stream, "\t%s, %s, %s", get_field_rd(inst), get_field_r1(inst), get_field_imm5(inst));
+	  fprintf_func(stream, "\t%s, %s, %s", get_field_rd(inst), get_field_r1(inst), get_field_imm5(inst));
 	  break;
 	case INST_TYPE_RD_RFSL:
-	  fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_rfsl(inst));
+	  fprintf_func(stream, "\t%s, %s", get_field_rd(inst), get_field_rfsl(inst));
 	  break;
 	case INST_TYPE_R1_RFSL:
-	  fprintf(stream, "\t%s, %s", get_field_r1(inst), get_field_rfsl(inst));
+	  fprintf_func(stream, "\t%s, %s", get_field_r1(inst), get_field_rfsl(inst));
 	  break;
 	case INST_TYPE_RD_SPECIAL:
-	  fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_special(inst, op));
+	  fprintf_func(stream, "\t%s, %s", get_field_rd(inst), get_field_special(inst, op));
 	  break;
 	case INST_TYPE_SPECIAL_R1:
-	  fprintf(stream, "\t%s, %s", get_field_special(inst, op), get_field_r1(inst));
+	  fprintf_func(stream, "\t%s, %s", get_field_special(inst, op), get_field_r1(inst));
 	  break;
 	case INST_TYPE_RD_R1:
-	  fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_r1(inst));
+	  fprintf_func(stream, "\t%s, %s", get_field_rd(inst), get_field_r1(inst));
 	  break;
 	case INST_TYPE_R1_R2:
-	  fprintf(stream, "\t%s, %s", get_field_r1(inst), get_field_r2(inst));
+	  fprintf_func(stream, "\t%s, %s", get_field_r1(inst), get_field_r2(inst));
 	  break;
 	case INST_TYPE_R1_IMM:
-	  fprintf(stream, "\t%s, %s", get_field_r1(inst), get_field_imm(inst));
+	  fprintf_func(stream, "\t%s, %s", get_field_r1(inst), get_field_imm(inst));
 	  /* The non-pc relative instructions are returns, which shouldn't 
 	     have a label printed */
 	  if (info->print_address_func && op->inst_offset_type == INST_PC_OFFSET && info->symbol_at_address_func) {
@@ -888,16 +888,16 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
 	    }
 	    immval += memaddr;
 	    if (immval > 0 && info->symbol_at_address_func(immval, info)) {
-	      fprintf (stream, "\t// ");
+	      fprintf_func (stream, "\t// ");
 	      info->print_address_func (immval, info);
 	    } else {
-	      fprintf (stream, "\t\t// ");
-	      fprintf (stream, "%x", immval);
+	      fprintf_func (stream, "\t\t// ");
+	      fprintf_func (stream, "%x", immval);
 	    }
 	  }
 	  break;
         case INST_TYPE_RD_IMM:
-	  fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_imm(inst));
+	  fprintf_func(stream, "\t%s, %s", get_field_rd(inst), get_field_imm(inst));
 	  if (info->print_address_func && info->symbol_at_address_func) {
 	    if (immfound)
 	      immval |= (get_int_field_imm(inst) & 0x0000ffff);
@@ -909,13 +909,13 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
 	    if (op->inst_offset_type == INST_PC_OFFSET)
 	      immval += (int) memaddr;
 	    if (info->symbol_at_address_func(immval, info)) {
-	      fprintf (stream, "\t// ");
+	      fprintf_func (stream, "\t// ");
 	      info->print_address_func (immval, info);
 	    } 
 	  }
 	  break;
         case INST_TYPE_IMM:
-	  fprintf(stream, "\t%s", get_field_imm(inst));
+	  fprintf_func(stream, "\t%s", get_field_imm(inst));
 	  if (info->print_address_func && info->symbol_at_address_func && op->instr != imm) {
 	    if (immfound)
 	      immval |= (get_int_field_imm(inst) & 0x0000ffff);
@@ -927,39 +927,39 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
 	    if (op->inst_offset_type == INST_PC_OFFSET)
 	      immval += (int) memaddr;
 	    if (immval > 0 && info->symbol_at_address_func(immval, info)) {
-	      fprintf (stream, "\t// ");
+	      fprintf_func (stream, "\t// ");
 	      info->print_address_func (immval, info);
 	    } else if (op->inst_offset_type == INST_PC_OFFSET) {
-	      fprintf (stream, "\t\t// ");
-	      fprintf (stream, "%x", immval);
+	      fprintf_func (stream, "\t\t// ");
+	      fprintf_func (stream, "%x", immval);
 	    }
 	  }
 	  break;
         case INST_TYPE_RD_R2:
-	  fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_r2(inst));
+	  fprintf_func(stream, "\t%s, %s", get_field_rd(inst), get_field_r2(inst));
 	  break;
   case INST_TYPE_R2:
-     fprintf(stream, "\t%s", get_field_r2(inst));
+     fprintf_func(stream, "\t%s", get_field_r2(inst));
      break;
   case INST_TYPE_R1:
-     fprintf(stream, "\t%s", get_field_r1(inst));
+     fprintf_func(stream, "\t%s", get_field_r1(inst));
      break;
   case INST_TYPE_RD_R1_SPECIAL:
-     fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_r2(inst));
+     fprintf_func(stream, "\t%s, %s", get_field_rd(inst), get_field_r2(inst));
      break;
   case INST_TYPE_RD_IMM15:
-     fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_imm15(inst));
+     fprintf_func(stream, "\t%s, %s", get_field_rd(inst), get_field_imm15(inst));
      break;
      /* For tuqula instruction */
   case INST_TYPE_RD:
-     fprintf(stream, "\t%s", get_field_rd(inst));
+     fprintf_func(stream, "\t%s", get_field_rd(inst));
      break;
   case INST_TYPE_RFSL:
-     fprintf(stream, "\t%s", get_field_rfsl(inst));
+     fprintf_func(stream, "\t%s", get_field_rfsl(inst));
      break;
   default:
 	  /* if the disassembler lags the instruction set */
-	  fprintf (stream, "\tundecoded operands, inst is 0x%04lx", inst);
+	  fprintf_func (stream, "\tundecoded operands, inst is 0x%04lx", inst);
 	  break;
 	}
     }
commit 14a6063a91083c9cbe1bc502ee58fc7ca146bc1a
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Apr 12 16:19:26 2010 -0700

    Implement cpu_get_real_ticks for Alpha.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/qemu-timer.h b/qemu-timer.h
index 62da887..1494f79 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -209,6 +209,19 @@ static inline int64_t cpu_get_real_ticks(void)
     return (int64_t)(count * cyc_per_count);
 }
 
+#elif defined(__alpha__)
+
+static inline int64_t cpu_get_real_ticks(void)
+{
+    uint64_t cc;
+    uint32_t cur, ofs;
+
+    asm volatile("rpcc %0" : "=r"(cc));
+    cur = cc;
+    ofs = cc >> 32;
+    return cur - ofs;
+}
+
 #else
 /* The host CPU doesn't have an easily accessible cycle counter.
    Just return a monotonically increasing value.  This will be
commit 18f8e2c08bbd0dd8d32a3a536787076b8b958a4b
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Apr 12 16:18:43 2010 -0700

    target-alpha: Implement RPCC.
    
    A minimal implementation that more or less corresponds to the
    user-level version used by target-i386.  More hoops will want
    to be jumped through when alpha gets system-level emulation.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 817504b..314d6ac 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -355,7 +355,6 @@ struct CPUAlphaState {
     uint64_t ir[31];
     float64 fir[31];
     uint64_t pc;
-    uint32_t pcc[2];
     uint64_t ipr[IPR_LAST];
     uint64_t ps;
     uint64_t unique;
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index bfc095c..ff5ae26 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -21,6 +21,7 @@
 #include "host-utils.h"
 #include "softfloat.h"
 #include "helper.h"
+#include "qemu-timer.h"
 
 /*****************************************************************************/
 /* Exceptions processing helpers */
@@ -33,8 +34,8 @@ void QEMU_NORETURN helper_excp (int excp, int error)
 
 uint64_t helper_load_pcc (void)
 {
-    /* XXX: TODO */
-    return 0;
+    /* ??? This isn't a timer for which we have any rate info.  */
+    return (uint32_t)cpu_get_real_ticks();
 }
 
 uint64_t helper_load_fpcr (void)
commit 6910b8f66a9ad0c2c2052b4be884e11b76049718
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Apr 7 15:42:26 2010 -0700

    target-alpha: Fix load-locked/store-conditional.
    
    Use an exception plus start_exclusive to implement the compare-and-swap.
    This follows the example set by the MIPS and PPC ports.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/linux-user/main.c b/linux-user/main.c
index 5680d8e..18b52c0 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2349,6 +2349,51 @@ void cpu_loop(CPUM68KState *env)
 #endif /* TARGET_M68K */
 
 #ifdef TARGET_ALPHA
+static void do_store_exclusive(CPUAlphaState *env, int reg, int quad)
+{
+    target_ulong addr, val, tmp;
+    target_siginfo_t info;
+    int ret = 0;
+
+    addr = env->lock_addr;
+    tmp = env->lock_st_addr;
+    env->lock_addr = -1;
+    env->lock_st_addr = 0;
+
+    start_exclusive();
+    mmap_lock();
+
+    if (addr == tmp) {
+        if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) {
+            goto do_sigsegv;
+        }
+
+        if (val == env->lock_value) {
+            tmp = env->ir[reg];
+            if (quad ? put_user_u64(tmp, addr) : put_user_u32(tmp, addr)) {
+                goto do_sigsegv;
+            }
+            ret = 1;
+        }
+    }
+    env->ir[reg] = ret;
+    env->pc += 4;
+
+    mmap_unlock();
+    end_exclusive();
+    return;
+
+ do_sigsegv:
+    mmap_unlock();
+    end_exclusive();
+
+    info.si_signo = TARGET_SIGSEGV;
+    info.si_errno = 0;
+    info.si_code = TARGET_SEGV_MAPERR;
+    info._sifields._sigfault._addr = addr;
+    queue_signal(env, TARGET_SIGSEGV, &info);
+}
+
 void cpu_loop (CPUState *env)
 {
     int trapnr;
@@ -2373,6 +2418,7 @@ void cpu_loop (CPUState *env)
             exit(1);
             break;
         case EXCP_ARITH:
+            env->lock_addr = -1;
             info.si_signo = TARGET_SIGFPE;
             info.si_errno = 0;
             info.si_code = TARGET_FPE_FLTINV;
@@ -2384,6 +2430,7 @@ void cpu_loop (CPUState *env)
             exit(1);
             break;
         case EXCP_DFAULT:
+            env->lock_addr = -1;
             info.si_signo = TARGET_SIGSEGV;
             info.si_errno = 0;
             info.si_code = 0;  /* ??? SEGV_MAPERR vs SEGV_ACCERR.  */
@@ -2407,6 +2454,7 @@ void cpu_loop (CPUState *env)
             exit(1);
             break;
         case EXCP_UNALIGN:
+            env->lock_addr = -1;
             info.si_signo = TARGET_SIGBUS;
             info.si_errno = 0;
             info.si_code = TARGET_BUS_ADRALN;
@@ -2415,6 +2463,7 @@ void cpu_loop (CPUState *env)
             break;
         case EXCP_OPCDEC:
         do_sigill:
+            env->lock_addr = -1;
             info.si_signo = TARGET_SIGILL;
             info.si_errno = 0;
             info.si_code = TARGET_ILL_ILLOPC;
@@ -2425,6 +2474,7 @@ void cpu_loop (CPUState *env)
             /* No-op.  Linux simply re-enables the FPU.  */
             break;
         case EXCP_CALL_PAL ... (EXCP_CALL_PALP - 1):
+            env->lock_addr = -1;
             switch ((trapnr >> 6) | 0x80) {
             case 0x80:
                 /* BPT */
@@ -2514,11 +2564,16 @@ void cpu_loop (CPUState *env)
         case EXCP_DEBUG:
             info.si_signo = gdb_handlesig (env, TARGET_SIGTRAP);
             if (info.si_signo) {
+                env->lock_addr = -1;
                 info.si_errno = 0;
                 info.si_code = TARGET_TRAP_BRKPT;
                 queue_signal(env, info.si_signo, &info);
             }
             break;
+        case EXCP_STL_C:
+        case EXCP_STQ_C:
+            do_store_exclusive(env, env->error_code, trapnr - EXCP_STL_C);
+            break;
         default:
             printf ("Unhandled trap: 0x%x\n", trapnr);
             cpu_dump_state(env, stderr, fprintf, 0);
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index c397930..817504b 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -355,11 +355,13 @@ struct CPUAlphaState {
     uint64_t ir[31];
     float64 fir[31];
     uint64_t pc;
-    uint64_t lock;
     uint32_t pcc[2];
     uint64_t ipr[IPR_LAST];
     uint64_t ps;
     uint64_t unique;
+    uint64_t lock_addr;
+    uint64_t lock_st_addr;
+    uint64_t lock_value;
     float_status fp_status;
     /* The following fields make up the FPCR, but in FP_STATUS format.  */
     uint8_t fpcr_exc_status;
@@ -440,6 +442,8 @@ enum {
     /* Pseudo exception for console */
     EXCP_CONSOLE_DISPATCH = 0x4001,
     EXCP_CONSOLE_FIXUP    = 0x4002,
+    EXCP_STL_C            = 0x4003,
+    EXCP_STQ_C            = 0x4004,
 };
 
 /* Arithmetic exception */
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 9a039cb..b6d2160 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -557,12 +557,15 @@ void cpu_dump_state (CPUState *env, FILE *f,
         if ((i % 3) == 2)
             cpu_fprintf(f, "\n");
     }
-    cpu_fprintf(f, "\n");
+
+    cpu_fprintf(f, "lock_a   " TARGET_FMT_lx " lock_v   " TARGET_FMT_lx "\n",
+                env->lock_addr, env->lock_value);
+
     for (i = 0; i < 31; i++) {
         cpu_fprintf(f, "FIR%02d    " TARGET_FMT_lx " ", i,
                     *((uint64_t *)(&env->fir[i])));
         if ((i % 3) == 2)
             cpu_fprintf(f, "\n");
     }
-    cpu_fprintf(f, "\nlock     " TARGET_FMT_lx "\n", env->lock);
+    cpu_fprintf(f, "\n");
 }
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index a209130..bfc095c 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1159,6 +1159,7 @@ void helper_hw_rei (void)
     env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
     env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
     env->intr_flag = 0;
+    env->lock_addr = -1;
     /* XXX: re-enable interrupts and memory mapping */
 }
 
@@ -1167,6 +1168,7 @@ void helper_hw_ret (uint64_t a)
     env->pc = a & ~3;
     env->ipr[IPR_EXC_ADDR] = a & 1;
     env->intr_flag = 0;
+    env->lock_addr = -1;
     /* XXX: re-enable interrupts and memory mapping */
 }
 
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 924fc70..3a1c625 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -86,7 +86,9 @@ static TCGv_ptr cpu_env;
 static TCGv cpu_ir[31];
 static TCGv cpu_fir[31];
 static TCGv cpu_pc;
-static TCGv cpu_lock;
+static TCGv cpu_lock_addr;
+static TCGv cpu_lock_st_addr;
+static TCGv cpu_lock_value;
 #ifdef CONFIG_USER_ONLY
 static TCGv cpu_uniq;
 #endif
@@ -123,8 +125,15 @@ static void alpha_translate_init(void)
     cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
                                     offsetof(CPUState, pc), "pc");
 
-    cpu_lock = tcg_global_mem_new_i64(TCG_AREG0,
-                                      offsetof(CPUState, lock), "lock");
+    cpu_lock_addr = tcg_global_mem_new_i64(TCG_AREG0,
+					   offsetof(CPUState, lock_addr),
+					   "lock_addr");
+    cpu_lock_st_addr = tcg_global_mem_new_i64(TCG_AREG0,
+					      offsetof(CPUState, lock_st_addr),
+					      "lock_st_addr");
+    cpu_lock_value = tcg_global_mem_new_i64(TCG_AREG0,
+					    offsetof(CPUState, lock_value),
+					    "lock_value");
 
 #ifdef CONFIG_USER_ONLY
     cpu_uniq = tcg_global_mem_new_i64(TCG_AREG0,
@@ -189,14 +198,16 @@ static inline void gen_qemu_lds(TCGv t0, TCGv t1, int flags)
 
 static inline void gen_qemu_ldl_l(TCGv t0, TCGv t1, int flags)
 {
-    tcg_gen_mov_i64(cpu_lock, t1);
     tcg_gen_qemu_ld32s(t0, t1, flags);
+    tcg_gen_mov_i64(cpu_lock_addr, t1);
+    tcg_gen_mov_i64(cpu_lock_value, t0);
 }
 
 static inline void gen_qemu_ldq_l(TCGv t0, TCGv t1, int flags)
 {
-    tcg_gen_mov_i64(cpu_lock, t1);
     tcg_gen_qemu_ld64(t0, t1, flags);
+    tcg_gen_mov_i64(cpu_lock_addr, t1);
+    tcg_gen_mov_i64(cpu_lock_value, t0);
 }
 
 static inline void gen_load_mem(DisasContext *ctx,
@@ -205,25 +216,31 @@ static inline void gen_load_mem(DisasContext *ctx,
                                 int ra, int rb, int32_t disp16, int fp,
                                 int clear)
 {
-    TCGv addr;
+    TCGv addr, va;
 
-    if (unlikely(ra == 31))
+    /* LDQ_U with ra $31 is UNOP.  Other various loads are forms of
+       prefetches, which we can treat as nops.  No worries about
+       missed exceptions here.  */
+    if (unlikely(ra == 31)) {
         return;
+    }
 
     addr = tcg_temp_new();
     if (rb != 31) {
         tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-        if (clear)
+        if (clear) {
             tcg_gen_andi_i64(addr, addr, ~0x7);
+        }
     } else {
-        if (clear)
+        if (clear) {
             disp16 &= ~0x7;
+        }
         tcg_gen_movi_i64(addr, disp16);
     }
-    if (fp)
-        tcg_gen_qemu_load(cpu_fir[ra], addr, ctx->mem_idx);
-    else
-        tcg_gen_qemu_load(cpu_ir[ra], addr, ctx->mem_idx);
+
+    va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
+    tcg_gen_qemu_load(va, addr, ctx->mem_idx);
+
     tcg_temp_free(addr);
 }
 
@@ -257,73 +274,105 @@ static inline void gen_qemu_sts(TCGv t0, TCGv t1, int flags)
     tcg_temp_free_i32(tmp32);
 }
 
-static inline void gen_qemu_stl_c(TCGv t0, TCGv t1, int flags)
-{
-    int l1, l2;
-
-    l1 = gen_new_label();
-    l2 = gen_new_label();
-    tcg_gen_brcond_i64(TCG_COND_NE, cpu_lock, t1, l1);
-    tcg_gen_qemu_st32(t0, t1, flags);
-    tcg_gen_movi_i64(t0, 1);
-    tcg_gen_br(l2);
-    gen_set_label(l1);
-    tcg_gen_movi_i64(t0, 0);
-    gen_set_label(l2);
-    tcg_gen_movi_i64(cpu_lock, -1);
-}
-
-static inline void gen_qemu_stq_c(TCGv t0, TCGv t1, int flags)
-{
-    int l1, l2;
-
-    l1 = gen_new_label();
-    l2 = gen_new_label();
-    tcg_gen_brcond_i64(TCG_COND_NE, cpu_lock, t1, l1);
-    tcg_gen_qemu_st64(t0, t1, flags);
-    tcg_gen_movi_i64(t0, 1);
-    tcg_gen_br(l2);
-    gen_set_label(l1);
-    tcg_gen_movi_i64(t0, 0);
-    gen_set_label(l2);
-    tcg_gen_movi_i64(cpu_lock, -1);
-}
-
 static inline void gen_store_mem(DisasContext *ctx,
                                  void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1,
                                                             int flags),
                                  int ra, int rb, int32_t disp16, int fp,
-                                 int clear, int local)
+                                 int clear)
 {
-    TCGv addr;
-    if (local)
-        addr = tcg_temp_local_new();
-    else
-        addr = tcg_temp_new();
+    TCGv addr, va;
+
+    addr = tcg_temp_new();
     if (rb != 31) {
         tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-        if (clear)
+        if (clear) {
             tcg_gen_andi_i64(addr, addr, ~0x7);
+        }
     } else {
-        if (clear)
+        if (clear) {
             disp16 &= ~0x7;
+        }
         tcg_gen_movi_i64(addr, disp16);
     }
-    if (ra != 31) {
-        if (fp)
-            tcg_gen_qemu_store(cpu_fir[ra], addr, ctx->mem_idx);
-        else
-            tcg_gen_qemu_store(cpu_ir[ra], addr, ctx->mem_idx);
+
+    if (ra == 31) {
+        va = tcg_const_i64(0);
     } else {
-        TCGv zero;
-        if (local)
-            zero = tcg_const_local_i64(0);
-        else
-            zero = tcg_const_i64(0);
-        tcg_gen_qemu_store(zero, addr, ctx->mem_idx);
-        tcg_temp_free(zero);
+        va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
     }
+    tcg_gen_qemu_store(va, addr, ctx->mem_idx);
+
     tcg_temp_free(addr);
+    if (ra == 31) {
+        tcg_temp_free(va);
+    }
+}
+
+static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
+                                        int32_t disp16, int quad)
+{
+    TCGv addr;
+
+    if (ra == 31) {
+        /* ??? Don't bother storing anything.  The user can't tell
+           the difference, since the zero register always reads zero.  */
+        return NO_EXIT;
+    }
+
+#if defined(CONFIG_USER_ONLY)
+    addr = cpu_lock_st_addr;
+#else
+    addr = tcg_local_new();
+#endif
+
+    if (rb != 31) {
+        tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
+    } else {
+        tcg_gen_movi_i64(addr, disp16);
+    }
+
+#if defined(CONFIG_USER_ONLY)
+    /* ??? This is handled via a complicated version of compare-and-swap
+       in the cpu_loop.  Hopefully one day we'll have a real CAS opcode
+       in TCG so that this isn't necessary.  */
+    return gen_excp(ctx, quad ? EXCP_STQ_C : EXCP_STL_C, ra);
+#else
+    /* ??? In system mode we are never multi-threaded, so CAS can be
+       implemented via a non-atomic load-compare-store sequence.  */
+    {
+        int lab_fail, lab_done;
+        TCGv val;
+
+        lab_fail = gen_new_label();
+        lab_done = gen_new_label();
+        tcg_gen_brcond(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
+
+        val = tcg_temp_new();
+        if (quad) {
+            tcg_gen_qemu_ld64(val, addr, ctx->mem_idx);
+        } else {
+            tcg_gen_qemu_ld32s(val, addr, ctx->mem_idx);
+        }
+        tcg_gen_brcond(TCG_COND_NE, val, cpu_lock_value, lab_fail);
+
+        if (quad) {
+            tcg_gen_qemu_st64(cpu_ir[ra], addr, ctx->mem_idx);
+        } else {
+            tcg_gen_qemu_st32(cpu_ir[ra], addr, ctx->mem_idx);
+        }
+        tcg_gen_movi_i64(cpu_ir[ra], 1);
+        tcg_gen_br(lab_done);
+
+        gen_set_label(lab_fail);
+        tcg_gen_movi_i64(cpu_ir[ra], 0);
+
+        gen_set_label(lab_done);
+        tcg_gen_movi_i64(cpu_lock_addr, -1);
+
+        tcg_temp_free(addr);
+        return NO_EXIT;
+    }
+#endif
 }
 
 static int use_goto_tb(DisasContext *ctx, uint64_t dest)
@@ -1533,15 +1582,15 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
         break;
     case 0x0D:
         /* STW */
-        gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0, 0);
+        gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0);
         break;
     case 0x0E:
         /* STB */
-        gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0, 0);
+        gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0);
         break;
     case 0x0F:
         /* STQ_U */
-        gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1, 0);
+        gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1);
         break;
     case 0x10:
         switch (fn7) {
@@ -2974,19 +3023,19 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
         break;
     case 0x24:
         /* STF */
-        gen_store_mem(ctx, &gen_qemu_stf, ra, rb, disp16, 1, 0, 0);
+        gen_store_mem(ctx, &gen_qemu_stf, ra, rb, disp16, 1, 0);
         break;
     case 0x25:
         /* STG */
-        gen_store_mem(ctx, &gen_qemu_stg, ra, rb, disp16, 1, 0, 0);
+        gen_store_mem(ctx, &gen_qemu_stg, ra, rb, disp16, 1, 0);
         break;
     case 0x26:
         /* STS */
-        gen_store_mem(ctx, &gen_qemu_sts, ra, rb, disp16, 1, 0, 0);
+        gen_store_mem(ctx, &gen_qemu_sts, ra, rb, disp16, 1, 0);
         break;
     case 0x27:
         /* STT */
-        gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0, 0);
+        gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0);
         break;
     case 0x28:
         /* LDL */
@@ -3006,19 +3055,19 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
         break;
     case 0x2C:
         /* STL */
-        gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp16, 0, 0, 0);
+        gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp16, 0, 0);
         break;
     case 0x2D:
         /* STQ */
-        gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 0, 0);
+        gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 0);
         break;
     case 0x2E:
         /* STL_C */
-        gen_store_mem(ctx, &gen_qemu_stl_c, ra, rb, disp16, 0, 0, 1);
+        ret = gen_store_conditional(ctx, ra, rb, disp16, 0);
         break;
     case 0x2F:
         /* STQ_C */
-        gen_store_mem(ctx, &gen_qemu_stq_c, ra, rb, disp16, 0, 0, 1);
+        ret = gen_store_conditional(ctx, ra, rb, disp16, 1);
         break;
     case 0x30:
         /* BR */
@@ -3284,6 +3333,7 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
 #else
     pal_init(env);
 #endif
+    env->lock_addr = -1;
 
     /* Initialize IPR */
 #if defined (CONFIG_USER_ONLY)
commit 8aa3fa2038d9d0a7d69acdac505d990acc5eafc8
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Apr 7 13:32:50 2010 -0700

    target-alpha: Indicate NORETURN status when raising exception.
    
    When (indirectly) calling raise_exception, don't emit cleanup
    code at the end of the TB, as it is unused.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 4321a25..924fc70 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -74,7 +74,11 @@ typedef enum {
 
     /* We are exiting the TB, but have neither emitted a goto_tb, nor
        updated the PC for the next instruction to be executed.  */
-    EXIT_PC_STALE
+    EXIT_PC_STALE,
+
+    /* We are ending the TB with a noreturn function call, e.g. longjmp.
+       No following code will be executed.  */
+    EXIT_NORETURN,
 } ExitStatus;
 
 /* global register indexes */
@@ -134,7 +138,7 @@ static void alpha_translate_init(void)
     done_init = 1;
 }
 
-static inline void gen_excp(DisasContext *ctx, int exception, int error_code)
+static ExitStatus gen_excp(DisasContext *ctx, int exception, int error_code)
 {
     TCGv_i32 tmp1, tmp2;
 
@@ -144,11 +148,13 @@ static inline void gen_excp(DisasContext *ctx, int exception, int error_code)
     gen_helper_excp(tmp1, tmp2);
     tcg_temp_free_i32(tmp2);
     tcg_temp_free_i32(tmp1);
+
+    return EXIT_NORETURN;
 }
 
-static inline void gen_invalid(DisasContext *ctx)
+static inline ExitStatus gen_invalid(DisasContext *ctx)
 {
-    gen_excp(ctx, EXCP_OPCDEC, 0);
+    return gen_excp(ctx, EXCP_OPCDEC, 0);
 }
 
 static inline void gen_qemu_ldf(TCGv t0, TCGv t1, int flags)
@@ -1457,9 +1463,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
 #endif
         if (palcode >= 0x80 && palcode < 0xC0) {
             /* Unprivileged PAL call */
-            gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x3F) << 6), 0);
-            /* PC updated by gen_excp.  */
-            ret = EXIT_PC_UPDATED;
+            ret = gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x3F) << 6), 0);
             break;
         }
 #ifndef CONFIG_USER_ONLY
@@ -1467,7 +1471,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             /* Privileged PAL code */
             if (ctx->mem_idx & 1)
                 goto invalid_opc;
-            gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x3F) << 6), 0);
+            ret = gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x3F) << 6), 0);
         }
 #endif
         /* Invalid PAL call */
@@ -3075,9 +3079,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
         ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
         break;
     invalid_opc:
-        gen_invalid(ctx);
-        /* PC updated by gen_excp.  */
-        ret = EXIT_PC_UPDATED;
+        ret = gen_invalid(ctx);
         break;
     }
 
@@ -3181,6 +3183,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
 
     switch (ret) {
     case EXIT_GOTO_TB:
+    case EXIT_NORETURN:
         break;
     case EXIT_PC_STALE:
         tcg_gen_movi_i64(cpu_pc, ctx.pc);
commit a4b388ff51c2feb5eca563feae9bfc5fc1c5c85c
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Apr 12 16:17:22 2010 -0700

    target-alpha: Enable NPTL.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index e2dadb0..172b7cf 100755
--- a/configure
+++ b/configure
@@ -2432,6 +2432,7 @@ case "$target_arch2" in
   ;;
   alpha)
     target_phys_bits=64
+    target_nptl="yes"
   ;;
   arm|armeb)
     TARGET_ARCH=arm
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index eb77ade..17599eb 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5768,7 +5768,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         ret = get_errno(fsync(arg1));
         break;
     case TARGET_NR_clone:
-#if defined(TARGET_SH4)
+#if defined(TARGET_SH4) || defined(TARGET_ALPHA)
         ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
 #elif defined(TARGET_CRIS)
         ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 8afe16d..c397930 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -411,15 +411,6 @@ static inline int cpu_mmu_index (CPUState *env)
     return (env->ps >> 3) & 3;
 }
 
-#if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
-{
-    if (newsp)
-        env->ir[30] = newsp;
-    /* FIXME: Zero syscall return value.  */
-}
-#endif
-
 #include "cpu-all.h"
 #include "exec-all.h"
 
@@ -477,7 +468,7 @@ enum {
     IR_S4   = 13,
     IR_S5   = 14,
     IR_S6   = 15,
-#define IR_FP IR_S6
+    IR_FP   = IR_S6,
     IR_A0   = 16,
     IR_A1   = 17,
     IR_A2   = 18,
@@ -490,7 +481,7 @@ enum {
     IR_T11  = 25,
     IR_RA   = 26,
     IR_T12  = 27,
-#define IR_PV IR_T12
+    IR_PV   = IR_T12,
     IR_AT   = 28,
     IR_GP   = 29,
     IR_SP   = 30,
@@ -531,4 +522,20 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
     *flags = env->ps;
 }
 
+#if defined(CONFIG_USER_ONLY)
+static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->ir[IR_SP] = newsp;
+    }
+    env->ir[IR_V0] = 0;
+    env->ir[IR_A3] = 0;
+}
+
+static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
+{
+    env->unique = newtls;
+}
+#endif
+
 #endif /* !defined (__CPU_ALPHA_H__) */
commit 49563a727494197ad87936bfd07841878878b650
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Mar 29 10:48:14 2010 -0700

    target-alpha: Update commentary for opcode 0x1A.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 2a9cee9..4321a25 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2531,13 +2531,16 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
         break;
 #endif
     case 0x1A:
-        if (rb != 31)
+        /* JMP, JSR, RET, JSR_COROUTINE.  These only differ by the branch
+           prediction stack action, which of course we don't implement.  */
+        if (rb != 31) {
             tcg_gen_andi_i64(cpu_pc, cpu_ir[rb], ~3);
-        else
+        } else {
             tcg_gen_movi_i64(cpu_pc, 0);
-        if (ra != 31)
+        }
+        if (ra != 31) {
             tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
-        /* Those four jumps only differ by the branch prediction hint */
+        }
         ret = EXIT_PC_UPDATED;
         break;
     case 0x1B:
commit 4af7037462c03b1a7d5cf8ecd423c85bf221acaf
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Mar 16 15:10:49 2010 -0700

    target-alpha: Emit goto_tb opcodes.
    
    Use an ExitStatus enumeration instead of magic numbers as the return
    value from translate_one.  Emit goto_tb opcodes when ending a TB via
    a direct branch.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index d7591cc..2a9cee9 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -43,12 +43,13 @@
 
 typedef struct DisasContext DisasContext;
 struct DisasContext {
+    struct TranslationBlock *tb;
+    CPUAlphaState *env;
     uint64_t pc;
     int mem_idx;
 #if !defined (CONFIG_USER_ONLY)
     int pal_mode;
 #endif
-    CPUAlphaState *env;
     uint32_t amask;
 
     /* Current rounding mode for this TB.  */
@@ -57,6 +58,25 @@ struct DisasContext {
     int tb_ftz;
 };
 
+/* Return values from translate_one, indicating the state of the TB.
+   Note that zero indicates that we are not exiting the TB.  */
+
+typedef enum {
+    NO_EXIT,
+
+    /* We have emitted one or more goto_tb.  No fixup required.  */
+    EXIT_GOTO_TB,
+
+    /* We are not using a goto_tb (for whatever reason), but have updated
+       the PC (for whatever reason), so there's no need to do it again on
+       exiting the TB.  */
+    EXIT_PC_UPDATED,
+
+    /* We are exiting the TB, but have neither emitted a goto_tb, nor
+       updated the PC for the next instruction to be executed.  */
+    EXIT_PC_STALE
+} ExitStatus;
+
 /* global register indexes */
 static TCGv_ptr cpu_env;
 static TCGv cpu_ir[31];
@@ -300,77 +320,126 @@ static inline void gen_store_mem(DisasContext *ctx,
     tcg_temp_free(addr);
 }
 
-static void gen_bcond_pcload(DisasContext *ctx, int32_t disp, int lab_true)
+static int use_goto_tb(DisasContext *ctx, uint64_t dest)
 {
-    int lab_over = gen_new_label();
+    /* Check for the dest on the same page as the start of the TB.  We
+       also want to suppress goto_tb in the case of single-steping and IO.  */
+    return (((ctx->tb->pc ^ dest) & TARGET_PAGE_MASK) == 0
+            && !ctx->env->singlestep_enabled
+            && !(ctx->tb->cflags & CF_LAST_IO));
+}
 
-    tcg_gen_movi_i64(cpu_pc, ctx->pc);
-    tcg_gen_br(lab_over);
-    gen_set_label(lab_true);
-    tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp << 2));
-    gen_set_label(lab_over);
+static ExitStatus gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
+{
+    uint64_t dest = ctx->pc + (disp << 2);
+
+    if (ra != 31) {
+        tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
+    }
+
+    /* Notice branch-to-next; used to initialize RA with the PC.  */
+    if (disp == 0) {
+        return 0;
+    } else if (use_goto_tb(ctx, dest)) {
+        tcg_gen_goto_tb(0);
+        tcg_gen_movi_i64(cpu_pc, dest);
+        tcg_gen_exit_tb((long)ctx->tb);
+        return EXIT_GOTO_TB;
+    } else {
+        tcg_gen_movi_i64(cpu_pc, dest);
+        return EXIT_PC_UPDATED;
+    }
 }
 
-static void gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
-                      int32_t disp, int mask)
+static ExitStatus gen_bcond_internal(DisasContext *ctx, TCGCond cond,
+                                     TCGv cmp, int32_t disp)
 {
+    uint64_t dest = ctx->pc + (disp << 2);
     int lab_true = gen_new_label();
 
-    if (likely(ra != 31)) {
+    if (use_goto_tb(ctx, dest)) {
+        tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
+
+        tcg_gen_goto_tb(0);
+        tcg_gen_movi_i64(cpu_pc, ctx->pc);
+        tcg_gen_exit_tb((long)ctx->tb);
+
+        gen_set_label(lab_true);
+        tcg_gen_goto_tb(1);
+        tcg_gen_movi_i64(cpu_pc, dest);
+        tcg_gen_exit_tb((long)ctx->tb + 1);
+
+        return EXIT_GOTO_TB;
+    } else {
+        int lab_over = gen_new_label();
+
+        /* ??? Consider using either
+             movi pc, next
+             addi tmp, pc, disp
+             movcond pc, cond, 0, tmp, pc
+           or
+             setcond tmp, cond, 0
+             movi pc, next
+             neg tmp, tmp
+             andi tmp, tmp, disp
+             add pc, pc, tmp
+           The current diamond subgraph surely isn't efficient.  */
+
+        tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
+        tcg_gen_movi_i64(cpu_pc, ctx->pc);
+        tcg_gen_br(lab_over);
+        gen_set_label(lab_true);
+        tcg_gen_movi_i64(cpu_pc, dest);
+        gen_set_label(lab_over);
+
+        return EXIT_PC_UPDATED;
+    }
+}
+
+static ExitStatus gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
+                            int32_t disp, int mask)
+{
+    TCGv cmp_tmp;
+
+    if (unlikely(ra == 31)) {
+        cmp_tmp = tcg_const_i64(0);
+    } else {
+        cmp_tmp = tcg_temp_new();
         if (mask) {
-            TCGv tmp = tcg_temp_new();
-            tcg_gen_andi_i64(tmp, cpu_ir[ra], 1);
-            tcg_gen_brcondi_i64(cond, tmp, 0, lab_true);
-            tcg_temp_free(tmp);
+            tcg_gen_andi_i64(cmp_tmp, cpu_ir[ra], 1);
         } else {
-            tcg_gen_brcondi_i64(cond, cpu_ir[ra], 0, lab_true);
+            tcg_gen_mov_i64(cmp_tmp, cpu_ir[ra]);
         }
-    } else {
-        /* Very uncommon case - Do not bother to optimize.  */
-        TCGv tmp = tcg_const_i64(0);
-        tcg_gen_brcondi_i64(cond, tmp, 0, lab_true);
-        tcg_temp_free(tmp);
     }
-    gen_bcond_pcload(ctx, disp, lab_true);
+
+    return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
 }
 
-/* Generate a forward TCG branch to LAB_TRUE if RA cmp 0.0.
-   This is complicated by the fact that -0.0 compares the same as +0.0.  */
+/* Fold -0.0 for comparison with COND.  */
 
-static void gen_fbcond_internal(TCGCond cond, TCGv src, int lab_true)
+static void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src)
 {
-    int lab_false = -1;
     uint64_t mzero = 1ull << 63;
-    TCGv tmp;
 
     switch (cond) {
     case TCG_COND_LE:
     case TCG_COND_GT:
         /* For <= or >, the -0.0 value directly compares the way we want.  */
-        tcg_gen_brcondi_i64(cond, src, 0, lab_true);
+        tcg_gen_mov_i64(dest, src);
         break;
 
     case TCG_COND_EQ:
     case TCG_COND_NE:
         /* For == or !=, we can simply mask off the sign bit and compare.  */
-        /* ??? Assume that the temporary is reclaimed at the branch.  */
-        tmp = tcg_temp_new();
-        tcg_gen_andi_i64(tmp, src, mzero - 1);
-        tcg_gen_brcondi_i64(cond, tmp, 0, lab_true);
+        tcg_gen_andi_i64(dest, src, mzero - 1);
         break;
 
     case TCG_COND_GE:
-        /* For >=, emit two branches to the destination.  */
-        tcg_gen_brcondi_i64(cond, src, 0, lab_true);
-        tcg_gen_brcondi_i64(TCG_COND_EQ, src, mzero, lab_true);
-        break;
-
     case TCG_COND_LT:
-        /* For <, first filter out -0.0 to what will be the fallthru.  */
-        lab_false = gen_new_label();
-        tcg_gen_brcondi_i64(TCG_COND_EQ, src, mzero, lab_false);
-        tcg_gen_brcondi_i64(cond, src, 0, lab_true);
-        gen_set_label(lab_false);
+        /* For >= or <, map -0.0 to +0.0 via comparison and mask.  */
+        tcg_gen_setcondi_i64(TCG_COND_NE, dest, src, mzero);
+        tcg_gen_neg_i64(dest, dest);
+        tcg_gen_and_i64(dest, dest, src);
         break;
 
     default:
@@ -378,24 +447,24 @@ static void gen_fbcond_internal(TCGCond cond, TCGv src, int lab_true)
     }
 }
 
-static void gen_fbcond(DisasContext *ctx, TCGCond cond, int ra, int32_t disp)
+static ExitStatus gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
+                             int32_t disp)
 {
-    int lab_true;
+    TCGv cmp_tmp;
 
     if (unlikely(ra == 31)) {
         /* Very uncommon case, but easier to optimize it to an integer
            comparison than continuing with the floating point comparison.  */
-        gen_bcond(ctx, cond, ra, disp, 0);
-        return;
+        return gen_bcond(ctx, cond, ra, disp, 0);
     }
 
-    lab_true = gen_new_label();
-    gen_fbcond_internal(cond, cpu_fir[ra], lab_true);
-    gen_bcond_pcload(ctx, disp, lab_true);
+    cmp_tmp = tcg_temp_new();
+    gen_fold_mzero(cond, cmp_tmp, cpu_fir[ra]);
+    return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
 }
 
 static void gen_cmov(TCGCond cond, int ra, int rb, int rc,
-		     int islit, uint8_t lit, int mask)
+                     int islit, uint8_t lit, int mask)
 {
     TCGCond inv_cond = tcg_invert_cond(cond);
     int l1;
@@ -429,18 +498,23 @@ static void gen_cmov(TCGCond cond, int ra, int rb, int rc,
 
 static void gen_fcmov(TCGCond cond, int ra, int rb, int rc)
 {
-    TCGv va = cpu_fir[ra];
+    TCGv cmp_tmp;
     int l1;
 
-    if (unlikely(rc == 31))
+    if (unlikely(rc == 31)) {
         return;
+    }
+
+    cmp_tmp = tcg_temp_new();
     if (unlikely(ra == 31)) {
-        /* ??? Assume that the temporary is reclaimed at the branch.  */
-        va = tcg_const_i64(0);
+        tcg_gen_movi_i64(cmp_tmp, 0);
+    } else {
+        gen_fold_mzero(cond, cmp_tmp, cpu_fir[ra]);
     }
 
     l1 = gen_new_label();
-    gen_fbcond_internal(tcg_invert_cond(cond), va, l1);
+    tcg_gen_brcondi_i64(tcg_invert_cond(cond), cmp_tmp, 0, l1);
+    tcg_temp_free(cmp_tmp);
 
     if (rb != 31)
         tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[rb]);
@@ -1335,14 +1409,14 @@ static void gen_rx(int ra, int set)
     tcg_temp_free_i32(tmp);
 }
 
-static inline int translate_one(DisasContext *ctx, uint32_t insn)
+static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
 {
     uint32_t palcode;
     int32_t disp21, disp16, disp12;
     uint16_t fn11;
     uint8_t opc, ra, rb, rc, fpfn, fn7, fn2, islit, real_islit;
     uint8_t lit;
-    int ret;
+    ExitStatus ret;
 
     /* Decode all instruction fields */
     opc = insn >> 26;
@@ -1363,10 +1437,10 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
     fpfn = fn11 & 0x3F;
     fn7 = (insn >> 5) & 0x0000007F;
     fn2 = (insn >> 5) & 0x00000003;
-    ret = 0;
     LOG_DISAS("opc %02x ra %2d rb %2d rc %2d disp16 %6d\n",
               opc, ra, rb, rc, disp16);
 
+    ret = NO_EXIT;
     switch (opc) {
     case 0x00:
         /* CALL_PAL */
@@ -1384,7 +1458,8 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
         if (palcode >= 0x80 && palcode < 0xC0) {
             /* Unprivileged PAL call */
             gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x3F) << 6), 0);
-            ret = 3;
+            /* PC updated by gen_excp.  */
+            ret = EXIT_PC_UPDATED;
             break;
         }
 #ifndef CONFIG_USER_ONLY
@@ -2395,13 +2470,11 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
         switch ((uint16_t)disp16) {
         case 0x0000:
             /* TRAPB */
-            /* No-op. Just exit from the current tb */
-            ret = 2;
+            /* No-op.  */
             break;
         case 0x0400:
             /* EXCB */
-            /* No-op. Just exit from the current tb */
-            ret = 2;
+            /* No-op.  */
             break;
         case 0x4000:
             /* MB */
@@ -2465,21 +2538,7 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
         if (ra != 31)
             tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
         /* Those four jumps only differ by the branch prediction hint */
-        switch (fn2) {
-        case 0x0:
-            /* JMP */
-            break;
-        case 0x1:
-            /* JSR */
-            break;
-        case 0x2:
-            /* RET */
-            break;
-        case 0x3:
-            /* JSR_COROUTINE */
-            break;
-        }
-        ret = 1;
+        ret = EXIT_PC_UPDATED;
         break;
     case 0x1B:
         /* HW_LD (PALcode) */
@@ -2770,7 +2829,7 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
                 tcg_temp_free(tmp2);
             }
             tcg_temp_free(tmp1);
-            ret = 2;
+            ret = EXIT_PC_STALE;
         }
         break;
 #endif
@@ -2795,7 +2854,7 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
             gen_helper_hw_ret(tmp);
             tcg_temp_free(tmp);
         }
-        ret = 2;
+        ret = EXIT_PC_UPDATED;
         break;
 #endif
     case 0x1F:
@@ -2956,85 +3015,66 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
         break;
     case 0x30:
         /* BR */
-        if (ra != 31)
-            tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
-        tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp21 << 2));
-        ret = 1;
+        ret = gen_bdirect(ctx, ra, disp21);
         break;
     case 0x31: /* FBEQ */
-        gen_fbcond(ctx, TCG_COND_EQ, ra, disp21);
-        ret = 1;
+        ret = gen_fbcond(ctx, TCG_COND_EQ, ra, disp21);
         break;
     case 0x32: /* FBLT */
-        gen_fbcond(ctx, TCG_COND_LT, ra, disp21);
-        ret = 1;
+        ret = gen_fbcond(ctx, TCG_COND_LT, ra, disp21);
         break;
     case 0x33: /* FBLE */
-        gen_fbcond(ctx, TCG_COND_LE, ra, disp21);
-        ret = 1;
+        ret = gen_fbcond(ctx, TCG_COND_LE, ra, disp21);
         break;
     case 0x34:
         /* BSR */
-        if (ra != 31)
-            tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
-        tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp21 << 2));
-        ret = 1;
+        ret = gen_bdirect(ctx, ra, disp21);
         break;
     case 0x35: /* FBNE */
-        gen_fbcond(ctx, TCG_COND_NE, ra, disp21);
-        ret = 1;
+        ret = gen_fbcond(ctx, TCG_COND_NE, ra, disp21);
         break;
     case 0x36: /* FBGE */
-        gen_fbcond(ctx, TCG_COND_GE, ra, disp21);
-        ret = 1;
+        ret = gen_fbcond(ctx, TCG_COND_GE, ra, disp21);
         break;
     case 0x37: /* FBGT */
-        gen_fbcond(ctx, TCG_COND_GT, ra, disp21);
-        ret = 1;
+        ret = gen_fbcond(ctx, TCG_COND_GT, ra, disp21);
         break;
     case 0x38:
         /* BLBC */
-        gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1);
-        ret = 1;
+        ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1);
         break;
     case 0x39:
         /* BEQ */
-        gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 0);
-        ret = 1;
+        ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 0);
         break;
     case 0x3A:
         /* BLT */
-        gen_bcond(ctx, TCG_COND_LT, ra, disp21, 0);
-        ret = 1;
+        ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21, 0);
         break;
     case 0x3B:
         /* BLE */
-        gen_bcond(ctx, TCG_COND_LE, ra, disp21, 0);
-        ret = 1;
+        ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21, 0);
         break;
     case 0x3C:
         /* BLBS */
-        gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1);
-        ret = 1;
+        ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1);
         break;
     case 0x3D:
         /* BNE */
-        gen_bcond(ctx, TCG_COND_NE, ra, disp21, 0);
-        ret = 1;
+        ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 0);
         break;
     case 0x3E:
         /* BGE */
-        gen_bcond(ctx, TCG_COND_GE, ra, disp21, 0);
-        ret = 1;
+        ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21, 0);
         break;
     case 0x3F:
         /* BGT */
-        gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
-        ret = 1;
+        ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
         break;
     invalid_opc:
         gen_invalid(ctx);
-        ret = 3;
+        /* PC updated by gen_excp.  */
+        ret = EXIT_PC_UPDATED;
         break;
     }
 
@@ -3051,15 +3091,17 @@ static inline void gen_intermediate_code_internal(CPUState *env,
     uint16_t *gen_opc_end;
     CPUBreakpoint *bp;
     int j, lj = -1;
-    int ret;
+    ExitStatus ret;
     int num_insns;
     int max_insns;
 
     pc_start = tb->pc;
     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+
+    ctx.tb = tb;
+    ctx.env = env;
     ctx.pc = pc_start;
     ctx.amask = env->amask;
-    ctx.env = env;
 #if defined (CONFIG_USER_ONLY)
     ctx.mem_idx = 0;
 #else
@@ -3083,7 +3125,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
         max_insns = CF_COUNT_MASK;
 
     gen_icount_start();
-    for (ret = 0; ret == 0;) {
+    do {
         if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
             QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
                 if (bp->pc == ctx.pc) {
@@ -3114,36 +3156,39 @@ static inline void gen_intermediate_code_internal(CPUState *env,
 
         ctx.pc += 4;
         ret = translate_one(ctxp, insn);
-        if (ret != 0)
-            break;
-        /* if we reach a page boundary or are single stepping, stop
-         * generation
-         */
-        if (env->singlestep_enabled) {
-            gen_excp(&ctx, EXCP_DEBUG, 0);
-            break;
-        }
 
-        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
-            break;
-
-        if (gen_opc_ptr >= gen_opc_end)
-            break;
-
-        if (num_insns >= max_insns)
-            break;
-
-        if (singlestep) {
-            break;
+        if (ret == NO_EXIT) {
+            /* If we reach a page boundary, are single stepping,
+               or exhaust instruction count, stop generation.  */
+            if (env->singlestep_enabled) {
+                gen_excp(&ctx, EXCP_DEBUG, 0);
+                ret = EXIT_PC_UPDATED;
+            } else if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0
+                       || gen_opc_ptr >= gen_opc_end
+                       || num_insns >= max_insns
+                       || singlestep) {
+                ret = EXIT_PC_STALE;
+            }
         }
+    } while (ret == NO_EXIT);
+
+    if (tb->cflags & CF_LAST_IO) {
+        gen_io_end();
     }
-    if (ret != 1 && ret != 3) {
+
+    switch (ret) {
+    case EXIT_GOTO_TB:
+        break;
+    case EXIT_PC_STALE:
         tcg_gen_movi_i64(cpu_pc, ctx.pc);
+        /* FALLTHRU */
+    case EXIT_PC_UPDATED:
+        tcg_gen_exit_tb(0);
+        break;
+    default:
+        abort();
     }
-    if (tb->cflags & CF_LAST_IO)
-        gen_io_end();
-    /* Generate the return instruction */
-    tcg_gen_exit_tb(0);
+
     gen_icount_end(tb, num_insns);
     *gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
@@ -3155,6 +3200,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
         tb->size = ctx.pc - pc_start;
         tb->icount = num_insns;
     }
+
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
commit 593f17e5f2125a7186a4a1917cb8603ffb636d48
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Apr 7 10:17:24 2010 -0700

    target-alpha: Implement cvtlq inline.
    
    It's a simple shift and mask sequence.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 10c78d0..ccf6a2a 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -83,7 +83,6 @@ DEF_HELPER_FLAGS_1(cvtqf, TCG_CALL_CONST, i64, i64)
 DEF_HELPER_FLAGS_1(cvtgf, TCG_CALL_CONST, i64, i64)
 DEF_HELPER_FLAGS_1(cvtgq, TCG_CALL_CONST, i64, i64)
 DEF_HELPER_FLAGS_1(cvtqg, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtlq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
 
 DEF_HELPER_FLAGS_1(cvttq, TCG_CALL_CONST, i64, i64)
 DEF_HELPER_FLAGS_1(cvttq_c, TCG_CALL_CONST, i64, i64)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index f9cd07a..a209130 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1152,13 +1152,6 @@ uint64_t helper_cvtqg (uint64_t a)
     return float64_to_g(fr);
 }
 
-uint64_t helper_cvtlq (uint64_t a)
-{
-    int32_t lo = a >> 29;
-    int32_t hi = a >> 32;
-    return (lo & 0x3FFFFFFF) | (hi & 0xc0000000);
-}
-
 /* PALcode support special instructions */
 #if !defined (CONFIG_USER_ONLY)
 void helper_hw_rei (void)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 1c296cf..d7591cc 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -598,6 +598,28 @@ static inline void gen_fp_exc_raise(int rc, int fn11)
     gen_fp_exc_raise_ignore(rc, fn11, fn11 & QUAL_I ? 0 : float_flag_inexact);
 }
 
+static void gen_fcvtlq(int rb, int rc)
+{
+    if (unlikely(rc == 31)) {
+        return;
+    }
+    if (unlikely(rb == 31)) {
+        tcg_gen_movi_i64(cpu_fir[rc], 0);
+    } else {
+        TCGv tmp = tcg_temp_new();
+
+        /* The arithmetic right shift here, plus the sign-extended mask below
+           yields a sign-extended result without an explicit ext32s_i64.  */
+        tcg_gen_sari_i64(tmp, cpu_fir[rb], 32);
+        tcg_gen_shri_i64(cpu_fir[rc], cpu_fir[rb], 29);
+        tcg_gen_andi_i64(tmp, tmp, (int32_t)0xc0000000);
+        tcg_gen_andi_i64(cpu_fir[rc], cpu_fir[rc], 0x3fffffff);
+        tcg_gen_or_i64(cpu_fir[rc], cpu_fir[rc], tmp);
+
+        tcg_temp_free(tmp);
+    }
+}
+
 static void gen_fcvtql(int rb, int rc)
 {
     if (unlikely(rc == 31)) {
@@ -647,7 +669,6 @@ static inline void glue(gen_f, name)(int rb, int rc)    \
         tcg_temp_free(tmp);                             \
     }                                                   \
 }
-FARITH2(cvtlq)
 
 /* ??? VAX instruction qualifiers ignored.  */
 FARITH2(sqrtf)
commit ac316ca4b7b27c853c0d9d6b43abdbefc97297d6
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Apr 12 16:14:54 2010 -0700

    target-alpha: Implement rs/rc properly.
    
    This is a per-cpu flag; there's no need for a spinlock of any kind.
    
    We were also failing to manipulate the flag with $31 as a target reg
    and failing to clear the flag on execution of a return-from-interrupt
    instruction.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/linux-user/main.c b/linux-user/main.c
index 71a1b67..5680d8e 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2358,6 +2358,11 @@ void cpu_loop (CPUState *env)
     while (1) {
         trapnr = cpu_alpha_exec (env);
 
+        /* All of the traps imply a transition through PALcode, which
+           implies an REI instruction has been executed.  Which means
+           that the intr_flag should be cleared.  */
+        env->intr_flag = 0;
+
         switch (trapnr) {
         case EXCP_RESET:
             fprintf(stderr, "Reset requested. Exit\n");
@@ -2444,7 +2449,7 @@ void cpu_loop (CPUState *env)
                                     env->ir[IR_A0], env->ir[IR_A1],
                                     env->ir[IR_A2], env->ir[IR_A3],
                                     env->ir[IR_A4], env->ir[IR_A5]);
-		if (trapnr != TARGET_NR_sigreturn
+                if (trapnr != TARGET_NR_sigreturn
                     && trapnr != TARGET_NR_rt_sigreturn) {
                     env->ir[IR_V0] = (sysret < 0 ? -sysret : sysret);
                     env->ir[IR_A3] = (sysret < 0);
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 73413f2..10c78d0 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -2,8 +2,6 @@
 
 DEF_HELPER_2(excp, void, int, int)
 DEF_HELPER_FLAGS_0(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64)
-DEF_HELPER_FLAGS_0(rc, TCG_CALL_CONST, i64)
-DEF_HELPER_FLAGS_0(rs, TCG_CALL_CONST, i64)
 
 DEF_HELPER_2(addqv, i64, i64, i64)
 DEF_HELPER_2(addlv, i64, i64, i64)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index ded71f6..f9cd07a 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -47,32 +47,6 @@ void helper_store_fpcr (uint64_t val)
     cpu_alpha_store_fpcr (env, val);
 }
 
-static spinlock_t intr_cpu_lock = SPIN_LOCK_UNLOCKED;
-
-uint64_t helper_rs(void)
-{
-    uint64_t tmp;
-
-    spin_lock(&intr_cpu_lock);
-    tmp = env->intr_flag;
-    env->intr_flag = 1;
-    spin_unlock(&intr_cpu_lock);
-
-    return tmp;
-}
-
-uint64_t helper_rc(void)
-{
-    uint64_t tmp;
-
-    spin_lock(&intr_cpu_lock);
-    tmp = env->intr_flag;
-    env->intr_flag = 0;
-    spin_unlock(&intr_cpu_lock);
-
-    return tmp;
-}
-
 uint64_t helper_addqv (uint64_t op1, uint64_t op2)
 {
     uint64_t tmp = op1;
@@ -1191,6 +1165,7 @@ void helper_hw_rei (void)
 {
     env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
     env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
+    env->intr_flag = 0;
     /* XXX: re-enable interrupts and memory mapping */
 }
 
@@ -1198,6 +1173,7 @@ void helper_hw_ret (uint64_t a)
 {
     env->pc = a & ~3;
     env->ipr[IPR_EXC_ADDR] = a & 1;
+    env->intr_flag = 0;
     /* XXX: re-enable interrupts and memory mapping */
 }
 
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 96d876b..1c296cf 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1301,6 +1301,19 @@ static void gen_cmp(TCGCond cond, int ra, int rb, int rc,
     }
 }
 
+static void gen_rx(int ra, int set)
+{
+    TCGv_i32 tmp;
+
+    if (ra != 31) {
+        tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, offsetof(CPUState, intr_flag));
+    }
+
+    tmp = tcg_const_i32(set);
+    tcg_gen_st8_i32(tmp, cpu_env, offsetof(CPUState, intr_flag));
+    tcg_temp_free_i32(tmp);
+}
+
 static inline int translate_one(DisasContext *ctx, uint32_t insn)
 {
     uint32_t palcode;
@@ -2392,16 +2405,14 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
             break;
         case 0xE000:
             /* RC */
-            if (ra != 31)
-                gen_helper_rc(cpu_ir[ra]);
+            gen_rx(ra, 0);
             break;
         case 0xE800:
             /* ECB */
             break;
         case 0xF000:
             /* RS */
-            if (ra != 31)
-                gen_helper_rs(cpu_ir[ra]);
+            gen_rx(ra, 1);
             break;
         case 0xF800:
             /* WH64 */
commit dc96be4b975d51f03d0b08e191fddf85b92c0267
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Apr 12 16:12:20 2010 -0700

    target-alpha: Implement cpys{, n, e} inline.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 6072a26..73413f2 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -77,10 +77,6 @@ DEF_HELPER_FLAGS_2(cmpgeq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
 DEF_HELPER_FLAGS_2(cmpgle, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
 DEF_HELPER_FLAGS_2(cmpglt, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
 
-DEF_HELPER_FLAGS_2(cpys, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cpysn, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cpyse, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-
 DEF_HELPER_FLAGS_1(cvtts, TCG_CALL_CONST, i64, i64)
 DEF_HELPER_FLAGS_1(cvtst, TCG_CALL_CONST, i64, i64)
 DEF_HELPER_FLAGS_1(cvtqs, TCG_CALL_CONST, i64, i64)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index dd1af84..ded71f6 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -921,24 +921,6 @@ uint64_t helper_sqrtt (uint64_t a)
     return float64_to_t(fr);
 }
 
-
-/* Sign copy */
-uint64_t helper_cpys(uint64_t a, uint64_t b)
-{
-    return (a & 0x8000000000000000ULL) | (b & ~0x8000000000000000ULL);
-}
-
-uint64_t helper_cpysn(uint64_t a, uint64_t b)
-{
-    return ((~a) & 0x8000000000000000ULL) | (b & ~0x8000000000000000ULL);
-}
-
-uint64_t helper_cpyse(uint64_t a, uint64_t b)
-{
-    return (a & 0xFFF0000000000000ULL) | (b & ~0xFFF0000000000000ULL);
-}
-
-
 /* Comparisons */
 uint64_t helper_cmptun (uint64_t a, uint64_t b)
 {
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 1e9ff58..96d876b 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -774,6 +774,81 @@ static inline void glue(gen_f, name)(DisasContext *ctx,         \
 IEEE_INTCVT(cvtqs)
 IEEE_INTCVT(cvtqt)
 
+static void gen_cpys_internal(int ra, int rb, int rc, int inv_a, uint64_t mask)
+{
+    TCGv va, vb, vmask;
+    int za = 0, zb = 0;
+
+    if (unlikely(rc == 31)) {
+        return;
+    }
+
+    vmask = tcg_const_i64(mask);
+
+    TCGV_UNUSED_I64(va);
+    if (ra == 31) {
+        if (inv_a) {
+            va = vmask;
+        } else {
+            za = 1;
+        }
+    } else {
+        va = tcg_temp_new_i64();
+        tcg_gen_mov_i64(va, cpu_fir[ra]);
+        if (inv_a) {
+            tcg_gen_andc_i64(va, vmask, va);
+        } else {
+            tcg_gen_and_i64(va, va, vmask);
+        }
+    }
+
+    TCGV_UNUSED_I64(vb);
+    if (rb == 31) {
+        zb = 1;
+    } else {
+        vb = tcg_temp_new_i64();
+        tcg_gen_andc_i64(vb, cpu_fir[rb], vmask);
+    }
+
+    switch (za << 1 | zb) {
+    case 0 | 0:
+        tcg_gen_or_i64(cpu_fir[rc], va, vb);
+        break;
+    case 0 | 1:
+        tcg_gen_mov_i64(cpu_fir[rc], va);
+        break;
+    case 2 | 0:
+        tcg_gen_mov_i64(cpu_fir[rc], vb);
+        break;
+    case 2 | 1:
+        tcg_gen_movi_i64(cpu_fir[rc], 0);
+        break;
+    }
+
+    tcg_temp_free(vmask);
+    if (ra != 31) {
+        tcg_temp_free(va);
+    }
+    if (rb != 31) {
+        tcg_temp_free(vb);
+    }
+}
+
+static inline void gen_fcpys(int ra, int rb, int rc)
+{
+    gen_cpys_internal(ra, rb, rc, 0, 0x8000000000000000ULL);
+}
+
+static inline void gen_fcpysn(int ra, int rb, int rc)
+{
+    gen_cpys_internal(ra, rb, rc, 1, 0x8000000000000000ULL);
+}
+
+static inline void gen_fcpyse(int ra, int rb, int rc)
+{
+    gen_cpys_internal(ra, rb, rc, 0, 0xFFF0000000000000ULL);
+}
+
 #define FARITH3(name)                                           \
 static inline void glue(gen_f, name)(int ra, int rb, int rc)    \
 {                                                               \
@@ -802,10 +877,6 @@ static inline void glue(gen_f, name)(int ra, int rb, int rc)    \
         tcg_temp_free(vb);                                      \
     }                                                           \
 }
-/* ??? Ought to expand these inline; simple masking operations.  */
-FARITH3(cpys)
-FARITH3(cpysn)
-FARITH3(cpyse)
 
 /* ??? VAX instruction qualifiers ignored.  */
 FARITH3(addf)
commit caa972256d793359fddc57a54506d7645b3bf9e2
Merge: 70ec48e... e53f27b...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Apr 26 15:10:14 2010 -0500

    Merge remote branch 'qmp/for-anthony' into staging

commit e53f27b9d9df73461308618151fa6e6392aebd85
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Apr 16 17:25:23 2010 +0200

    stash away SCM_RIGHTS fd until a getfd command arrives
    
    If there is already a fd in s->msgfd before recvmsg it is
    closed by parts that this patch does not touch.  So, only
    one descriptor can be "leaked" by attaching it to a command
    other than getfd.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/monitor.c b/monitor.c
index 0dc24a2..754bcc5 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2415,15 +2415,6 @@ static int do_getfd(Monitor *mon, const QDict *qdict, QObject **ret_data)
         return -1;
     }
 
-    fd = dup(fd);
-    if (fd == -1) {
-        if (errno == EMFILE)
-            qerror_report(QERR_TOO_MANY_FILES);
-        else
-            qerror_report(QERR_UNDEFINED_ERROR);
-        return -1;
-    }
-
     QLIST_FOREACH(monfd, &mon->fds, next) {
         if (strcmp(monfd->name, fdname) != 0) {
             continue;
diff --git a/qemu-char.c b/qemu-char.c
index 05df971..ac65a1c 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2000,8 +2000,9 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr,
 static int tcp_get_msgfd(CharDriverState *chr)
 {
     TCPCharDriver *s = chr->opaque;
-
-    return s->msgfd;
+    int fd = s->msgfd;
+    s->msgfd = -1;
+    return fd;
 }
 
 #ifndef _WIN32
@@ -2089,10 +2090,6 @@ static void tcp_chr_read(void *opaque)
             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
         if (size > 0)
             qemu_chr_read(chr, buf, size);
-        if (s->msgfd != -1) {
-            close(s->msgfd);
-            s->msgfd = -1;
-        }
     }
 }
 
commit 97331287ed2c928af6b9f31728d29ef60c3b8cd8
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Apr 6 16:55:54 2010 +0200

    chardev: Document mux option
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index f4b3bfe..83b54c3 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1175,32 +1175,33 @@ DEFHEADING()
 DEFHEADING(Character device options:)
 
 DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
-    "-chardev null,id=id\n"
+    "-chardev null,id=id[,mux=on|off]\n"
     "-chardev socket,id=id[,host=host],port=host[,to=to][,ipv4][,ipv6][,nodelay]\n"
-    "         [,server][,nowait][,telnet] (tcp)\n"
-    "-chardev socket,id=id,path=path[,server][,nowait][,telnet] (unix)\n"
+    "         [,server][,nowait][,telnet][,mux=on|off] (tcp)\n"
+    "-chardev socket,id=id,path=path[,server][,nowait][,telnet],[mux=on|off] (unix)\n"
     "-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]\n"
-    "         [,localport=localport][,ipv4][,ipv6]\n"
-    "-chardev msmouse,id=id\n"
+    "         [,localport=localport][,ipv4][,ipv6][,mux=on|off]\n"
+    "-chardev msmouse,id=id[,mux=on|off]\n"
     "-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]\n"
-    "-chardev file,id=id,path=path\n"
-    "-chardev pipe,id=id,path=path\n"
+    "         [,mux=on|off]\n"
+    "-chardev file,id=id,path=path[,mux=on|off]\n"
+    "-chardev pipe,id=id,path=path[,mux=on|off]\n"
 #ifdef _WIN32
-    "-chardev console,id=id\n"
-    "-chardev serial,id=id,path=path\n"
+    "-chardev console,id=id[,mux=on|off]\n"
+    "-chardev serial,id=id,path=path[,mux=on|off]\n"
 #else
-    "-chardev pty,id=id\n"
-    "-chardev stdio,id=id\n"
+    "-chardev pty,id=id[,mux=on|off]\n"
+    "-chardev stdio,id=id[,mux=on|off]\n"
 #endif
 #ifdef CONFIG_BRLAPI
-    "-chardev braille,id=id\n"
+    "-chardev braille,id=id[,mux=on|off]\n"
 #endif
 #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
         || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
-    "-chardev tty,id=id,path=path\n"
+    "-chardev tty,id=id,path=path[,mux=on|off]\n"
 #endif
 #if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
-    "-chardev parport,id=id,path=path\n"
+    "-chardev parport,id=id,path=path[,mux=on|off]\n"
 #endif
     , QEMU_ARCH_ALL
 )
@@ -1210,7 +1211,7 @@ STEXI
 The general form of a character device option is:
 @table @option
 
- at item -chardev @var{backend} ,id=@var{id} [, at var{options}]
+ at item -chardev @var{backend} ,id=@var{id} [,mux=on|off] [, at var{options}]
 @findex -chardev
 Backend is one of:
 @option{null},
@@ -1232,6 +1233,10 @@ The specific backend will determine the applicable options.
 All devices must have an id, which can be any string up to 127 characters long.
 It is used to uniquely identify this device in other command line directives.
 
+A character device may be used in multiplexing mode by multiple front-ends.
+The key sequence of @key{Control-a} and @key{c} will rotate the input focus
+between attached front-ends. Specify @option{mux=on} to enable this mode.
+
 Options to each backend are described below.
 
 @item -chardev null ,id=@var{id}
commit 157b9319878e67f5c28b8cf39216d42f4b162586
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Apr 6 16:55:53 2010 +0200

    monitor: Reorder intialization to drop initial mux focus
    
    So far a multiplexed monitor started disabled. Restore this property for
    the new way of configuring by moving the monitor initialization before
    all devices (the last one to attach to a char-mux will gain the focus).
    
    Once we have a real use case for that, we may also consider assigning
    the initial focus explicitly.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/vl.c b/vl.c
index 20d24be..a485c58 100644
--- a/vl.c
+++ b/vl.c
@@ -3618,6 +3618,10 @@ int main(int argc, char **argv, char **envp)
         }
     }
 
+    if (qemu_opts_foreach(&qemu_mon_opts, mon_init_func, NULL, 1) != 0) {
+        exit(1);
+    }
+
     if (foreach_device_config(DEV_SERIAL, serial_parse) < 0)
         exit(1);
     if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0)
@@ -3730,9 +3734,6 @@ int main(int argc, char **argv, char **envp)
 
     text_consoles_set_display(ds);
 
-    if (qemu_opts_foreach(&qemu_mon_opts, mon_init_func, NULL, 1) != 0)
-        exit(1);
-
     if (gdbstub_dev && gdbserver_start(gdbstub_dev) < 0) {
         fprintf(stderr, "qemu: could not open gdbserver on device '%s'\n",
                 gdbstub_dev);
commit 140e065d72a2301b0b5f769be664e10ebe223888
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Apr 6 16:55:52 2010 +0200

    monitor: Cleanup ID assignment for compat switch
    
    Canonicalize the ID assignment when creating monitor devices via the
    legacy switch and use less easily colliding names.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/vl.c b/vl.c
index 9ef6f2c..20d24be 100644
--- a/vl.c
+++ b/vl.c
@@ -2348,11 +2348,9 @@ static void monitor_parse(const char *optarg, const char *mode)
     if (strstart(optarg, "chardev:", &p)) {
         snprintf(label, sizeof(label), "%s", p);
     } else {
-        if (monitor_device_index) {
-            snprintf(label, sizeof(label), "monitor%d",
-                     monitor_device_index);
-        } else {
-            snprintf(label, sizeof(label), "monitor");
+        snprintf(label, sizeof(label), "compat_monitor%d",
+                 monitor_device_index);
+        if (monitor_device_index == 0) {
             def = 1;
         }
         opts = qemu_chr_parse_compat(label, optarg);
commit 0e8d2b5575938b8876a3c4bb66ee13c5d306fb6d
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Tue Apr 6 18:55:54 2010 -0300

    Monitor: Return before exiting with 'quit'
    
    The 'quit' Monitor command (implemented by do_quit()) calls
    exit() directly, this is problematic under QMP because QEMU
    exits before having a chance to send the ok response.
    
    Clients don't know if QEMU exited because of a problem or
    because the 'quit' command has been executed.
    
    This commit fixes that by moving the exit() call to the main
    loop, so that do_quit() requests the system to quit, instead
    of calling exit() directly.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/monitor.c b/monitor.c
index ef84298..0dc24a2 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1017,7 +1017,8 @@ static void do_info_cpu_stats(Monitor *mon)
  */
 static int do_quit(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
-    exit(0);
+    monitor_suspend(mon);
+    qemu_system_exit_request();
     return 0;
 }
 
diff --git a/sysemu.h b/sysemu.h
index d0effa0..fa921df 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -45,9 +45,11 @@ void cpu_disable_ticks(void);
 void qemu_system_reset_request(void);
 void qemu_system_shutdown_request(void);
 void qemu_system_powerdown_request(void);
+void qemu_system_exit_request(void);
 int qemu_shutdown_requested(void);
 int qemu_reset_requested(void);
 int qemu_powerdown_requested(void);
+int qemu_exit_requested(void);
 extern qemu_irq qemu_system_powerdown;
 void qemu_system_reset(void);
 
diff --git a/vl.c b/vl.c
index a5a0f41..9ef6f2c 100644
--- a/vl.c
+++ b/vl.c
@@ -1697,6 +1697,7 @@ static int shutdown_requested;
 static int powerdown_requested;
 int debug_requested;
 int vmstop_requested;
+static int exit_requested;
 
 int qemu_shutdown_requested(void)
 {
@@ -1719,6 +1720,12 @@ int qemu_powerdown_requested(void)
     return r;
 }
 
+int qemu_exit_requested(void)
+{
+    /* just return it, we'll exit() anyway */
+    return exit_requested;
+}
+
 static int qemu_debug_requested(void)
 {
     int r = debug_requested;
@@ -1789,6 +1796,12 @@ void qemu_system_powerdown_request(void)
     qemu_notify_event();
 }
 
+void qemu_system_exit_request(void)
+{
+    exit_requested = 1;
+    qemu_notify_event();
+}
+
 #ifdef _WIN32
 static void host_main_loop_wait(int *timeout)
 {
@@ -1925,6 +1938,8 @@ static int vm_can_run(void)
         return 0;
     if (debug_requested)
         return 0;
+    if (exit_requested)
+        return 0;
     return 1;
 }
 
@@ -1977,6 +1992,9 @@ static void main_loop(void)
         if ((r = qemu_vmstop_requested())) {
             vm_stop(r);
         }
+        if (qemu_exit_requested()) {
+            exit(0);
+        }
     }
     pause_all_vcpus();
 }
commit 70ec48ef55e5a3d5ecef8599f3fbdfb87f0740dc
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Apr 10 22:22:28 2010 +0200

    tcg-hppa: Remove automatically implemented opcodes.
    
    Remove neg, ext8u, ext16u, as requested.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 6536a42..cb605f1 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -1431,19 +1431,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
         tcg_out_ext16s(s, args[0], args[1]);
         break;
 
-    /* These three correspond exactly to the fallback implementation.
-       But by including them we reduce the number of TCG ops that
-       need to be generated, and these opcodes are fairly common.  */
-    case INDEX_op_neg_i32:
-        tcg_out_arith(s, args[0], TCG_REG_R0, args[1], INSN_SUB);
-        break;
-    case INDEX_op_ext8u_i32:
-        tcg_out_andi(s, args[0], args[1], 0xff);
-        break;
-    case INDEX_op_ext16u_i32:
-        tcg_out_andi(s, args[0], args[1], 0xffff);
-        break;
-
     case INDEX_op_brcond_i32:
         tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], args[3]);
         break;
@@ -1550,13 +1537,10 @@ static const TCGTargetOpDef hppa_op_defs[] = {
 
     { INDEX_op_bswap16_i32, { "r", "r" } },
     { INDEX_op_bswap32_i32, { "r", "r" } },
-    { INDEX_op_neg_i32, { "r", "r" } },
     { INDEX_op_not_i32, { "r", "r" } },
 
     { INDEX_op_ext8s_i32, { "r", "r" } },
-    { INDEX_op_ext8u_i32, { "r", "r" } },
     { INDEX_op_ext16s_i32, { "r", "r" } },
-    { INDEX_op_ext16u_i32, { "r", "r" } },
 
     { INDEX_op_brcond_i32, { "rZ", "rJ" } },
     { INDEX_op_brcond2_i32,  { "rZ", "rZ", "rJ", "rJ" } },
diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h
index 7e21f1d..a5cc440 100644
--- a/tcg/hppa/tcg-target.h
+++ b/tcg/hppa/tcg-target.h
@@ -89,15 +89,17 @@ enum {
 #define TCG_TARGET_HAS_rot_i32
 #define TCG_TARGET_HAS_ext8s_i32
 #define TCG_TARGET_HAS_ext16s_i32
-#define TCG_TARGET_HAS_ext8u_i32
-#define TCG_TARGET_HAS_ext16u_i32
 #define TCG_TARGET_HAS_bswap16_i32
 #define TCG_TARGET_HAS_bswap32_i32
 #define TCG_TARGET_HAS_not_i32
-#define TCG_TARGET_HAS_neg_i32
 #define TCG_TARGET_HAS_andc_i32
 // #define TCG_TARGET_HAS_orc_i32
 
+/* optional instructions automatically implemented */
+#undef TCG_TARGET_HAS_neg_i32           /* sub rd, 0, rs */
+#undef TCG_TARGET_HAS_ext8u_i32         /* and rd, rs, 0xff */
+#undef TCG_TARGET_HAS_ext16u_i32        /* and rd, rs, 0xffff */
+
 #define TCG_TARGET_HAS_GUEST_BASE
 
 /* Note: must be synced with dyngen-exec.h */
commit 2d097a83e223d3e06de5047e95eeadf1f919ac56
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Apr 9 21:49:00 2010 +0200

    tcg-hppa: Fix branch offset during retranslation.
    
    Branch offsets should only be overwritten during relocation,
    to support partial retranslation.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 6941e22..6536a42 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -723,8 +723,11 @@ static void tcg_out_branch(TCGContext *s, int label_index, int nul)
 
         tcg_out32(s, op | reassemble_17(val));
     } else {
+        /* We need to keep the offset unchanged for retranslation.  */
+        uint32_t old_insn = *(uint32_t *)s->code_ptr;
+
         tcg_out_reloc(s, s->code_ptr, R_PARISC_PCREL17F, label_index, 0);
-        tcg_out32(s, op);
+        tcg_out32(s, op | (old_insn & 0x1f1ffdu));
     }
 }
 
@@ -777,11 +780,14 @@ static void tcg_out_brcond(TCGContext *s, int cond, TCGArg c1,
         tcg_out32(s, op | reassemble_12(val));
         tcg_out_nop(s);
     } else {
+        /* We need to keep the offset unchanged for retranslation.  */
+        uint32_t old_insn = *(uint32_t *)s->code_ptr;
+
         tcg_out_reloc(s, s->code_ptr, R_PARISC_PCREL12F, label_index, 0);
         /* ??? Assume that all branches to undefined labels are forward.
            Which means that if the nul bit is set, the delay slot is
            not executed if the branch is taken, which is what we want.  */
-        tcg_out32(s, op | 2);
+        tcg_out32(s, op | 2 | (old_insn & 0x1ffdu));
     }
 }
 
commit 739734cb5cf90c3e692d41b51fa095240b49ddd7
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Apr 9 10:49:10 2010 -0700

    tcg-hppa: Schedule the address masking after the TLB load.
    
    Issue the tlb load as early as possible and perform the address
    masking while the load is completing.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 2f3b770..6941e22 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -904,7 +904,6 @@ static int tcg_out_tlb_read(TCGContext *s, int r0, int r1, int addrlo,
        CPU_TLB_ENTRY_BITS is > 3, so we can't merge that shift with the
        add that follows.  */
     tcg_out_extr(s, r1, addrlo, TARGET_PAGE_BITS, CPU_TLB_BITS, 0);
-    tcg_out_andi(s, r0, addrlo, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
     tcg_out_shli(s, r1, r1, CPU_TLB_ENTRY_BITS);
     tcg_out_arith(s, r1, r1, TCG_AREG0, INSN_ADDL);
 
@@ -927,6 +926,12 @@ static int tcg_out_tlb_read(TCGContext *s, int r0, int r1, int addrlo,
         tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, r1, offset);
     }
 
+    /* Compute the value that ought to appear in the TLB for a hit, namely, the page
+       of the address.  We include the low N bits of the address to catch unaligned
+       accesses and force them onto the slow path.  Do this computation after having
+       issued the load from the TLB slot to give the load time to complete.  */
+    tcg_out_andi(s, r0, addrlo, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
+
     /* If not equal, jump to lab_miss. */
     if (TARGET_LONG_BITS == 64) {
         tcg_out_brcond2(s, TCG_COND_NE, TCG_REG_R20, TCG_REG_R23,
commit f061b40e91b96d32e535cc81362904c685483506
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Apr 9 10:48:02 2010 -0700

    tcg-hppa: Fix softmmu loads and stores.
    
    Along the tlb hit path, we were modifying the variables holding the input
    register numbers, which lead to incorrect expansion of the tlb miss path.
    Fix this by extracting the tlb hit path to separate functions with their
    own local variables.  This also makes the difference between softmmu and
    user-only easier to read.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index ffdaf00..2f3b770 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -939,108 +939,97 @@ static int tcg_out_tlb_read(TCGContext *s, int r0, int r1, int addrlo,
 }
 #endif
 
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
+static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo_reg, int datahi_reg,
+                                   int addr_reg, int addend_reg, int opc)
 {
-    int addr_reg, addr_reg2;
-    int data_reg, data_reg2;
-    int r0, r1, mem_index, s_bits, bswap;
-    tcg_target_long offset;
-#if defined(CONFIG_SOFTMMU)
-    int lab1, lab2, argreg;
-#endif
-
-    data_reg = *args++;
-    data_reg2 = (opc == 3 ? *args++ : TCG_REG_R0);
-    addr_reg = *args++;
-    addr_reg2 = (TARGET_LONG_BITS == 64 ? *args++ : TCG_REG_R0);
-    mem_index = *args;
-    s_bits = opc & 3;
-
-    r0 = TCG_REG_R26;
-    r1 = TCG_REG_R25;
-
-#if defined(CONFIG_SOFTMMU)
-    lab1 = gen_new_label();
-    lab2 = gen_new_label();
-
-    offset = tcg_out_tlb_read(s, r0, r1, addr_reg, addr_reg2, s_bits, lab1,
-                              offsetof(CPUState,
-                                       tlb_table[mem_index][0].addr_read));
-
-    /* TLB Hit.  */
-    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, (offset ? TCG_REG_R1 : r1),
-               offsetof(CPUState, tlb_table[mem_index][0].addend) - offset);
-
-    tcg_out_arith(s, r0, addr_reg, TCG_REG_R20, INSN_ADDL);
-    offset = TCG_REG_R0;
-#else
-    r0 = addr_reg;
-    offset = GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_R0;
-#endif
-
 #ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 0;
+    const int bswap = 0;
 #else
-    bswap = 1;
+    const int bswap = 1;
 #endif
+
     switch (opc) {
     case 0:
-        tcg_out_ldst_index(s, data_reg, r0, offset, INSN_LDBX);
+        tcg_out_ldst_index(s, datalo_reg, addr_reg, addend_reg, INSN_LDBX);
         break;
     case 0 | 4:
-        tcg_out_ldst_index(s, data_reg, r0, offset, INSN_LDBX);
-        tcg_out_ext8s(s, data_reg, data_reg);
+        tcg_out_ldst_index(s, datalo_reg, addr_reg, addend_reg, INSN_LDBX);
+        tcg_out_ext8s(s, datalo_reg, datalo_reg);
         break;
     case 1:
-        tcg_out_ldst_index(s, data_reg, r0, offset, INSN_LDHX);
+        tcg_out_ldst_index(s, datalo_reg, addr_reg, addend_reg, INSN_LDHX);
         if (bswap) {
-            tcg_out_bswap16(s, data_reg, data_reg, 0);
+            tcg_out_bswap16(s, datalo_reg, datalo_reg, 0);
         }
         break;
     case 1 | 4:
-        tcg_out_ldst_index(s, data_reg, r0, offset, INSN_LDHX);
+        tcg_out_ldst_index(s, datalo_reg, addr_reg, addend_reg, INSN_LDHX);
         if (bswap) {
-            tcg_out_bswap16(s, data_reg, data_reg, 1);
+            tcg_out_bswap16(s, datalo_reg, datalo_reg, 1);
         } else {
-            tcg_out_ext16s(s, data_reg, data_reg);
+            tcg_out_ext16s(s, datalo_reg, datalo_reg);
         }
         break;
     case 2:
-        tcg_out_ldst_index(s, data_reg, r0, offset, INSN_LDWX);
+        tcg_out_ldst_index(s, datalo_reg, addr_reg, addend_reg, INSN_LDWX);
         if (bswap) {
-            tcg_out_bswap32(s, data_reg, data_reg, TCG_REG_R20);
+            tcg_out_bswap32(s, datalo_reg, datalo_reg, TCG_REG_R20);
         }
         break;
     case 3:
         if (bswap) {
-            int t = data_reg2;
-            data_reg2 = data_reg;
-            data_reg = t;
+            int t = datahi_reg;
+            datahi_reg = datalo_reg;
+            datalo_reg = t;
         }
-        if (offset == TCG_REG_R0) {
-            /* Make sure not to clobber the base register.  */
-            if (data_reg2 == r0) {
-                tcg_out_ldst(s, data_reg, r0, 4, INSN_LDW);
-                tcg_out_ldst(s, data_reg2, r0, 0, INSN_LDW);
-            } else {
-                tcg_out_ldst(s, data_reg2, r0, 0, INSN_LDW);
-                tcg_out_ldst(s, data_reg, r0, 4, INSN_LDW);
-            }
+        /* We can't access the low-part with a reg+reg addressing mode,
+           so perform the addition now and use reg_ofs addressing mode.  */
+        if (addend_reg != TCG_REG_R0) {
+            tcg_out_arith(s, TCG_REG_R20, addr_reg, addend_reg, INSN_ADD);
+            addr_reg = TCG_REG_R20;
+	}
+        /* Make sure not to clobber the base register.  */
+        if (datahi_reg == addr_reg) {
+            tcg_out_ldst(s, datalo_reg, addr_reg, 4, INSN_LDW);
+            tcg_out_ldst(s, datahi_reg, addr_reg, 0, INSN_LDW);
         } else {
-            tcg_out_addi2(s, TCG_REG_R20, r0, 4);
-            tcg_out_ldst_index(s, data_reg2, r0, offset, INSN_LDWX);
-            tcg_out_ldst_index(s, data_reg, TCG_REG_R20, offset, INSN_LDWX);
+            tcg_out_ldst(s, datahi_reg, addr_reg, 0, INSN_LDW);
+            tcg_out_ldst(s, datalo_reg, addr_reg, 4, INSN_LDW);
         }
         if (bswap) {
-            tcg_out_bswap32(s, data_reg, data_reg, TCG_REG_R20);
-            tcg_out_bswap32(s, data_reg2, data_reg2, TCG_REG_R20);
+            tcg_out_bswap32(s, datalo_reg, datalo_reg, TCG_REG_R20);
+            tcg_out_bswap32(s, datahi_reg, datahi_reg, TCG_REG_R20);
         }
         break;
     default:
         tcg_abort();
     }
+}
+
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
+{
+    int datalo_reg = *args++;
+    /* Note that datahi_reg is only used for 64-bit loads.  */
+    int datahi_reg = (opc == 3 ? *args++ : TCG_REG_R0);
+    int addrlo_reg = *args++;
 
 #if defined(CONFIG_SOFTMMU)
+    /* Note that addrhi_reg is only used for 64-bit guests.  */
+    int addrhi_reg = (TARGET_LONG_BITS == 64 ? *args++ : TCG_REG_R0);
+    int mem_index = *args;
+    int lab1, lab2, argreg, offset;
+
+    lab1 = gen_new_label();
+    lab2 = gen_new_label();
+
+    offset = offsetof(CPUState, tlb_table[mem_index][0].addr_read);
+    offset = tcg_out_tlb_read(s, TCG_REG_R26, TCG_REG_R25, addrlo_reg, addrhi_reg,
+                              opc & 3, lab1, offset);
+
+    /* TLB Hit.  */
+    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, (offset ? TCG_REG_R1 : TCG_REG_R25),
+               offsetof(CPUState, tlb_table[mem_index][0].addend) - offset);
+    tcg_out_qemu_ld_direct(s, datalo_reg, datahi_reg, addrlo_reg, TCG_REG_R20, opc);
     tcg_out_branch(s, lab2, 1);
 
     /* TLB Miss.  */
@@ -1048,34 +1037,34 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     tcg_out_label(s, lab1, (tcg_target_long)s->code_ptr);
 
     argreg = TCG_REG_R26;
-    tcg_out_mov(s, argreg--, addr_reg);
+    tcg_out_mov(s, argreg--, addrlo_reg);
     if (TARGET_LONG_BITS == 64) {
-        tcg_out_mov(s, argreg--, addr_reg2);
+        tcg_out_mov(s, argreg--, addrhi_reg);
     }
     tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
 
-    tcg_out_call(s, qemu_ld_helpers[s_bits]);
+    tcg_out_call(s, qemu_ld_helpers[opc & 3]);
 
     switch (opc) {
     case 0:
-        tcg_out_andi(s, data_reg, TCG_REG_RET0, 0xff);
+        tcg_out_andi(s, datalo_reg, TCG_REG_RET0, 0xff);
         break;
     case 0 | 4:
-        tcg_out_ext8s(s, data_reg, TCG_REG_RET0);
+        tcg_out_ext8s(s, datalo_reg, TCG_REG_RET0);
         break;
     case 1:
-        tcg_out_andi(s, data_reg, TCG_REG_RET0, 0xffff);
+        tcg_out_andi(s, datalo_reg, TCG_REG_RET0, 0xffff);
         break;
     case 1 | 4:
-        tcg_out_ext16s(s, data_reg, TCG_REG_RET0);
+        tcg_out_ext16s(s, datalo_reg, TCG_REG_RET0);
         break;
     case 2:
     case 2 | 4:
-        tcg_out_mov(s, data_reg, TCG_REG_RET0);
+        tcg_out_mov(s, datalo_reg, TCG_REG_RET0);
         break;
     case 3:
-        tcg_out_mov(s, data_reg, TCG_REG_RET0);
-        tcg_out_mov(s, data_reg2, TCG_REG_RET1);
+        tcg_out_mov(s, datahi_reg, TCG_REG_RET0);
+        tcg_out_mov(s, datalo_reg, TCG_REG_RET1);
         break;
     default:
         tcg_abort();
@@ -1083,92 +1072,83 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 
     /* label2: */
     tcg_out_label(s, lab2, (tcg_target_long)s->code_ptr);
+#else
+    tcg_out_qemu_ld_direct(s, datalo_reg, datahi_reg, addrlo_reg,
+                           (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_R0), opc);
 #endif
 }
 
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
+static void tcg_out_qemu_st_direct(TCGContext *s, int datalo_reg, int datahi_reg,
+                                   int addr_reg, int opc)
 {
-    int addr_reg, addr_reg2;
-    int data_reg, data_reg2;
-    int r0, r1, mem_index, s_bits, bswap;
-#if defined(CONFIG_SOFTMMU)
-    tcg_target_long offset;
-    int lab1, lab2, argreg;
-#endif
-
-    data_reg = *args++;
-    data_reg2 = (opc == 3 ? *args++ : 0);
-    addr_reg = *args++;
-    addr_reg2 = (TARGET_LONG_BITS == 64 ? *args++ : 0);
-    mem_index = *args;
-    s_bits = opc;
-
-    r0 = TCG_REG_R26;
-    r1 = TCG_REG_R25;
-
-#if defined(CONFIG_SOFTMMU)
-    lab1 = gen_new_label();
-    lab2 = gen_new_label();
-
-    offset = tcg_out_tlb_read(s, r0, r1, addr_reg, addr_reg2, s_bits, lab1,
-                              offsetof(CPUState,
-                                       tlb_table[mem_index][0].addr_write));
-
-    /* TLB Hit.  */
-    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, (offset ? TCG_REG_R1 : r1),
-               offsetof(CPUState, tlb_table[mem_index][0].addend) - offset);
-
-    tcg_out_arith(s, r0, addr_reg, TCG_REG_R20, INSN_ADDL);
-#else
-    /* There are no indexed stores, so if GUEST_BASE is set
-       we must do the add explicitly.  Careful to avoid R20,
-       which is used for the bswaps to follow.  */
-    if (GUEST_BASE == 0) {
-        r0 = addr_reg;
-    } else {
-        tcg_out_arith(s, TCG_REG_R31, addr_reg, TCG_GUEST_BASE_REG, INSN_ADDL);
-        r0 = TCG_REG_R31;
-    }
-#endif
-
 #ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 0;
+    const int bswap = 0;
 #else
-    bswap = 1;
+    const int bswap = 1;
 #endif
+
     switch (opc) {
     case 0:
-        tcg_out_ldst(s, data_reg, r0, 0, INSN_STB);
+        tcg_out_ldst(s, datalo_reg, addr_reg, 0, INSN_STB);
         break;
     case 1:
         if (bswap) {
-            tcg_out_bswap16(s, TCG_REG_R20, data_reg, 0);
-            data_reg = TCG_REG_R20;
+            tcg_out_bswap16(s, TCG_REG_R20, datalo_reg, 0);
+            datalo_reg = TCG_REG_R20;
         }
-        tcg_out_ldst(s, data_reg, r0, 0, INSN_STH);
+        tcg_out_ldst(s, datalo_reg, addr_reg, 0, INSN_STH);
         break;
     case 2:
         if (bswap) {
-            tcg_out_bswap32(s, TCG_REG_R20, data_reg, TCG_REG_R20);
-            data_reg = TCG_REG_R20;
+            tcg_out_bswap32(s, TCG_REG_R20, datalo_reg, TCG_REG_R20);
+            datalo_reg = TCG_REG_R20;
         }
-        tcg_out_ldst(s, data_reg, r0, 0, INSN_STW);
+        tcg_out_ldst(s, datalo_reg, addr_reg, 0, INSN_STW);
         break;
     case 3:
         if (bswap) {
-            tcg_out_bswap32(s, TCG_REG_R20, data_reg, TCG_REG_R20);
-            tcg_out_bswap32(s, TCG_REG_R23, data_reg2, TCG_REG_R23);
-            data_reg2 = TCG_REG_R20;
-            data_reg = TCG_REG_R23;
+            tcg_out_bswap32(s, TCG_REG_R20, datalo_reg, TCG_REG_R20);
+            tcg_out_bswap32(s, TCG_REG_R23, datahi_reg, TCG_REG_R23);
+            datahi_reg = TCG_REG_R20;
+            datalo_reg = TCG_REG_R23;
         }
-        tcg_out_ldst(s, data_reg2, r0, 0, INSN_STW);
-        tcg_out_ldst(s, data_reg, r0, 4, INSN_STW);
+        tcg_out_ldst(s, datahi_reg, addr_reg, 0, INSN_STW);
+        tcg_out_ldst(s, datalo_reg, addr_reg, 4, INSN_STW);
         break;
     default:
         tcg_abort();
     }
 
+}
+
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
+{
+    int datalo_reg = *args++;
+    /* Note that datahi_reg is only used for 64-bit loads.  */
+    int datahi_reg = (opc == 3 ? *args++ : TCG_REG_R0);
+    int addrlo_reg = *args++;
+
 #if defined(CONFIG_SOFTMMU)
+    /* Note that addrhi_reg is only used for 64-bit guests.  */
+    int addrhi_reg = (TARGET_LONG_BITS == 64 ? *args++ : TCG_REG_R0);
+    int mem_index = *args;
+    int lab1, lab2, argreg, offset;
+
+    lab1 = gen_new_label();
+    lab2 = gen_new_label();
+
+    offset = offsetof(CPUState, tlb_table[mem_index][0].addr_write);
+    offset = tcg_out_tlb_read(s, TCG_REG_R26, TCG_REG_R25, addrlo_reg, addrhi_reg,
+                              opc, lab1, offset);
+
+    /* TLB Hit.  */
+    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, (offset ? TCG_REG_R1 : TCG_REG_R25),
+               offsetof(CPUState, tlb_table[mem_index][0].addend) - offset);
+
+    /* There are no indexed stores, so we must do this addition explitly.
+       Careful to avoid R20, which is used for the bswaps to follow.  */
+    tcg_out_arith(s, TCG_REG_R31, addrlo_reg, TCG_REG_R20, INSN_ADDL);
+    tcg_out_qemu_st_direct(s, datalo_reg, datahi_reg, TCG_REG_R31, opc);
     tcg_out_branch(s, lab2, 1);
 
     /* TLB Miss.  */
@@ -1176,22 +1156,22 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
     tcg_out_label(s, lab1, (tcg_target_long)s->code_ptr);
 
     argreg = TCG_REG_R26;
-    tcg_out_mov(s, argreg--, addr_reg);
+    tcg_out_mov(s, argreg--, addrlo_reg);
     if (TARGET_LONG_BITS == 64) {
-        tcg_out_mov(s, argreg--, addr_reg2);
+        tcg_out_mov(s, argreg--, addrhi_reg);
     }
 
     switch(opc) {
     case 0:
-        tcg_out_andi(s, argreg--, data_reg, 0xff);
+        tcg_out_andi(s, argreg--, datalo_reg, 0xff);
         tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
         break;
     case 1:
-        tcg_out_andi(s, argreg--, data_reg, 0xffff);
+        tcg_out_andi(s, argreg--, datalo_reg, 0xffff);
         tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
         break;
     case 2:
-        tcg_out_mov(s, argreg--, data_reg);
+        tcg_out_mov(s, argreg--, datalo_reg);
         tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
         break;
     case 3:
@@ -1205,8 +1185,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
             argreg = TCG_REG_R20;
             tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
         }
-        tcg_out_mov(s, TCG_REG_R23, data_reg2);
-        tcg_out_mov(s, TCG_REG_R24, data_reg);
+        tcg_out_mov(s, TCG_REG_R23, datahi_reg);
+        tcg_out_mov(s, TCG_REG_R24, datalo_reg);
         tcg_out_st(s, TCG_TYPE_I32, argreg, TCG_REG_SP,
                    TCG_TARGET_CALL_STACK_OFFSET - 4);
         break;
@@ -1214,10 +1194,18 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
         tcg_abort();
     }
 
-    tcg_out_call(s, qemu_st_helpers[s_bits]);
+    tcg_out_call(s, qemu_st_helpers[opc]);
 
     /* label2: */
     tcg_out_label(s, lab2, (tcg_target_long)s->code_ptr);
+#else
+    /* There are no indexed stores, so if GUEST_BASE is set we must do the add
+       explicitly.  Careful to avoid R20, which is used for the bswaps to follow.  */
+    if (GUEST_BASE != 0) {
+        tcg_out_arith(s, TCG_REG_R31, addrlo_reg, TCG_GUEST_BASE_REG, INSN_ADDL);
+        addrlo_reg = TCG_REG_R31;
+    }
+    tcg_out_qemu_st_direct(s, datalo_reg, datahi_reg, addrlo_reg, opc);
 #endif
 }
 
commit 884d348b7bd4c6f1c1993dafd2e89ac31fe4e543
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Apr 9 10:46:40 2010 -0700

    tcg-hppa: Fix GUEST_BASE initialization in prologue.
    
    Load from the guest_base variable rather than embed a constant.
    Always reserve TCG_GUEST_BASE_REG if guest base support enabled.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index c9410b2..ffdaf00 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -34,10 +34,6 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 /* This is an 8 byte temp slot in the stack frame.  */
 #define STACK_TEMP_OFS -16
 
-#ifndef GUEST_BASE
-#define GUEST_BASE 0
-#endif
-
 #ifdef CONFIG_USE_GUEST_BASE
 #define TCG_GUEST_BASE_REG TCG_REG_R16
 #else
@@ -1649,9 +1645,13 @@ void tcg_target_qemu_prologue(TCGContext *s)
                    TCG_REG_SP, -frame_size + i * 4);
     }
 
-    if (GUEST_BASE != 0) {
-        tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
-    }
+#ifdef CONFIG_USE_GUEST_BASE
+    /* Note that GUEST_BASE can change after the prologue is generated.
+       To combat that, load the value from the variable instead of
+       embedding a constant here.  */
+    tcg_out_ld(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG,
+               TCG_REG_R0, (tcg_target_long)&guest_base);
+#endif
 
     /* Jump to TB, and adjust R18 to be the return address.  */
     tcg_out32(s, INSN_BLE_SR4 | INSN_R2(TCG_REG_R26));
@@ -1696,9 +1696,9 @@ void tcg_target_init(TCGContext *s)
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_DP);  /* data pointer */
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);  /* stack pointer */
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R31); /* ble link reg */
-    if (GUEST_BASE != 0) {
-        tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
-    }
+#ifdef CONFIG_USE_GUEST_BASE
+    tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
+#endif
 
     tcg_add_target_add_op_defs(hppa_op_defs);
 }
commit 0085bd5161190840ed810d771a63c8a66e7bc380
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Apr 9 10:45:49 2010 -0700

    tcg-hppa: Constrain immediate inputs to and_i32, or_i32, andc_i32.
    
    Define "M" constraint for and_mask_p and "O" constraint for or_mask_p.
    Assume that inputs are correct in tcg_out_ori and tcg_out_andi.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index daddaab..c9410b2 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -97,6 +97,9 @@ static inline int check_fit_tl(tcg_target_long val, unsigned int bits)
    Copied from gcc sources.  */
 static inline int or_mask_p(tcg_target_ulong mask)
 {
+    if (mask == 0 || mask == -1) {
+        return 0;
+    }
     mask += mask & -mask;
     return (mask & (mask - 1)) == 0;
 }
@@ -213,6 +216,12 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
     case 'K':
         ct->ct |= TCG_CT_CONST_MS11;
         break;
+    case 'M':
+        ct->ct |= TCG_CT_CONST_AND;
+        break;
+    case 'O':
+        ct->ct |= TCG_CT_CONST_OR;
+        break;
     default:
         return -1;
     }
@@ -236,6 +245,10 @@ static int tcg_target_const_match(tcg_target_long val,
         return check_fit_tl(val, 11);
     } else if (ct & TCG_CT_CONST_MS11) {
         return check_fit_tl(-val, 11);
+    } else if (ct & TCG_CT_CONST_AND) {
+        return and_mask_p(val);
+    } else if (ct & TCG_CT_CONST_OR) {
+        return or_mask_p(val);
     }
     return 0;
 }
@@ -474,70 +487,54 @@ static void tcg_out_vshd(TCGContext *s, int ret, int hi, int lo, int creg)
 
 static void tcg_out_ori(TCGContext *s, int ret, int arg, tcg_target_ulong m)
 {
-    if (m == 0) {
-        tcg_out_mov(s, ret, arg);
-    } else if (m == -1) {
-        tcg_out_movi(s, TCG_TYPE_I32, ret, -1);
-    } else if (or_mask_p(m)) {
-        int bs0, bs1;
-
-        for (bs0 = 0; bs0 < 32; bs0++) {
-            if ((m & (1u << bs0)) != 0) {
-                break;
-            }
+    int bs0, bs1;
+
+    /* Note that the argument is constrained to match or_mask_p.  */
+    for (bs0 = 0; bs0 < 32; bs0++) {
+        if ((m & (1u << bs0)) != 0) {
+            break;
         }
-        for (bs1 = bs0; bs1 < 32; bs1++) {
-            if ((m & (1u << bs1)) == 0) {
-                break;
-            }
+    }
+    for (bs1 = bs0; bs1 < 32; bs1++) {
+        if ((m & (1u << bs1)) == 0) {
+            break;
         }
-        assert(bs1 == 32 || (1ul << bs1) > m);
-
-        tcg_out_mov(s, ret, arg);
-        tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(-1)
-                  | INSN_SHDEP_CP(31 - bs0) | INSN_DEP_LEN(bs1 - bs0));
-    } else {
-        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R1, m);
-        tcg_out_arith(s, ret, arg, TCG_REG_R1, INSN_OR);
     }
+    assert(bs1 == 32 || (1ul << bs1) > m);
+
+    tcg_out_mov(s, ret, arg);
+    tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(-1)
+              | INSN_SHDEP_CP(31 - bs0) | INSN_DEP_LEN(bs1 - bs0));
 }
 
 static void tcg_out_andi(TCGContext *s, int ret, int arg, tcg_target_ulong m)
 {
-    if (m == 0) {
-        tcg_out_mov(s, ret, TCG_REG_R0);
-    } else if (m == -1) {
-        tcg_out_mov(s, ret, arg);
-    } else if (and_mask_p(m)) {
-        int ls0, ls1, ms0;
+    int ls0, ls1, ms0;
 
-        for (ls0 = 0; ls0 < 32; ls0++) {
-            if ((m & (1u << ls0)) == 0) {
-                break;
-            }
+    /* Note that the argument is constrained to match and_mask_p.  */
+    for (ls0 = 0; ls0 < 32; ls0++) {
+        if ((m & (1u << ls0)) == 0) {
+            break;
         }
-        for (ls1 = ls0; ls1 < 32; ls1++) {
-            if ((m & (1u << ls1)) != 0) {
-                break;
-            }
+    }
+    for (ls1 = ls0; ls1 < 32; ls1++) {
+        if ((m & (1u << ls1)) != 0) {
+            break;
         }
-        for (ms0 = ls1; ms0 < 32; ms0++) {
-            if ((m & (1u << ms0)) == 0) {
-                break;
-            }
+    }
+    for (ms0 = ls1; ms0 < 32; ms0++) {
+        if ((m & (1u << ms0)) == 0) {
+            break;
         }
-        assert (ms0 == 32);
+    }
+    assert (ms0 == 32);
 
-        if (ls1 == 32) {
-            tcg_out_extr(s, ret, arg, 0, ls0, 0);
-        } else {
-            tcg_out_mov(s, ret, arg);
-            tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(0)
-                      | INSN_SHDEP_CP(31 - ls0) | INSN_DEP_LEN(ls1 - ls0));
-        }
+    if (ls1 == 32) {
+        tcg_out_extr(s, ret, arg, 0, ls0, 0);
     } else {
-        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R1, m);
-        tcg_out_arith(s, ret, arg, TCG_REG_R1, INSN_AND);
+        tcg_out_mov(s, ret, arg);
+        tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(0)
+                  | INSN_SHDEP_CP(31 - ls0) | INSN_DEP_LEN(ls1 - ls0));
     }
 }
 
@@ -1539,10 +1536,13 @@ static const TCGTargetOpDef hppa_op_defs[] = {
 
     { INDEX_op_add_i32, { "r", "rZ", "ri" } },
     { INDEX_op_sub_i32, { "r", "rI", "ri" } },
-    { INDEX_op_and_i32, { "r", "rZ", "ri" } },
-    { INDEX_op_or_i32, { "r", "rZ", "ri" } },
+    { INDEX_op_and_i32, { "r", "rZ", "rM" } },
+    { INDEX_op_or_i32, { "r", "rZ", "rO" } },
     { INDEX_op_xor_i32, { "r", "rZ", "rZ" } },
-    { INDEX_op_andc_i32, { "r", "rZ", "ri" } },
+    /* Note that the second argument will be inverted, which means
+       we want a constant whose inversion matches M, and that O = ~M.
+       See the implementation of and_mask_p.  */
+    { INDEX_op_andc_i32, { "r", "rZ", "rO" } },
 
     { INDEX_op_mul_i32, { "r", "r", "r" } },
     { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h
index b76e389..7e21f1d 100644
--- a/tcg/hppa/tcg-target.h
+++ b/tcg/hppa/tcg-target.h
@@ -73,6 +73,8 @@ enum {
 #define TCG_CT_CONST_S5   0x0200
 #define TCG_CT_CONST_S11  0x0400
 #define TCG_CT_CONST_MS11 0x0800
+#define TCG_CT_CONST_AND  0x1000
+#define TCG_CT_CONST_OR   0x2000
 
 /* used for function call generation */
 #define TCG_REG_CALL_STACK TCG_REG_SP
commit ed18c5ce1d2aabdaa0a138463789b9fe812bb0e0
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Apr 26 10:27:22 2010 -0700

    linux-user: Fix sparc32plus stat64 syscalls.
    
    Check TARGET_ABI_BITS, not TARGET_LONG_BITS, when deciding
    whether or not the guest needs special 64-bit stat translation.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 26c0fb4..eb77ade 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4021,7 +4021,7 @@ static inline abi_long host_to_target_stat64(void *cpu_env,
     } else
 #endif
     {
-#if (TARGET_LONG_BITS == 64) && (!defined(TARGET_ALPHA))
+#if TARGET_ABI_BITS == 64 && !defined(TARGET_ALPHA)
         struct target_stat *target_st;
 #else
         struct target_stat64 *target_st;
commit 060718c19423fd1b24fa3a232bf99c5c97a7d61b
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Apr 26 10:17:24 2010 -0700

    target-sparc: Fix -singlestep.
    
    Single-stepping was not properly updating npc, resulting in some
    instructions being executed twice.  In addition, we were emitting
    dead code at the end of the TB.
    
    Fix both by teaching gen_goto_tb to avoid goto_tb for single-step
    and removing the special-case code in gen_intermediate_code_internal.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index b54c520..be2a116 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -79,6 +79,7 @@ typedef struct DisasContext {
     int mem_idx;
     int fpu_enabled;
     int address_mask_32bit;
+    int singlestep;
     uint32_t cc_op;  /* current CC operation */
     struct TranslationBlock *tb;
     sparc_def_t *def;
@@ -234,7 +235,8 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num,
 
     tb = s->tb;
     if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) &&
-        (npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK))  {
+        (npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) &&
+        !s->singlestep)  {
         /* jump to same page: we can use a direct jump */
         tcg_gen_goto_tb(tb_num);
         tcg_gen_movi_tl(cpu_pc, pc);
@@ -4694,6 +4696,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
 #ifdef TARGET_SPARC64
     dc->address_mask_32bit = env->pstate & PS_AM;
 #endif
+    dc->singlestep = (env->singlestep_enabled || singlestep);
     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
 
     cpu_tmp0 = tcg_temp_new();
@@ -4754,9 +4757,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
             break;
         /* if single step mode, we generate only one instruction and
            generate an exception */
-        if (env->singlestep_enabled || singlestep) {
-            tcg_gen_movi_tl(cpu_pc, dc->pc);
-            tcg_gen_exit_tb(0);
+        if (dc->singlestep) {
             break;
         }
     } while ((gen_opc_ptr < gen_opc_end) &&
commit 6164e6d6e86e8f3f0b5ff7ae08b677026cb291c3
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Tue Mar 23 13:37:13 2010 -0300

    kvm_init_vcpu requires global lock held
    
    Since it accesses data protected by the lock.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpus.c b/cpus.c
index 8450ee4..2bf87d2 100644
--- a/cpus.c
+++ b/cpus.c
@@ -401,6 +401,7 @@ static void *kvm_cpu_thread_fn(void *arg)
 {
     CPUState *env = arg;
 
+    qemu_mutex_lock(&qemu_global_mutex);
     qemu_thread_self(env->thread);
     if (kvm_enabled())
         kvm_init_vcpu(env);
@@ -408,7 +409,6 @@ static void *kvm_cpu_thread_fn(void *arg)
     kvm_block_io_signals(env);
 
     /* signal CPU creation */
-    qemu_mutex_lock(&qemu_global_mutex);
     env->created = 1;
     qemu_cond_signal(&qemu_cpu_cond);
 
commit 204204308b011d5fe494970255b318ec444d1d45
Author: Sheng Yang <sheng at linux.intel.com>
Date:   Tue Mar 23 13:37:12 2010 -0300

    kvm: allow qemu to set EPT identity mapping address
    
    If we use larger BIOS image than current 256KB, we would need move reserved
    TSS and EPT identity mapping pages. Currently TSS support this, but not
    EPT.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index bb6dafa..f73b47b 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -326,6 +326,25 @@ static int kvm_has_msr_star(CPUState *env)
     return 0;
 }
 
+static int kvm_init_identity_map_page(KVMState *s)
+{
+#ifdef KVM_CAP_SET_IDENTITY_MAP_ADDR
+    int ret;
+    uint64_t addr = 0xfffbc000;
+
+    if (!kvm_check_extension(s, KVM_CAP_SET_IDENTITY_MAP_ADDR)) {
+        return 0;
+    }
+
+    ret = kvm_vm_ioctl(s, KVM_SET_IDENTITY_MAP_ADDR, &addr);
+    if (ret < 0) {
+        fprintf(stderr, "kvm_set_identity_map_addr: %s\n", strerror(ret));
+        return ret;
+    }
+#endif
+    return 0;
+}
+
 int kvm_arch_init(KVMState *s, int smp_cpus)
 {
     int ret;
@@ -353,7 +372,12 @@ int kvm_arch_init(KVMState *s, int smp_cpus)
         perror("e820_add_entry() table is full");
         exit(1);
     }
-    return kvm_vm_ioctl(s, KVM_SET_TSS_ADDR, 0xfffbd000);
+    ret = kvm_vm_ioctl(s, KVM_SET_TSS_ADDR, 0xfffbd000);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return kvm_init_identity_map_page(s);
 }
                     
 static void set_v8086_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
commit 7c80eef899ff0feb1ab6730d4dd3bc3aee046093
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Tue Mar 23 13:37:11 2010 -0300

    kvm: handle internal error
    
    Port qemu-kvm's KVM_EXIT_INTERNAL_ERROR handling to upstream.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index d050115..9c8aa7d 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -730,6 +730,32 @@ static int kvm_handle_io(uint16_t port, void *data, int direction, int size,
     return 1;
 }
 
+#ifdef KVM_CAP_INTERNAL_ERROR_DATA
+static void kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
+{
+
+    if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) {
+        int i;
+
+        fprintf(stderr, "KVM internal error. Suberror: %d\n",
+                run->internal.suberror);
+
+        for (i = 0; i < run->internal.ndata; ++i) {
+            fprintf(stderr, "extra data[%d]: %"PRIx64"\n",
+                    i, (uint64_t)run->internal.data[i]);
+        }
+    }
+    cpu_dump_state(env, stderr, fprintf, 0);
+    if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
+        fprintf(stderr, "emulation failure\n");
+    }
+    /* FIXME: Should trigger a qmp message to let management know
+     * something went wrong.
+     */
+    vm_stop(0);
+}
+#endif
+
 void kvm_flush_coalesced_mmio_buffer(void)
 {
 #ifdef KVM_CAP_COALESCED_MMIO
@@ -845,6 +871,11 @@ int kvm_cpu_exec(CPUState *env)
         case KVM_EXIT_EXCEPTION:
             DPRINTF("kvm_exit_exception\n");
             break;
+#ifdef KVM_CAP_INTERNAL_ERROR_DATA
+        case KVM_EXIT_INTERNAL_ERROR:
+            kvm_handle_internal_error(env, run);
+            break;
+#endif
         case KVM_EXIT_DEBUG:
             DPRINTF("kvm_exit_debug\n");
 #ifdef KVM_CAP_SET_GUEST_DEBUG
commit b5e5a934174ade5dcfc98a41f21f8a6c4816dd54
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Tue Mar 23 13:37:10 2010 -0300

    target-i386: print EFER in cpu_dump_state
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/target-i386/helper.c b/target-i386/helper.c
index 3835835..c9508a8 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -356,6 +356,7 @@ void cpu_dump_state(CPUState *env, FILE *f,
                         cc_op_name);
         }
     }
+    cpu_fprintf(f, "EFER=%016" PRIx64 "\n", env->efer);
     if (flags & X86_DUMP_FPU) {
         int fptag;
         fptag = 0;
commit ff44f1a3737bfda3cac294b8e92d8ec5ddf3abf5
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Mar 12 15:20:49 2010 +0100

    KVM: x86: Add debug register saving and restoring
    
    Make use of the new KVM_GET/SET_DEBUGREGS to save/restore the x86 debug
    registers.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 2ede4b9..d050115 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -64,6 +64,7 @@ struct KVMState
     int migration_log;
     int vcpu_events;
     int robust_singlestep;
+    int debugregs;
 #ifdef KVM_CAP_SET_GUEST_DEBUG
     struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
 #endif
@@ -664,6 +665,11 @@ int kvm_init(int smp_cpus)
         kvm_check_extension(s, KVM_CAP_X86_ROBUST_SINGLESTEP);
 #endif
 
+    s->debugregs = 0;
+#ifdef KVM_CAP_DEBUGREGS
+    s->debugregs = kvm_check_extension(s, KVM_CAP_DEBUGREGS);
+#endif
+
     ret = kvm_arch_init(s, smp_cpus);
     if (ret < 0)
         goto err;
@@ -939,6 +945,11 @@ int kvm_has_robust_singlestep(void)
     return kvm_state->robust_singlestep;
 }
 
+int kvm_has_debugregs(void)
+{
+    return kvm_state->debugregs;
+}
+
 void kvm_setup_guest_memory(void *start, size_t size)
 {
     if (!kvm_has_sync_mmu()) {
diff --git a/kvm.h b/kvm.h
index ae87d85..70bfbf8 100644
--- a/kvm.h
+++ b/kvm.h
@@ -40,6 +40,7 @@ int kvm_init(int smp_cpus);
 int kvm_has_sync_mmu(void);
 int kvm_has_vcpu_events(void);
 int kvm_has_robust_singlestep(void);
+int kvm_has_debugregs(void);
 
 #ifdef NEED_CPU_H
 int kvm_init_vcpu(CPUState *env);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 5513472..bb6dafa 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -874,6 +874,53 @@ static int kvm_guest_debug_workarounds(CPUState *env)
     return ret;
 }
 
+static int kvm_put_debugregs(CPUState *env)
+{
+#ifdef KVM_CAP_DEBUGREGS
+    struct kvm_debugregs dbgregs;
+    int i;
+
+    if (!kvm_has_debugregs()) {
+        return 0;
+    }
+
+    for (i = 0; i < 4; i++) {
+        dbgregs.db[i] = env->dr[i];
+    }
+    dbgregs.dr6 = env->dr[6];
+    dbgregs.dr7 = env->dr[7];
+    dbgregs.flags = 0;
+
+    return kvm_vcpu_ioctl(env, KVM_SET_DEBUGREGS, &dbgregs);
+#else
+    return 0;
+#endif
+}
+
+static int kvm_get_debugregs(CPUState *env)
+{
+#ifdef KVM_CAP_DEBUGREGS
+    struct kvm_debugregs dbgregs;
+    int i, ret;
+
+    if (!kvm_has_debugregs()) {
+        return 0;
+    }
+
+    ret = kvm_vcpu_ioctl(env, KVM_GET_DEBUGREGS, &dbgregs);
+    if (ret < 0) {
+       return ret;
+    }
+    for (i = 0; i < 4; i++) {
+        env->dr[i] = dbgregs.db[i];
+    }
+    env->dr[4] = env->dr[6] = dbgregs.dr6;
+    env->dr[5] = env->dr[7] = dbgregs.dr7;
+#endif
+
+    return 0;
+}
+
 int kvm_arch_put_registers(CPUState *env, int level)
 {
     int ret;
@@ -909,6 +956,10 @@ int kvm_arch_put_registers(CPUState *env, int level)
     if (ret < 0)
         return ret;
 
+    ret = kvm_put_debugregs(env);
+    if (ret < 0)
+        return ret;
+
     return 0;
 }
 
@@ -940,6 +991,10 @@ int kvm_arch_get_registers(CPUState *env)
     if (ret < 0)
         return ret;
 
+    ret = kvm_get_debugregs(env);
+    if (ret < 0)
+        return ret;
+
     return 0;
 }
 
commit 04f8c053cca9c329eebb761f3a1ffef3d349b84c
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Tue Apr 6 16:39:42 2010 -0300

    QMP: Check "arguments" member's type
    
    Otherwise the following input crashes QEMU:
    
    { "execute": "migrate", "arguments": "tcp:0:4446" }
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/monitor.c b/monitor.c
index 0611b29..ef84298 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4437,6 +4437,9 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
     obj = qdict_get(input, "arguments");
     if (!obj) {
         args = qdict_new();
+    } else if (qobject_type(obj) != QTYPE_QDICT) {
+        qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "arguments", "object");
+        goto err_input;
     } else {
         args = qobject_to_qdict(obj);
         QINCREF(args);
commit abaf2f52716625d4b1e29204cab644ed656504cf
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Apr 7 14:53:49 2010 -0300

    QError: Improve QERR_QMP_BAD_INPUT_OBJECT desc
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qerror.c b/qerror.c
index b6aaec7..034c7de 100644
--- a/qerror.c
+++ b/qerror.c
@@ -170,7 +170,7 @@ static const QErrorStringTable qerror_table[] = {
     },
     {
         .error_fmt = QERR_QMP_BAD_INPUT_OBJECT,
-        .desc      = "Bad QMP input object",
+        .desc      = "Expected '%(expected)' in QMP input",
     },
     {
         .error_fmt = QERR_QMP_BAD_INPUT_OBJECT_MEMBER,
commit 88f7db846264223f6059ec329e7b7a77026ad475
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Apr 7 14:49:37 2010 -0300

    QMP: Use QERR_QMP_BAD_INPUT_OBJECT_MEMBER
    
    The QERR_QMP_BAD_INPUT_OBJECT error is going to be used only
    for two problems: the input is not an object or the "execute"
    key is missing.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/monitor.c b/monitor.c
index c25d551..0611b29 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4404,7 +4404,7 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
         qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "execute");
         goto err_input;
     } else if (qobject_type(obj) != QTYPE_QSTRING) {
-        qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "string");
+        qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute", "string");
         goto err_input;
     }
 
commit 7dfb61238a472acf6fb48d9a444564b9b99a4b56
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Apr 7 14:46:33 2010 -0300

    QError: New QERR_QMP_BAD_INPUT_OBJECT_MEMBER
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qerror.c b/qerror.c
index 8d885cd..b6aaec7 100644
--- a/qerror.c
+++ b/qerror.c
@@ -173,6 +173,10 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Bad QMP input object",
     },
     {
+        .error_fmt = QERR_QMP_BAD_INPUT_OBJECT_MEMBER,
+        .desc      = "QMP input object member '%(member)' expects '%(expected)'",
+    },
+    {
         .error_fmt = QERR_SET_PASSWD_FAILED,
         .desc      = "Could not set password",
     },
diff --git a/qerror.h b/qerror.h
index bae08c0..c98c61a 100644
--- a/qerror.h
+++ b/qerror.h
@@ -145,6 +145,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_QMP_BAD_INPUT_OBJECT \
     "{ 'class': 'QMPBadInputObject', 'data': { 'expected': %s } }"
 
+#define QERR_QMP_BAD_INPUT_OBJECT_MEMBER \
+    "{ 'class': 'QMPBadInputObjectMember', 'data': { 'member': %s, 'expected': %s } }"
+
 #define QERR_SET_PASSWD_FAILED \
     "{ 'class': 'SetPasswdFailed', 'data': {} }"
 
commit a303f9e37b87ced34e966dc2c0b7f86bc5e74035
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 25 20:42:43 2010 +0000

    sh4: remove dead assignments, spotted by clang analyzer
    
    Value stored is never read.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/r2d.c b/hw/r2d.c
index 74b718a..38c4f6a 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -229,7 +229,6 @@ static void r2d_init(ram_addr_t ram_size,
     struct SH7750State *s;
     ram_addr_t sdram_addr;
     qemu_irq *irq;
-    PCIBus *pci;
     DriveInfo *dinfo;
     int i;
 
@@ -248,7 +247,7 @@ static void r2d_init(ram_addr_t ram_size,
     /* Register peripherals */
     s = sh7750_init(env);
     irq = r2d_fpga_init(0x04000000, sh7750_irl(s));
-    pci = sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4);
+    sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4);
 
     sm501_init(0x10000000, SM501_VRAM_SIZE, irq[SM501], serial_hds[2]);
 
commit 9fad3eb7fa27616846b1ef477947771337bbe0fd
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 25 20:33:43 2010 +0000

    ppc: add missing 'break', spotted by clang analyzer
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index df698a8..d9bbd93 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -486,6 +486,7 @@ static uint32_t dcr_read_ebc (void *opaque, int dcrn)
             ret = 0x00000000;
             break;
         }
+        break;
     default:
         ret = 0x00000000;
         break;
commit 05f92404cd8e0fa3204182350d19c74451f9c4b7
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 25 20:32:49 2010 +0000

    ppc: remove dead assignments, spotted by clang analyzer
    
    Value stored is never read.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c
index f40d618..7c7075e 100644
--- a/hw/ppc405_boards.c
+++ b/hw/ppc405_boards.c
@@ -187,7 +187,6 @@ static void ref405ep_init (ram_addr_t ram_size,
     target_ulong kernel_base, kernel_size, initrd_base, initrd_size;
     int linux_boot;
     int fl_idx, fl_sectors, len;
-    int ppc_boot_device = boot_device[0];
     DriveInfo *dinfo;
 
     /* XXX: fix this */
@@ -326,7 +325,6 @@ static void ref405ep_init (ram_addr_t ram_size,
         }
         env->gpr[4] = initrd_base;
         env->gpr[5] = initrd_size;
-        ppc_boot_device = 'm';
         if (kernel_cmdline != NULL) {
             len = strlen(kernel_cmdline);
             bdloc -= ((len + 255) & ~255);
@@ -508,7 +506,6 @@ static void taihu_405ep_init(ram_addr_t ram_size,
     target_ulong kernel_base, kernel_size, initrd_base, initrd_size;
     int linux_boot;
     int fl_idx, fl_sectors;
-    int ppc_boot_device = boot_device[0];
     DriveInfo *dinfo;
 
     /* RAM is soldered to the board so the size cannot be changed */
@@ -625,7 +622,6 @@ static void taihu_405ep_init(ram_addr_t ram_size,
             initrd_base = 0;
             initrd_size = 0;
         }
-        ppc_boot_device = 'm';
     } else {
         kernel_base = 0;
         kernel_size = 0;
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index c28223b..a5479c4 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -198,7 +198,6 @@ static inline int _pte_check(mmu_ctx_t *ctx, int is_64b, target_ulong pte0,
     target_ulong ptem, mmask;
     int access, ret, pteh, ptev, pp;
 
-    access = 0;
     ret = -1;
     /* Check validity and table match */
 #if defined(TARGET_PPC64)
@@ -493,7 +492,7 @@ static inline int get_bat(CPUState *env, mmu_ctx_t *ctx, target_ulong virtual,
                           int rw, int type)
 {
     target_ulong *BATlt, *BATut, *BATu, *BATl;
-    target_ulong base, BEPIl, BEPIu, bl;
+    target_ulong BEPIl, BEPIu, bl;
     int i, valid, prot;
     int ret = -1;
 
@@ -509,7 +508,6 @@ static inline int get_bat(CPUState *env, mmu_ctx_t *ctx, target_ulong virtual,
         BATut = env->DBAT[0];
         break;
     }
-    base = virtual & 0xFFFC0000;
     for (i = 0; i < env->nb_BATs; i++) {
         BATu = &BATut[i];
         BATl = &BATlt[i];
@@ -1755,11 +1753,15 @@ void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
 void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
 {
     target_ulong mask;
+#if defined(FLUSH_ALL_TLBS)
     int do_inval;
+#endif
 
     dump_store_bat(env, 'I', 0, nr, value);
     if (env->IBAT[0][nr] != value) {
+#if defined(FLUSH_ALL_TLBS)
         do_inval = 0;
+#endif
         mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
         if (env->IBAT[1][nr] & 0x40) {
             /* Invalidate BAT only if it is valid */
@@ -1792,11 +1794,15 @@ void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
 void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
 {
     target_ulong mask;
+#if defined(FLUSH_ALL_TLBS)
     int do_inval;
+#endif
 
     dump_store_bat(env, 'I', 1, nr, value);
     if (env->IBAT[1][nr] != value) {
+#if defined(FLUSH_ALL_TLBS)
         do_inval = 0;
+#endif
         if (env->IBAT[1][nr] & 0x40) {
 #if !defined(FLUSH_ALL_TLBS)
             mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 3869c24..3d9d5ee 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3398,7 +3398,7 @@ static void gen_b(DisasContext *ctx)
 static inline void gen_bcond(DisasContext *ctx, int type)
 {
     uint32_t bo = BO(ctx->opcode);
-    int l1 = gen_new_label();
+    int l1;
     TCGv target;
 
     ctx->exception = POWERPC_EXCP_BRANCH;
commit b2c58871c9fd3a6fe7f670b97af7708809477721
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 25 20:31:42 2010 +0000

    alpha: add missing 'break', spotted by clang analyzer
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 46335cd..9a039cb 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -466,6 +466,7 @@ int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp)
             env->ipr[IPR_SYSPTBR] = val;
         else
             ret = -1;
+        break;
     case IPR_TBCHK:
         /* Read-only */
         ret = -1;
commit f88fe4e3706ca59af06fdd0e2d696f720328db56
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 25 20:30:17 2010 +0000

    alpha: remove dead assignments, spotted by clang analyzer
    
    Value stored is never read.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/alpha_palcode.c b/hw/alpha_palcode.c
index 6293d10..033b542 100644
--- a/hw/alpha_palcode.c
+++ b/hw/alpha_palcode.c
@@ -79,9 +79,7 @@ static void pal_reset (CPUState *env)
 static void do_swappal (CPUState *env, uint64_t palid)
 {
     pal_handler_t *pal_handler;
-    int status;
 
-    status = 0;
     switch (palid) {
     case 0 ... 2:
         pal_handler = &pal_handlers[palid];
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index d903800..1e9ff58 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1234,8 +1234,8 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
 {
     uint32_t palcode;
     int32_t disp21, disp16, disp12;
-    uint16_t fn11, fn16;
-    uint8_t opc, ra, rb, rc, sbz, fpfn, fn7, fn2, islit, real_islit;
+    uint16_t fn11;
+    uint8_t opc, ra, rb, rc, fpfn, fn7, fn2, islit, real_islit;
     uint8_t lit;
     int ret;
 
@@ -1244,7 +1244,6 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
     ra = (insn >> 21) & 0x1F;
     rb = (insn >> 16) & 0x1F;
     rc = insn & 0x1F;
-    sbz = (insn >> 13) & 0x07;
     real_islit = islit = (insn >> 12) & 1;
     if (rb == 31 && !islit) {
         islit = 1;
@@ -1255,7 +1254,6 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
     disp21 = ((int32_t)((insn & 0x001FFFFF) << 11)) >> 11;
     disp16 = (int16_t)(insn & 0x0000FFFF);
     disp12 = (int32_t)((insn & 0x00000FFF) << 20) >> 20;
-    fn16 = insn & 0x0000FFFF;
     fn11 = (insn >> 5) & 0x000007FF;
     fpfn = fn11 & 0x3F;
     fn7 = (insn >> 5) & 0x0000007F;
@@ -1290,7 +1288,6 @@ static inline int translate_one(DisasContext *ctx, uint32_t insn)
             if (ctx->mem_idx & 1)
                 goto invalid_opc;
             gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x3F) << 6), 0);
-            ret = 3;
         }
 #endif
         /* Invalid PAL call */
@@ -3140,8 +3137,8 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
     env->ipr[IPR_EXC_MASK] = 0;
 #else
     {
-        uint64_t hwpcb;
-        hwpcb = env->ipr[IPR_PCBB];
+        // uint64_t hwpcb;
+        // hwpcb = env->ipr[IPR_PCBB];
         env->ipr[IPR_ASN] = 0;
         env->ipr[IPR_ASTEN] = 0;
         env->ipr[IPR_ASTSR] = 0;
commit 183aa45407e7b665d88842f8e288f6bbcac15e22
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 25 20:00:33 2010 +0000

    microblaze: remove dead assignments, spotted by clang analyzer
    
    Value stored is never read.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 9b7af55..93344b1 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -164,7 +164,6 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
 
     if (kernel_filename) {
         uint64_t entry, low, high;
-        int kcmdline_len;
         uint32_t base32;
 
         /* Boots a kernel elf binary.  */
@@ -187,7 +186,7 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
         }
 
         boot_info.cmdline = ddr_base + kernel_size + 8192;
-        if (kernel_cmdline && (kcmdline_len = strlen(kernel_cmdline))) {
+        if (kernel_cmdline && strlen(kernel_cmdline)) {
             pstrcpy_targphys("cmdline", boot_info.cmdline, 256, kernel_cmdline);
         }
         /* Provide a device-tree.  */
diff --git a/target-microblaze/mmu.c b/target-microblaze/mmu.c
index d868ac5..b38f7d9 100644
--- a/target-microblaze/mmu.c
+++ b/target-microblaze/mmu.c
@@ -60,8 +60,7 @@ static void mmu_change_pid(CPUState *env, unsigned int newpid)
 {
     struct microblaze_mmu *mmu = &env->mmu;
     unsigned int i;
-    unsigned int tlb_size;
-    uint32_t tlb_tag, mask, t;
+    uint32_t t;
 
     if (newpid & ~0xff)
         qemu_log("Illegal rpid=%x\n", newpid);
@@ -70,10 +69,6 @@ static void mmu_change_pid(CPUState *env, unsigned int newpid)
         /* Lookup and decode.  */
         t = mmu->rams[RAM_TAG][i];
         if (t & TLB_VALID) {
-            tlb_size = tlb_decode_size((t & TLB_PAGESZ_MASK) >> 7);
-            mask = ~(tlb_size - 1);
-
-            tlb_tag = t & TLB_EPN_MASK;
             if (mmu->tids[i] && ((mmu->regs[MMU_R_PID] & 0xff) == mmu->tids[i]))
                 mmu_flush_idx(env, i);
         }
commit 37ca43a141a9cefd6733a6e9281690cd1a1dc419
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 25 19:50:51 2010 +0000

    m68k: remove dead assignments, spotted by clang analyzer
    
    Value stored is never read.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 99cf6dd..5351880 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -541,7 +541,6 @@ static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize)
             offset = read_im32(s);
             return gen_im32(offset);
         case 2: /* pc displacement  */
-            tmp = tcg_temp_new();
             offset = s->pc;
             offset += ldsw_code(s->pc);
             s->pc += 2;
@@ -2969,7 +2968,6 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
     int j, lj;
     target_ulong pc_start;
     int pc_offset;
-    int last_cc_op;
     int num_insns;
     int max_insns;
 
@@ -3023,7 +3021,6 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
         }
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
             gen_io_start();
-        last_cc_op = dc->cc_op;
         dc->insn_pc = dc->pc;
 	disas_m68k_insn(env, dc);
         num_insns++;
commit 0d84be5bd0df34c2663b38d6efd7d850d15f2eb0
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 25 19:46:46 2010 +0000

    cris: remove dead assignments, spotted by clang analyzer
    
    Value stored is never read.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
index dedd107..187ece1 100644
--- a/hw/etraxfs_eth.c
+++ b/hw/etraxfs_eth.c
@@ -401,7 +401,7 @@ static void eth_update_ma(struct fs_eth *eth, int ma)
 	eth->macaddr[ma][i++] = eth->regs[reg] >> 16;
 	eth->macaddr[ma][i++] = eth->regs[reg] >> 24;
 	eth->macaddr[ma][i++] = eth->regs[reg + 1];
-	eth->macaddr[ma][i++] = eth->regs[reg + 1] >> 8;
+	eth->macaddr[ma][i] = eth->regs[reg + 1] >> 8;
 
 	D(printf("set mac%d=%x.%x.%x.%x.%x.%x\n", ma,
 		 eth->macaddr[ma][0], eth->macaddr[ma][1],
diff --git a/target-cris/mmu.c b/target-cris/mmu.c
index b6892bb..2a5ded8 100644
--- a/target-cris/mmu.c
+++ b/target-cris/mmu.c
@@ -327,7 +327,6 @@ int cris_mmu_translate(struct cris_mmu_result *res,
 		       CPUState *env, uint32_t vaddr,
 		       int rw, int mmu_idx)
 {
-	uint32_t phy = vaddr;
 	int seg;
 	int miss = 0;
 	int is_user = mmu_idx == MMU_USER_IDX;
@@ -351,8 +350,7 @@ int cris_mmu_translate(struct cris_mmu_result *res,
 
 		miss = 0;
 		base = cris_mmu_translate_seg(env, seg);
-		phy = base | (0x0fffffff & vaddr);
-		res->phy = phy;
+                res->phy = base | (0x0fffffff & vaddr);
 		res->prot = PAGE_BITS;
 	}
 	else
diff --git a/target-cris/translate.c b/target-cris/translate.c
index f8baa88..a7014fa 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -1292,13 +1292,12 @@ static void dec_prep_alu_r(DisasContext *dc, int rs, int rd,
 static int dec_prep_move_m(DisasContext *dc, int s_ext, int memsize,
 			   TCGv dst)
 {
-	unsigned int rs, rd;
+	unsigned int rs;
 	uint32_t imm;
 	int is_imm;
 	int insn_len = 2;
 
 	rs = dc->op1;
-	rd = dc->op2;
 	is_imm = rs == 15 && dc->postinc;
 
 	/* Load [$rs] onto T1.  */
@@ -1367,14 +1366,12 @@ static unsigned int dec_bccq(DisasContext *dc)
 	int32_t offset;
 	int sign;
 	uint32_t cond = dc->op2;
-	int tmp;
 
 	offset = EXTRACT_FIELD (dc->ir, 1, 7);
 	sign = EXTRACT_FIELD(dc->ir, 0, 0);
 
 	offset *= 2;
 	offset |= sign << 8;
-	tmp = offset;
 	offset = sign_extend(offset, 8);
 
 	LOG_DIS("b%s %x\n", cc_name(cond), dc->pc + offset);
commit 22ed1d34789b184aaaa28c1e4620ce4467744cec
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 25 19:31:06 2010 +0000

    arm: remove dead assignments, spotted by clang analyzer
    
    Value stored is never read.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/arm-dis.c b/arm-dis.c
index 5028555..fe7ac99 100644
--- a/arm-dis.c
+++ b/arm-dis.c
@@ -2515,7 +2515,6 @@ print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb)
 			  {
 			    func (stream, "<illegal constant %.8x:%x:%x>",
                                   bits, cmode, op);
-                            size = 32;
 			    break;
 			  }
                         switch (size)
diff --git a/hw/omap1.c b/hw/omap1.c
index a554d90..8649dbd 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -2348,7 +2348,6 @@ static void omap_clkm_write(void *opaque, target_phys_addr_t addr,
         return;
 
     case 0x0c:	/* ARM_EWUPCT */
-        diff = s->clkm.arm_ewupct ^ value;
         s->clkm.arm_ewupct = value & 0x003f;
         return;
 
diff --git a/hw/omap2.c b/hw/omap2.c
index a3fa89d..bd1b35e 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -1968,7 +1968,7 @@ struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
 
     s->irq = irq;
     s->codec.rxdrq = *drq ++;
-    s->codec.txdrq = *drq ++;
+    s->codec.txdrq = *drq;
     omap_eac_reset(s);
 
 #ifdef HAS_AUDIO
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index 2a8419e..ca0a7d1 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -126,7 +126,6 @@ static void sx1_init(ram_addr_t ram_size,
     static uint32_t cs1val = 0x00215070;
     static uint32_t cs2val = 0x00001139;
     static uint32_t cs3val = 0x00001139;
-    ram_addr_t phys_flash;
     DriveInfo *dinfo;
     int fl_idx;
     uint32_t flash_size = flash0_size;
@@ -140,7 +139,7 @@ static void sx1_init(ram_addr_t ram_size,
 
     /* External Flash (EMIFS) */
     cpu_register_physical_memory(OMAP_CS0_BASE, flash_size,
-                    (phys_flash = qemu_ram_alloc(flash_size)) | IO_MEM_ROM);
+                                 qemu_ram_alloc(flash_size) | IO_MEM_ROM);
 
     io = cpu_register_io_memory(static_readfn, static_writefn, &cs0val);
     cpu_register_physical_memory(OMAP_CS0_BASE + flash_size,
@@ -171,8 +170,7 @@ static void sx1_init(ram_addr_t ram_size,
     if ((version == 1) &&
             (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
         cpu_register_physical_memory(OMAP_CS1_BASE, flash1_size,
-                        (phys_flash = qemu_ram_alloc(flash1_size)) |
-                        IO_MEM_ROM);
+                                     qemu_ram_alloc(flash1_size) | IO_MEM_ROM);
         io = cpu_register_io_memory(static_readfn, static_writefn, &cs1val);
         cpu_register_physical_memory(OMAP_CS1_BASE + flash1_size,
                         OMAP_CS1_SIZE - flash1_size, io);
diff --git a/hw/palm.c b/hw/palm.c
index 6d19167..ba7c398 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -206,7 +206,6 @@ static void palmte_init(ram_addr_t ram_size,
     static uint32_t cs1val = 0x0000e1a0;
     static uint32_t cs2val = 0x0000e1a0;
     static uint32_t cs3val = 0xe1a0e1a0;
-    ram_addr_t phys_flash;
     int rom_size, rom_loaded = 0;
     DisplayState *ds = get_displaystate();
 
@@ -214,7 +213,7 @@ static void palmte_init(ram_addr_t ram_size,
 
     /* External Flash (EMIFS) */
     cpu_register_physical_memory(OMAP_CS0_BASE, flash_size,
-                    (phys_flash = qemu_ram_alloc(flash_size)) | IO_MEM_ROM);
+                    qemu_ram_alloc(flash_size) | IO_MEM_ROM);
 
     io = cpu_register_io_memory(static_readfn, static_writefn, &cs0val);
     cpu_register_physical_memory(OMAP_CS0_BASE + flash_size,
diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index 6b2adba..20fe93d 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -542,7 +542,9 @@ static int ctz32 (uint32_t n)
     }
     if (!(n & 0x1)) {
         ret++;
+#if 0 /* This is not necessary as n is never 0 */
         n = n >> 1;
+#endif
     }
 #if 0 /* This is not necessary as n is never 0 */
     if (!n)
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
index bd6397b..f3d3f41 100644
--- a/hw/pflash_cfi02.c
+++ b/hw/pflash_cfi02.c
@@ -582,7 +582,9 @@ static int ctz32 (uint32_t n)
     }
     if (!(n & 0x1)) {
         ret++;
+#if 0 /* This is not necessary as n is never 0 */
         n = n >> 1;
+#endif
     }
 #if 0 /* This is not necessary as n is never 0 */
     if (!n)
diff --git a/hw/sd.c b/hw/sd.c
index cc2839d..c928120 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -1143,12 +1143,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
 }
 
 static sd_rsp_type_t sd_app_command(SDState *sd,
-                                    SDRequest req) {
-    uint32_t rca;
-
-    if (sd_cmd_type[req.cmd] == sd_ac || sd_cmd_type[req.cmd] == sd_adtc)
-        rca = req.arg >> 16;
-
+                                    SDRequest req)
+{
     DPRINTF("ACMD%d 0x%08x\n", req.cmd, req.arg);
     switch (req.cmd) {
     case 6:	/* ACMD6:  SET_BUS_WIDTH */
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index e4a2447..f7d58e1 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -160,7 +160,6 @@ static void smc91c111_do_tx(smc91c111_state *s)
     int i;
     int len;
     int control;
-    int add_crc;
     int packetnum;
     uint8_t *p;
 
@@ -187,20 +186,22 @@ static void smc91c111_do_tx(smc91c111_state *s)
             len = 64;
         }
 #if 0
-        /* The card is supposed to append the CRC to the frame.  However
-           none of the other network traffic has the CRC appended.
-           Suspect this is low level ethernet detail we don't need to worry
-           about.  */
-        add_crc = (control & 0x10) || (s->tcr & TCR_NOCRC) == 0;
-        if (add_crc) {
-            uint32_t crc;
-
-            crc = crc32(~0, p, len);
-            memcpy(p + len, &crc, 4);
-            len += 4;
+        {
+            int add_crc;
+
+            /* The card is supposed to append the CRC to the frame.
+               However none of the other network traffic has the CRC
+               appended.  Suspect this is low level ethernet detail we
+               don't need to worry about.  */
+            add_crc = (control & 0x10) || (s->tcr & TCR_NOCRC) == 0;
+            if (add_crc) {
+                uint32_t crc;
+
+                crc = crc32(~0, p, len);
+                memcpy(p + len, &crc, 4);
+                len += 4;
+            }
         }
-#else
-        add_crc = 0;
 #endif
         if (s->ctr & CTR_AUTO_RELEASE)
             /* Race?  */
@@ -670,14 +671,14 @@ static ssize_t smc91c111_receive(VLANClientState *nc, const uint8_t *buf, size_t
         *(p++) = crc & 0xff; crc >>= 8;
         *(p++) = crc & 0xff; crc >>= 8;
         *(p++) = crc & 0xff; crc >>= 8;
-        *(p++) = crc & 0xff; crc >>= 8;
+        *(p++) = crc & 0xff;
     }
     if (size & 1) {
         *(p++) = buf[size - 1];
-        *(p++) = 0x60;
+        *p = 0x60;
     } else {
         *(p++) = 0;
-        *(p++) = 0x40;
+        *p = 0x40;
     }
     /* TODO: Raise early RX interrupt?  */
     s->int_level |= INT_RCV;
diff --git a/hw/spitz.c b/hw/spitz.c
index 564519b..c3b5cd8 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -721,7 +721,7 @@ static void spitz_ssp_attach(PXA2xxState *cpu)
     mux = ssi_create_slave(cpu->ssp[CORGI_SSP_PORT - 1], "corgi-ssp");
 
     bus = qdev_get_child_bus(mux, "ssi0");
-    dev = ssi_create_slave(bus, "spitz-lcdtg");
+    ssi_create_slave(bus, "spitz-lcdtg");
 
     bus = qdev_get_child_bus(mux, "ssi1");
     dev = ssi_create_slave(bus, "ads7846");
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 44c9eee..5755f8a 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -1367,7 +1367,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
             gpio_out[GPIO_D][0] = qdev_get_gpio_in(mux, 0);
 
             bus = qdev_get_child_bus(mux, "ssi0");
-            dev = ssi_create_slave(bus, "ssi-sd");
+            ssi_create_slave(bus, "ssi-sd");
 
             bus = qdev_get_child_bus(mux, "ssi1");
             dev = ssi_create_slave(bus, "ssd0323");
diff --git a/hw/tusb6010.c b/hw/tusb6010.c
index 3887233..4864be5 100644
--- a/hw/tusb6010.c
+++ b/hw/tusb6010.c
@@ -425,7 +425,6 @@ static uint32_t tusb_async_readw(void *opaque, target_phys_addr_t addr)
         return s->rx_config[epnum];
     case TUSB_EP_MAX_PACKET_SIZE_OFFSET ...
             (TUSB_EP_MAX_PACKET_SIZE_OFFSET + 0x3b):
-        epnum = (offset - TUSB_EP_MAX_PACKET_SIZE_OFFSET) >> 2;
         return 0x00000000;	/* TODO */
     case TUSB_WAIT_COUNT:
         return 0x00;		/* TODO */
@@ -630,7 +629,6 @@ static void tusb_async_writew(void *opaque, target_phys_addr_t addr,
         break;
     case TUSB_EP_MAX_PACKET_SIZE_OFFSET ...
             (TUSB_EP_MAX_PACKET_SIZE_OFFSET + 0x3b):
-        epnum = (offset - TUSB_EP_MAX_PACKET_SIZE_OFFSET) >> 2;
         return;		/* TODO */
     case TUSB_WAIT_COUNT:
         return;		/* TODO */
diff --git a/hw/wm8750.c b/hw/wm8750.c
index 6064da0..ce43c23 100644
--- a/hw/wm8750.c
+++ b/hw/wm8750.c
@@ -62,12 +62,11 @@ static const uint8_t wm8750_vol_db_table[] = {
 
 static inline void wm8750_in_load(WM8750State *s)
 {
-    int acquired;
     if (s->idx_in + s->req_in <= sizeof(s->data_in))
         return;
     s->idx_in = audio_MAX(0, (int) sizeof(s->data_in) - s->req_in);
-    acquired = AUD_read(*s->in[0], s->data_in + s->idx_in,
-                    sizeof(s->data_in) - s->idx_in);
+    AUD_read(*s->in[0], s->data_in + s->idx_in,
+             sizeof(s->data_in) - s->idx_in);
 }
 
 static inline void wm8750_out_flush(WM8750State *s)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 5c54919..0eccca5 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5242,7 +5242,6 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
             if (!u) {
                 /* Extract.  */
                 imm = (insn >> 8) & 0xf;
-                count = q + 1;
 
                 if (imm > 7 && !q)
                     return 1;
commit 7f5b7d3e2c19c0aa52dcac0a10d473c7fd142450
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 25 18:58:25 2010 +0000

    x86: remove dead assignments, spotted by clang analyzer
    
    Value stored is never read.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/acpi.c b/hw/acpi.c
index 5c01c2e..e3b63b7 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -88,8 +88,7 @@ static uint32_t get_pmtmr(PIIX4PMState *s)
 static int get_pmsts(PIIX4PMState *s)
 {
     int64_t d;
-    int pmsts;
-    pmsts = s->pmsts;
+
     d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, get_ticks_per_sec());
     if (d >= s->tmr_overflow_time)
         s->pmsts |= TMROF_EN;
@@ -206,8 +205,8 @@ static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
 static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
 {
     //    PIIX4PMState *s = opaque;
-    addr &= 0x3f;
 #ifdef DEBUG
+    addr &= 0x3f;
     printf("PM writel port=0x%04x val=0x%08x\n", addr, val);
 #endif
 }
diff --git a/hw/i8259.c b/hw/i8259.c
index 37ef04e..ea48e0e 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -234,7 +234,9 @@ int pic_read_irq(PicState2 *s)
                 irq2 = 7;
             }
             intno = s->pics[1].irq_base + irq2;
+#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_LATENCY)
             irq = irq2 + 8;
+#endif
         } else {
             intno = s->pics[0].irq_base + irq;
         }
diff --git a/hw/parallel.c b/hw/parallel.c
index 12693d4..be8e2d5 100644
--- a/hw/parallel.c
+++ b/hw/parallel.c
@@ -414,15 +414,14 @@ parallel_ioport_eppdata_read_hw4(void *opaque, uint32_t addr)
 
 static void parallel_ioport_ecp_write(void *opaque, uint32_t addr, uint32_t val)
 {
-    addr &= 7;
-    pdebug("wecp%d=%02x\n", addr, val);
+    pdebug("wecp%d=%02x\n", addr & 7, val);
 }
 
 static uint32_t parallel_ioport_ecp_read(void *opaque, uint32_t addr)
 {
     uint8_t ret = 0xff;
-    addr &= 7;
-    pdebug("recp%d:%02x\n", addr, ret);
+
+    pdebug("recp%d:%02x\n", addr & 7, ret);
     return ret;
 }
 
diff --git a/hw/pc.c b/hw/pc.c
index b797f21..b659344 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -813,9 +813,7 @@ static void pc_init1(ram_addr_t ram_size,
     ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
     int bios_size, isa_bios_size;
     PCIBus *pci_bus;
-    ISADevice *isa_dev;
     int piix3_devfn = -1;
-    CPUState *env;
     qemu_irq *cpu_irq;
     qemu_irq *isa_irq;
     qemu_irq *i8259;
@@ -845,7 +843,7 @@ static void pc_init1(ram_addr_t ram_size,
     }
 
     for (i = 0; i < smp_cpus; i++) {
-        env = pc_new_cpu(cpu_model);
+        pc_new_cpu(cpu_model);
     }
 
     vmport_init();
@@ -1014,7 +1012,7 @@ static void pc_init1(ram_addr_t ram_size,
         }
     }
 
-    isa_dev = isa_create_simple("i8042");
+    isa_create_simple("i8042");
     DMA_init(0);
 #ifdef HAS_AUDIO
     audio_init(pci_enabled ? pci_bus : NULL, isa_irq);
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 343fd17..cc45c50 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -105,7 +105,7 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
 {
     int dom, pci_bus;
     unsigned slot;
-    int type, bus;
+    int type;
     PCIDevice *dev;
     DriveInfo *dinfo = NULL;
     const char *pci_addr = qdict_get_str(qdict, "pci_addr");
@@ -119,7 +119,6 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
         goto err;
     }
     type = dinfo->type;
-    bus = drive_get_max_bus (type);
 
     switch (type) {
     case IF_SCSI:
diff --git a/hw/vga.c b/hw/vga.c
index bb65677..845dbcc 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -169,7 +169,10 @@ static void vga_precise_update_retrace_info(VGACommonState *s)
     int vretr_start_line;
     int vretr_end_line;
 
-    int div2, sldiv2, dots;
+    int dots;
+#if 0
+    int div2, sldiv2;
+#endif
     int clocking_mode;
     int clock_sel;
     const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
@@ -190,8 +193,6 @@ static void vga_precise_update_retrace_info(VGACommonState *s)
     vretr_end_line = s->cr[0x11] & 0xf;
 
 
-    div2 = (s->cr[0x17] >> 2) & 1;
-    sldiv2 = (s->cr[0x17] >> 3) & 1;
 
     clocking_mode = (s->sr[0x01] >> 3) & 1;
     clock_sel = (s->msr >> 2) & 3;
@@ -216,6 +217,8 @@ static void vga_precise_update_retrace_info(VGACommonState *s)
     r->htotal = htotal_chars;
 
 #if 0
+    div2 = (s->cr[0x17] >> 2) & 1;
+    sldiv2 = (s->cr[0x17] >> 3) & 1;
     printf (
         "hz=%f\n"
         "htotal = %d\n"
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 307aabd..6311b68 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -763,7 +763,6 @@ static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip,
             if (s->cc_op != CC_OP_DYNAMIC)
                 gen_op_set_cc_op(s->cc_op);
             gen_jmp_im(cur_eip);
-            state_saved = 1;
         }
         svm_flags |= (1 << (4 + ot));
         next_eip = s->pc - s->cs_base;
@@ -7744,7 +7743,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
     target_ulong pc_ptr;
     uint16_t *gen_opc_end;
     CPUBreakpoint *bp;
-    int j, lj, cflags;
+    int j, lj;
     uint64_t flags;
     target_ulong pc_start;
     target_ulong cs_base;
@@ -7755,7 +7754,6 @@ static inline void gen_intermediate_code_internal(CPUState *env,
     pc_start = tb->pc;
     cs_base = tb->cs_base;
     flags = tb->flags;
-    cflags = tb->cflags;
 
     dc->pe = (flags >> HF_PE_SHIFT) & 1;
     dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
commit 9678d9501bc5f2e6e06170013dec8667057c3b62
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 25 18:35:52 2010 +0000

    Remove dead assignments in various common files, spotted by clang analyzer
    
    Value stored is never read.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/console.c b/console.c
index 8bcd00b..7070b1b 100644
--- a/console.c
+++ b/console.c
@@ -829,7 +829,6 @@ static void console_clear_xy(TextConsole *s, int x, int y)
     TextCell *c = &s->cells[y1 * s->width + x];
     c->ch = ' ';
     c->t_attrib = s->t_attrib_default;
-    c++;
     update_xy(s, x, y);
 }
 
diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 95017a1..9a466f3 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -575,7 +575,7 @@ static void blk_alloc(struct XenDevice *xendev)
 static int blk_init(struct XenDevice *xendev)
 {
     struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
-    int index, mode, qflags, have_barriers, info = 0;
+    int index, qflags, have_barriers, info = 0;
     char *h;
 
     /* read xenstore entries */
@@ -609,10 +609,8 @@ static int blk_init(struct XenDevice *xendev)
 
     /* read-only ? */
     if (strcmp(blkdev->mode, "w") == 0) {
-	mode   = O_RDWR;
 	qflags = BDRV_O_RDWR;
     } else {
-	mode   = O_RDONLY;
 	qflags = 0;
 	info  |= VDISK_READONLY;
     }
diff --git a/net/tap.c b/net/tap.c
index 303d69f..0147dab 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -346,7 +346,7 @@ static int launch_script(const char *setup_script, const char *ifname, int fd)
         parg = args;
         *parg++ = (char *)setup_script;
         *parg++ = (char *)ifname;
-        *parg++ = NULL;
+        *parg = NULL;
         execv(setup_script, args);
         _exit(1);
     } else if (pid > 0) {
diff --git a/slirp/cksum.c b/slirp/cksum.c
index c3b45f7..48a1792 100644
--- a/slirp/cksum.c
+++ b/slirp/cksum.c
@@ -110,7 +110,6 @@ int cksum(struct mbuf *m, int len)
 	if (byte_swapped) {
 		REDUCE;
 		sum <<= 8;
-		byte_swapped = 0;
 		if (mlen == -1) {
 			s_util.c[1] = *(u_int8_t *)w;
 			sum += s_util.s;
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 54f7fa9..beceff0 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -550,14 +550,18 @@ void tcg_register_helper(void *func, const char *name)
 void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
                    int sizemask, TCGArg ret, int nargs, TCGArg *args)
 {
+#ifdef TCG_TARGET_I386
     int call_type;
+#endif
     int i;
     int real_args;
     int nb_rets;
     TCGArg *nparam;
     *gen_opc_ptr++ = INDEX_op_call;
     nparam = gen_opparam_ptr++;
+#ifdef TCG_TARGET_I386
     call_type = (flags & TCG_CALL_TYPE_MASK);
+#endif
     if (ret != TCG_CALL_DUMMY_ARG) {
 #if TCG_TARGET_REG_BITS < 64
         if (sizemask & 1) {
diff --git a/vnc.c b/vnc.c
index 9ba603c..d332099 100644
--- a/vnc.c
+++ b/vnc.c
@@ -1234,17 +1234,16 @@ static long vnc_client_write_plain(VncState *vs)
  */
 void vnc_client_write(void *opaque)
 {
-    long ret;
     VncState *vs = opaque;
 
 #ifdef CONFIG_VNC_SASL
     if (vs->sasl.conn &&
         vs->sasl.runSSF &&
-        !vs->sasl.waitWriteSSF)
-        ret = vnc_client_write_sasl(vs);
-    else
+        !vs->sasl.waitWriteSSF) {
+        vnc_client_write_sasl(vs);
+    } else
 #endif /* CONFIG_VNC_SASL */
-        ret = vnc_client_write_plain(vs);
+        vnc_client_write_plain(vs);
 }
 
 void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
@@ -1725,12 +1724,8 @@ static void framebuffer_update_request(VncState *vs, int incremental,
                                        int x_position, int y_position,
                                        int w, int h)
 {
-    if (x_position > ds_get_width(vs->ds))
-        x_position = ds_get_width(vs->ds);
     if (y_position > ds_get_height(vs->ds))
         y_position = ds_get_height(vs->ds);
-    if (x_position + w >= ds_get_width(vs->ds))
-        w = ds_get_width(vs->ds)  - x_position;
     if (y_position + h >= ds_get_height(vs->ds))
         h = ds_get_height(vs->ds) - y_position;
 
commit d4c4e6fdc7f5077fba3446f6e650eb94d07a0be5
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 25 18:23:04 2010 +0000

    usb: remove dead assignments, spotted by clang analyzer
    
    Value stored is never read.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index ee0e9e3..b692503 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -152,11 +152,10 @@ static void do_attach(USBDevice *dev)
 int usb_device_attach(USBDevice *dev)
 {
     USBBus *bus = usb_bus_from_device(dev);
-    USBDevice *hub;
 
     if (bus->nfree == 1) {
         /* Create a new hub and chain it on.  */
-        hub = usb_create_simple(bus, "usb-hub");
+        usb_create_simple(bus, "usb-hub");
     }
     do_attach(dev);
     return 0;
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 1aee7fe..2a1edfc 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -366,11 +366,10 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
         {
             unsigned int n = index - 1;
             USBHubPort *port;
-            USBDevice *dev;
+
             if (n >= s->nb_ports)
                 goto fail;
             port = &s->ports[n];
-            dev = port->port.dev;
             switch(value) {
             case PORT_ENABLE:
                 port->wPortStatus &= ~PORT_STAT_ENABLE;
diff --git a/hw/usb-net.c b/hw/usb-net.c
index ff0ca44..a43bd17 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -972,11 +972,10 @@ static int rndis_keepalive_response(USBNetState *s,
 
 static int rndis_parse(USBNetState *s, uint8_t *data, int length)
 {
-    uint32_t msg_type, msg_length;
+    uint32_t msg_type;
     le32 *tmp = (le32 *) data;
 
-    msg_type = le32_to_cpup(tmp++);
-    msg_length = le32_to_cpup(tmp++);
+    msg_type = le32_to_cpup(tmp);
 
     switch (msg_type) {
     case RNDIS_INITIALIZE_MSG:
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 7cd5ca0..9f80e15 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -599,7 +599,9 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
 {
     int dir;
     size_t len = 0;
+#ifdef DEBUG_ISOCH
     const char *str = NULL;
+#endif
     int pid;
     int ret;
     int i;
@@ -663,15 +665,21 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
     dir = OHCI_BM(ed->flags, ED_D);
     switch (dir) {
     case OHCI_TD_DIR_IN:
+#ifdef DEBUG_ISOCH
         str = "in";
+#endif
         pid = USB_TOKEN_IN;
         break;
     case OHCI_TD_DIR_OUT:
+#ifdef DEBUG_ISOCH
         str = "out";
+#endif
         pid = USB_TOKEN_OUT;
         break;
     case OHCI_TD_DIR_SETUP:
+#ifdef DEBUG_ISOCH
         str = "setup";
+#endif
         pid = USB_TOKEN_SETUP;
         break;
     default:
@@ -834,7 +842,9 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
 {
     int dir;
     size_t len = 0;
+#ifdef DEBUG_PACKET
     const char *str = NULL;
+#endif
     int pid;
     int ret;
     int i;
@@ -871,15 +881,21 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
 
     switch (dir) {
     case OHCI_TD_DIR_IN:
+#ifdef DEBUG_PACKET
         str = "in";
+#endif
         pid = USB_TOKEN_IN;
         break;
     case OHCI_TD_DIR_OUT:
+#ifdef DEBUG_PACKET
         str = "out";
+#endif
         pid = USB_TOKEN_OUT;
         break;
     case OHCI_TD_DIR_SETUP:
+#ifdef DEBUG_PACKET
         str = "setup";
+#endif
         pid = USB_TOKEN_SETUP;
         break;
     default:
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index 69f0e44..5b2483a 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -449,7 +449,7 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
         /* handle serial break */
         if (s->event_trigger && s->event_trigger & FTDI_BI) {
             s->event_trigger &= ~FTDI_BI;
-            *data++ = FTDI_BI;
+            *data = FTDI_BI;
             ret = 2;
             break;
         } else {
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 7c45d7f..624d55b 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -698,7 +698,6 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_
 
     if (pid == USB_TOKEN_IN) {
         if (len > max_len) {
-            len = max_len;
             ret = USB_RET_BABBLE;
             goto out;
         }
@@ -865,8 +864,7 @@ static void uhci_async_complete(USBPacket *packet, void *opaque)
         UHCI_TD td;
         uint32_t link = async->td;
         uint32_t int_mask = 0, val;
-        int len;
- 
+
         cpu_physical_memory_read(link & ~0xf, (uint8_t *) &td, sizeof(td));
         le32_to_cpus(&td.link);
         le32_to_cpus(&td.ctrl);
@@ -874,7 +872,7 @@ static void uhci_async_complete(USBPacket *packet, void *opaque)
         le32_to_cpus(&td.buffer);
 
         uhci_async_unlink(s, async);
-        len = uhci_complete_td(s, &td, async, &int_mask);
+        uhci_complete_td(s, &td, async, &int_mask);
         s->pending_int_mask |= int_mask;
 
         /* update the status bits of the TD */
diff --git a/usb-linux.c b/usb-linux.c
index d0d7cff..ecfe668 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -287,7 +287,7 @@ static void async_cancel(USBPacket *unused, void *opaque)
 static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
 {
     int dev_descr_len, config_descr_len;
-    int interface, nb_interfaces, nb_configurations;
+    int interface, nb_interfaces;
     int ret, i;
 
     if (configuration == 0) /* address state - ignore */
@@ -299,7 +299,6 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
     dev_descr_len = dev->descr[0];
     if (dev_descr_len > dev->descr_len)
         goto fail;
-    nb_configurations = dev->descr[17];
 
     i += dev_descr_len;
     while (i < dev->descr_len) {
commit 7300c07991e05e66e04528aa1c72e31c127a79cd
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 25 18:20:28 2010 +0000

    bt: remove dead assignments, spotted by clang analyzer
    
    Value stored is never read.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/bt-host.c b/bt-host.c
index 33b2761..6931e7c 100644
--- a/bt-host.c
+++ b/bt-host.c
@@ -50,19 +50,19 @@ static void bt_host_send(struct HCIInfo *hci,
     struct bt_host_hci_s *s = (struct bt_host_hci_s *) hci;
     uint8_t pkt = type;
     struct iovec iv[2];
-    int ret;
 
     iv[0].iov_base = (void *)&pkt;
     iv[0].iov_len  = 1;
     iv[1].iov_base = (void *) data;
     iv[1].iov_len  = len;
 
-    while ((ret = writev(s->fd, iv, 2)) < 0)
+    while (writev(s->fd, iv, 2) < 0) {
         if (errno != EAGAIN && errno != EINTR) {
             fprintf(stderr, "qemu: error %i writing bluetooth packet.\n",
                             errno);
             return;
         }
+    }
 }
 
 static void bt_host_cmd(struct HCIInfo *hci, const uint8_t *data, int len)
diff --git a/hw/bt-hci-csr.c b/hw/bt-hci-csr.c
index 7300ea6..982577d 100644
--- a/hw/bt-hci-csr.c
+++ b/hw/bt-hci-csr.c
@@ -226,7 +226,7 @@ static void csrhci_in_packet(struct csrhci_s *s, uint8_t *pkt)
         *rpkt ++ = 0x20;	/* Operational settings negotation Ok */
         memcpy(rpkt, pkt, 7); rpkt += 7;
         *rpkt ++ = 0xff;
-        *rpkt ++ = 0xff;
+        *rpkt = 0xff;
         break;
 
     case H4_ALIVE_PKT:
@@ -238,7 +238,7 @@ static void csrhci_in_packet(struct csrhci_s *s, uint8_t *pkt)
         rpkt = csrhci_out_packet_csr(s, H4_ALIVE_PKT, 2);
 
         *rpkt ++ = 0xcc;
-        *rpkt ++ = 0x00;
+        *rpkt = 0x00;
         break;
 
     default:
diff --git a/hw/bt-hci.c b/hw/bt-hci.c
index 669866a..f1ee92c 100644
--- a/hw/bt-hci.c
+++ b/hw/bt-hci.c
@@ -994,13 +994,12 @@ static int bt_hci_features_req(struct bt_hci_s *hci, uint16_t handle)
 
 static int bt_hci_version_req(struct bt_hci_s *hci, uint16_t handle)
 {
-    struct bt_device_s *slave;
     evt_read_remote_version_complete params;
 
     if (bt_hci_handle_bad(hci, handle))
         return -ENODEV;
 
-    slave = bt_hci_remote_dev(hci, handle);
+    bt_hci_remote_dev(hci, handle);
 
     bt_hci_event_status(hci, HCI_SUCCESS);
 
@@ -2080,7 +2079,6 @@ static void bt_submit_sco(struct HCIInfo *info,
                 const uint8_t *data, int length)
 {
     struct bt_hci_s *hci = hci_from_info(info);
-    struct bt_link_s *link;
     uint16_t handle;
     int datalen;
 
@@ -2089,7 +2087,6 @@ static void bt_submit_sco(struct HCIInfo *info,
 
     handle = acl_handle((data[1] << 8) | data[0]);
     datalen = data[2];
-    data += 3;
     length -= 3;
 
     if (bt_hci_handle_bad(hci, handle)) {
@@ -2097,7 +2094,6 @@ static void bt_submit_sco(struct HCIInfo *info,
                         __FUNCTION__, handle);
         return;
     }
-    handle &= ~HCI_HANDLE_OFFSET;
 
     if (datalen > length) {
         fprintf(stderr, "%s: SCO packet too short (%iB < %iB)\n",
@@ -2105,7 +2101,6 @@ static void bt_submit_sco(struct HCIInfo *info,
         return;
     }
 
-    link = hci->lm.handle[handle].link;
     /* TODO */
 
     /* TODO: increase counter and send EVT_NUM_COMP_PKTS if synchronous
commit 2cc2026063a7500670a76edd5ece59936ceec441
Author: Richard Henderson <rth at twiddle.net>
Date:   Sun Apr 25 11:01:25 2010 -0700

    linux-user: Fix Sparc64 syscall returns.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/linux-user/main.c b/linux-user/main.c
index b394c00..71a1b67 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -940,7 +940,8 @@ static void flush_windows(CPUSPARCState *env)
 
 void cpu_loop (CPUSPARCState *env)
 {
-    int trapnr, ret;
+    int trapnr;
+    abi_long ret;
     target_siginfo_t info;
 
     while (1) {
@@ -958,7 +959,7 @@ void cpu_loop (CPUSPARCState *env)
                               env->regwptr[0], env->regwptr[1],
                               env->regwptr[2], env->regwptr[3],
                               env->regwptr[4], env->regwptr[5]);
-            if ((unsigned int)ret >= (unsigned int)(-515)) {
+            if ((abi_ulong)ret >= (abi_ulong)(-515)) {
 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
                 env->xcc |= PSR_CARRY;
 #else
commit 88bf79500b7659aa7978b445393479d76e9c0c9e
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 25 15:27:14 2010 +0000

    Fix dead initialization, spotted by clang analyzer
    
    Fix clang warnings:
    /src/qemu/block/vvfat.c:1102:9: warning: Value stored to 'index3' during its initialization is never read
        int index3=index1+1;
    /src/qemu/cmd.c:290:15: warning: Value stored to 'p' during its initialization is never read
            char *p = result;
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/block/vvfat.c b/block/vvfat.c
index 0701df4..66259b4 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -1099,8 +1099,8 @@ static inline void vvfat_close_current_file(BDRVVVFATState *s)
  */
 static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num,int index1,int index2)
 {
-    int index3=index1+1;
     while(1) {
+        int index3;
 	mapping_t* mapping;
 	index3=(index1+index2)/2;
 	mapping=array_get(&(s->mapping),index3);
diff --git a/cmd.c b/cmd.c
index cc70311..2336334 100644
--- a/cmd.c
+++ b/cmd.c
@@ -287,7 +287,8 @@ static char *qemu_strsep(char **input, const char *delim)
 {
     char *result = *input;
     if (result != NULL) {
-        char *p = result;
+        char *p;
+
         for (p = result; *p != '\0'; p++) {
             if (strchr(delim, *p)) {
                 break;
commit f64052478e3828393aea4248da4047b86d48f83f
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Apr 22 16:47:31 2010 -0700

    Remove IO_MEM_SUBWIDTH.
    
    Greatly simplify the subpage implementation by not supporting
    multiple devices at the same address at different widths.  We
    don't need full copies of mem_read/mem_write/opaque for each
    address, only a single index back into the main io_mem_* arrays.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpu-common.h b/cpu-common.h
index b730ca0..b24cecc 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -125,7 +125,6 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr,
 /* Acts like a ROM when read and like a device when written.  */
 #define IO_MEM_ROMD        (1)
 #define IO_MEM_SUBPAGE     (2)
-#define IO_MEM_SUBWIDTH    (4)
 
 #endif
 
diff --git a/exec.c b/exec.c
index 43366ac..14d1fd7 100644
--- a/exec.c
+++ b/exec.c
@@ -2549,16 +2549,15 @@ static inline void tlb_set_dirty(CPUState *env,
 #define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
 typedef struct subpage_t {
     target_phys_addr_t base;
-    CPUReadMemoryFunc * const *mem_read[TARGET_PAGE_SIZE][4];
-    CPUWriteMemoryFunc * const *mem_write[TARGET_PAGE_SIZE][4];
-    void *opaque[TARGET_PAGE_SIZE][2][4];
-    ram_addr_t region_offset[TARGET_PAGE_SIZE][2][4];
+    ram_addr_t sub_io_index[TARGET_PAGE_SIZE];
+    ram_addr_t region_offset[TARGET_PAGE_SIZE];
 } subpage_t;
 
 static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
                              ram_addr_t memory, ram_addr_t region_offset);
-static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
-                           ram_addr_t orig_memory, ram_addr_t region_offset);
+static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
+                                ram_addr_t orig_memory,
+                                ram_addr_t region_offset);
 #define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
                       need_subpage)                                     \
     do {                                                                \
@@ -2596,7 +2595,7 @@ void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
     PhysPageDesc *p;
     CPUState *env;
     ram_addr_t orig_size = size;
-    void *subpage;
+    subpage_t *subpage;
 
     cpu_notify_set_memory(start_addr, size, phys_offset);
 
@@ -2615,7 +2614,7 @@ void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
 
             CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
                           need_subpage);
-            if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
+            if (need_subpage) {
                 if (!(orig_memory & IO_MEM_SUBPAGE)) {
                     subpage = subpage_init((addr & TARGET_PAGE_MASK),
                                            &p->phys_offset, orig_memory,
@@ -2647,7 +2646,7 @@ void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
                 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
                               end_addr2, need_subpage);
 
-                if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
+                if (need_subpage) {
                     subpage = subpage_init((addr & TARGET_PAGE_MASK),
                                            &p->phys_offset, IO_MEM_UNASSIGNED,
                                            addr & TARGET_PAGE_MASK);
@@ -3145,89 +3144,65 @@ static CPUWriteMemoryFunc * const watch_mem_write[3] = {
     watch_mem_writel,
 };
 
-static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
-                                 unsigned int len)
+static inline uint32_t subpage_readlen (subpage_t *mmio,
+                                        target_phys_addr_t addr,
+                                        unsigned int len)
 {
-    uint32_t ret;
-    unsigned int idx;
-
-    idx = SUBPAGE_IDX(addr);
+    unsigned int idx = SUBPAGE_IDX(addr);
 #if defined(DEBUG_SUBPAGE)
     printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
            mmio, len, addr, idx);
 #endif
-    ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
-                                       addr + mmio->region_offset[idx][0][len]);
 
-    return ret;
+    addr += mmio->region_offset[idx];
+    idx = mmio->sub_io_index[idx];
+    return io_mem_read[idx][len](io_mem_opaque[idx], addr);
 }
 
 static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
-                              uint32_t value, unsigned int len)
+                                     uint32_t value, unsigned int len)
 {
-    unsigned int idx;
-
-    idx = SUBPAGE_IDX(addr);
+    unsigned int idx = SUBPAGE_IDX(addr);
 #if defined(DEBUG_SUBPAGE)
-    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
-           mmio, len, addr, idx, value);
+    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n",
+           __func__, mmio, len, addr, idx, value);
 #endif
-    (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
-                                  addr + mmio->region_offset[idx][1][len],
-                                  value);
+
+    addr += mmio->region_offset[idx];
+    idx = mmio->sub_io_index[idx];
+    io_mem_write[idx][len](io_mem_opaque[idx], addr, value);
 }
 
 static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
 {
-#if defined(DEBUG_SUBPAGE)
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-
     return subpage_readlen(opaque, addr, 0);
 }
 
 static void subpage_writeb (void *opaque, target_phys_addr_t addr,
                             uint32_t value)
 {
-#if defined(DEBUG_SUBPAGE)
-    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
-#endif
     subpage_writelen(opaque, addr, value, 0);
 }
 
 static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
 {
-#if defined(DEBUG_SUBPAGE)
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-
     return subpage_readlen(opaque, addr, 1);
 }
 
 static void subpage_writew (void *opaque, target_phys_addr_t addr,
                             uint32_t value)
 {
-#if defined(DEBUG_SUBPAGE)
-    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
-#endif
     subpage_writelen(opaque, addr, value, 1);
 }
 
 static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
 {
-#if defined(DEBUG_SUBPAGE)
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-
     return subpage_readlen(opaque, addr, 2);
 }
 
-static void subpage_writel (void *opaque,
-                         target_phys_addr_t addr, uint32_t value)
+static void subpage_writel (void *opaque, target_phys_addr_t addr,
+                            uint32_t value)
 {
-#if defined(DEBUG_SUBPAGE)
-    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
-#endif
     subpage_writelen(opaque, addr, value, 2);
 }
 
@@ -3247,7 +3222,6 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
                              ram_addr_t memory, ram_addr_t region_offset)
 {
     int idx, eidx;
-    unsigned int i;
 
     if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
         return -1;
@@ -3257,27 +3231,18 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
     printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
            mmio, start, end, idx, eidx, memory);
 #endif
-    memory >>= IO_MEM_SHIFT;
+    memory = (memory >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
     for (; idx <= eidx; idx++) {
-        for (i = 0; i < 4; i++) {
-            if (io_mem_read[memory][i]) {
-                mmio->mem_read[idx][i] = &io_mem_read[memory][i];
-                mmio->opaque[idx][0][i] = io_mem_opaque[memory];
-                mmio->region_offset[idx][0][i] = region_offset;
-            }
-            if (io_mem_write[memory][i]) {
-                mmio->mem_write[idx][i] = &io_mem_write[memory][i];
-                mmio->opaque[idx][1][i] = io_mem_opaque[memory];
-                mmio->region_offset[idx][1][i] = region_offset;
-            }
-        }
+        mmio->sub_io_index[idx] = memory;
+        mmio->region_offset[idx] = region_offset;
     }
 
     return 0;
 }
 
-static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
-                           ram_addr_t orig_memory, ram_addr_t region_offset)
+static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
+                                ram_addr_t orig_memory,
+                                ram_addr_t region_offset)
 {
     subpage_t *mmio;
     int subpage_memory;
@@ -3291,8 +3256,7 @@ static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
            mmio, base, TARGET_PAGE_SIZE, subpage_memory);
 #endif
     *phys = subpage_memory | IO_MEM_SUBPAGE;
-    subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
-                         region_offset);
+    subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, orig_memory, region_offset);
 
     return mmio;
 }
@@ -3322,8 +3286,6 @@ static int cpu_register_io_memory_fixed(int io_index,
                                         CPUWriteMemoryFunc * const *mem_write,
                                         void *opaque)
 {
-    int i, subwidth = 0;
-
     if (io_index <= 0) {
         io_index = get_free_io_mem_idx();
         if (io_index == -1)
@@ -3334,14 +3296,11 @@ static int cpu_register_io_memory_fixed(int io_index,
             return -1;
     }
 
-    for(i = 0;i < 3; i++) {
-        if (!mem_read[i] || !mem_write[i])
-            subwidth = IO_MEM_SUBWIDTH;
-        io_mem_read[io_index][i] = mem_read[i];
-        io_mem_write[io_index][i] = mem_write[i];
-    }
+    memcpy(io_mem_read[io_index], mem_read, 3 * sizeof(CPUReadMemoryFunc*));
+    memcpy(io_mem_write[io_index], mem_write, 3 * sizeof(CPUWriteMemoryFunc*));
     io_mem_opaque[io_index] = opaque;
-    return (io_index << IO_MEM_SHIFT) | subwidth;
+
+    return (io_index << IO_MEM_SHIFT);
 }
 
 int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
commit 6495a044575c01aee960c54e8a138ac51ed8a835
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Apr 22 17:24:58 2010 -0700

    linux-user: Remove ELFLOAD32.
    
    The ABI-specific types used by linux_binprm and image_info
    are different after forcing TARGET_ABI32 on.  Which means
    that the parameters that load_elf_binary_multi sees are not
    those that loader_exec passed.  This is inherently broken
    and is more trouble than it's worth fixing.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 5897051..65beed5 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -88,7 +88,6 @@ obj-y = main.o syscall.o strace.o mmap.o signal.o thunk.o \
       elfload.o linuxload.o uaccess.o gdbstub.o cpu-uname.o
 
 obj-$(TARGET_HAS_BFLT) += flatload.o
-obj-$(TARGET_HAS_ELFLOAD32) += elfload32.o
 
 obj-$(TARGET_I386) += vm86.o
 
diff --git a/configure b/configure
index 7c06719..e2dadb0 100755
--- a/configure
+++ b/configure
@@ -2413,7 +2413,6 @@ ln -s $source_path/Makefile.target $target_dir/Makefile
 echo "# Automatically generated by configure - do not modify" > $config_target_mak
 
 bflt="no"
-elfload32="no"
 target_nptl="no"
 interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_arch2/g"`
 echo "CONFIG_QEMU_PREFIX=\"$interp_prefix1\"" >> $config_target_mak
@@ -2510,7 +2509,6 @@ case "$target_arch2" in
   ;;
   sparc64)
     TARGET_BASE_ARCH=sparc
-    elfload32="yes"
     target_phys_bits=64
   ;;
   sparc32plus)
@@ -2609,10 +2607,6 @@ if test "$target_user_only" = "yes" \
         -a "$nptl" = "yes" -a "$target_nptl" = "yes"; then
   echo "CONFIG_USE_NPTL=y" >> $config_target_mak
 fi
-# 32 bit ELF loader in addition to native 64 bit loader?
-if test "$target_user_only" = "yes" -a "$elfload32" = "yes"; then
-  echo "TARGET_HAS_ELFLOAD32=y" >> $config_target_mak
-fi
 if test "$target_user_only" = "yes" -a "$guest_base" = "yes"; then
   echo "CONFIG_USE_GUEST_BASE=y" >> $config_target_mak
 fi
diff --git a/linux-user/elfload32.c b/linux-user/elfload32.c
deleted file mode 100644
index 4b4648c..0000000
--- a/linux-user/elfload32.c
+++ /dev/null
@@ -1,30 +0,0 @@
-#define TARGET_ABI32
-#define load_elf_binary load_elf_binary32
-#define do_init_thread do_init_thread32
-
-#include "elfload.c"
-
-#undef load_elf_binary
-#undef do_init_thread
-
-int load_elf_binary(struct linux_binprm *bprm, struct target_pt_regs *regs,
-                    struct image_info *info);
-
-int load_elf_binary_multi(struct linux_binprm *bprm,
-                          struct target_pt_regs *regs,
-                          struct image_info *info)
-{
-    struct elfhdr *elf_ex;
-    int retval;
-
-    elf_ex = (struct elfhdr *) bprm->buf;          /* exec-header */
-    if (elf_ex->e_ident[EI_CLASS] == ELFCLASS64) {
-        retval = load_elf_binary(bprm, regs, info);
-    } else {
-        retval = load_elf_binary32(bprm, regs, info);
-        if (personality(info->personality) == PER_LINUX)
-            info->personality = PER_LINUX32;
-    }
-
-    return retval;
-}
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 2d778a2..13ad9aa 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -184,11 +184,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
                 && bprm->buf[1] == 'E'
                 && bprm->buf[2] == 'L'
                 && bprm->buf[3] == 'F') {
-#ifndef TARGET_HAS_ELFLOAD32
-            retval = load_elf_binary(bprm,regs,infop);
-#else
-            retval = load_elf_binary_multi(bprm, regs, infop);
-#endif
+            retval = load_elf_binary(bprm, regs, infop);
 #if defined(TARGET_HAS_BFLT)
         } else if (bprm->buf[0] == 'b'
                 && bprm->buf[1] == 'F'
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 47fc686..dab3597 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -171,11 +171,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                     struct image_info * info);
 int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                     struct image_info * info);
-#ifdef TARGET_HAS_ELFLOAD32
-int load_elf_binary_multi(struct linux_binprm *bprm,
-                          struct target_pt_regs *regs,
-                          struct image_info *info);
-#endif
 
 abi_long memcpy_to_target(abi_ulong dest, const void *src,
                           unsigned long len);
commit e23886a91d954aac08b8b1dd0ff08ce4dbb842be
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sun Apr 25 05:46:22 2010 +0200

    tcg/arm: fix condition in zero/sign extension functions
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 2937c5a..8d23f47 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -483,9 +483,9 @@ static inline void tcg_out_ext8s(TCGContext *s, int cond,
         /* sxtb */
         tcg_out32(s, 0x06af0070 | (cond << 28) | (rd << 12) | rn);
     } else {
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+        tcg_out_dat_reg(s, cond, ARITH_MOV,
                         rd, 0, rn, SHIFT_IMM_LSL(24));
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+        tcg_out_dat_reg(s, cond, ARITH_MOV,
                         rd, 0, rd, SHIFT_IMM_ASR(24));
     }
 }
@@ -503,9 +503,9 @@ static inline void tcg_out_ext16s(TCGContext *s, int cond,
         /* sxth */
         tcg_out32(s, 0x06bf0070 | (cond << 28) | (rd << 12) | rn);
     } else {
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+        tcg_out_dat_reg(s, cond, ARITH_MOV,
                         rd, 0, rn, SHIFT_IMM_LSL(16));
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+        tcg_out_dat_reg(s, cond, ARITH_MOV,
                         rd, 0, rd, SHIFT_IMM_ASR(16));
     }
 }
@@ -517,9 +517,9 @@ static inline void tcg_out_ext16u(TCGContext *s, int cond,
         /* uxth */
         tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | rn);
     } else {
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+        tcg_out_dat_reg(s, cond, ARITH_MOV,
                         rd, 0, rn, SHIFT_IMM_LSL(16));
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+        tcg_out_dat_reg(s, cond, ARITH_MOV,
                         rd, 0, rd, SHIFT_IMM_LSR(16));
     }
 }
commit 20d97356c9df6d68fbd37d6334fdb7063f24eab6
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri Apr 23 20:19:47 2010 +0000

    Fix OpenBSD build
    
    GCC 3.3.5 generates warnings for static forward declarations of data, so
    rearrange code to use static forward declarations of functions instead.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index f3e3cba..5436fec 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -52,7 +52,7 @@ typedef struct {
 #define  QCOW_EXT_MAGIC_END 0
 #define  QCOW_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA
 
-static BlockDriver bdrv_qcow2;
+static int qcow_create(const char *filename, QEMUOptionParameter *options);
 
 static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
 {
@@ -838,6 +838,245 @@ static int preallocate(BlockDriverState *bs)
     return 0;
 }
 
+static int qcow_make_empty(BlockDriverState *bs)
+{
+#if 0
+    /* XXX: not correct */
+    BDRVQcowState *s = bs->opaque;
+    uint32_t l1_length = s->l1_size * sizeof(uint64_t);
+    int ret;
+
+    memset(s->l1_table, 0, l1_length);
+    if (bdrv_pwrite(s->hd, s->l1_table_offset, s->l1_table, l1_length) < 0)
+        return -1;
+    ret = bdrv_truncate(s->hd, s->l1_table_offset + l1_length);
+    if (ret < 0)
+        return ret;
+
+    l2_cache_reset(bs);
+#endif
+    return 0;
+}
+
+/* XXX: put compressed sectors first, then all the cluster aligned
+   tables to avoid losing bytes in alignment */
+static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
+                                 const uint8_t *buf, int nb_sectors)
+{
+    BDRVQcowState *s = bs->opaque;
+    z_stream strm;
+    int ret, out_len;
+    uint8_t *out_buf;
+    uint64_t cluster_offset;
+
+    if (nb_sectors == 0) {
+        /* align end of file to a sector boundary to ease reading with
+           sector based I/Os */
+        cluster_offset = bdrv_getlength(s->hd);
+        cluster_offset = (cluster_offset + 511) & ~511;
+        bdrv_truncate(s->hd, cluster_offset);
+        return 0;
+    }
+
+    if (nb_sectors != s->cluster_sectors)
+        return -EINVAL;
+
+    out_buf = qemu_malloc(s->cluster_size + (s->cluster_size / 1000) + 128);
+
+    /* best compression, small window, no zlib header */
+    memset(&strm, 0, sizeof(strm));
+    ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,
+                       Z_DEFLATED, -12,
+                       9, Z_DEFAULT_STRATEGY);
+    if (ret != 0) {
+        qemu_free(out_buf);
+        return -1;
+    }
+
+    strm.avail_in = s->cluster_size;
+    strm.next_in = (uint8_t *)buf;
+    strm.avail_out = s->cluster_size;
+    strm.next_out = out_buf;
+
+    ret = deflate(&strm, Z_FINISH);
+    if (ret != Z_STREAM_END && ret != Z_OK) {
+        qemu_free(out_buf);
+        deflateEnd(&strm);
+        return -1;
+    }
+    out_len = strm.next_out - out_buf;
+
+    deflateEnd(&strm);
+
+    if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
+        /* could not compress: write normal cluster */
+        bdrv_write(bs, sector_num, buf, s->cluster_sectors);
+    } else {
+        cluster_offset = qcow2_alloc_compressed_cluster_offset(bs,
+            sector_num << 9, out_len);
+        if (!cluster_offset)
+            return -1;
+        cluster_offset &= s->cluster_offset_mask;
+        BLKDBG_EVENT(s->hd, BLKDBG_WRITE_COMPRESSED);
+        if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
+            qemu_free(out_buf);
+            return -1;
+        }
+    }
+
+    qemu_free(out_buf);
+    return 0;
+}
+
+static void qcow_flush(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    bdrv_flush(s->hd);
+}
+
+static BlockDriverAIOCB *qcow_aio_flush(BlockDriverState *bs,
+         BlockDriverCompletionFunc *cb, void *opaque)
+{
+     BDRVQcowState *s = bs->opaque;
+
+     return bdrv_aio_flush(s->hd, cb, opaque);
+}
+
+static int64_t qcow_vm_state_offset(BDRVQcowState *s)
+{
+	return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits);
+}
+
+static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+{
+    BDRVQcowState *s = bs->opaque;
+    bdi->cluster_size = s->cluster_size;
+    bdi->vm_state_offset = qcow_vm_state_offset(s);
+    return 0;
+}
+
+
+static int qcow_check(BlockDriverState *bs)
+{
+    return qcow2_check_refcounts(bs);
+}
+
+#if 0
+static void dump_refcounts(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    int64_t nb_clusters, k, k1, size;
+    int refcount;
+
+    size = bdrv_getlength(s->hd);
+    nb_clusters = size_to_clusters(s, size);
+    for(k = 0; k < nb_clusters;) {
+        k1 = k;
+        refcount = get_refcount(bs, k);
+        k++;
+        while (k < nb_clusters && get_refcount(bs, k) == refcount)
+            k++;
+        printf("%lld: refcount=%d nb=%lld\n", k, refcount, k - k1);
+    }
+}
+#endif
+
+static int qcow_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
+                           int64_t pos, int size)
+{
+    BDRVQcowState *s = bs->opaque;
+    int growable = bs->growable;
+    int ret;
+
+    BLKDBG_EVENT(s->hd, BLKDBG_VMSTATE_SAVE);
+    bs->growable = 1;
+    ret = bdrv_pwrite(bs, qcow_vm_state_offset(s) + pos, buf, size);
+    bs->growable = growable;
+
+    return ret;
+}
+
+static int qcow_load_vmstate(BlockDriverState *bs, uint8_t *buf,
+                           int64_t pos, int size)
+{
+    BDRVQcowState *s = bs->opaque;
+    int growable = bs->growable;
+    int ret;
+
+    BLKDBG_EVENT(s->hd, BLKDBG_VMSTATE_LOAD);
+    bs->growable = 1;
+    ret = bdrv_pread(bs, qcow_vm_state_offset(s) + pos, buf, size);
+    bs->growable = growable;
+
+    return ret;
+}
+
+static QEMUOptionParameter qcow_create_options[] = {
+    {
+        .name = BLOCK_OPT_SIZE,
+        .type = OPT_SIZE,
+        .help = "Virtual disk size"
+    },
+    {
+        .name = BLOCK_OPT_BACKING_FILE,
+        .type = OPT_STRING,
+        .help = "File name of a base image"
+    },
+    {
+        .name = BLOCK_OPT_BACKING_FMT,
+        .type = OPT_STRING,
+        .help = "Image format of the base image"
+    },
+    {
+        .name = BLOCK_OPT_ENCRYPT,
+        .type = OPT_FLAG,
+        .help = "Encrypt the image"
+    },
+    {
+        .name = BLOCK_OPT_CLUSTER_SIZE,
+        .type = OPT_SIZE,
+        .help = "qcow2 cluster size"
+    },
+    {
+        .name = BLOCK_OPT_PREALLOC,
+        .type = OPT_STRING,
+        .help = "Preallocation mode (allowed values: off, metadata)"
+    },
+    { NULL }
+};
+
+static BlockDriver bdrv_qcow2 = {
+    .format_name	= "qcow2",
+    .instance_size	= sizeof(BDRVQcowState),
+    .bdrv_probe		= qcow_probe,
+    .bdrv_open		= qcow_open,
+    .bdrv_close		= qcow_close,
+    .bdrv_create	= qcow_create,
+    .bdrv_flush		= qcow_flush,
+    .bdrv_is_allocated	= qcow_is_allocated,
+    .bdrv_set_key	= qcow_set_key,
+    .bdrv_make_empty	= qcow_make_empty,
+
+    .bdrv_aio_readv	= qcow_aio_readv,
+    .bdrv_aio_writev	= qcow_aio_writev,
+    .bdrv_aio_flush	= qcow_aio_flush,
+    .bdrv_write_compressed = qcow_write_compressed,
+
+    .bdrv_snapshot_create   = qcow2_snapshot_create,
+    .bdrv_snapshot_goto     = qcow2_snapshot_goto,
+    .bdrv_snapshot_delete   = qcow2_snapshot_delete,
+    .bdrv_snapshot_list     = qcow2_snapshot_list,
+    .bdrv_get_info	= qcow_get_info,
+
+    .bdrv_save_vmstate    = qcow_save_vmstate,
+    .bdrv_load_vmstate    = qcow_load_vmstate,
+
+    .bdrv_change_backing_file   = qcow2_change_backing_file,
+
+    .create_options = qcow_create_options,
+    .bdrv_check = qcow_check,
+};
+
 static int qcow_create2(const char *filename, int64_t total_size,
                         const char *backing_file, const char *backing_format,
                         int flags, size_t cluster_size, int prealloc)
@@ -1082,245 +1321,6 @@ static int qcow_create(const char *filename, QEMUOptionParameter *options)
         cluster_size, prealloc);
 }
 
-static int qcow_make_empty(BlockDriverState *bs)
-{
-#if 0
-    /* XXX: not correct */
-    BDRVQcowState *s = bs->opaque;
-    uint32_t l1_length = s->l1_size * sizeof(uint64_t);
-    int ret;
-
-    memset(s->l1_table, 0, l1_length);
-    if (bdrv_pwrite(s->hd, s->l1_table_offset, s->l1_table, l1_length) < 0)
-        return -1;
-    ret = bdrv_truncate(s->hd, s->l1_table_offset + l1_length);
-    if (ret < 0)
-        return ret;
-
-    l2_cache_reset(bs);
-#endif
-    return 0;
-}
-
-/* XXX: put compressed sectors first, then all the cluster aligned
-   tables to avoid losing bytes in alignment */
-static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
-                                 const uint8_t *buf, int nb_sectors)
-{
-    BDRVQcowState *s = bs->opaque;
-    z_stream strm;
-    int ret, out_len;
-    uint8_t *out_buf;
-    uint64_t cluster_offset;
-
-    if (nb_sectors == 0) {
-        /* align end of file to a sector boundary to ease reading with
-           sector based I/Os */
-        cluster_offset = bdrv_getlength(s->hd);
-        cluster_offset = (cluster_offset + 511) & ~511;
-        bdrv_truncate(s->hd, cluster_offset);
-        return 0;
-    }
-
-    if (nb_sectors != s->cluster_sectors)
-        return -EINVAL;
-
-    out_buf = qemu_malloc(s->cluster_size + (s->cluster_size / 1000) + 128);
-
-    /* best compression, small window, no zlib header */
-    memset(&strm, 0, sizeof(strm));
-    ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,
-                       Z_DEFLATED, -12,
-                       9, Z_DEFAULT_STRATEGY);
-    if (ret != 0) {
-        qemu_free(out_buf);
-        return -1;
-    }
-
-    strm.avail_in = s->cluster_size;
-    strm.next_in = (uint8_t *)buf;
-    strm.avail_out = s->cluster_size;
-    strm.next_out = out_buf;
-
-    ret = deflate(&strm, Z_FINISH);
-    if (ret != Z_STREAM_END && ret != Z_OK) {
-        qemu_free(out_buf);
-        deflateEnd(&strm);
-        return -1;
-    }
-    out_len = strm.next_out - out_buf;
-
-    deflateEnd(&strm);
-
-    if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
-        /* could not compress: write normal cluster */
-        bdrv_write(bs, sector_num, buf, s->cluster_sectors);
-    } else {
-        cluster_offset = qcow2_alloc_compressed_cluster_offset(bs,
-            sector_num << 9, out_len);
-        if (!cluster_offset)
-            return -1;
-        cluster_offset &= s->cluster_offset_mask;
-        BLKDBG_EVENT(s->hd, BLKDBG_WRITE_COMPRESSED);
-        if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
-            qemu_free(out_buf);
-            return -1;
-        }
-    }
-
-    qemu_free(out_buf);
-    return 0;
-}
-
-static void qcow_flush(BlockDriverState *bs)
-{
-    BDRVQcowState *s = bs->opaque;
-    bdrv_flush(s->hd);
-}
-
-static BlockDriverAIOCB *qcow_aio_flush(BlockDriverState *bs,
-         BlockDriverCompletionFunc *cb, void *opaque)
-{
-     BDRVQcowState *s = bs->opaque;
-
-     return bdrv_aio_flush(s->hd, cb, opaque);
-}
-
-static int64_t qcow_vm_state_offset(BDRVQcowState *s)
-{
-	return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits);
-}
-
-static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
-{
-    BDRVQcowState *s = bs->opaque;
-    bdi->cluster_size = s->cluster_size;
-    bdi->vm_state_offset = qcow_vm_state_offset(s);
-    return 0;
-}
-
-
-static int qcow_check(BlockDriverState *bs)
-{
-    return qcow2_check_refcounts(bs);
-}
-
-#if 0
-static void dump_refcounts(BlockDriverState *bs)
-{
-    BDRVQcowState *s = bs->opaque;
-    int64_t nb_clusters, k, k1, size;
-    int refcount;
-
-    size = bdrv_getlength(s->hd);
-    nb_clusters = size_to_clusters(s, size);
-    for(k = 0; k < nb_clusters;) {
-        k1 = k;
-        refcount = get_refcount(bs, k);
-        k++;
-        while (k < nb_clusters && get_refcount(bs, k) == refcount)
-            k++;
-        printf("%lld: refcount=%d nb=%lld\n", k, refcount, k - k1);
-    }
-}
-#endif
-
-static int qcow_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
-                           int64_t pos, int size)
-{
-    BDRVQcowState *s = bs->opaque;
-    int growable = bs->growable;
-    int ret;
-
-    BLKDBG_EVENT(s->hd, BLKDBG_VMSTATE_SAVE);
-    bs->growable = 1;
-    ret = bdrv_pwrite(bs, qcow_vm_state_offset(s) + pos, buf, size);
-    bs->growable = growable;
-
-    return ret;
-}
-
-static int qcow_load_vmstate(BlockDriverState *bs, uint8_t *buf,
-                           int64_t pos, int size)
-{
-    BDRVQcowState *s = bs->opaque;
-    int growable = bs->growable;
-    int ret;
-
-    BLKDBG_EVENT(s->hd, BLKDBG_VMSTATE_LOAD);
-    bs->growable = 1;
-    ret = bdrv_pread(bs, qcow_vm_state_offset(s) + pos, buf, size);
-    bs->growable = growable;
-
-    return ret;
-}
-
-static QEMUOptionParameter qcow_create_options[] = {
-    {
-        .name = BLOCK_OPT_SIZE,
-        .type = OPT_SIZE,
-        .help = "Virtual disk size"
-    },
-    {
-        .name = BLOCK_OPT_BACKING_FILE,
-        .type = OPT_STRING,
-        .help = "File name of a base image"
-    },
-    {
-        .name = BLOCK_OPT_BACKING_FMT,
-        .type = OPT_STRING,
-        .help = "Image format of the base image"
-    },
-    {
-        .name = BLOCK_OPT_ENCRYPT,
-        .type = OPT_FLAG,
-        .help = "Encrypt the image"
-    },
-    {
-        .name = BLOCK_OPT_CLUSTER_SIZE,
-        .type = OPT_SIZE,
-        .help = "qcow2 cluster size"
-    },
-    {
-        .name = BLOCK_OPT_PREALLOC,
-        .type = OPT_STRING,
-        .help = "Preallocation mode (allowed values: off, metadata)"
-    },
-    { NULL }
-};
-
-static BlockDriver bdrv_qcow2 = {
-    .format_name	= "qcow2",
-    .instance_size	= sizeof(BDRVQcowState),
-    .bdrv_probe		= qcow_probe,
-    .bdrv_open		= qcow_open,
-    .bdrv_close		= qcow_close,
-    .bdrv_create	= qcow_create,
-    .bdrv_flush		= qcow_flush,
-    .bdrv_is_allocated	= qcow_is_allocated,
-    .bdrv_set_key	= qcow_set_key,
-    .bdrv_make_empty	= qcow_make_empty,
-
-    .bdrv_aio_readv	= qcow_aio_readv,
-    .bdrv_aio_writev	= qcow_aio_writev,
-    .bdrv_aio_flush	= qcow_aio_flush,
-    .bdrv_write_compressed = qcow_write_compressed,
-
-    .bdrv_snapshot_create   = qcow2_snapshot_create,
-    .bdrv_snapshot_goto     = qcow2_snapshot_goto,
-    .bdrv_snapshot_delete   = qcow2_snapshot_delete,
-    .bdrv_snapshot_list     = qcow2_snapshot_list,
-    .bdrv_get_info	= qcow_get_info,
-
-    .bdrv_save_vmstate    = qcow_save_vmstate,
-    .bdrv_load_vmstate    = qcow_load_vmstate,
-
-    .bdrv_change_backing_file   = qcow2_change_backing_file,
-
-    .create_options = qcow_create_options,
-    .bdrv_check = qcow_check,
-};
-
 static void bdrv_qcow2_init(void)
 {
     bdrv_register(&bdrv_qcow2);
commit c4162574c46307511f0fbd142164a45db98e2a23
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri Apr 23 19:22:22 2010 +0000

    m68k: fix if statement with empty body, spotted by clang
    
    Fix clang error:
      CC    m68k-softmmu/helper.o
    /src/qemu/target-m68k/helper.c:773:33: error: if statement has empty body [-Wempty-body]
        else if (val & (1ull << 47));
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 2dfd48f..b4ebb14 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -768,10 +768,11 @@ void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
 {
     uint64_t val;
     val = env->macc[acc];
-    if (val == 0)
+    if (val == 0) {
         env->macsr |= MACSR_Z;
-    else if (val & (1ull << 47));
+    } else if (val & (1ull << 47)) {
         env->macsr |= MACSR_N;
+    }
     if (env->macsr & (MACSR_PAV0 << acc)) {
         env->macsr |= MACSR_V;
     }
commit 67774a0444d42311c89898dd22240b5794a7f403
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri Apr 23 19:22:17 2010 +0000

    m68k-dis: fix unused return value, spotted by clang
    
    Fix clang errors like:
      CC    libdis/m68k-dis.o
    /src/qemu/m68k-dis.c:1796:7: error: expression result unused [-Wunused-value]
          FETCH_DATA (info, p);
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/m68k-dis.c b/m68k-dis.c
index 7cd88f8..d93943e 100644
--- a/m68k-dis.c
+++ b/m68k-dis.c
@@ -572,38 +572,38 @@ static const char *const reg_half_names[] =
 #endif
 
 /* Get a 1 byte signed integer.  */
-#define NEXTBYTE(p)  (p += 2, FETCH_DATA (info, p), COERCE_SIGNED_CHAR(p[-1]))
+#define NEXTBYTE(p)  (p += 2, fetch_data(info, p), COERCE_SIGNED_CHAR(p[-1]))
 
 /* Get a 2 byte signed integer.  */
 #define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
 #define NEXTWORD(p)  \
-  (p += 2, FETCH_DATA (info, p), \
+  (p += 2, fetch_data(info, p), \
    COERCE16 ((p[-2] << 8) + p[-1]))
 
 /* Get a 4 byte signed integer.  */
 #define COERCE32(x) ((bfd_signed_vma) ((x) ^ 0x80000000) - 0x80000000)
 #define NEXTLONG(p)  \
-  (p += 4, FETCH_DATA (info, p), \
+  (p += 4, fetch_data(info, p), \
    (COERCE32 ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])))
 
 /* Get a 4 byte unsigned integer.  */
 #define NEXTULONG(p)  \
-  (p += 4, FETCH_DATA (info, p), \
+  (p += 4, fetch_data(info, p), \
    (unsigned int) ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1]))
 
 /* Get a single precision float.  */
 #define NEXTSINGLE(val, p) \
-  (p += 4, FETCH_DATA (info, p), \
+  (p += 4, fetch_data(info, p), \
    floatformat_to_double (&floatformat_ieee_single_big, (char *) p - 4, &val))
 
 /* Get a double precision float.  */
 #define NEXTDOUBLE(val, p) \
-  (p += 8, FETCH_DATA (info, p), \
+  (p += 8, fetch_data(info, p), \
    floatformat_to_double (&floatformat_ieee_double_big, (char *) p - 8, &val))
 
 /* Get an extended precision float.  */
 #define NEXTEXTEND(val, p) \
-  (p += 12, FETCH_DATA (info, p), \
+  (p += 12, fetch_data(info, p), \
    floatformat_to_double (&floatformat_m68881_ext, (char *) p - 12, &val))
 
 /* Need a function to convert from packed to double
@@ -611,7 +611,7 @@ static const char *const reg_half_names[] =
    packed number than a double anyway, so maybe
    there should be a special case to handle this... */
 #define NEXTPACKED(p) \
-  (p += 12, FETCH_DATA (info, p), 0.0)
+  (p += 12, fetch_data(info, p), 0.0)
 
 /* Maximum length of an instruction.  */
 #define MAXLEN 22
@@ -630,12 +630,8 @@ struct private
 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
    on error.  */
-#define FETCH_DATA(info, addr) \
-  ((addr) <= ((struct private *) (info->private_data))->max_fetched \
-   ? 1 : fetch_data ((info), (addr)))
-
 static int
-fetch_data (struct disassemble_info *info, bfd_byte *addr)
+fetch_data2(struct disassemble_info *info, bfd_byte *addr)
 {
   int status;
   struct private *priv = (struct private *)info->private_data;
@@ -654,7 +650,17 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
     priv->max_fetched = addr;
   return 1;
 }
-
+
+static int
+fetch_data(struct disassemble_info *info, bfd_byte *addr)
+{
+    if (addr <= ((struct private *) (info->private_data))->max_fetched) {
+        return 1;
+    } else {
+        return fetch_data2(info, addr);
+    }
+}
+
 /* This function is used to print to the bit-bucket.  */
 static int
 dummy_printer (FILE *file ATTRIBUTE_UNUSED,
@@ -728,64 +734,64 @@ fetch_arg (unsigned char *buffer,
       break;
 
     case 'k':
-      FETCH_DATA (info, buffer + 3);
+      fetch_data(info, buffer + 3);
       val = (buffer[3] >> 4);
       break;
 
     case 'C':
-      FETCH_DATA (info, buffer + 3);
+      fetch_data(info, buffer + 3);
       val = buffer[3];
       break;
 
     case '1':
-      FETCH_DATA (info, buffer + 3);
+      fetch_data(info, buffer + 3);
       val = (buffer[2] << 8) + buffer[3];
       val >>= 12;
       break;
 
     case '2':
-      FETCH_DATA (info, buffer + 3);
+      fetch_data(info, buffer + 3);
       val = (buffer[2] << 8) + buffer[3];
       val >>= 6;
       break;
 
     case '3':
     case 'j':
-      FETCH_DATA (info, buffer + 3);
+      fetch_data(info, buffer + 3);
       val = (buffer[2] << 8) + buffer[3];
       break;
 
     case '4':
-      FETCH_DATA (info, buffer + 5);
+      fetch_data(info, buffer + 5);
       val = (buffer[4] << 8) + buffer[5];
       val >>= 12;
       break;
 
     case '5':
-      FETCH_DATA (info, buffer + 5);
+      fetch_data(info, buffer + 5);
       val = (buffer[4] << 8) + buffer[5];
       val >>= 6;
       break;
 
     case '6':
-      FETCH_DATA (info, buffer + 5);
+      fetch_data(info, buffer + 5);
       val = (buffer[4] << 8) + buffer[5];
       break;
 
     case '7':
-      FETCH_DATA (info, buffer + 3);
+      fetch_data(info, buffer + 3);
       val = (buffer[2] << 8) + buffer[3];
       val >>= 7;
       break;
 
     case '8':
-      FETCH_DATA (info, buffer + 3);
+      fetch_data(info, buffer + 3);
       val = (buffer[2] << 8) + buffer[3];
       val >>= 10;
       break;
 
     case '9':
-      FETCH_DATA (info, buffer + 3);
+      fetch_data(info, buffer + 3);
       val = (buffer[2] << 8) + buffer[3];
       val >>= 5;
       break;
@@ -1793,12 +1799,12 @@ match_insn_m68k (bfd_vma memaddr,
 	 this because we know exactly what the second word is, and we
 	 aren't going to print anything based on it.  */
       p = buffer + 6;
-      FETCH_DATA (info, p);
+      fetch_data(info, p);
       buffer[2] = buffer[4];
       buffer[3] = buffer[5];
     }
 
-  FETCH_DATA (info, p);
+  fetch_data(info, p);
 
   d = best->args;
 
@@ -1963,7 +1969,7 @@ print_insn_m68k (bfd_vma memaddr, disassemble_info *info)
       break;
     }
 
-  FETCH_DATA (info, buffer + 2);
+  fetch_data(info, buffer + 2);
   major_opcode = (buffer[0] >> 4) & 15;
 
   for (i = 0; i < numopcodes[major_opcode]; i++)
@@ -1977,7 +1983,7 @@ print_insn_m68k (bfd_vma memaddr, disassemble_info *info)
 	  /* Only fetch the next two bytes if we need to.  */
 	  && (((0xffff & match) == 0)
 	      ||
-	      (FETCH_DATA (info, buffer + 4)
+              (fetch_data(info, buffer + 4)
 	       && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
 	       && ((0xff & buffer[3] & match) == (0xff & opcode)))
 	      )
commit 4aa720f717570c9a4cb26b5f8528461f1be0996b
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri Apr 23 19:22:12 2010 +0000

    Fix harmless if statement with empty body, spotted by clang
    
    This clang error is harmless but worth fixing:
      CC    libhw32/rc4030.o
    /src/qemu/hw/rc4030.c:244:66: error: if statement has empty body [-Wempty-body]
            DPRINTF("read 0x%02x at " TARGET_FMT_plx "\n", val, addr);
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/rc4030.c b/hw/rc4030.c
index c2b2a3e..2a8233a 100644
--- a/hw/rc4030.c
+++ b/hw/rc4030.c
@@ -240,8 +240,9 @@ static uint32_t rc4030_readl(void *opaque, target_phys_addr_t addr)
         break;
     }
 
-    if ((addr & ~3) != 0x230)
+    if ((addr & ~3) != 0x230) {
         DPRINTF("read 0x%02x at " TARGET_FMT_plx "\n", val, addr);
+    }
 
     return val;
 }
commit 43d5438997c49896879f5522b0dfa98f0052888d
Merge: 1e1ea48... 41db525...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 23 13:48:33 2010 -0500

    Merge remote branch 'origin/master' into staging

commit 41db525e9c6e4c98d6e41c403c7dc704ce0e77aa
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Apr 22 22:56:42 2010 -0700

    target-sparc: Fix address masking in ldqf and stqf.
    
    Use address_mask on both addr and addr+8 in both these routines,
    rather than explicit masking with 0xffffffff.
    
    Reformulate address_mask to return a result, rather than masking
    a pass-by-reference argument.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 704631a..b27778b 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -201,12 +201,13 @@ static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
 
 #endif
 
-static inline void address_mask(CPUState *env1, target_ulong *addr)
+static inline target_ulong address_mask(CPUState *env1, target_ulong addr)
 {
 #ifdef TARGET_SPARC64
     if (AM_CHECK(env1))
-        *addr &= 0xffffffffULL;
+        addr &= 0xffffffffULL;
 #endif
+    return addr;
 }
 
 static void raise_exception(int tt)
@@ -1923,7 +1924,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         raise_exception(TT_PRIV_ACT);
 
     helper_check_align(addr, size - 1);
-    address_mask(env, &addr);
+    addr = address_mask(env, addr);
 
     switch (asi) {
     case 0x82: // Primary no-fault
@@ -2026,7 +2027,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
         raise_exception(TT_PRIV_ACT);
 
     helper_check_align(addr, size - 1);
-    address_mask(env, &addr);
+    addr = address_mask(env, addr);
 
     /* Convert to little endian */
     switch (asi) {
@@ -2944,8 +2945,7 @@ void helper_stdf(target_ulong addr, int mem_idx)
         break;
     }
 #else
-    address_mask(env, &addr);
-    stfq_raw(addr, DT0);
+    stfq_raw(address_mask(env, addr), DT0);
 #endif
 }
 
@@ -2969,8 +2969,7 @@ void helper_lddf(target_ulong addr, int mem_idx)
         break;
     }
 #else
-    address_mask(env, &addr);
-    DT0 = ldfq_raw(addr);
+    DT0 = ldfq_raw(address_mask(env, addr));
 #endif
 }
 
@@ -3003,9 +3002,8 @@ void helper_ldqf(target_ulong addr, int mem_idx)
         break;
     }
 #else
-    address_mask(env, &addr);
-    u.ll.upper = ldq_raw(addr);
-    u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
+    u.ll.upper = ldq_raw(address_mask(env, addr));
+    u.ll.lower = ldq_raw(address_mask(env, addr + 8));
     QT0 = u.q;
 #endif
 }
@@ -3040,9 +3038,8 @@ void helper_stqf(target_ulong addr, int mem_idx)
     }
 #else
     u.q = QT0;
-    address_mask(env, &addr);
-    stq_raw(addr, u.ll.upper);
-    stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
+    stq_raw(address_mask(env, addr), u.ll.upper);
+    stq_raw(address_mask(env, addr + 8), u.ll.lower);
 #endif
 }
 
commit 1e1ea48d42e011b9bdd0d689d184e7cac4617b66
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Apr 21 20:35:45 2010 +0100

    block: Free iovec arrays allocated by multiwrite_merge()
    
    A new iovec array is allocated when creating a merged write request.
    This patch ensures that the iovec array is deleted in addition to its
    qiov owner.
    
    Reported-by: Leszek Urbanski <tygrys at moo.pl>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 12cf434..7974215 100644
--- a/block.c
+++ b/block.c
@@ -1739,6 +1739,9 @@ static void multiwrite_user_cb(MultiwriteCB *mcb)
 
     for (i = 0; i < mcb->num_callbacks; i++) {
         mcb->callbacks[i].cb(mcb->callbacks[i].opaque, mcb->error);
+        if (mcb->callbacks[i].free_qiov) {
+            qemu_iovec_destroy(mcb->callbacks[i].free_qiov);
+        }
         qemu_free(mcb->callbacks[i].free_qiov);
         qemu_vfree(mcb->callbacks[i].free_buf);
     }
commit d4c146f0da2ace38b1a0e9ba42374901198909cf
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Thu Apr 15 14:11:35 2010 +0100

    qcow2: Use QLIST_FOREACH_SAFE macro
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 30ded6a..f3e3cba 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -539,14 +539,8 @@ static void run_dependent_requests(QCowL2Meta *m)
         QLIST_REMOVE(m, next_in_flight);
     }
 
-    /*
-     * Restart all dependent requests.
-     * Can't use QLIST_FOREACH here - the next link might not be the same
-     * any more after the callback  (request could depend on a different
-     * request now)
-     */
-    for (req = m->dependent_requests.lh_first; req != NULL; req = next) {
-        next = req->next_depend.le_next;
+    /* Restart all dependent requests */
+    QLIST_FOREACH_SAFE(req, &m->dependent_requests, next_depend, next) {
         qcow_aio_write_cb(req, 0);
     }
 
commit 2be5064953540d5451480375519389f104eb7909
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Apr 14 12:13:36 2010 +0100

    linux-aio: Fix typo in read() EINTR check
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/linux-aio.c b/linux-aio.c
index 5e892b0..68f4b3d 100644
--- a/linux-aio.c
+++ b/linux-aio.c
@@ -123,7 +123,7 @@ static void qemu_laio_completion_cb(void *opaque)
 
         do {
             ret = read(s->efd, &val, sizeof(val));
-        } while (ret == 1 && errno == EINTR);
+        } while (ret == -1 && errno == EINTR);
 
         if (ret == -1 && errno == EAGAIN)
             break;
commit adfe078e4b658c5406be089980c5b9034bae42a4
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Tue Apr 13 10:29:35 2010 +0100

    qemu-img: Fix BRDV_O_FLAGS typo
    
    It should be BDRV_O_FLAGS instead of BRDV_O_FLAGS.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-img.c b/qemu-img.c
index b30effa..7203b8b 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -37,7 +37,7 @@ typedef struct img_cmd_t {
 } img_cmd_t;
 
 /* Default to cache=writeback as data integrity is not important for qemu-tcg. */
-#define BRDV_O_FLAGS BDRV_O_CACHE_WB
+#define BDRV_O_FLAGS BDRV_O_CACHE_WB
 
 static void QEMU_NORETURN error(const char *fmt, ...)
 {
@@ -345,7 +345,7 @@ static int img_create(int argc, char **argv)
                 }
             }
 
-            bs = bdrv_new_open(backing_file->value.s, fmt, BRDV_O_FLAGS);
+            bs = bdrv_new_open(backing_file->value.s, fmt, BDRV_O_FLAGS);
             bdrv_get_geometry(bs, &size);
             size *= 512;
             bdrv_delete(bs);
@@ -400,7 +400,7 @@ static int img_check(int argc, char **argv)
         help();
     filename = argv[optind++];
 
-    bs = bdrv_new_open(filename, fmt, BRDV_O_FLAGS);
+    bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS);
     ret = bdrv_check(bs);
     switch(ret) {
     case 0:
@@ -446,7 +446,7 @@ static int img_commit(int argc, char **argv)
         help();
     filename = argv[optind++];
 
-    bs = bdrv_new_open(filename, fmt, BRDV_O_FLAGS | BDRV_O_RDWR);
+    bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
     ret = bdrv_commit(bs);
     switch(ret) {
     case 0:
@@ -603,7 +603,7 @@ static int img_convert(int argc, char **argv)
 
     total_sectors = 0;
     for (bs_i = 0; bs_i < bs_n; bs_i++) {
-        bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BRDV_O_FLAGS);
+        bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS);
         if (!bs[bs_i])
             error("Could not open '%s'", argv[optind + bs_i]);
         bdrv_get_geometry(bs[bs_i], &bs_sectors);
@@ -661,7 +661,7 @@ static int img_convert(int argc, char **argv)
         }
     }
 
-    out_bs = bdrv_new_open(out_filename, out_fmt, BRDV_O_FLAGS | BDRV_O_RDWR);
+    out_bs = bdrv_new_open(out_filename, out_fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
 
     bs_i = 0;
     bs_offset = 0;
@@ -885,7 +885,7 @@ static int img_info(int argc, char **argv)
         help();
     filename = argv[optind++];
 
-    bs = bdrv_new_open(filename, fmt, BRDV_O_FLAGS | BDRV_O_NO_BACKING);
+    bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING);
     bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
     bdrv_get_geometry(bs, &total_sectors);
     get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
@@ -1075,7 +1075,7 @@ static int img_rebase(int argc, char **argv)
      * Ignore the old backing file for unsafe rebase in case we want to correct
      * the reference to a renamed or moved backing file.
      */
-    flags = BRDV_O_FLAGS | BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
+    flags = BDRV_O_FLAGS | BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
     bs = bdrv_new_open(filename, fmt, flags);
 
     /* Find the right drivers for the backing files */
@@ -1106,7 +1106,7 @@ static int img_rebase(int argc, char **argv)
 
         bs_old_backing = bdrv_new("old_backing");
         bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
-        if (bdrv_open(bs_old_backing, backing_name, BRDV_O_FLAGS,
+        if (bdrv_open(bs_old_backing, backing_name, BDRV_O_FLAGS,
             old_backing_drv))
         {
             error("Could not open old backing file '%s'", backing_name);
@@ -1114,7 +1114,7 @@ static int img_rebase(int argc, char **argv)
         }
 
         bs_new_backing = bdrv_new("new_backing");
-        if (bdrv_open(bs_new_backing, out_baseimg, BRDV_O_FLAGS | BDRV_O_RDWR,
+        if (bdrv_open(bs_new_backing, out_baseimg, BDRV_O_FLAGS | BDRV_O_RDWR,
             new_backing_drv))
         {
             error("Could not open new backing file '%s'", out_baseimg);
commit f163d0736ce0ccf50128254409a6cfc0258fa943
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Tue Apr 13 10:29:34 2010 +0100

    qemu-img: Eliminate bdrv_new_open() code duplication
    
    Several commands have code to create a BlockDriverState and open a file.
    The bdrv_new_open() function can be used to perform these steps.  This
    patch converts the qemu-img commands to actually use bdrv_new_open().
    
    Replaced the bdrv_new_open() 'readonly' argument with bdrv_open()-style
    flags to support generic flags like BDRV_O_NO_BACKING.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-img.c b/qemu-img.c
index 18e43a0..b30effa 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -190,12 +190,11 @@ static int read_password(char *buf, int buf_size)
 
 static BlockDriverState *bdrv_new_open(const char *filename,
                                        const char *fmt,
-                                       int readonly)
+                                       int flags)
 {
     BlockDriverState *bs;
     BlockDriver *drv;
     char password[256];
-    int flags = BRDV_O_FLAGS;
 
     bs = bdrv_new("");
     if (!bs)
@@ -207,9 +206,6 @@ static BlockDriverState *bdrv_new_open(const char *filename,
     } else {
         drv = NULL;
     }
-    if (!readonly) {
-        flags |= BDRV_O_RDWR;
-    }
     if (bdrv_open(bs, filename, flags, drv) < 0) {
         error("Could not open '%s'", filename);
     }
@@ -349,7 +345,7 @@ static int img_create(int argc, char **argv)
                 }
             }
 
-            bs = bdrv_new_open(backing_file->value.s, fmt, 1);
+            bs = bdrv_new_open(backing_file->value.s, fmt, BRDV_O_FLAGS);
             bdrv_get_geometry(bs, &size);
             size *= 512;
             bdrv_delete(bs);
@@ -384,7 +380,6 @@ static int img_check(int argc, char **argv)
 {
     int c, ret;
     const char *filename, *fmt;
-    BlockDriver *drv;
     BlockDriverState *bs;
 
     fmt = NULL;
@@ -405,19 +400,7 @@ static int img_check(int argc, char **argv)
         help();
     filename = argv[optind++];
 
-    bs = bdrv_new("");
-    if (!bs)
-        error("Not enough memory");
-    if (fmt) {
-        drv = bdrv_find_format(fmt);
-        if (!drv)
-            error("Unknown file format '%s'", fmt);
-    } else {
-        drv = NULL;
-    }
-    if (bdrv_open(bs, filename, BRDV_O_FLAGS, drv) < 0) {
-        error("Could not open '%s'", filename);
-    }
+    bs = bdrv_new_open(filename, fmt, BRDV_O_FLAGS);
     ret = bdrv_check(bs);
     switch(ret) {
     case 0:
@@ -443,7 +426,6 @@ static int img_commit(int argc, char **argv)
 {
     int c, ret;
     const char *filename, *fmt;
-    BlockDriver *drv;
     BlockDriverState *bs;
 
     fmt = NULL;
@@ -464,19 +446,7 @@ static int img_commit(int argc, char **argv)
         help();
     filename = argv[optind++];
 
-    bs = bdrv_new("");
-    if (!bs)
-        error("Not enough memory");
-    if (fmt) {
-        drv = bdrv_find_format(fmt);
-        if (!drv)
-            error("Unknown file format '%s'", fmt);
-    } else {
-        drv = NULL;
-    }
-    if (bdrv_open(bs, filename, BRDV_O_FLAGS | BDRV_O_RDWR, drv) < 0) {
-        error("Could not open '%s'", filename);
-    }
+    bs = bdrv_new_open(filename, fmt, BRDV_O_FLAGS | BDRV_O_RDWR);
     ret = bdrv_commit(bs);
     switch(ret) {
     case 0:
@@ -633,7 +603,7 @@ static int img_convert(int argc, char **argv)
 
     total_sectors = 0;
     for (bs_i = 0; bs_i < bs_n; bs_i++) {
-        bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, 1);
+        bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BRDV_O_FLAGS);
         if (!bs[bs_i])
             error("Could not open '%s'", argv[optind + bs_i]);
         bdrv_get_geometry(bs[bs_i], &bs_sectors);
@@ -691,7 +661,7 @@ static int img_convert(int argc, char **argv)
         }
     }
 
-    out_bs = bdrv_new_open(out_filename, out_fmt, 0);
+    out_bs = bdrv_new_open(out_filename, out_fmt, BRDV_O_FLAGS | BDRV_O_RDWR);
 
     bs_i = 0;
     bs_offset = 0;
@@ -889,7 +859,6 @@ static int img_info(int argc, char **argv)
 {
     int c;
     const char *filename, *fmt;
-    BlockDriver *drv;
     BlockDriverState *bs;
     char fmt_name[128], size_buf[128], dsize_buf[128];
     uint64_t total_sectors;
@@ -916,19 +885,7 @@ static int img_info(int argc, char **argv)
         help();
     filename = argv[optind++];
 
-    bs = bdrv_new("");
-    if (!bs)
-        error("Not enough memory");
-    if (fmt) {
-        drv = bdrv_find_format(fmt);
-        if (!drv)
-            error("Unknown file format '%s'", fmt);
-    } else {
-        drv = NULL;
-    }
-    if (bdrv_open(bs, filename, BRDV_O_FLAGS | BDRV_O_NO_BACKING, drv) < 0) {
-        error("Could not open '%s'", filename);
-    }
+    bs = bdrv_new_open(filename, fmt, BRDV_O_FLAGS | BDRV_O_NO_BACKING);
     bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
     bdrv_get_geometry(bs, &total_sectors);
     get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
@@ -1028,13 +985,7 @@ static int img_snapshot(int argc, char **argv)
     filename = argv[optind++];
 
     /* Open the image */
-    bs = bdrv_new("");
-    if (!bs)
-        error("Not enough memory");
-
-    if (bdrv_open(bs, filename, bdrv_oflags, NULL) < 0) {
-        error("Could not open '%s'", filename);
-    }
+    bs = bdrv_new_open(filename, NULL, bdrv_oflags);
 
     /* Perform the requested action */
     switch(action) {
@@ -1080,7 +1031,7 @@ static int img_snapshot(int argc, char **argv)
 static int img_rebase(int argc, char **argv)
 {
     BlockDriverState *bs, *bs_old_backing, *bs_new_backing;
-    BlockDriver *drv, *old_backing_drv, *new_backing_drv;
+    BlockDriver *old_backing_drv, *new_backing_drv;
     char *filename;
     const char *fmt, *out_basefmt, *out_baseimg;
     int c, flags, ret;
@@ -1124,22 +1075,8 @@ static int img_rebase(int argc, char **argv)
      * Ignore the old backing file for unsafe rebase in case we want to correct
      * the reference to a renamed or moved backing file.
      */
-    bs = bdrv_new("");
-    if (!bs)
-        error("Not enough memory");
-
-    drv = NULL;
-    if (fmt) {
-        drv = bdrv_find_format(fmt);
-        if (drv == NULL) {
-            error("Invalid format name: '%s'", fmt);
-        }
-    }
-
     flags = BRDV_O_FLAGS | BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
-    if (bdrv_open(bs, filename, flags, drv) < 0) {
-        error("Could not open '%s'", filename);
-    }
+    bs = bdrv_new_open(filename, fmt, flags);
 
     /* Find the right drivers for the backing files */
     old_backing_drv = NULL;
commit 8a22f02a88b5c37bdbd48fc18ff6e572a8ffdfe2
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Tue Apr 13 10:29:33 2010 +0100

    block: Convert first_drv to QLIST
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 5d087de..12cf434 100644
--- a/block.c
+++ b/block.c
@@ -58,7 +58,8 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
 static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
     QTAILQ_HEAD_INITIALIZER(bdrv_states);
 
-static BlockDriver *first_drv;
+static QLIST_HEAD(, BlockDriver) bdrv_drivers =
+    QLIST_HEAD_INITIALIZER(bdrv_drivers);
 
 /* If non-zero, use only whitelisted block drivers */
 static int use_bdrv_whitelist;
@@ -142,8 +143,7 @@ void bdrv_register(BlockDriver *bdrv)
     if (!bdrv->bdrv_aio_flush)
         bdrv->bdrv_aio_flush = bdrv_aio_flush_em;
 
-    bdrv->next = first_drv;
-    first_drv = bdrv;
+    QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list);
 }
 
 /* create a new block device (by default it is empty) */
@@ -162,9 +162,10 @@ BlockDriverState *bdrv_new(const char *device_name)
 BlockDriver *bdrv_find_format(const char *format_name)
 {
     BlockDriver *drv1;
-    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
-        if (!strcmp(drv1->format_name, format_name))
+    QLIST_FOREACH(drv1, &bdrv_drivers, list) {
+        if (!strcmp(drv1->format_name, format_name)) {
             return drv1;
+        }
     }
     return NULL;
 }
@@ -265,10 +266,11 @@ static BlockDriver *find_protocol(const char *filename)
         len = sizeof(protocol) - 1;
     memcpy(protocol, filename, len);
     protocol[len] = '\0';
-    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
+    QLIST_FOREACH(drv1, &bdrv_drivers, list) {
         if (drv1->protocol_name &&
-            !strcmp(drv1->protocol_name, protocol))
+            !strcmp(drv1->protocol_name, protocol)) {
             return drv1;
+        }
     }
     return NULL;
 }
@@ -282,7 +284,7 @@ static BlockDriver *find_hdev_driver(const char *filename)
     int score_max = 0, score;
     BlockDriver *drv = NULL, *d;
 
-    for (d = first_drv; d; d = d->next) {
+    QLIST_FOREACH(d, &bdrv_drivers, list) {
         if (d->bdrv_probe_device) {
             score = d->bdrv_probe_device(filename);
             if (score > score_max) {
@@ -317,7 +319,7 @@ static BlockDriver *find_image_format(const char *filename)
     }
 
     score_max = 0;
-    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
+    QLIST_FOREACH(drv1, &bdrv_drivers, list) {
         if (drv1->bdrv_probe) {
             score = drv1->bdrv_probe(buf, ret, filename);
             if (score > score_max) {
@@ -1157,7 +1159,7 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
 {
     BlockDriver *drv;
 
-    for (drv = first_drv; drv != NULL; drv = drv->next) {
+    QLIST_FOREACH(drv, &bdrv_drivers, list) {
         it(opaque, drv->format_name);
     }
 }
diff --git a/block_int.h b/block_int.h
index 466a38c..d4067ff 100644
--- a/block_int.h
+++ b/block_int.h
@@ -126,7 +126,7 @@ struct BlockDriver {
     /* Set if newly created images are not guaranteed to contain only zeros */
     int no_zero_init;
 
-    struct BlockDriver *next;
+    QLIST_ENTRY(BlockDriver) list;
 };
 
 struct BlockDriverState {
commit 85de0ba5e9dc8d318cd2c34b7a8d368946160a24
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Apr 13 12:41:35 2010 +0200

    block.h: bdrv_create2 doesn't exist any more
    
    The bdrv_create2 implementation has disappeared long ago. Remove its
    prototype from the header file, too.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.h b/block.h
index 4a57dd5..05ad572 100644
--- a/block.h
+++ b/block.h
@@ -57,10 +57,6 @@ BlockDriver *bdrv_find_format(const char *format_name);
 BlockDriver *bdrv_find_whitelisted_format(const char *format_name);
 int bdrv_create(BlockDriver *drv, const char* filename,
     QEMUOptionParameter *options);
-int bdrv_create2(BlockDriver *drv,
-                 const char *filename, int64_t size_in_sectors,
-                 const char *backing_file, const char *backing_format,
-                 int flags);
 BlockDriverState *bdrv_new(const char *device_name);
 void bdrv_delete(BlockDriverState *bs);
 int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
commit 3cc128bb1e2f41b64ca82d8252fb678a60611de0
Author: Bruce Rogers <brogers at novell.com>
Date:   Mon Apr 12 06:56:00 2010 -0600

    Remove un-needed code
    
    The bdrv_set_geometry_hint call below is not needed - it's just setting
    what was just read.
    
    Signed-off-by: Bruce Rogers <brogers at novell.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 01d77b8..b05d15e 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -494,7 +494,6 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
     s->rq = NULL;
     s->sector_mask = (s->conf->logical_block_size / 512) - 1;
     bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
-    bdrv_set_geometry_hint(s->bs, cylinders, heads, secs);
 
     s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
 
commit 1b7bdbc13ccbec154c0ef768f70c9eb604befb8c
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Sat Apr 10 07:02:42 2010 +0100

    block: Convert bdrv_first to QTAILQ
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 61da183..5d087de 100644
--- a/block.c
+++ b/block.c
@@ -55,7 +55,8 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
 static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
                          const uint8_t *buf, int nb_sectors);
 
-static BlockDriverState *bdrv_first;
+static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
+    QTAILQ_HEAD_INITIALIZER(bdrv_states);
 
 static BlockDriver *first_drv;
 
@@ -148,16 +149,12 @@ void bdrv_register(BlockDriver *bdrv)
 /* create a new block device (by default it is empty) */
 BlockDriverState *bdrv_new(const char *device_name)
 {
-    BlockDriverState **pbs, *bs;
+    BlockDriverState *bs;
 
     bs = qemu_mallocz(sizeof(BlockDriverState));
     pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
     if (device_name[0] != '\0') {
-        /* insert at the end */
-        pbs = &bdrv_first;
-        while (*pbs != NULL)
-            pbs = &(*pbs)->next;
-        *pbs = bs;
+        QTAILQ_INSERT_TAIL(&bdrv_states, bs, list);
     }
     return bs;
 }
@@ -545,13 +542,10 @@ void bdrv_close(BlockDriverState *bs)
 
 void bdrv_delete(BlockDriverState *bs)
 {
-    BlockDriverState **pbs;
-
-    pbs = &bdrv_first;
-    while (*pbs != bs && *pbs != NULL)
-        pbs = &(*pbs)->next;
-    if (*pbs == bs)
-        *pbs = bs->next;
+    /* remove from list, if necessary */
+    if (bs->device_name[0] != '\0') {
+        QTAILQ_REMOVE(&bdrv_states, bs, list);
+    }
 
     bdrv_close(bs);
     qemu_free(bs);
@@ -1172,9 +1166,10 @@ BlockDriverState *bdrv_find(const char *name)
 {
     BlockDriverState *bs;
 
-    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
-        if (!strcmp(name, bs->device_name))
+    QTAILQ_FOREACH(bs, &bdrv_states, list) {
+        if (!strcmp(name, bs->device_name)) {
             return bs;
+        }
     }
     return NULL;
 }
@@ -1183,7 +1178,7 @@ void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque)
 {
     BlockDriverState *bs;
 
-    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
+    QTAILQ_FOREACH(bs, &bdrv_states, list) {
         it(opaque, bs);
     }
 }
@@ -1203,10 +1198,12 @@ void bdrv_flush_all(void)
 {
     BlockDriverState *bs;
 
-    for (bs = bdrv_first; bs != NULL; bs = bs->next)
-        if (bs->drv && !bdrv_is_read_only(bs) && 
-            (!bdrv_is_removable(bs) || bdrv_is_inserted(bs)))
+    QTAILQ_FOREACH(bs, &bdrv_states, list) {
+        if (bs->drv && !bdrv_is_read_only(bs) &&
+            (!bdrv_is_removable(bs) || bdrv_is_inserted(bs))) {
             bdrv_flush(bs);
+        }
+    }
 }
 
 /*
@@ -1340,7 +1337,7 @@ void bdrv_info(Monitor *mon, QObject **ret_data)
 
     bs_list = qlist_new();
 
-    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
+    QTAILQ_FOREACH(bs, &bdrv_states, list) {
         QObject *bs_obj;
         const char *type = "unknown";
 
@@ -1445,7 +1442,7 @@ void bdrv_info_stats(Monitor *mon, QObject **ret_data)
 
     devices = qlist_new();
 
-    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
+    QTAILQ_FOREACH(bs, &bdrv_states, list) {
         obj = qobject_from_jsonf("{ 'device': %s, 'stats': {"
                                  "'rd_bytes': %" PRId64 ","
                                  "'wr_bytes': %" PRId64 ","
diff --git a/block_int.h b/block_int.h
index d5a808d..466a38c 100644
--- a/block_int.h
+++ b/block_int.h
@@ -26,6 +26,7 @@
 
 #include "block.h"
 #include "qemu-option.h"
+#include "qemu-queue.h"
 
 #define BLOCK_FLAG_ENCRYPT	1
 #define BLOCK_FLAG_COMPRESS	2
@@ -180,7 +181,7 @@ struct BlockDriverState {
     char device_name[32];
     unsigned long *dirty_bitmap;
     int64_t dirty_count;
-    BlockDriverState *next;
+    QTAILQ_ENTRY(BlockDriverState) list;
     void *private;
 };
 
commit b66460e4e938910b0e5495e6d3d7b2d5b3cf9c99
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Fri Apr 9 15:22:13 2010 +0100

    block: Do not export bdrv_first
    
    The bdrv_first linked list of BlockDriverStates is currently extern so
    that block migration can iterate the list.  However, since there is
    already a bdrv_iterate() function there is no need to expose bdrv_first.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block-migration.c b/block-migration.c
index 92349a2..7d04d6d 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -230,12 +230,42 @@ static void set_dirty_tracking(int enable)
     }
 }
 
-static void init_blk_migration(Monitor *mon, QEMUFile *f)
+static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
 {
+    Monitor *mon = opaque;
     BlkMigDevState *bmds;
-    BlockDriverState *bs;
     int64_t sectors;
 
+    if (bs->type == BDRV_TYPE_HD) {
+        sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
+        if (sectors == 0) {
+            return;
+        }
+
+        bmds = qemu_mallocz(sizeof(BlkMigDevState));
+        bmds->bs = bs;
+        bmds->bulk_completed = 0;
+        bmds->total_sectors = sectors;
+        bmds->completed_sectors = 0;
+        bmds->shared_base = block_mig_state.shared_base;
+
+        block_mig_state.total_sector_sum += sectors;
+
+        if (bmds->shared_base) {
+            monitor_printf(mon, "Start migration for %s with shared base "
+                                "image\n",
+                           bs->device_name);
+        } else {
+            monitor_printf(mon, "Start full migration for %s\n",
+                           bs->device_name);
+        }
+
+        QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
+    }
+}
+
+static void init_blk_migration(Monitor *mon, QEMUFile *f)
+{
     block_mig_state.submitted = 0;
     block_mig_state.read_done = 0;
     block_mig_state.transferred = 0;
@@ -245,34 +275,7 @@ static void init_blk_migration(Monitor *mon, QEMUFile *f)
     block_mig_state.total_time = 0;
     block_mig_state.reads = 0;
 
-    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
-        if (bs->type == BDRV_TYPE_HD) {
-            sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
-            if (sectors == 0) {
-                continue;
-            }
-
-            bmds = qemu_mallocz(sizeof(BlkMigDevState));
-            bmds->bs = bs;
-            bmds->bulk_completed = 0;
-            bmds->total_sectors = sectors;
-            bmds->completed_sectors = 0;
-            bmds->shared_base = block_mig_state.shared_base;
-
-            block_mig_state.total_sector_sum += sectors;
-
-            if (bmds->shared_base) {
-                monitor_printf(mon, "Start migration for %s with shared base "
-                                    "image\n",
-                               bs->device_name);
-            } else {
-                monitor_printf(mon, "Start full migration for %s\n",
-                               bs->device_name);
-            }
-
-            QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
-        }
-    }
+    bdrv_iterate(init_blk_migration_it, mon);
 }
 
 static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f)
diff --git a/block.c b/block.c
index ed4c819..61da183 100644
--- a/block.c
+++ b/block.c
@@ -55,7 +55,7 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
 static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
                          const uint8_t *buf, int nb_sectors);
 
-BlockDriverState *bdrv_first;
+static BlockDriverState *bdrv_first;
 
 static BlockDriver *first_drv;
 
diff --git a/block_int.h b/block_int.h
index e7e1e7e..d5a808d 100644
--- a/block_int.h
+++ b/block_int.h
@@ -200,8 +200,6 @@ void qemu_aio_release(void *p);
 
 void *qemu_blockalign(BlockDriverState *bs, size_t size);
 
-extern BlockDriverState *bdrv_first;
-
 #ifdef _WIN32
 int is_windows_drive(const char *filename);
 #endif
commit 763b6084baaf7d4e8b93f8b74f23a37b2fdb4eb4
Author: Christoph Hellwig <hch at lst.de>
Date:   Tue Apr 6 19:12:04 2010 +0200

    cleanup block driver option handling in vl.c
    
    Assign directly to the bdrv_flags variable instead of using
    magic numbers before translating to the BDRV_O_* options.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/vl.c b/vl.c
index 0c76d33..a5a0f41 100644
--- a/vl.c
+++ b/vl.c
@@ -783,10 +783,8 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
     QEMUMachine *machine = opaque;
     int max_devs;
     int index;
-    int cache;
-    int aio = 0;
     int ro = 0;
-    int bdrv_flags;
+    int bdrv_flags = 0;
     int on_read_error, on_write_error;
     const char *devaddr;
     DriveInfo *dinfo;
@@ -795,7 +793,6 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
     *fatal_error = 1;
 
     translation = BIOS_ATA_TRANSLATION_AUTO;
-    cache = 1;
 
     if (machine && machine->use_scsi) {
         type = IF_SCSI;
@@ -909,13 +906,13 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
     }
 
     if ((buf = qemu_opt_get(opts, "cache")) != NULL) {
-        if (!strcmp(buf, "off") || !strcmp(buf, "none"))
-            cache = 0;
-        else if (!strcmp(buf, "writethrough"))
-            cache = 1;
-        else if (!strcmp(buf, "writeback"))
-            cache = 2;
-        else {
+        if (!strcmp(buf, "off") || !strcmp(buf, "none")) {
+            bdrv_flags |= BDRV_O_NOCACHE;
+        } else if (!strcmp(buf, "writeback")) {
+            bdrv_flags |= BDRV_O_CACHE_WB;
+        } else if (!strcmp(buf, "writethrough")) {
+            /* this is the default */
+        } else {
            fprintf(stderr, "qemu: invalid cache option\n");
            return NULL;
         }
@@ -923,11 +920,11 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
 
 #ifdef CONFIG_LINUX_AIO
     if ((buf = qemu_opt_get(opts, "aio")) != NULL) {
-        if (!strcmp(buf, "threads"))
-            aio = 0;
-        else if (!strcmp(buf, "native"))
-            aio = 1;
-        else {
+        if (!strcmp(buf, "native")) {
+            bdrv_flags |= BDRV_O_NATIVE_AIO;
+        } else if (!strcmp(buf, "threads")) {
+            /* this is the default */
+        } else {
            fprintf(stderr, "qemu: invalid aio option\n");
            return NULL;
         }
@@ -1101,20 +1098,10 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
         *fatal_error = 0;
         return NULL;
     }
-    bdrv_flags = 0;
     if (snapshot) {
-        bdrv_flags |= BDRV_O_SNAPSHOT;
-        cache = 2; /* always use write-back with snapshot */
-    }
-    if (cache == 0) /* no caching */
-        bdrv_flags |= BDRV_O_NOCACHE;
-    else if (cache == 2) /* write-back */
-        bdrv_flags |= BDRV_O_CACHE_WB;
-
-    if (aio == 1) {
-        bdrv_flags |= BDRV_O_NATIVE_AIO;
-    } else {
-        bdrv_flags &= ~BDRV_O_NATIVE_AIO;
+        /* always use write-back with snapshot */
+        bdrv_flags &= ~BDRV_O_CACHE_MASK;
+        bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB);
     }
 
     if (media == MEDIA_CDROM) {
commit c46e116723803012853690f7938d7f66b92489db
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 23 17:41:24 2010 +0100

    qcow2: Return 0/-errno in l2_allocate
    
    Returning NULL on error doesn't allow distinguishing between different errors.
    Change the interface to return an integer for -errno.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index d5c52a9..639e05e 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -220,13 +220,14 @@ static int write_l1_entry(BDRVQcowState *s, int l1_index)
  *
  */
 
-static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index)
+static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
 {
     BDRVQcowState *s = bs->opaque;
     int min_index;
     uint64_t old_l2_offset;
     uint64_t *l2_table;
     int64_t l2_offset;
+    int ret;
 
     old_l2_offset = s->l1_table[l1_index];
 
@@ -234,14 +235,15 @@ static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index)
 
     l2_offset = qcow2_alloc_clusters(bs, s->l2_size * sizeof(uint64_t));
     if (l2_offset < 0) {
-        return NULL;
+        return l2_offset;
     }
 
     /* update the L1 entry */
 
     s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
-    if (write_l1_entry(s, l1_index) < 0) {
-        return NULL;
+    ret = write_l1_entry(s, l1_index);
+    if (ret < 0) {
+        return ret;
     }
 
     /* allocate a new entry in the l2 cache */
@@ -255,24 +257,27 @@ static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index)
     } else {
         /* if there was an old l2 table, read it from the disk */
         BLKDBG_EVENT(s->hd, BLKDBG_L2_ALLOC_COW_READ);
-        if (bdrv_pread(s->hd, old_l2_offset,
-                       l2_table, s->l2_size * sizeof(uint64_t)) !=
-            s->l2_size * sizeof(uint64_t))
-            return NULL;
+        ret = bdrv_pread(s->hd, old_l2_offset, l2_table,
+            s->l2_size * sizeof(uint64_t));
+        if (ret < 0) {
+            return ret;
+        }
     }
     /* write the l2 table to the file */
     BLKDBG_EVENT(s->hd, BLKDBG_L2_ALLOC_WRITE);
-    if (bdrv_pwrite(s->hd, l2_offset,
-                    l2_table, s->l2_size * sizeof(uint64_t)) !=
-        s->l2_size * sizeof(uint64_t))
-        return NULL;
+    ret = bdrv_pwrite(s->hd, l2_offset, l2_table,
+        s->l2_size * sizeof(uint64_t));
+    if (ret < 0) {
+        return ret;
+    }
 
     /* update the l2 cache entry */
 
     s->l2_cache_offsets[min_index] = l2_offset;
     s->l2_cache_counts[min_index] = 1;
 
-    return l2_table;
+    *table = l2_table;
+    return 0;
 }
 
 static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size,
@@ -510,7 +515,8 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
 {
     BDRVQcowState *s = bs->opaque;
     unsigned int l1_index, l2_index;
-    uint64_t l2_offset, *l2_table;
+    uint64_t l2_offset;
+    uint64_t *l2_table = NULL;
     int ret;
 
     /* seek the the l2 offset in the l1 table */
@@ -536,9 +542,9 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
     } else {
         if (l2_offset)
             qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t));
-        l2_table = l2_allocate(bs, l1_index);
-        if (l2_table == NULL) {
-            return -EIO;
+        ret = l2_allocate(bs, l1_index, &l2_table);
+        if (ret < 0) {
+            return ret;
         }
         l2_offset = s->l1_table[l1_index] & ~QCOW_OFLAG_COPIED;
     }
commit f7defcb62792eff05fa8a7ffec6a927a88087b83
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 23 17:28:22 2010 +0100

    qcow2: Return 0/-errno in write_l1_entry
    
    Change write_l1_entry to return the real error code instead of -1.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index d2774d1..d5c52a9 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -193,7 +193,7 @@ static int write_l1_entry(BDRVQcowState *s, int l1_index)
 {
     uint64_t buf[L1_ENTRIES_PER_SECTOR];
     int l1_start_index;
-    int i;
+    int i, ret;
 
     l1_start_index = l1_index & ~(L1_ENTRIES_PER_SECTOR - 1);
     for (i = 0; i < L1_ENTRIES_PER_SECTOR; i++) {
@@ -201,10 +201,10 @@ static int write_l1_entry(BDRVQcowState *s, int l1_index)
     }
 
     BLKDBG_EVENT(s->hd, BLKDBG_L1_UPDATE);
-    if (bdrv_pwrite(s->hd, s->l1_table_offset + 8 * l1_start_index,
-        buf, sizeof(buf)) != sizeof(buf))
-    {
-        return -1;
+    ret = bdrv_pwrite(s->hd, s->l1_table_offset + 8 * l1_start_index,
+        buf, sizeof(buf));
+    if (ret < 0) {
+        return ret;
     }
 
     return 0;
commit c835d00fc8d6c23af7e9182981ef7a07f1c6d12c
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 23 12:53:47 2010 +0100

    qcow2: Fix error return code in qcow2_alloc_cluster_link_l2
    
    Fix qcow2_alloc_cluster_link_l2 to return the real error code like it does in
    all other error cases.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 2f37acd..d2774d1 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -687,8 +687,8 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
                     (i << s->cluster_bits)) | QCOW_OFLAG_COPIED);
      }
 
-    if (write_l2_entries(s, l2_table, l2_offset, l2_index, m->nb_clusters) < 0) {
-        ret = -1;
+    ret = write_l2_entries(s, l2_table, l2_offset, l2_index, m->nb_clusters);
+    if (ret < 0) {
         goto err;
     }
 
commit 79a31189d4e3d226c6c700d630476ec63bbc19a2
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 23 12:49:17 2010 +0100

    qcow2: Return 0/-errno in write_l2_entries
    
    Change write_l2_entries to return the real error code instead of -1.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 8cb4b38..2f37acd 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -627,12 +627,13 @@ static int write_l2_entries(BDRVQcowState *s, uint64_t *l2_table,
     int start_offset = (8 * l2_index) & ~511;
     int end_offset = (8 * (l2_index + num) + 511) & ~511;
     size_t len = end_offset - start_offset;
+    int ret;
 
     BLKDBG_EVENT(s->hd, BLKDBG_L2_UPDATE);
-    if (bdrv_pwrite(s->hd, l2_offset + start_offset, &l2_table[l2_start_index],
-        len) != len)
-    {
-        return -1;
+    ret = bdrv_pwrite(s->hd, l2_offset + start_offset,
+        &l2_table[l2_start_index], len);
+    if (ret < 0) {
+        return ret;
     }
 
     return 0;
commit 50779cc264aa1abd75aa5afa34740d4fd8481f1d
Author: Christoph Hellwig <hch at lst.de>
Date:   Tue Apr 6 19:13:44 2010 +0200

    block: split raw_getlength
    
    Split up the raw_getlength into separate generic, solaris and BSD
    versions to reduce the ifdef maze a bit.  The BSD variant still
    is a complete maze, but to clean it up properly we'd need some
    people using the BSD variants to figure out what code is used
    for what variant.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/raw-posix.c b/block/raw-posix.c
index 6521ca4..4cda9c1 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -627,29 +627,48 @@ static int64_t raw_getlength(BlockDriverState *bs)
     } else
         return st.st_size;
 }
-#else /* !__OpenBSD__ */
-static int64_t  raw_getlength(BlockDriverState *bs)
+#elif defined(__sun__)
+static int64_t raw_getlength(BlockDriverState *bs)
+{
+    BDRVRawState *s = bs->opaque;
+    struct dk_minfo minfo;
+    int ret;
+
+    ret = fd_open(bs);
+    if (ret < 0) {
+        return ret;
+    }
+
+    /*
+     * Use the DKIOCGMEDIAINFO ioctl to read the size.
+     */
+    ret = ioctl(s->fd, DKIOCGMEDIAINFO, &minfo);
+    if (ret != -1) {
+        return minfo.dki_lbsize * minfo.dki_capacity;
+    }
+
+    /*
+     * There are reports that lseek on some devices fails, but
+     * irc discussion said that contingency on contingency was overkill.
+     */
+    return lseek(s->fd, 0, SEEK_END);
+}
+#elif defined(CONFIG_BSD)
+static int64_t raw_getlength(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
     int fd = s->fd;
     int64_t size;
-#ifdef CONFIG_BSD
     struct stat sb;
 #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
     int reopened = 0;
 #endif
-#endif
-#ifdef __sun__
-    struct dk_minfo minfo;
-    int rv;
-#endif
     int ret;
 
     ret = fd_open(bs);
     if (ret < 0)
         return ret;
 
-#ifdef CONFIG_BSD
 #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
 again:
 #endif
@@ -684,24 +703,24 @@ again:
             }
         }
 #endif
-    } else
-#endif
-#ifdef __sun__
-    /*
-     * use the DKIOCGMEDIAINFO ioctl to read the size.
-     */
-    rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
-    if ( rv != -1 ) {
-        size = minfo.dki_lbsize * minfo.dki_capacity;
-    } else /* there are reports that lseek on some devices
-              fails, but irc discussion said that contingency
-              on contingency was overkill */
-#endif
-    {
+    } else {
         size = lseek(fd, 0, SEEK_END);
     }
     return size;
 }
+#else
+static int64_t raw_getlength(BlockDriverState *bs)
+{
+    BDRVRawState *s = bs->opaque;
+    int ret;
+
+    ret = fd_open(bs);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return lseek(s->fd, 0, SEEK_END);
+}
 #endif
 
 static int raw_create(const char *filename, QEMUOptionParameter *options)
commit 6db956039db8a6333265d458be561dc1bc2b4481
Author: Christoph Hellwig <hch at lst.de>
Date:   Mon Apr 5 16:53:57 2010 +0200

    block: get rid of the BDRV_O_FILE flag
    
    BDRV_O_FILE is only used to communicate between bdrv_file_open and bdrv_open.
    It affects two things:  first bdrv_open only searches for protocols using
    find_protocol instead of all image formats and host drivers.  We can easily
    move that to the caller and pass the found driver to bdrv_open.  Second
    it is used to not force a read-write open of a snapshot file.  But we never
    use bdrv_file_open to open snapshots and this behaviour doesn't make sense
    to start with.
    
    qemu-io abused the BDRV_O_FILE for it's growable option, switch it to
    using bdrv_file_open to make sure we only open files as growable were
    we can actually support that.
    
    This patch requires Kevin's "[PATCH] Replace calls of old bdrv_open" to
    be applied first.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index e74264d..ed4c819 100644
--- a/block.c
+++ b/block.c
@@ -335,10 +335,16 @@ static BlockDriver *find_image_format(const char *filename)
 int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
 {
     BlockDriverState *bs;
+    BlockDriver *drv;
     int ret;
 
+    drv = find_protocol(filename);
+    if (!drv) {
+        return -ENOENT;
+    }
+
     bs = bdrv_new("");
-    ret = bdrv_open(bs, filename, flags | BDRV_O_FILE, NULL);
+    ret = bdrv_open(bs, filename, flags, drv);
     if (ret < 0) {
         bdrv_delete(bs);
         return ret;
@@ -416,9 +422,8 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
     }
 
     pstrcpy(bs->filename, sizeof(bs->filename), filename);
-    if (flags & BDRV_O_FILE) {
-        drv = find_protocol(filename);
-    } else if (!drv) {
+
+    if (!drv) {
         drv = find_hdev_driver(filename);
         if (!drv) {
             drv = find_image_format(filename);
@@ -450,14 +455,12 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
      * Clear flags that are internal to the block layer before opening the
      * image.
      */
-    open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
+    open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
 
     /*
      * Snapshots should be writeable.
-     *
-     * XXX(hch): and what is the point of a snapshot during a read-only open?
      */
-    if (!(flags & BDRV_O_FILE) && bs->is_temporary) {
+    if (bs->is_temporary) {
         open_flags |= BDRV_O_RDWR;
     }
 
diff --git a/block.h b/block.h
index c5900c8..4a57dd5 100644
--- a/block.h
+++ b/block.h
@@ -29,10 +29,6 @@ typedef struct QEMUSnapshotInfo {
 
 #define BDRV_O_RDWR        0x0002
 #define BDRV_O_SNAPSHOT    0x0008 /* open the file read only and save writes in a snapshot */
-#define BDRV_O_FILE        0x0010 /* open as a raw file (do not try to
-                                     use a disk image format on top of
-                                     it (default for
-                                     bdrv_file_open()) */
 #define BDRV_O_NOCACHE     0x0020 /* do not use the host page cache */
 #define BDRV_O_CACHE_WB    0x0040 /* use write-back caching */
 #define BDRV_O_NATIVE_AIO  0x0080 /* use native AIO instead of the thread pool */
diff --git a/qemu-io.c b/qemu-io.c
index ffb5817..8517b90 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1276,23 +1276,23 @@ static int openfile(char *name, int flags, int growable)
 		return 1;
 	}
 
-	bs = bdrv_new("hda");
-	if (!bs)
-		return 1;
-
 	if (growable) {
-		flags |= BDRV_O_FILE;
-	}
-
-	if (bdrv_open(bs, name, flags, NULL) < 0) {
-		fprintf(stderr, "%s: can't open device %s\n", progname, name);
-		bs = NULL;
-		return 1;
+		if (bdrv_file_open(&bs, name, flags)) {
+			fprintf(stderr, "%s: can't open device %s\n", progname, name);
+			return 1;
+		}
+	} else {
+		bs = bdrv_new("hda");
+		if (!bs)
+			return 1;
+
+		if (bdrv_open(bs, name, flags, NULL) < 0) {
+			fprintf(stderr, "%s: can't open device %s\n", progname, name);
+			bs = NULL;
+			return 1;
+		}
 	}
 
-	if (growable) {
-		bs->growable = 1;
-	}
 	return 0;
 }
 
commit d6e9098e10e82feeddb824d7c3d0cf61aff96c29
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 31 14:40:27 2010 +0200

    Replace calls of old bdrv_open
    
    What is known today as bdrv_open2 becomes the new bdrv_open. All remaining
    callers of the old function are converted to the new one. In some places they
    even know the right format, so they should have used bdrv_open2 from the
    beginning.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 9351aa3..e74264d 100644
--- a/block.c
+++ b/block.c
@@ -338,7 +338,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
     int ret;
 
     bs = bdrv_new("");
-    ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL);
+    ret = bdrv_open(bs, filename, flags | BDRV_O_FILE, NULL);
     if (ret < 0) {
         bdrv_delete(bs);
         return ret;
@@ -348,13 +348,8 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
     return 0;
 }
 
-int bdrv_open(BlockDriverState *bs, const char *filename, int flags)
-{
-    return bdrv_open2(bs, filename, flags, NULL);
-}
-
-int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
-               BlockDriver *drv)
+int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
+              BlockDriver *drv)
 {
     int ret, open_flags;
     char tmp_filename[PATH_MAX];
@@ -379,7 +374,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
 
         /* if there is a backing file, use it */
         bs1 = bdrv_new("");
-        ret = bdrv_open2(bs1, filename, 0, drv);
+        ret = bdrv_open(bs1, filename, 0, drv);
         if (ret < 0) {
             bdrv_delete(bs1);
             return ret;
@@ -491,9 +486,8 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
 
         /* backing files always opened read-only */
         open_flags &= ~BDRV_O_RDWR;
-        
-        ret = bdrv_open2(bs->backing_hd, backing_filename, open_flags,
-                         back_drv);
+
+        ret = bdrv_open(bs->backing_hd, backing_filename, open_flags, back_drv);
         if (ret < 0) {
             bdrv_close(bs);
             return ret;
@@ -605,12 +599,12 @@ int bdrv_commit(BlockDriverState *bs)
         bdrv_delete(bs->backing_hd);
         bs->backing_hd = NULL;
         bs_rw = bdrv_new("");
-        rw_ret = bdrv_open2(bs_rw, filename, open_flags | BDRV_O_RDWR, NULL);
+        rw_ret = bdrv_open(bs_rw, filename, open_flags | BDRV_O_RDWR, NULL);
         if (rw_ret < 0) {
             bdrv_delete(bs_rw);
             /* try to re-open read-only */
             bs_ro = bdrv_new("");
-            ret = bdrv_open2(bs_ro, filename, open_flags & ~BDRV_O_RDWR, NULL);
+            ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, NULL);
             if (ret < 0) {
                 bdrv_delete(bs_ro);
                 /* drive not functional anymore */
@@ -662,7 +656,7 @@ ro_cleanup:
         bdrv_delete(bs->backing_hd);
         bs->backing_hd = NULL;
         bs_ro = bdrv_new("");
-        ret = bdrv_open2(bs_ro, filename, open_flags & ~BDRV_O_RDWR, NULL);
+        ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, NULL);
         if (ret < 0) {
             bdrv_delete(bs_ro);
             /* drive not functional anymore */
diff --git a/block.h b/block.h
index 14443f1..c5900c8 100644
--- a/block.h
+++ b/block.h
@@ -68,9 +68,8 @@ int bdrv_create2(BlockDriver *drv,
 BlockDriverState *bdrv_new(const char *device_name);
 void bdrv_delete(BlockDriverState *bs);
 int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
-int bdrv_open(BlockDriverState *bs, const char *filename, int flags);
-int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
-               BlockDriver *drv);
+int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
+              BlockDriver *drv);
 void bdrv_close(BlockDriverState *bs);
 int bdrv_check(BlockDriverState *bs);
 int bdrv_read(BlockDriverState *bs, int64_t sector_num,
diff --git a/block/qcow2.c b/block/qcow2.c
index 67affa6..30ded6a 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -52,7 +52,7 @@ typedef struct {
 #define  QCOW_EXT_MAGIC_END 0
 #define  QCOW_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA
 
-
+static BlockDriver bdrv_qcow2;
 
 static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
 {
@@ -1033,7 +1033,7 @@ exit:
     if (ret == 0 && prealloc) {
         BlockDriverState *bs;
         bs = bdrv_new("");
-        bdrv_open(bs, filename, BDRV_O_CACHE_WB | BDRV_O_RDWR);
+        bdrv_open(bs, filename, BDRV_O_CACHE_WB | BDRV_O_RDWR, &bdrv_qcow2);
         preallocate(bs);
         bdrv_close(bs);
     }
diff --git a/block/vmdk.c b/block/vmdk.c
index 007fca4..6fdea1d 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -390,7 +390,7 @@ static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
             return -1;
         }
         parent_open = 1;
-        if (bdrv_open(bs->backing_hd, parent_img_name, 0) < 0)
+        if (bdrv_open(bs->backing_hd, parent_img_name, 0, NULL) < 0)
             goto failure;
         parent_open = 0;
     }
diff --git a/block/vvfat.c b/block/vvfat.c
index 36f6ab4..0701df4 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -2795,8 +2795,11 @@ static int enable_write_target(BDRVVVFATState *s)
     if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0)
 	return -1;
     s->qcow = bdrv_new("");
-    if (s->qcow == NULL || bdrv_open(s->qcow, s->qcow_filename, BDRV_O_RDWR) < 0)
+    if (s->qcow == NULL ||
+        bdrv_open(s->qcow, s->qcow_filename, BDRV_O_RDWR, bdrv_qcow) < 0)
+    {
 	return -1;
+    }
 
 #ifndef _WIN32
     unlink(s->qcow_filename);
diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index beadf90..95017a1 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -629,7 +629,7 @@ static int blk_init(struct XenDevice *xendev)
         xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
 	blkdev->bs = bdrv_new(blkdev->dev);
 	if (blkdev->bs) {
-	    if (bdrv_open2(blkdev->bs, blkdev->filename, qflags,
+	    if (bdrv_open(blkdev->bs, blkdev->filename, qflags,
                            bdrv_find_whitelisted_format(blkdev->fileproto))
                 != 0) {
 		bdrv_delete(blkdev->bs);
diff --git a/monitor.c b/monitor.c
index ba60f97..c25d551 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1099,7 +1099,7 @@ static int do_change_block(Monitor *mon, const char *device,
     if (eject_device(mon, bs, 0) < 0) {
         return -1;
     }
-    if (bdrv_open2(bs, filename, BDRV_O_RDWR, drv) < 0) {
+    if (bdrv_open(bs, filename, BDRV_O_RDWR, drv) < 0) {
         qerror_report(QERR_OPEN_FILE_FAILED, filename);
         return -1;
     }
diff --git a/qemu-img.c b/qemu-img.c
index 9b28664..18e43a0 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -210,7 +210,7 @@ static BlockDriverState *bdrv_new_open(const char *filename,
     if (!readonly) {
         flags |= BDRV_O_RDWR;
     }
-    if (bdrv_open2(bs, filename, flags, drv) < 0) {
+    if (bdrv_open(bs, filename, flags, drv) < 0) {
         error("Could not open '%s'", filename);
     }
     if (bdrv_is_encrypted(bs)) {
@@ -415,7 +415,7 @@ static int img_check(int argc, char **argv)
     } else {
         drv = NULL;
     }
-    if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
+    if (bdrv_open(bs, filename, BRDV_O_FLAGS, drv) < 0) {
         error("Could not open '%s'", filename);
     }
     ret = bdrv_check(bs);
@@ -474,7 +474,7 @@ static int img_commit(int argc, char **argv)
     } else {
         drv = NULL;
     }
-    if (bdrv_open2(bs, filename, BRDV_O_FLAGS | BDRV_O_RDWR, drv) < 0) {
+    if (bdrv_open(bs, filename, BRDV_O_FLAGS | BDRV_O_RDWR, drv) < 0) {
         error("Could not open '%s'", filename);
     }
     ret = bdrv_commit(bs);
@@ -926,7 +926,7 @@ static int img_info(int argc, char **argv)
     } else {
         drv = NULL;
     }
-    if (bdrv_open2(bs, filename, BRDV_O_FLAGS | BDRV_O_NO_BACKING, drv) < 0) {
+    if (bdrv_open(bs, filename, BRDV_O_FLAGS | BDRV_O_NO_BACKING, drv) < 0) {
         error("Could not open '%s'", filename);
     }
     bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
@@ -1032,7 +1032,7 @@ static int img_snapshot(int argc, char **argv)
     if (!bs)
         error("Not enough memory");
 
-    if (bdrv_open2(bs, filename, bdrv_oflags, NULL) < 0) {
+    if (bdrv_open(bs, filename, bdrv_oflags, NULL) < 0) {
         error("Could not open '%s'", filename);
     }
 
@@ -1137,7 +1137,7 @@ static int img_rebase(int argc, char **argv)
     }
 
     flags = BRDV_O_FLAGS | BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
-    if (bdrv_open2(bs, filename, flags, drv) < 0) {
+    if (bdrv_open(bs, filename, flags, drv) < 0) {
         error("Could not open '%s'", filename);
     }
 
@@ -1169,7 +1169,7 @@ static int img_rebase(int argc, char **argv)
 
         bs_old_backing = bdrv_new("old_backing");
         bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
-        if (bdrv_open2(bs_old_backing, backing_name, BRDV_O_FLAGS,
+        if (bdrv_open(bs_old_backing, backing_name, BRDV_O_FLAGS,
             old_backing_drv))
         {
             error("Could not open old backing file '%s'", backing_name);
@@ -1177,7 +1177,7 @@ static int img_rebase(int argc, char **argv)
         }
 
         bs_new_backing = bdrv_new("new_backing");
-        if (bdrv_open2(bs_new_backing, out_baseimg, BRDV_O_FLAGS | BDRV_O_RDWR,
+        if (bdrv_open(bs_new_backing, out_baseimg, BRDV_O_FLAGS | BDRV_O_RDWR,
             new_backing_drv))
         {
             error("Could not open new backing file '%s'", out_baseimg);
diff --git a/qemu-io.c b/qemu-io.c
index 6b83714..ffb5817 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1284,7 +1284,7 @@ static int openfile(char *name, int flags, int growable)
 		flags |= BDRV_O_FILE;
 	}
 
-	if (bdrv_open(bs, name, flags) < 0) {
+	if (bdrv_open(bs, name, flags, NULL) < 0) {
 		fprintf(stderr, "%s: can't open device %s\n", progname, name);
 		bs = NULL;
 		return 1;
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 6d854d3..25aa913 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -333,7 +333,7 @@ int main(int argc, char **argv)
     if (bs == NULL)
         return 1;
 
-    if (bdrv_open(bs, argv[optind], flags) < 0)
+    if (bdrv_open(bs, argv[optind], flags, NULL) < 0)
         return 1;
 
     fd_size = bs->total_sectors * 512;
diff --git a/vl.c b/vl.c
index fe2dd6f..0c76d33 100644
--- a/vl.c
+++ b/vl.c
@@ -1129,7 +1129,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
 
     bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
 
-    if (bdrv_open2(dinfo->bdrv, file, bdrv_flags, drv) < 0) {
+    if (bdrv_open(dinfo->bdrv, file, bdrv_flags, drv) < 0) {
         fprintf(stderr, "qemu: could not open disk image %s: %s\n",
                         file, strerror(errno));
         return NULL;
commit 4768fa902c3860f2fe34403e6e1c83bfca6da034
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 26 17:37:20 2010 +0100

    qcow2: Fix creation of large images
    
    qcow_create2 assumes that the new image will only need one cluster for its
    refcount table initially. Obviously that's not true any more when the image is
    big enough (exact value depends on the cluster size).
    
    This patch calculates the refcount table size dynamically.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 80c99af..67affa6 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -850,10 +850,11 @@ static int qcow_create2(const char *filename, int64_t total_size,
 {
 
     int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
-    int ref_clusters, backing_format_len = 0;
+    int ref_clusters, reftable_clusters, backing_format_len = 0;
     int rounded_ext_bf_len = 0;
     QCowHeader header;
     uint64_t tmp, offset;
+    uint64_t old_ref_clusters;
     QCowCreateState s1, *s = &s1;
     QCowExtension ext_bf = {0, 0};
     int ret;
@@ -912,17 +913,37 @@ static int qcow_create2(const char *filename, int64_t total_size,
     header.l1_size = cpu_to_be32(l1_size);
     offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size);
 
-    s->refcount_table = qemu_mallocz(s->cluster_size);
+    /* count how many refcount blocks needed */
+
+#define NUM_CLUSTERS(bytes) \
+    (((bytes) + (s->cluster_size) - 1) / (s->cluster_size))
+
+    ref_clusters = NUM_CLUSTERS(NUM_CLUSTERS(offset) * sizeof(uint16_t));
+
+    do {
+        uint64_t image_clusters;
+        old_ref_clusters = ref_clusters;
+
+        /* Number of clusters used for the refcount table */
+        reftable_clusters = NUM_CLUSTERS(ref_clusters * sizeof(uint64_t));
+
+        /* Number of clusters that the whole image will have */
+        image_clusters = NUM_CLUSTERS(offset) + ref_clusters
+            + reftable_clusters;
+
+        /* Number of refcount blocks needed for the image */
+        ref_clusters = NUM_CLUSTERS(image_clusters * sizeof(uint16_t));
+
+    } while (ref_clusters != old_ref_clusters);
+
+    s->refcount_table = qemu_mallocz(reftable_clusters * s->cluster_size);
 
     s->refcount_table_offset = offset;
     header.refcount_table_offset = cpu_to_be64(offset);
-    header.refcount_table_clusters = cpu_to_be32(1);
-    offset += s->cluster_size;
+    header.refcount_table_clusters = cpu_to_be32(reftable_clusters);
+    offset += (reftable_clusters * s->cluster_size);
     s->refcount_block_offset = offset;
 
-    /* count how many refcount blocks needed */
-    tmp = offset >> s->cluster_bits;
-    ref_clusters = (tmp >> (s->cluster_bits - REFCOUNT_SHIFT)) + 1;
     for (i=0; i < ref_clusters; i++) {
         s->refcount_table[i] = cpu_to_be64(offset);
         offset += s->cluster_size;
@@ -934,7 +955,8 @@ static int qcow_create2(const char *filename, int64_t total_size,
     qcow2_create_refcount_update(s, 0, header_size);
     qcow2_create_refcount_update(s, s->l1_table_offset,
         l1_size * sizeof(uint64_t));
-    qcow2_create_refcount_update(s, s->refcount_table_offset, s->cluster_size);
+    qcow2_create_refcount_update(s, s->refcount_table_offset,
+        reftable_clusters * s->cluster_size);
     qcow2_create_refcount_update(s, s->refcount_block_offset,
         ref_clusters * s->cluster_size);
 
@@ -986,8 +1008,9 @@ static int qcow_create2(const char *filename, int64_t total_size,
         }
     }
     lseek(fd, s->refcount_table_offset, SEEK_SET);
-    ret = qemu_write_full(fd, s->refcount_table, s->cluster_size);
-    if (ret != s->cluster_size) {
+    ret = qemu_write_full(fd, s->refcount_table,
+        reftable_clusters * s->cluster_size);
+    if (ret != reftable_clusters * s->cluster_size) {
         ret = -errno;
         goto exit;
     }
commit 8252278afb4b646a5a21cf8c30bb0a0066825078
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Mar 15 17:38:05 2010 +0100

    qcow2: Trigger blkdebug events
    
    This adds blkdebug events to qcow2 to allow injecting I/O errors in specific
    places.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.h b/block.h
index 2fd8361..14443f1 100644
--- a/block.h
+++ b/block.h
@@ -210,6 +210,50 @@ int64_t bdrv_get_dirty_count(BlockDriverState *bs);
 
 
 typedef enum {
+    BLKDBG_L1_UPDATE,
+
+    BLKDBG_L1_GROW_ALLOC_TABLE,
+    BLKDBG_L1_GROW_WRITE_TABLE,
+    BLKDBG_L1_GROW_ACTIVATE_TABLE,
+
+    BLKDBG_L2_LOAD,
+    BLKDBG_L2_UPDATE,
+    BLKDBG_L2_UPDATE_COMPRESSED,
+    BLKDBG_L2_ALLOC_COW_READ,
+    BLKDBG_L2_ALLOC_WRITE,
+
+    BLKDBG_READ,
+    BLKDBG_READ_AIO,
+    BLKDBG_READ_BACKING,
+    BLKDBG_READ_BACKING_AIO,
+    BLKDBG_READ_COMPRESSED,
+
+    BLKDBG_WRITE_AIO,
+    BLKDBG_WRITE_COMPRESSED,
+
+    BLKDBG_VMSTATE_LOAD,
+    BLKDBG_VMSTATE_SAVE,
+
+    BLKDBG_COW_READ,
+    BLKDBG_COW_WRITE,
+
+    BLKDBG_REFTABLE_LOAD,
+    BLKDBG_REFTABLE_GROW,
+
+    BLKDBG_REFBLOCK_LOAD,
+    BLKDBG_REFBLOCK_UPDATE,
+    BLKDBG_REFBLOCK_UPDATE_PART,
+    BLKDBG_REFBLOCK_ALLOC,
+    BLKDBG_REFBLOCK_ALLOC_HOOKUP,
+    BLKDBG_REFBLOCK_ALLOC_WRITE,
+    BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS,
+    BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE,
+    BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE,
+
+    BLKDBG_CLUSTER_ALLOC,
+    BLKDBG_CLUSTER_ALLOC_BYTES,
+    BLKDBG_CLUSTER_FREE,
+
     BLKDBG_EVENT_MAX,
 } BlkDebugEvent;
 
diff --git a/block/blkdebug.c b/block/blkdebug.c
index b813bfa..643c397 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -139,6 +139,48 @@ static QemuOptsList *config_groups[] = {
 };
 
 static const char *event_names[BLKDBG_EVENT_MAX] = {
+    [BLKDBG_L1_UPDATE]                      = "l1_update",
+    [BLKDBG_L1_GROW_ALLOC_TABLE]            = "l1_grow.alloc_table",
+    [BLKDBG_L1_GROW_WRITE_TABLE]            = "l1_grow.write_table",
+    [BLKDBG_L1_GROW_ACTIVATE_TABLE]         = "l1_grow.activate_table",
+
+    [BLKDBG_L2_LOAD]                        = "l2_load",
+    [BLKDBG_L2_UPDATE]                      = "l2_update",
+    [BLKDBG_L2_UPDATE_COMPRESSED]           = "l2_update_compressed",
+    [BLKDBG_L2_ALLOC_COW_READ]              = "l2_alloc.cow_read",
+    [BLKDBG_L2_ALLOC_WRITE]                 = "l2_alloc.write",
+
+    [BLKDBG_READ]                           = "read",
+    [BLKDBG_READ_AIO]                       = "read_aio",
+    [BLKDBG_READ_BACKING]                   = "read_backing",
+    [BLKDBG_READ_BACKING_AIO]               = "read_backing_aio",
+    [BLKDBG_READ_COMPRESSED]                = "read_compressed",
+
+    [BLKDBG_WRITE_AIO]                      = "write_aio",
+    [BLKDBG_WRITE_COMPRESSED]               = "write_compressed",
+
+    [BLKDBG_VMSTATE_LOAD]                   = "vmstate_load",
+    [BLKDBG_VMSTATE_SAVE]                   = "vmstate_save",
+
+    [BLKDBG_COW_READ]                       = "cow_read",
+    [BLKDBG_COW_WRITE]                      = "cow_write",
+
+    [BLKDBG_REFTABLE_LOAD]                  = "reftable_load",
+    [BLKDBG_REFTABLE_GROW]                  = "reftable_grow",
+
+    [BLKDBG_REFBLOCK_LOAD]                  = "refblock_load",
+    [BLKDBG_REFBLOCK_UPDATE]                = "refblock_update",
+    [BLKDBG_REFBLOCK_UPDATE_PART]           = "refblock_update_part",
+    [BLKDBG_REFBLOCK_ALLOC]                 = "refblock_alloc",
+    [BLKDBG_REFBLOCK_ALLOC_HOOKUP]          = "refblock_alloc.hookup",
+    [BLKDBG_REFBLOCK_ALLOC_WRITE]           = "refblock_alloc.write",
+    [BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS]    = "refblock_alloc.write_blocks",
+    [BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE]     = "refblock_alloc.write_table",
+    [BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE]    = "refblock_alloc.switch_table",
+
+    [BLKDBG_CLUSTER_ALLOC]                  = "cluster_alloc",
+    [BLKDBG_CLUSTER_ALLOC_BYTES]            = "cluster_alloc_bytes",
+    [BLKDBG_CLUSTER_FREE]                   = "cluster_free",
 };
 
 static int get_event_by_name(const char *name, BlkDebugEvent *event)
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index c7057b1..8cb4b38 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -54,12 +54,14 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
     memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
 
     /* write new table (align to cluster) */
+    BLKDBG_EVENT(s->hd, BLKDBG_L1_GROW_ALLOC_TABLE);
     new_l1_table_offset = qcow2_alloc_clusters(bs, new_l1_size2);
     if (new_l1_table_offset < 0) {
         qemu_free(new_l1_table);
         return new_l1_table_offset;
     }
 
+    BLKDBG_EVENT(s->hd, BLKDBG_L1_GROW_WRITE_TABLE);
     for(i = 0; i < s->l1_size; i++)
         new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
     ret = bdrv_pwrite(s->hd, new_l1_table_offset, new_l1_table, new_l1_size2);
@@ -69,6 +71,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
         new_l1_table[i] = be64_to_cpu(new_l1_table[i]);
 
     /* set new table */
+    BLKDBG_EVENT(s->hd, BLKDBG_L1_GROW_ACTIVATE_TABLE);
     cpu_to_be32w((uint32_t*)data, new_l1_size);
     cpu_to_be64w((uint64_t*)(data + 4), new_l1_table_offset);
     ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size), data,sizeof(data));
@@ -170,6 +173,8 @@ static uint64_t *l2_load(BlockDriverState *bs, uint64_t l2_offset)
 
     min_index = l2_cache_new_entry(bs);
     l2_table = s->l2_cache + (min_index << s->l2_bits);
+
+    BLKDBG_EVENT(s->hd, BLKDBG_L2_LOAD);
     if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
         s->l2_size * sizeof(uint64_t))
         return NULL;
@@ -195,6 +200,7 @@ static int write_l1_entry(BDRVQcowState *s, int l1_index)
         buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]);
     }
 
+    BLKDBG_EVENT(s->hd, BLKDBG_L1_UPDATE);
     if (bdrv_pwrite(s->hd, s->l1_table_offset + 8 * l1_start_index,
         buf, sizeof(buf)) != sizeof(buf))
     {
@@ -248,12 +254,14 @@ static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index)
         memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
     } else {
         /* if there was an old l2 table, read it from the disk */
+        BLKDBG_EVENT(s->hd, BLKDBG_L2_ALLOC_COW_READ);
         if (bdrv_pread(s->hd, old_l2_offset,
                        l2_table, s->l2_size * sizeof(uint64_t)) !=
             s->l2_size * sizeof(uint64_t))
             return NULL;
     }
     /* write the l2 table to the file */
+    BLKDBG_EVENT(s->hd, BLKDBG_L2_ALLOC_WRITE);
     if (bdrv_pwrite(s->hd, l2_offset,
                     l2_table, s->l2_size * sizeof(uint64_t)) !=
         s->l2_size * sizeof(uint64_t))
@@ -335,6 +343,7 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
                 /* read from the base image */
                 n1 = qcow2_backing_read1(bs->backing_hd, sector_num, buf, n);
                 if (n1 > 0) {
+                    BLKDBG_EVENT(s->hd, BLKDBG_READ_BACKING);
                     ret = bdrv_read(bs->backing_hd, sector_num, buf, n1);
                     if (ret < 0)
                         return -1;
@@ -347,6 +356,7 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
                 return -1;
             memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
         } else {
+            BLKDBG_EVENT(s->hd, BLKDBG_READ);
             ret = bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
             if (ret != n * 512)
                 return -1;
@@ -371,6 +381,7 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
     n = n_end - n_start;
     if (n <= 0)
         return 0;
+    BLKDBG_EVENT(s->hd, BLKDBG_COW_READ);
     ret = qcow_read(bs, start_sect + n_start, s->cluster_data, n);
     if (ret < 0)
         return ret;
@@ -380,6 +391,7 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
                         s->cluster_data, n, 1,
                         &s->aes_encrypt_key);
     }
+    BLKDBG_EVENT(s->hd, BLKDBG_COW_WRITE);
     ret = bdrv_write(s->hd, (cluster_offset >> 9) + n_start,
                      s->cluster_data, n);
     if (ret < 0)
@@ -592,6 +604,7 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
 
     /* compressed clusters never have the copied flag */
 
+    BLKDBG_EVENT(s->hd, BLKDBG_L2_UPDATE_COMPRESSED);
     l2_table[l2_index] = cpu_to_be64(cluster_offset);
     if (bdrv_pwrite(s->hd,
                     l2_offset + l2_index * sizeof(uint64_t),
@@ -615,6 +628,7 @@ static int write_l2_entries(BDRVQcowState *s, uint64_t *l2_table,
     int end_offset = (8 * (l2_index + num) + 511) & ~511;
     size_t len = end_offset - start_offset;
 
+    BLKDBG_EVENT(s->hd, BLKDBG_L2_UPDATE);
     if (bdrv_pwrite(s->hd, l2_offset + start_offset, &l2_table[l2_start_index],
         len) != len)
     {
@@ -866,6 +880,7 @@ int qcow2_decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
         nb_csectors = ((cluster_offset >> s->csize_shift) & s->csize_mask) + 1;
         sector_offset = coffset & 511;
         csize = nb_csectors * 512 - sector_offset;
+        BLKDBG_EVENT(s->hd, BLKDBG_READ_COMPRESSED);
         ret = bdrv_read(s->hd, coffset >> 9, s->cluster_data, nb_csectors);
         if (ret < 0) {
             return -1;
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 917fc88..47c9978 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -42,6 +42,7 @@ static int write_refcount_block(BDRVQcowState *s)
         return 0;
     }
 
+    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_UPDATE);
     if (bdrv_pwrite(s->hd, s->refcount_block_cache_offset,
             s->refcount_block_cache, size) != size)
     {
@@ -63,6 +64,7 @@ int qcow2_refcount_init(BlockDriverState *bs)
     refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t);
     s->refcount_table = qemu_malloc(refcount_table_size2);
     if (s->refcount_table_size > 0) {
+        BLKDBG_EVENT(s->hd, BLKDBG_REFTABLE_LOAD);
         ret = bdrv_pread(s->hd, s->refcount_table_offset,
                          s->refcount_table, refcount_table_size2);
         if (ret != refcount_table_size2)
@@ -93,6 +95,7 @@ static int load_refcount_block(BlockDriverState *bs,
         write_refcount_block(s);
     }
 
+    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_LOAD);
     ret = bdrv_pread(s->hd, refcount_block_offset, s->refcount_block_cache,
                      s->cluster_size);
     if (ret != s->cluster_size)
@@ -164,6 +167,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
     unsigned int refcount_table_index;
     int ret;
 
+    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC);
+
     /* Find the refcount block for the given cluster */
     refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
 
@@ -239,6 +244,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
     }
 
     /* Now the new refcount block needs to be written to disk */
+    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC_WRITE);
     ret = bdrv_pwrite(s->hd, new_block, s->refcount_block_cache,
         s->cluster_size);
     if (ret < 0) {
@@ -248,6 +254,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
     /* If the refcount table is big enough, just hook the block up there */
     if (refcount_table_index < s->refcount_table_size) {
         uint64_t data64 = cpu_to_be64(new_block);
+        BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC_HOOKUP);
         ret = bdrv_pwrite(s->hd,
             s->refcount_table_offset + refcount_table_index * sizeof(uint64_t),
             &data64, sizeof(data64));
@@ -270,6 +277,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
      * refcount table at once without producing an inconsistent state in
      * between.
      */
+    BLKDBG_EVENT(s->hd, BLKDBG_REFTABLE_GROW);
+
     /* Calculate the number of refcount blocks needed so far */
     uint64_t refcount_block_clusters = 1 << (s->cluster_bits - REFCOUNT_SHIFT);
     uint64_t blocks_used = (s->free_cluster_index +
@@ -325,6 +334,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
     }
 
     /* Write refcount blocks to disk */
+    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS);
     ret = bdrv_pwrite(s->hd, meta_offset, new_blocks,
         blocks_clusters * s->cluster_size);
     qemu_free(new_blocks);
@@ -337,6 +347,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
         cpu_to_be64s(&new_table[i]);
     }
 
+    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE);
     ret = bdrv_pwrite(s->hd, table_offset, new_table,
         table_size * sizeof(uint64_t));
     if (ret < 0) {
@@ -351,6 +362,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
     uint8_t data[12];
     cpu_to_be64w((uint64_t*)data, table_offset);
     cpu_to_be32w((uint32_t*)(data + 8), table_clusters);
+    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE);
     ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),
         data, sizeof(data));
     if (ret < 0) {
@@ -400,6 +412,7 @@ static int write_refcount_block_entries(BDRVQcowState *s,
         & ~(REFCOUNTS_PER_SECTOR - 1);
 
     size = (last_index - first_index) << REFCOUNT_SHIFT;
+    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_UPDATE_PART);
     if (bdrv_pwrite(s->hd,
         refcount_block_offset + (first_index << REFCOUNT_SHIFT),
         &s->refcount_block_cache[first_index], size) != size)
@@ -555,9 +568,11 @@ retry:
 
 int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size)
 {
+    BDRVQcowState *s = bs->opaque;
     int64_t offset;
     int ret;
 
+    BLKDBG_EVENT(s->hd, BLKDBG_CLUSTER_ALLOC);
     offset = alloc_clusters_noref(bs, size);
     ret = update_refcount(bs, offset, size, 1);
     if (ret < 0) {
@@ -574,6 +589,7 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
     int64_t offset, cluster_offset;
     int free_in_cluster;
 
+    BLKDBG_EVENT(s->hd, BLKDBG_CLUSTER_ALLOC_BYTES);
     assert(size > 0 && size <= s->cluster_size);
     if (s->free_byte_offset == 0) {
         s->free_byte_offset = qcow2_alloc_clusters(bs, s->cluster_size);
@@ -615,8 +631,10 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
 void qcow2_free_clusters(BlockDriverState *bs,
                           int64_t offset, int64_t size)
 {
+    BDRVQcowState *s = bs->opaque;
     int ret;
 
+    BLKDBG_EVENT(s->hd, BLKDBG_CLUSTER_FREE);
     ret = update_refcount(bs, offset, size, -1);
     if (ret < 0) {
         fprintf(stderr, "qcow2_free_clusters failed: %s\n", strerror(-ret));
diff --git a/block/qcow2.c b/block/qcow2.c
index 4e97eb6..80c99af 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -429,6 +429,7 @@ static void qcow_aio_read_cb(void *opaque, int ret)
                 acb->hd_iov.iov_base = (void *)acb->buf;
                 acb->hd_iov.iov_len = acb->cur_nr_sectors * 512;
                 qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
+                BLKDBG_EVENT(s->hd, BLKDBG_READ_BACKING_AIO);
                 acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num,
                                     &acb->hd_qiov, acb->cur_nr_sectors,
 				    qcow_aio_read_cb, acb);
@@ -464,6 +465,7 @@ static void qcow_aio_read_cb(void *opaque, int ret)
         acb->hd_iov.iov_base = (void *)acb->buf;
         acb->hd_iov.iov_len = acb->cur_nr_sectors * 512;
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
+        BLKDBG_EVENT(s->hd, BLKDBG_READ_AIO);
         acb->hd_aiocb = bdrv_aio_readv(s->hd,
                             (acb->cluster_offset >> 9) + index_in_cluster,
                             &acb->hd_qiov, acb->cur_nr_sectors,
@@ -619,6 +621,7 @@ static void qcow_aio_write_cb(void *opaque, int ret)
     acb->hd_iov.iov_base = (void *)src_buf;
     acb->hd_iov.iov_len = acb->cur_nr_sectors * 512;
     qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
+    BLKDBG_EVENT(s->hd, BLKDBG_WRITE_AIO);
     acb->hd_aiocb = bdrv_aio_writev(s->hd,
                                     (acb->cluster_offset >> 9) + index_in_cluster,
                                     &acb->hd_qiov, acb->cur_nr_sectors,
@@ -1141,6 +1144,7 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
         if (!cluster_offset)
             return -1;
         cluster_offset &= s->cluster_offset_mask;
+        BLKDBG_EVENT(s->hd, BLKDBG_WRITE_COMPRESSED);
         if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
             qemu_free(out_buf);
             return -1;
@@ -1211,6 +1215,7 @@ static int qcow_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
     int growable = bs->growable;
     int ret;
 
+    BLKDBG_EVENT(s->hd, BLKDBG_VMSTATE_SAVE);
     bs->growable = 1;
     ret = bdrv_pwrite(bs, qcow_vm_state_offset(s) + pos, buf, size);
     bs->growable = growable;
@@ -1225,6 +1230,7 @@ static int qcow_load_vmstate(BlockDriverState *bs, uint8_t *buf,
     int growable = bs->growable;
     int ret;
 
+    BLKDBG_EVENT(s->hd, BLKDBG_VMSTATE_LOAD);
     bs->growable = 1;
     ret = bdrv_pread(bs, qcow_vm_state_offset(s) + pos, buf, size);
     bs->growable = growable;
commit 8b9b0cc2fd1b866c0ce6c7f7385d840aad8b4c2c
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Mar 15 17:27:00 2010 +0100

    blkdebug: Add events and rules
    
    Block drivers can trigger a blkdebug event whenever they reach a place where it
    could be useful to inject an error for testing/debugging purposes.
    
    Rules are read from a blkdebug config file and describe which action is taken
    when an event is triggered. For now this is only injecting an error (with a few
    options) or changing the state (which is an integer). Rules can be declared to
    be active only in a specific state; this way later rules can distiguish on
    which path we came to trigger their event.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 0881c93..9351aa3 100644
--- a/block.c
+++ b/block.c
@@ -1535,6 +1535,18 @@ int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
     return drv->bdrv_load_vmstate(bs, buf, pos, size);
 }
 
+void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event)
+{
+    BlockDriver *drv = bs->drv;
+
+    if (!drv || !drv->bdrv_debug_event) {
+        return;
+    }
+
+    return drv->bdrv_debug_event(bs, event);
+
+}
+
 /**************************************************************/
 /* handling of snapshots */
 
diff --git a/block.h b/block.h
index edf5704..2fd8361 100644
--- a/block.h
+++ b/block.h
@@ -207,4 +207,13 @@ int bdrv_get_dirty(BlockDriverState *bs, int64_t sector);
 void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
                       int nr_sectors);
 int64_t bdrv_get_dirty_count(BlockDriverState *bs);
+
+
+typedef enum {
+    BLKDBG_EVENT_MAX,
+} BlkDebugEvent;
+
+#define BLKDBG_EVENT(bs, evt) bdrv_debug_event(bs, evt)
+void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event);
+
 #endif
diff --git a/block/blkdebug.c b/block/blkdebug.c
index dad3ac6..b813bfa 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -46,6 +46,7 @@ typedef struct BlkdebugVars {
 typedef struct BDRVBlkdebugState {
     BlockDriverState *hd;
     BlkdebugVars vars;
+    QLIST_HEAD(list, BlkdebugRule) rules[BLKDBG_EVENT_MAX];
 } BDRVBlkdebugState;
 
 typedef struct BlkdebugAIOCB {
@@ -61,16 +62,211 @@ static AIOPool blkdebug_aio_pool = {
     .cancel     = blkdebug_aio_cancel,
 };
 
+enum {
+    ACTION_INJECT_ERROR,
+    ACTION_SET_STATE,
+};
+
+typedef struct BlkdebugRule {
+    BlkDebugEvent event;
+    int action;
+    int state;
+    union {
+        struct {
+            int error;
+            int immediately;
+            int once;
+        } inject;
+        struct {
+            int new_state;
+        } set_state;
+    } options;
+    QLIST_ENTRY(BlkdebugRule) next;
+} BlkdebugRule;
+
+static QemuOptsList inject_error_opts = {
+    .name = "inject-error",
+    .head = QTAILQ_HEAD_INITIALIZER(inject_error_opts.head),
+    .desc = {
+        {
+            .name = "event",
+            .type = QEMU_OPT_STRING,
+        },
+        {
+            .name = "state",
+            .type = QEMU_OPT_NUMBER,
+        },
+        {
+            .name = "errno",
+            .type = QEMU_OPT_NUMBER,
+        },
+        {
+            .name = "once",
+            .type = QEMU_OPT_BOOL,
+        },
+        {
+            .name = "immediately",
+            .type = QEMU_OPT_BOOL,
+        },
+        { /* end of list */ }
+    },
+};
+
+static QemuOptsList set_state_opts = {
+    .name = "set-state",
+    .head = QTAILQ_HEAD_INITIALIZER(inject_error_opts.head),
+    .desc = {
+        {
+            .name = "event",
+            .type = QEMU_OPT_STRING,
+        },
+        {
+            .name = "state",
+            .type = QEMU_OPT_NUMBER,
+        },
+        {
+            .name = "new_state",
+            .type = QEMU_OPT_NUMBER,
+        },
+        { /* end of list */ }
+    },
+};
+
+static QemuOptsList *config_groups[] = {
+    &inject_error_opts,
+    &set_state_opts,
+    NULL
+};
+
+static const char *event_names[BLKDBG_EVENT_MAX] = {
+};
+
+static int get_event_by_name(const char *name, BlkDebugEvent *event)
+{
+    int i;
+
+    for (i = 0; i < BLKDBG_EVENT_MAX; i++) {
+        if (!strcmp(event_names[i], name)) {
+            *event = i;
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
+struct add_rule_data {
+    BDRVBlkdebugState *s;
+    int action;
+};
+
+static int add_rule(QemuOpts *opts, void *opaque)
+{
+    struct add_rule_data *d = opaque;
+    BDRVBlkdebugState *s = d->s;
+    const char* event_name;
+    BlkDebugEvent event;
+    struct BlkdebugRule *rule;
+
+    /* Find the right event for the rule */
+    event_name = qemu_opt_get(opts, "event");
+    if (!event_name || get_event_by_name(event_name, &event) < 0) {
+        return -1;
+    }
+
+    /* Set attributes common for all actions */
+    rule = qemu_mallocz(sizeof(*rule));
+    *rule = (struct BlkdebugRule) {
+        .event  = event,
+        .action = d->action,
+        .state  = qemu_opt_get_number(opts, "state", 0),
+    };
+
+    /* Parse action-specific options */
+    switch (d->action) {
+    case ACTION_INJECT_ERROR:
+        rule->options.inject.error = qemu_opt_get_number(opts, "errno", EIO);
+        rule->options.inject.once  = qemu_opt_get_bool(opts, "once", 0);
+        rule->options.inject.immediately =
+            qemu_opt_get_bool(opts, "immediately", 0);
+        break;
+
+    case ACTION_SET_STATE:
+        rule->options.set_state.new_state =
+            qemu_opt_get_number(opts, "new_state", 0);
+        break;
+    };
+
+    /* Add the rule */
+    QLIST_INSERT_HEAD(&s->rules[event], rule, next);
+
+    return 0;
+}
+
+static int read_config(BDRVBlkdebugState *s, const char *filename)
+{
+    FILE *f;
+    int ret;
+    struct add_rule_data d;
+
+    f = fopen(filename, "r");
+    if (f == NULL) {
+        return -errno;
+    }
+
+    ret = qemu_config_parse(f, config_groups, filename);
+    if (ret < 0) {
+        goto fail;
+    }
+
+    d.s = s;
+    d.action = ACTION_INJECT_ERROR;
+    qemu_opts_foreach(&inject_error_opts, add_rule, &d, 0);
+
+    d.action = ACTION_SET_STATE;
+    qemu_opts_foreach(&set_state_opts, add_rule, &d, 0);
+
+    ret = 0;
+fail:
+    fclose(f);
+    return ret;
+}
+
+/* Valid blkdebug filenames look like blkdebug:path/to/config:path/to/image */
 static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags)
 {
     BDRVBlkdebugState *s = bs->opaque;
+    int ret;
+    char *config, *c;
 
+    /* Parse the blkdebug: prefix */
     if (strncmp(filename, "blkdebug:", strlen("blkdebug:"))) {
         return -EINVAL;
     }
     filename += strlen("blkdebug:");
 
-    return bdrv_file_open(&s->hd, filename, flags);
+    /* Read rules from config file */
+    c = strchr(filename, ':');
+    if (c == NULL) {
+        return -EINVAL;
+    }
+
+    config = strdup(filename);
+    config[c - filename] = '\0';
+    ret = read_config(s, config);
+    free(config);
+    if (ret < 0) {
+        return ret;
+    }
+    filename = c + 1;
+
+    /* Open the backing file */
+    ret = bdrv_file_open(&s->hd, filename, flags);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return 0;
 }
 
 static void error_callback_bh(void *opaque)
@@ -146,6 +342,16 @@ static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
 static void blkdebug_close(BlockDriverState *bs)
 {
     BDRVBlkdebugState *s = bs->opaque;
+    BlkdebugRule *rule, *next;
+    int i;
+
+    for (i = 0; i < BLKDBG_EVENT_MAX; i++) {
+        QLIST_FOREACH_SAFE(rule, &s->rules[i], next, next) {
+            QLIST_REMOVE(rule, next);
+            qemu_free(rule);
+        }
+    }
+
     bdrv_delete(s->hd);
 }
 
@@ -162,6 +368,46 @@ static BlockDriverAIOCB *blkdebug_aio_flush(BlockDriverState *bs,
     return bdrv_aio_flush(s->hd, cb, opaque);
 }
 
+static void process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
+    BlkdebugVars *old_vars)
+{
+    BDRVBlkdebugState *s = bs->opaque;
+    BlkdebugVars *vars = &s->vars;
+
+    /* Only process rules for the current state */
+    if (rule->state && rule->state != old_vars->state) {
+        return;
+    }
+
+    /* Take the action */
+    switch (rule->action) {
+    case ACTION_INJECT_ERROR:
+        vars->inject_errno       = rule->options.inject.error;
+        vars->inject_once        = rule->options.inject.once;
+        vars->inject_immediately = rule->options.inject.immediately;
+        break;
+
+    case ACTION_SET_STATE:
+        vars->state              = rule->options.set_state.new_state;
+        break;
+    }
+}
+
+static void blkdebug_debug_event(BlockDriverState *bs, BlkDebugEvent event)
+{
+    BDRVBlkdebugState *s = bs->opaque;
+    struct BlkdebugRule *rule;
+    BlkdebugVars old_vars = s->vars;
+
+    if (event < 0 || event >= BLKDBG_EVENT_MAX) {
+        return;
+    }
+
+    QLIST_FOREACH(rule, &s->rules[event], next) {
+        process_rule(bs, rule, &old_vars);
+    }
+}
+
 static BlockDriver bdrv_blkdebug = {
     .format_name        = "blkdebug",
     .protocol_name      = "blkdebug",
@@ -175,6 +421,8 @@ static BlockDriver bdrv_blkdebug = {
     .bdrv_aio_readv     = blkdebug_aio_readv,
     .bdrv_aio_writev    = blkdebug_aio_writev,
     .bdrv_aio_flush     = blkdebug_aio_flush,
+
+    .bdrv_debug_event   = blkdebug_debug_event,
 };
 
 static void bdrv_blkdebug_init(void)
diff --git a/block_int.h b/block_int.h
index 71b633b..e7e1e7e 100644
--- a/block_int.h
+++ b/block_int.h
@@ -120,6 +120,8 @@ struct BlockDriver {
     /* Returns number of errors in image, -errno for internal errors */
     int (*bdrv_check)(BlockDriverState* bs);
 
+    void (*bdrv_debug_event)(BlockDriverState *bs, BlkDebugEvent event);
+
     /* Set if newly created images are not guaranteed to contain only zeros */
     int no_zero_init;
 
commit 25920d6ad61b078a69b6ba401d4d6cd46ce83804
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Mar 15 17:01:24 2010 +0100

    Make qemu-config available for tools
    
    To be able to use config files for blkdebug, we need to make these functions
    available in the tools. This involves moving two functions that can only be
    built in the context of the emulator.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index ed7bbda..69d6879 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -8,7 +8,7 @@ qobject-obj-y += qerror.o
 # block-obj-y is code used by both qemu system emulation and qemu-img
 
 block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o
-block-obj-y += nbd.o block.o aio.o aes.o osdep.o
+block-obj-y += nbd.o block.o aio.o aes.o osdep.o qemu-config.o
 block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 
@@ -76,7 +76,7 @@ common-obj-y += buffered_file.o migration.o migration-tcp.o qemu-sockets.o
 common-obj-y += qemu-char.o savevm.o #aio.o
 common-obj-y += msmouse.o ps2.o
 common-obj-y += qdev.o qdev-properties.o
-common-obj-y += qemu-config.o block-migration.o
+common-obj-y += block-migration.o
 
 common-obj-$(CONFIG_BRLAPI) += baum.o
 common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 157a111..9ffdba7 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -661,7 +661,7 @@ void qdev_prop_set_defaults(DeviceState *dev, Property *props)
 
 static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
 
-void qdev_prop_register_global(GlobalProperty *prop)
+static void qdev_prop_register_global(GlobalProperty *prop)
 {
     QTAILQ_INSERT_TAIL(&global_props, prop, next);
 }
@@ -689,3 +689,20 @@ void qdev_prop_set_globals(DeviceState *dev)
         }
     }
 }
+
+static int qdev_add_one_global(QemuOpts *opts, void *opaque)
+{
+    GlobalProperty *g;
+
+    g = qemu_mallocz(sizeof(*g));
+    g->driver   = qemu_opt_get(opts, "driver");
+    g->property = qemu_opt_get(opts, "property");
+    g->value    = qemu_opt_get(opts, "value");
+    qdev_prop_register_global(g);
+    return 0;
+}
+
+void qemu_add_globals(void)
+{
+    qemu_opts_foreach(&qemu_global_opts, qdev_add_one_global, NULL, 0);
+}
diff --git a/hw/qdev.h b/hw/qdev.h
index 40373c8..d8fbc73 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -273,7 +273,6 @@ void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
 void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
 void qdev_prop_set_defaults(DeviceState *dev, Property *props);
 
-void qdev_prop_register_global(GlobalProperty *prop);
 void qdev_prop_register_global_list(GlobalProperty *props);
 void qdev_prop_set_globals(DeviceState *dev);
 
diff --git a/qemu-config.c b/qemu-config.c
index 9b5fe78..9f0f143 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -378,23 +378,6 @@ int qemu_global_option(const char *str)
     return 0;
 }
 
-static int qemu_add_one_global(QemuOpts *opts, void *opaque)
-{
-    GlobalProperty *g;
-
-    g = qemu_mallocz(sizeof(*g));
-    g->driver   = qemu_opt_get(opts, "driver");
-    g->property = qemu_opt_get(opts, "property");
-    g->value    = qemu_opt_get(opts, "value");
-    qdev_prop_register_global(g);
-    return 0;
-}
-
-void qemu_add_globals(void)
-{
-    qemu_opts_foreach(&qemu_global_opts, qemu_add_one_global, NULL, 0);
-}
-
 struct ConfigWriteData {
     QemuOptsList *list;
     FILE *fp;
commit b9f66d96950b7c10253f9f27b9109df5ff8aa611
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Feb 19 16:24:35 2010 +0100

    blkdebug: Inject errors
    
    Add a mechanism to inject errors instead of passing requests on. With no
    further patches applied, you can use it by setting inject_errno in gdb.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/blkdebug.c b/block/blkdebug.c
index 2c7e0dd..dad3ac6 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -26,10 +26,41 @@
 #include "block_int.h"
 #include "module.h"
 
+#include <stdbool.h>
+
+typedef struct BlkdebugVars {
+    int state;
+
+    /* If inject_errno != 0, an error is injected for requests */
+    int inject_errno;
+
+    /* Decides if all future requests fail (false) or only the next one and
+     * after the next request inject_errno is reset to 0 (true) */
+    bool inject_once;
+
+    /* Decides if aio_readv/writev fails right away (true) or returns an error
+     * return value only in the callback (false) */
+    bool inject_immediately;
+} BlkdebugVars;
+
 typedef struct BDRVBlkdebugState {
     BlockDriverState *hd;
+    BlkdebugVars vars;
 } BDRVBlkdebugState;
 
+typedef struct BlkdebugAIOCB {
+    BlockDriverAIOCB common;
+    QEMUBH *bh;
+    int ret;
+} BlkdebugAIOCB;
+
+static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb);
+
+static AIOPool blkdebug_aio_pool = {
+    .aiocb_size = sizeof(BlkdebugAIOCB),
+    .cancel     = blkdebug_aio_cancel,
+};
+
 static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags)
 {
     BDRVBlkdebugState *s = bs->opaque;
@@ -42,11 +73,56 @@ static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags)
     return bdrv_file_open(&s->hd, filename, flags);
 }
 
+static void error_callback_bh(void *opaque)
+{
+    struct BlkdebugAIOCB *acb = opaque;
+    qemu_bh_delete(acb->bh);
+    acb->common.cb(acb->common.opaque, acb->ret);
+    qemu_aio_release(acb);
+}
+
+static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb)
+{
+    BlkdebugAIOCB *acb = (BlkdebugAIOCB*) blockacb;
+    qemu_aio_release(acb);
+}
+
+static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
+    BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BDRVBlkdebugState *s = bs->opaque;
+    int error = s->vars.inject_errno;
+    struct BlkdebugAIOCB *acb;
+    QEMUBH *bh;
+
+    if (s->vars.inject_once) {
+        s->vars.inject_errno = 0;
+    }
+
+    if (s->vars.inject_immediately) {
+        return NULL;
+    }
+
+    acb = qemu_aio_get(&blkdebug_aio_pool, bs, cb, opaque);
+    acb->ret = -error;
+
+    bh = qemu_bh_new(error_callback_bh, acb);
+    acb->bh = bh;
+    qemu_bh_schedule(bh);
+
+    return (BlockDriverAIOCB*) acb;
+}
+
 static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
     int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
     BlockDriverCompletionFunc *cb, void *opaque)
 {
     BDRVBlkdebugState *s = bs->opaque;
+
+    if (s->vars.inject_errno) {
+        return inject_error(bs, cb, opaque);
+    }
+
     BlockDriverAIOCB *acb =
         bdrv_aio_readv(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
     return acb;
@@ -57,6 +133,11 @@ static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
     BlockDriverCompletionFunc *cb, void *opaque)
 {
     BDRVBlkdebugState *s = bs->opaque;
+
+    if (s->vars.inject_errno) {
+        return inject_error(bs, cb, opaque);
+    }
+
     BlockDriverAIOCB *acb =
         bdrv_aio_writev(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
     return acb;
commit 6a1437273ca3685f4bc8065fd921834d9b5608e1
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Feb 18 17:48:12 2010 +0100

    blkdebug: Basic request passthrough
    
    This isn't doing anything interesting. It creates the blkdebug block driver as
    a protocol which just passes everything through to raw.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 2a87e2c..ed7bbda 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -14,7 +14,7 @@ block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 
 block-nested-y += cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
 block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o
-block-nested-y += parallels.o nbd.o
+block-nested-y += parallels.o nbd.o blkdebug.o
 block-nested-$(CONFIG_WIN32) += raw-win32.o
 block-nested-$(CONFIG_POSIX) += raw-posix.o
 block-nested-$(CONFIG_CURL) += curl.o
diff --git a/block/blkdebug.c b/block/blkdebug.c
new file mode 100644
index 0000000..2c7e0dd
--- /dev/null
+++ b/block/blkdebug.c
@@ -0,0 +1,104 @@
+/*
+ * Block protocol for I/O error injection
+ *
+ * Copyright (c) 2010 Kevin Wolf <kwolf at redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu-common.h"
+#include "block_int.h"
+#include "module.h"
+
+typedef struct BDRVBlkdebugState {
+    BlockDriverState *hd;
+} BDRVBlkdebugState;
+
+static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags)
+{
+    BDRVBlkdebugState *s = bs->opaque;
+
+    if (strncmp(filename, "blkdebug:", strlen("blkdebug:"))) {
+        return -EINVAL;
+    }
+    filename += strlen("blkdebug:");
+
+    return bdrv_file_open(&s->hd, filename, flags);
+}
+
+static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
+    int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+    BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BDRVBlkdebugState *s = bs->opaque;
+    BlockDriverAIOCB *acb =
+        bdrv_aio_readv(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
+    return acb;
+}
+
+static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
+    int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+    BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BDRVBlkdebugState *s = bs->opaque;
+    BlockDriverAIOCB *acb =
+        bdrv_aio_writev(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
+    return acb;
+}
+
+static void blkdebug_close(BlockDriverState *bs)
+{
+    BDRVBlkdebugState *s = bs->opaque;
+    bdrv_delete(s->hd);
+}
+
+static void blkdebug_flush(BlockDriverState *bs)
+{
+    BDRVBlkdebugState *s = bs->opaque;
+    bdrv_flush(s->hd);
+}
+
+static BlockDriverAIOCB *blkdebug_aio_flush(BlockDriverState *bs,
+    BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BDRVBlkdebugState *s = bs->opaque;
+    return bdrv_aio_flush(s->hd, cb, opaque);
+}
+
+static BlockDriver bdrv_blkdebug = {
+    .format_name        = "blkdebug",
+    .protocol_name      = "blkdebug",
+
+    .instance_size      = sizeof(BDRVBlkdebugState),
+
+    .bdrv_open          = blkdebug_open,
+    .bdrv_close         = blkdebug_close,
+    .bdrv_flush         = blkdebug_flush,
+
+    .bdrv_aio_readv     = blkdebug_aio_readv,
+    .bdrv_aio_writev    = blkdebug_aio_writev,
+    .bdrv_aio_flush     = blkdebug_aio_flush,
+};
+
+static void bdrv_blkdebug_init(void)
+{
+    bdrv_register(&bdrv_blkdebug);
+}
+
+block_init(bdrv_blkdebug_init);
commit 490b648e5b8987d4d497c222e0941a8b129a5eb6
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 5 18:21:56 2010 +0100

    qemu-config: Make qemu_config_parse more generic
    
    qemu_config_parse gets the option groups as a parameter now instead of
    hardcoding the VM configuration groups. This way it can be used for other
    configurations, too.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-config.c b/qemu-config.c
index 8254b35..9b5fe78 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -296,7 +296,7 @@ QemuOptsList qemu_cpudef_opts = {
     },
 };
 
-static QemuOptsList *lists[] = {
+static QemuOptsList *vm_config_groups[] = {
     &qemu_drive_opts,
     &qemu_chardev_opts,
     &qemu_device_opts,
@@ -309,7 +309,7 @@ static QemuOptsList *lists[] = {
     NULL,
 };
 
-QemuOptsList *qemu_find_opts(const char *group)
+static QemuOptsList *find_list(QemuOptsList **lists, const char *group)
 {
     int i;
 
@@ -323,6 +323,11 @@ QemuOptsList *qemu_find_opts(const char *group)
     return lists[i];
 }
 
+QemuOptsList *qemu_find_opts(const char *group)
+{
+    return find_list(vm_config_groups, group);
+}
+
 int qemu_set_option(const char *str)
 {
     char group[64], id[64], arg[64];
@@ -421,6 +426,7 @@ static int config_write_opts(QemuOpts *opts, void *opaque)
 void qemu_config_write(FILE *fp)
 {
     struct ConfigWriteData data = { .fp = fp };
+    QemuOptsList **lists = vm_config_groups;
     int i;
 
     fprintf(fp, "# qemu config file\n\n");
@@ -430,7 +436,7 @@ void qemu_config_write(FILE *fp)
     }
 }
 
-int qemu_config_parse(FILE *fp, const char *fname)
+int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
 {
     char line[1024], group[64], id[64], arg[64], value[1024];
     Location loc;
@@ -451,7 +457,7 @@ int qemu_config_parse(FILE *fp, const char *fname)
         }
         if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
             /* group with id */
-            list = qemu_find_opts(group);
+            list = find_list(lists, group);
             if (list == NULL)
                 goto out;
             opts = qemu_opts_create(list, id, 1);
@@ -459,7 +465,7 @@ int qemu_config_parse(FILE *fp, const char *fname)
         }
         if (sscanf(line, "[%63[^]]]", group) == 1) {
             /* group without id */
-            list = qemu_find_opts(group);
+            list = find_list(lists, group);
             if (list == NULL)
                 goto out;
             opts = qemu_opts_create(list, NULL, 0);
@@ -496,7 +502,7 @@ int qemu_read_config_file(const char *filename)
         return -errno;
     }
 
-    if (qemu_config_parse(f, filename) != 0) {
+    if (qemu_config_parse(f, vm_config_groups, filename) != 0) {
         return -EINVAL;
     }
     fclose(f);
diff --git a/qemu-config.h b/qemu-config.h
index 07a7a27..dd299c2 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -17,7 +17,7 @@ int qemu_global_option(const char *str);
 void qemu_add_globals(void);
 
 void qemu_config_write(FILE *fp);
-int qemu_config_parse(FILE *fp, const char *fname);
+int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname);
 
 int qemu_read_config_file(const char *filename);
 
commit dcfb0939bd7042c9d2622181263c01d78531f272
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 5 17:25:55 2010 +0100

    qemu-config: qemu_read_config_file() reads the normal config file
    
    Introduce a new function qemu_read_config_file which reads the VM configuration
    from a config file. Unlike qemu_config_parse it doesn't take a open file but a
    filename and reduces code duplication as a side effect.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-config.c b/qemu-config.c
index d4a2f43..8254b35 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -488,3 +488,18 @@ out:
     loc_pop(&loc);
     return res;
 }
+
+int qemu_read_config_file(const char *filename)
+{
+    FILE *f = fopen(filename, "r");
+    if (f == NULL) {
+        return -errno;
+    }
+
+    if (qemu_config_parse(f, filename) != 0) {
+        return -EINVAL;
+    }
+    fclose(f);
+
+    return 0;
+}
diff --git a/qemu-config.h b/qemu-config.h
index f217c58..07a7a27 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -19,4 +19,6 @@ void qemu_add_globals(void);
 void qemu_config_write(FILE *fp);
 int qemu_config_parse(FILE *fp, const char *fname);
 
+int qemu_read_config_file(const char *filename);
+
 #endif /* QEMU_CONFIG_H */
diff --git a/vl.c b/vl.c
index e58441b..fe2dd6f 100644
--- a/vl.c
+++ b/vl.c
@@ -2653,25 +2653,16 @@ int main(int argc, char **argv, char **envp)
     }
 
     if (defconfig) {
-        const char *fname;
-        FILE *fp;
+        int ret;
 
-        fname = CONFIG_QEMU_CONFDIR "/qemu.conf";
-        fp = fopen(fname, "r");
-        if (fp) {
-            if (qemu_config_parse(fp, fname) != 0) {
-                exit(1);
-            }
-            fclose(fp);
+        ret = qemu_read_config_file(CONFIG_QEMU_CONFDIR "/qemu.conf");
+        if (ret == -EINVAL) {
+            exit(1);
         }
 
-        fname = arch_config_name;
-        fp = fopen(fname, "r");
-        if (fp) {
-            if (qemu_config_parse(fp, fname) != 0) {
-                exit(1);
-            }
-            fclose(fp);
+        ret = qemu_read_config_file(arch_config_name);
+        if (ret == -EINVAL) {
+            exit(1);
         }
     }
     cpudef_init();
@@ -3327,16 +3318,12 @@ int main(int argc, char **argv, char **envp)
                 break;
             case QEMU_OPTION_readconfig:
                 {
-                    FILE *fp;
-                    fp = fopen(optarg, "r");
-                    if (fp == NULL) {
-                        fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
+                    int ret = qemu_read_config_file(optarg);
+                    if (ret < 0) {
+                        fprintf(stderr, "read config %s: %s\n", optarg,
+                            strerror(-ret));
                         exit(1);
                     }
-                    if (qemu_config_parse(fp, optarg) != 0) {
-                        exit(1);
-                    }
-                    fclose(fp);
                     break;
                 }
             case QEMU_OPTION_writeconfig:
commit 6c557ab975fc8e5edb4167a241266c7c4657054a
Author: Serge Ziryukin <ftrvxmtrx at gmail.com>
Date:   Thu Apr 22 14:14:24 2010 +0300

    audio/sdlaudio: remove unused variable
    
    Remove unused 'shift' variable spotted by clang.
    Also clean up aud_to_sdlfmt which used to get the value
    of shift.
    
    Signed-off-by: Serge Ziryukin <ftrvxmtrx at gmail.com>
    Signed-off-by: malc <av1474 at comtv.ru>

diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c
index 8e7e5cb..c353016 100644
--- a/audio/sdlaudio.c
+++ b/audio/sdlaudio.c
@@ -115,23 +115,19 @@ static int sdl_unlock_and_post (SDLAudioState *s, const char *forfn)
     return sdl_post (s, forfn);
 }
 
-static int aud_to_sdlfmt (audfmt_e fmt, int *shift)
+static int aud_to_sdlfmt (audfmt_e fmt)
 {
     switch (fmt) {
     case AUD_FMT_S8:
-        *shift = 0;
         return AUDIO_S8;
 
     case AUD_FMT_U8:
-        *shift = 0;
         return AUDIO_U8;
 
     case AUD_FMT_S16:
-        *shift = 1;
         return AUDIO_S16LSB;
 
     case AUD_FMT_U16:
-        *shift = 1;
         return AUDIO_U16LSB;
 
     default:
@@ -326,16 +322,13 @@ static int sdl_init_out (HWVoiceOut *hw, struct audsettings *as)
     SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
     SDLAudioState *s = &glob_sdl;
     SDL_AudioSpec req, obt;
-    int shift;
     int endianess;
     int err;
     audfmt_e effective_fmt;
     struct audsettings obt_as;
 
-    shift <<= as->nchannels == 2;
-
     req.freq = as->freq;
-    req.format = aud_to_sdlfmt (as->fmt, &shift);
+    req.format = aud_to_sdlfmt (as->fmt);
     req.channels = as->nchannels;
     req.samples = conf.nb_samples;
     req.callback = sdl_callback;
commit a6e4b143883b8504f6793966c36093354b38a889
Author: Andrzej Zaborowski <balrog at zabor.org>
Date:   Thu Apr 22 03:55:46 2010 +0200

    bt-sdp: Fix an excessive ; and assignment of the wrong variable
    
    Problem-spotted-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Andrew Zaborowski <balrogg at gmail.com>

diff --git a/hw/bt-sdp.c b/hw/bt-sdp.c
index b8732d0..cc0bf2f 100644
--- a/hw/bt-sdp.c
+++ b/hw/bt-sdp.c
@@ -159,7 +159,7 @@ static ssize_t sdp_svc_search(struct bt_l2cap_sdp_state_s *sdp,
 
     if (len < 3)
         return -SDP_INVALID_SYNTAX;
-    end = (req[0] << 8) | req[1];
+    max = (req[0] << 8) | req[1];
     req += 2;
     len -= 2;
 
@@ -171,7 +171,7 @@ static ssize_t sdp_svc_search(struct bt_l2cap_sdp_state_s *sdp,
     } else
         start = 0;
 
-    if (len > 1);
+    if (len > 1)
         return -SDP_INVALID_SYNTAX;
 
     /* Output the results */
commit 7b1df88f284f462ecb236931ad863a815f243195
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Thu Apr 22 03:41:24 2010 +0200

    bt-l2cap: fix if statement with empty body, spotted by clang
    
    Fix clang error:
      CC    bt-l2cap.o
    /src/qemu/hw/bt-l2cap.c:1000:41: error: if statement has empty body
    [-Wempty-body]
                /* TODO: Signal an error? */;
    
    This means that l2cap_sframe_in() may now get called.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Andrew Zaborowski <balrogg at gmail.com>

diff --git a/hw/bt-l2cap.c b/hw/bt-l2cap.c
index 70d731e..7e2f668 100644
--- a/hw/bt-l2cap.c
+++ b/hw/bt-l2cap.c
@@ -996,10 +996,10 @@ static void l2cap_iframe_in(struct l2cap_chan_s *ch, uint16_t cid,
         l2cap_rexmit_enable(ch, !(hdr->data[0] >> 7));
 
     if (hdr->data[0] & 1) {
-        if (len != 4)
-            /* TODO: Signal an error? */;
+        if (len != 4) {
+            /* TODO: Signal an error? */
             return;
-
+        }
         return l2cap_sframe_in(ch, le16_to_cpup((void *) hdr->data));
     }
 
commit 8bb414d2aac3b41695b528f21b7e285ebdb225e4
Author: malc <av1474 at comtv.ru>
Date:   Wed Apr 21 15:40:23 2010 +0400

    audio/alsa: Avoid snd_pcm_format_t vs audfmt_e mixup
    
    Spotted by Serge Ziryukin and based on his patch, thanks.
    
    Signed-off-by: malc <av1474 at comtv.ru>

diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index 88344ff..f0171f9 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -411,10 +411,11 @@ static int alsa_to_audfmt (snd_pcm_format_t alsafmt, audfmt_e *fmt,
 }
 
 static void alsa_dump_info (struct alsa_params_req *req,
-                            struct alsa_params_obt *obt)
+                            struct alsa_params_obt *obt,
+                            snd_pcm_format_t obtfmt)
 {
     dolog ("parameter | requested value | obtained value\n");
-    dolog ("format    |      %10d |     %10d\n", req->fmt, obt->fmt);
+    dolog ("format    |      %10d |     %10d\n", req->fmt, obtfmt);
     dolog ("channels  |      %10d |     %10d\n",
            req->nchannels, obt->nchannels);
     dolog ("frequency |      %10d |     %10d\n", req->freq, obt->freq);
@@ -666,15 +667,15 @@ static int alsa_open (int in, struct alsa_params_req *req,
     *handlep = handle;
 
     if (conf.verbose &&
-        (obt->fmt != req->fmt ||
+        (obtfmt != req->fmt ||
          obt->nchannels != req->nchannels ||
          obt->freq != req->freq)) {
         dolog ("Audio parameters for %s\n", typ);
-        alsa_dump_info (req, obt);
+        alsa_dump_info (req, obt, obtfmt);
     }
 
 #ifdef DEBUG
-    alsa_dump_info (req, obt);
+    alsa_dump_info (req, obt, obtfmt);
 #endif
     return 0;
 
commit 470e63633f371611c1a03ffe4229eadccfbe013b
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Mon Apr 12 11:58:59 2010 +0900

    pci: fix pci_find_bus().
    
    When looking down child bus, it should look parent bridge's
    bus number, not child bus's.
    Optimized tail recursion and style fix.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Cc: "Michael S. Tsirkin" <mst at redhat.com>
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pci.c b/hw/pci.c
index b6abd67..f167436 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1546,23 +1546,30 @@ static void pci_bridge_write_config(PCIDevice *d,
 
 PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
 {
-    PCIBus *sec, *ret;
+    PCIBus *sec;
 
-    if (!bus)
+    if (!bus) {
         return NULL;
+    }
 
     if (pci_bus_num(bus) == bus_num) {
         return bus;
     }
 
     /* try child bus */
-    QLIST_FOREACH(sec, &bus->child, sibling) {
-        if (!bus->parent_dev /* pci host bridge */
-            || (pci_bus_num(sec) <= bus_num &&
-                bus_num <= bus->parent_dev->config[PCI_SUBORDINATE_BUS]) ) {
-            ret = pci_find_bus(sec, bus_num);
-            if (ret) {
-                return ret;
+    if (!bus->parent_dev /* host pci bridge */ ||
+        (bus->parent_dev->config[PCI_SECONDARY_BUS] < bus_num &&
+         bus_num <= bus->parent_dev->config[PCI_SUBORDINATE_BUS])) {
+        for (; bus; bus = sec) {
+            QLIST_FOREACH(sec, &bus->child, sibling) {
+                assert(sec->parent_dev);
+                if (sec->parent_dev->config[PCI_SECONDARY_BUS] == bus_num) {
+                    return sec;
+                }
+                if (sec->parent_dev->config[PCI_SECONDARY_BUS] < bus_num &&
+                    bus_num <= sec->parent_dev->config[PCI_SUBORDINATE_BUS]) {
+                    break;
+                }
             }
         }
     }
commit ab07b980c442b4f94f8fe9c236d7702c19bf2c74
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Tue Apr 13 09:16:55 2010 +0300

    slirp: fix structure initialization in tcp_listen()
    
    A data structure of type sockaddr_in is allocated from stack but not
    properly initialized. This may lead to a failure in the bind() call
    later on. Fixed by filling the contents of the structure with zeroes
    before using it.
    
    Signed-off-by: Juha Riihimäki <juha.riihimaki at nokia.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/slirp/socket.c b/slirp/socket.c
index 8a257ac..eaad77a 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -587,6 +587,7 @@ tcp_listen(Slirp *slirp, u_int32_t haddr, u_int hport, u_int32_t laddr,
 	struct socket *so;
 	int s, opt = 1;
 	socklen_t addrlen = sizeof(addr);
+	memset(&addr, 0, addrlen);
 
 	DEBUG_CALL("tcp_listen");
 	DEBUG_ARG("haddr = %x", haddr);
commit d3538b45ea88e82d1b01959b4ca55d3696b71cb2
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Mon Apr 19 19:47:49 2010 +0000

    Compile event_notifier only once
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index ea97a03..2a87e2c 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -104,7 +104,7 @@ common-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
 common-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
 common-obj-$(CONFIG_COCOA) += cocoa.o
 common-obj-$(CONFIG_IOTHREAD) += qemu-thread.o
-common-obj-y += notify.o
+common-obj-y += notify.o event_notifier.o
 common-obj-y += qemu-timer.o
 
 slirp-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o
diff --git a/Makefile.target b/Makefile.target
index 3bd4b86..5897051 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -167,7 +167,6 @@ obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o
 # need to fix this properly
 obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
 obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
-obj-y += event_notifier.o
 obj-y += vhost_net.o
 obj-$(CONFIG_VHOST_NET) += vhost.o
 obj-y += rwhandler.o
commit 04c9a0cbc2bf496889cef6da2d61bf00ef190a4f
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Mon Apr 19 19:46:13 2010 +0000

    Compile vl.c once
    
    Since kvm.h can be used in files compiled once,
    we can partially revert
    b33612d03540fda7fa67485f1c20395beb7a2bf0.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index f4d2faf..ea97a03 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -128,7 +128,7 @@ user-obj-y += cutils.o cache-utils.o
 # libhw
 
 hw-obj-y =
-hw-obj-y += loader.o
+hw-obj-y += vl.o loader.o
 hw-obj-y += virtio.o virtio-console.o
 hw-obj-y += fw_cfg.o pci.o pci_host.o pcie_host.o
 hw-obj-y += watchdog.o
diff --git a/Makefile.target b/Makefile.target
index 34ceed6..3bd4b86 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -162,7 +162,7 @@ endif #CONFIG_BSD_USER
 # System emulator target
 ifdef CONFIG_SOFTMMU
 
-obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o vl.o balloon.o
+obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
 obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
commit 98c8573eb37bf5d7bb0c07225985a78537c73101
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Apr 19 18:59:30 2010 +0000

    provide a stub version of kvm-all.c if !CONFIG_KVM
    
    This allows limited use of kvm functions (which will return ENOSYS)
    even in once-compiled modules.  The patch also improves a bit the error
    messages for KVM initialization.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    [blauwirbel at gmail.com: fixed Win32 build]
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 95c9d23..34ceed6 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -1,6 +1,7 @@
 # -*- Mode: makefile -*-
 
 GENERATED_HEADERS = config-target.h
+CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
 
 include ../config-host.mak
 include config-devices.mak
@@ -171,6 +172,7 @@ obj-y += vhost_net.o
 obj-$(CONFIG_VHOST_NET) += vhost.o
 obj-y += rwhandler.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
+obj-$(CONFIG_NO_KVM) += kvm-stub.o
 LIBS+=-lz
 
 QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
diff --git a/kvm-all.c b/kvm-all.c
index 065fd6a..2ede4b9 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1157,9 +1157,9 @@ int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset)
     return r;
 }
 
-#ifdef KVM_IOEVENTFD
 int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
 {
+#ifdef KVM_IOEVENTFD
     struct kvm_ioeventfd kick = {
         .datamatch = val,
         .addr = addr,
@@ -1176,5 +1176,7 @@ int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
     if (r < 0)
         return r;
     return 0;
-}
+#else
+    return -ENOSYS;
 #endif
+}
diff --git a/kvm-stub.c b/kvm-stub.c
new file mode 100644
index 0000000..7be5f5d
--- /dev/null
+++ b/kvm-stub.c
@@ -0,0 +1,137 @@
+/*
+ * QEMU KVM stub
+ *
+ * Copyright Red Hat, Inc. 2010
+ *
+ * Author: Paolo Bonzini     <pbonzini at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "sysemu.h"
+#include "hw/hw.h"
+#include "gdbstub.h"
+#include "kvm.h"
+
+int kvm_irqchip_in_kernel(void)
+{
+    return 0;
+}
+
+int kvm_pit_in_kernel(void)
+{
+    return 0;
+}
+
+
+int kvm_init_vcpu(CPUState *env)
+{
+    return -ENOSYS;
+}
+
+int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size)
+{
+    return -ENOSYS;
+}
+
+int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size)
+{
+    return -ENOSYS;
+}
+
+int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
+{
+    return -ENOSYS;
+}
+
+int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
+{
+    return -ENOSYS;
+}
+
+int kvm_check_extension(KVMState *s, unsigned int extension)
+{
+    return 0;
+}
+
+int kvm_init(int smp_cpus)
+{
+    return -ENOSYS;
+}
+
+void kvm_flush_coalesced_mmio_buffer(void)
+{
+}
+
+void kvm_cpu_synchronize_state(CPUState *env)
+{
+}
+
+void kvm_cpu_synchronize_post_reset(CPUState *env)
+{
+}
+
+void kvm_cpu_synchronize_post_init(CPUState *env)
+{
+}
+
+int kvm_cpu_exec(CPUState *env)
+{
+    abort ();
+}
+
+int kvm_has_sync_mmu(void)
+{
+    return 0;
+}
+
+int kvm_has_vcpu_events(void)
+{
+    return 0;
+}
+
+int kvm_has_robust_singlestep(void)
+{
+    return 0;
+}
+
+void kvm_setup_guest_memory(void *start, size_t size)
+{
+}
+
+int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
+{
+    tb_flush(env);
+    return 0;
+}
+
+int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
+                          target_ulong len, int type)
+{
+    return -EINVAL;
+}
+
+int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
+                          target_ulong len, int type)
+{
+    return -EINVAL;
+}
+
+void kvm_remove_all_breakpoints(CPUState *current_env)
+{
+}
+
+#ifndef _WIN32
+int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset)
+{
+    abort();
+}
+#endif
+
+int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
+{
+    return -ENOSYS;
+}
diff --git a/kvm.h b/kvm.h
index b90c67a..ae87d85 100644
--- a/kvm.h
+++ b/kvm.h
@@ -23,8 +23,9 @@
 #include <linux/kvm.h>
 #endif
 
-#ifdef CONFIG_KVM
 extern int kvm_allowed;
+
+#if defined CONFIG_KVM || !defined NEED_CPU_H
 #define kvm_enabled() (kvm_allowed)
 #else
 #define kvm_enabled() (0)
@@ -167,15 +168,7 @@ static inline void cpu_synchronize_post_init(CPUState *env)
     }
 }
 
-#if defined(KVM_IOEVENTFD) && defined(CONFIG_KVM)
-int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign);
-#else
-static inline
-int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign)
-{
-    return -ENOSYS;
-}
 #endif
 
-#endif
+int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign);
 #endif
diff --git a/vl.c b/vl.c
index 2f6c167..e58441b 100644
--- a/vl.c
+++ b/vl.c
@@ -3157,10 +3157,6 @@ int main(int argc, char **argv, char **envp)
                 do_smbios_option(optarg);
                 break;
             case QEMU_OPTION_enable_kvm:
-                if (!(kvm_available())) {
-                    printf("Option %s not supported for this target\n", popt->name);
-                    exit(1);
-                }
                 kvm_allowed = 1;
                 break;
             case QEMU_OPTION_usb:
@@ -3506,12 +3502,14 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
-    if (kvm_enabled()) {
-        int ret;
-
-        ret = kvm_init(smp_cpus);
+    if (kvm_allowed) {
+        int ret = kvm_init(smp_cpus);
         if (ret < 0) {
-            fprintf(stderr, "failed to initialize KVM\n");
+            if (!kvm_available()) {
+                printf("KVM not supported for this target\n");
+            } else {
+                fprintf(stderr, "failed to initialize KVM: %s\n", strerror(-ret));
+            }
             exit(1);
         }
     }
commit c66b5c2cb6bf5ab9869bf0739ff3cdf143ab778c
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: don't try to load constants using pc
    
    There is statistically almost 0 chances to use this code, so
    remove it.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index c07d284..2937c5a 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -396,19 +396,12 @@ static inline void tcg_out_dat_imm(TCGContext *s,
 static inline void tcg_out_movi32(TCGContext *s,
                 int cond, int rd, int32_t arg)
 {
-    int offset = (uint32_t) arg - ((uint32_t) s->code_ptr + 8);
-
     /* TODO: This is very suboptimal, we can easily have a constant
      * pool somewhere after all the instructions.  */
 
     if (arg < 0 && arg > -0x100)
         return tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0, (~arg) & 0xff);
 
-    if (offset < 0x100 && offset > -0x100)
-        return offset >= 0 ?
-                tcg_out_dat_imm(s, cond, ARITH_ADD, rd, 15, offset) :
-                tcg_out_dat_imm(s, cond, ARITH_SUB, rd, 15, -offset);
-
     if (use_armv7_instructions) {
         /* use movw/movt */
         /* movw */
commit 914ccf51b07af860021863e0f8e46eac9ffbcb68
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: optimize register allocation order
    
    The beginning of the register allocation order list on the TCG arm
    target matches the list of clobbered registers. This means that when an
    helper is called, there is almost always clobbered registers that have
    to be spilled.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index a60637e..c07d284 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -89,10 +89,6 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 #endif
 
 static const int tcg_target_reg_alloc_order[] = {
-    TCG_REG_R0,
-    TCG_REG_R1,
-    TCG_REG_R2,
-    TCG_REG_R3,
     TCG_REG_R4,
     TCG_REG_R5,
     TCG_REG_R6,
@@ -101,8 +97,12 @@ static const int tcg_target_reg_alloc_order[] = {
     TCG_REG_R9,
     TCG_REG_R10,
     TCG_REG_R11,
-    TCG_REG_R12,
     TCG_REG_R13,
+    TCG_REG_R0,
+    TCG_REG_R1,
+    TCG_REG_R2,
+    TCG_REG_R3,
+    TCG_REG_R12,
     TCG_REG_R14,
 };
 
commit bf5675efe33888fe058210be98259a34faf4d4e5
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: fix argument alignment in qemu_st64
    
    64-bit arguments should be aligned on an even register as specified
    by the "Procedure Call Standard for the ARM Architecture".
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 58e83c5..a60637e 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1273,13 +1273,16 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
         break;
     case 3:
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                        TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(0));
-        if (data_reg2 != TCG_REG_R2) {
+        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R8, 0, mem_index);
+        tcg_out32(s, (COND_AL << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */
+        if (data_reg != TCG_REG_R2) {
             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                            TCG_REG_R2, 0, data_reg2, SHIFT_IMM_LSL(0));
+                            TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
+        }
+        if (data_reg2 != TCG_REG_R3) {
+            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                            TCG_REG_R3, 0, data_reg2, SHIFT_IMM_LSL(0));
         }
-        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
         break;
     }
 # else
@@ -1318,10 +1321,8 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
 
     tcg_out_bl(s, COND_AL, (tcg_target_long) qemu_st_helpers[s_bits] -
                     (tcg_target_long) s->code_ptr);
-# if TARGET_LONG_BITS == 64
     if (opc == 3)
         tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
-# endif
 
     *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
 #else /* !CONFIG_SOFTMMU */
@@ -1727,7 +1728,7 @@ static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_qemu_st8, { "s", "s" } },
     { INDEX_op_qemu_st16, { "s", "s" } },
     { INDEX_op_qemu_st32, { "s", "s" } },
-    { INDEX_op_qemu_st64, { "s", "S", "s" } },
+    { INDEX_op_qemu_st64, { "S", "S", "s" } },
 #else
     { INDEX_op_qemu_ld8u, { "r", "l", "l" } },
     { INDEX_op_qemu_ld8s, { "r", "l", "l" } },
@@ -1739,7 +1740,7 @@ static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_qemu_st8, { "s", "s", "s" } },
     { INDEX_op_qemu_st16, { "s", "s", "s" } },
     { INDEX_op_qemu_st32, { "s", "s", "s" } },
-    { INDEX_op_qemu_st64, { "s", "S", "s", "s" } },
+    { INDEX_op_qemu_st64, { "S", "S", "s", "s" } },
 #endif
 
     { INDEX_op_bswap16_i32, { "r", "r" } },
commit 2633a2d015b0ba57432f1e11970cc080eb5119a3
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: remove useless register tests in qemu_ld/st
    
    addr_reg, data_reg and data_reg2 can't be register r0 or r1 du to the
    constraints. Don't check if they equals these registers.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 361cebb..58e83c5 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1048,10 +1048,8 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 # if TARGET_LONG_BITS == 32
     tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R1, 0, mem_index);
 # else
-    if (addr_reg2 != TCG_REG_R1) {
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                        TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
-    }
+    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                    TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
     tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
 # endif
     tcg_out_bl(s, COND_AL, (tcg_target_long) qemu_ld_helpers[s_bits] -
@@ -1257,10 +1255,8 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
     tcg_out_b(s, COND_EQ, 8);
 
     /* TODO: move this code to where the constants pool will be */
-    if (addr_reg != TCG_REG_R0) {
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                        TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0));
-    }
+    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                    TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0));
 # if TARGET_LONG_BITS == 32
     switch (opc) {
     case 0:
@@ -1272,17 +1268,13 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
         break;
     case 2:
-        if (data_reg != TCG_REG_R1) {
-            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                            TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(0));
-        }
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                        TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(0));
         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
         break;
     case 3:
-        if (data_reg != TCG_REG_R1) {
-            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                            TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(0));
-        }
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                        TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(0));
         if (data_reg2 != TCG_REG_R2) {
             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                             TCG_REG_R2, 0, data_reg2, SHIFT_IMM_LSL(0));
@@ -1291,10 +1283,8 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
         break;
     }
 # else
-    if (addr_reg2 != TCG_REG_R1) {
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                        TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
-    }
+    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                    TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
     switch (opc) {
     case 0:
         tcg_out_ext8u(s, COND_AL, TCG_REG_R2, data_reg);
commit 67dcab7327bb7fe02912734bf774ca44d84b41a1
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: bswap arguments in qemu_ld/st if needed
    
    On big endian targets, data arguments of qemu_ld/st ops have to be
    byte swapped. Two temporary registers are needed for qemu_st to do
    the bswap. r0 and r1 are used in system mode, do the same in user
    mode, which implies reworking the constraints.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index d019ca7..361cebb 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -151,57 +151,55 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
          break;
 
     case 'r':
-#ifndef CONFIG_SOFTMMU
-    case 'd':
-    case 'D':
-    case 'x':
-    case 'X':
-#endif
         ct->ct |= TCG_CT_REG;
         tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
         break;
 
-#ifdef CONFIG_SOFTMMU
-    /* qemu_ld/st inputs (unless 'X', 'd' or 'D') */
-    case 'x':
+    /* qemu_ld address */
+    case 'l':
         ct->ct |= TCG_CT_REG;
         tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
+#ifdef CONFIG_SOFTMMU
+        /* r0 and r1 will be overwritten when reading the tlb entry,
+           so don't use these. */
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
+#endif
         break;
-
-    /* qemu_ld64 data_reg */
-    case 'd':
+    case 'L':
         ct->ct |= TCG_CT_REG;
         tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
-        /* r1 is still needed to load data_reg2, so don't use it.  */
+#ifdef CONFIG_SOFTMMU
+        /* r1 is still needed to load data_reg or data_reg2,
+           so don't use it. */
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
+#endif
         break;
 
-    /* qemu_ld/st64 data_reg2 */
-    case 'D':
+    /* qemu_st address & data_reg */
+    case 's':
         ct->ct |= TCG_CT_REG;
         tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
-        /* r0, r1 and optionally r2 will be overwritten by the address
-         * and the low word of data, so don't use these.  */
+        /* r0 and r1 will be overwritten when reading the tlb entry
+           (softmmu only) and doing the byte swapping, so don't
+           use these. */
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
-# if TARGET_LONG_BITS == 64
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
-# endif
         break;
-
-# if TARGET_LONG_BITS == 64
-    /* qemu_ld/st addr_reg2 */
-    case 'X':
+    /* qemu_st64 data_reg2 */
+    case 'S':
         ct->ct |= TCG_CT_REG;
         tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
-        /* r0 will be overwritten by the low word of base, so don't use it.  */
+        /* r0 and r1 will be overwritten when reading the tlb entry
+            (softmmu only) and doing the byte swapping, so don't
+            use these. */
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
-        break;
-# endif
+#ifdef CONFIG_SOFTMMU
+        /* r2 is still needed to load data_reg, so don't use it. */
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
 #endif
+        break;
 
     default:
         return -1;
@@ -533,6 +531,21 @@ static inline void tcg_out_ext16u(TCGContext *s, int cond,
     }
 }
 
+static inline void tcg_out_bswap16s(TCGContext *s, int cond, int rd, int rn)
+{
+    if (use_armv6_instructions) {
+        /* revsh */
+        tcg_out32(s, 0x06ff0fb0 | (cond << 28) | (rd << 12) | rn);
+    } else {
+        tcg_out_dat_reg(s, cond, ARITH_MOV,
+                        TCG_REG_R8, 0, rn, SHIFT_IMM_LSL(24));
+        tcg_out_dat_reg(s, cond, ARITH_MOV,
+                        TCG_REG_R8, 0, TCG_REG_R8, SHIFT_IMM_ASR(16));
+        tcg_out_dat_reg(s, cond, ARITH_ORR,
+                        rd, TCG_REG_R8, rn, SHIFT_IMM_LSR(8));
+    }
+}
+
 static inline void tcg_out_bswap16(TCGContext *s, int cond, int rd, int rn)
 {
     if (use_armv6_instructions) {
@@ -912,7 +925,7 @@ static void *qemu_st_helpers[4] = {
 
 static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 {
-    int addr_reg, data_reg, data_reg2;
+    int addr_reg, data_reg, data_reg2, bswap;
 #ifdef CONFIG_SOFTMMU
     int mem_index, s_bits;
 # if TARGET_LONG_BITS == 64
@@ -921,6 +934,11 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     uint32_t *label_ptr;
 #endif
 
+#ifdef TARGET_WORDS_BIGENDIAN
+    bswap = 1;
+#else
+    bswap = 0;
+#endif
     data_reg = *args++;
     if (opc == 3)
         data_reg2 = *args++;
@@ -987,17 +1005,35 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
         break;
     case 1:
         tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+        if (bswap) {
+            tcg_out_bswap16(s, COND_EQ, data_reg, data_reg);
+        }
         break;
     case 1 | 4:
-        tcg_out_ld16s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+        if (bswap) {
+            tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+            tcg_out_bswap16s(s, COND_EQ, data_reg, data_reg);
+        } else {
+            tcg_out_ld16s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+        }
         break;
     case 2:
     default:
         tcg_out_ld32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+        if (bswap) {
+            tcg_out_bswap32(s, COND_EQ, data_reg, data_reg);
+        }
         break;
     case 3:
-        tcg_out_ld32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
-        tcg_out_ld32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
+        if (bswap) {
+            tcg_out_ld32_rwb(s, COND_EQ, data_reg2, TCG_REG_R1, addr_reg);
+            tcg_out_ld32_12(s, COND_EQ, data_reg, TCG_REG_R1, 4);
+            tcg_out_bswap32(s, COND_EQ, data_reg2, data_reg2);
+            tcg_out_bswap32(s, COND_EQ, data_reg, data_reg);
+        } else {
+            tcg_out_ld32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
+            tcg_out_ld32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
+        }
         break;
     }
 
@@ -1075,23 +1111,38 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
         break;
     case 1:
         tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
+        if (bswap) {
+            tcg_out_bswap16(s, COND_AL, data_reg, data_reg);
+        }
         break;
     case 1 | 4:
-        tcg_out_ld16s_8(s, COND_AL, data_reg, addr_reg, 0);
+        if (bswap) {
+            tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
+            tcg_out_bswap16s(s, COND_AL, data_reg, data_reg);
+        } else {
+            tcg_out_ld16s_8(s, COND_AL, data_reg, addr_reg, 0);
+        }
         break;
     case 2:
     default:
         tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
+        if (bswap) {
+            tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
+        }
         break;
     case 3:
         /* TODO: use block load -
          * check that data_reg2 > data_reg or the other way */
         if (data_reg == addr_reg) {
-            tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, 4);
-            tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
+            tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
+            tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
         } else {
-            tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
-            tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, 4);
+            tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
+            tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
+        }
+        if (bswap) {
+            tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
+            tcg_out_bswap32(s, COND_AL, data_reg2, data_reg2);
         }
         break;
     }
@@ -1100,7 +1151,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 
 static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
 {
-    int addr_reg, data_reg, data_reg2;
+    int addr_reg, data_reg, data_reg2, bswap;
 #ifdef CONFIG_SOFTMMU
     int mem_index, s_bits;
 # if TARGET_LONG_BITS == 64
@@ -1109,6 +1160,11 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
     uint32_t *label_ptr;
 #endif
 
+#ifdef TARGET_WORDS_BIGENDIAN
+    bswap = 1;
+#else
+    bswap = 0;
+#endif
     data_reg = *args++;
     if (opc == 3)
         data_reg2 = *args++;
@@ -1168,15 +1224,32 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
         tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
         break;
     case 1:
-        tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+        if (bswap) {
+            tcg_out_bswap16(s, COND_EQ, TCG_REG_R0, data_reg);
+            tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
+        } else {
+            tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+        }
         break;
     case 2:
     default:
-        tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+        if (bswap) {
+            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
+            tcg_out_st32_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
+        } else {
+            tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+        }
         break;
     case 3:
-        tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
-        tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
+        if (bswap) {
+            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2);
+            tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, addr_reg);
+            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
+            tcg_out_st32_12(s, COND_EQ, data_reg, TCG_REG_R1, 4);
+        } else {
+            tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
+            tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
+        }
         break;
     }
 
@@ -1271,9 +1344,9 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
             i = ctz32(offset) & ~1;
             rot = ((32 - i) << 7) & 0xf00;
 
-            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R8, addr_reg,
+            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R1, addr_reg,
                             ((offset >> i) & 0xff) | rot);
-            addr_reg = TCG_REG_R8;
+            addr_reg = TCG_REG_R1;
             offset &= ~(0xff << i);
         }
     }
@@ -1282,17 +1355,34 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
         tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0);
         break;
     case 1:
-        tcg_out_st16_8(s, COND_AL, data_reg, addr_reg, 0);
+        if (bswap) {
+            tcg_out_bswap16(s, COND_AL, TCG_REG_R0, data_reg);
+            tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addr_reg, 0);
+        } else {
+            tcg_out_st16_8(s, COND_AL, data_reg, addr_reg, 0);
+        }
         break;
     case 2:
     default:
-        tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
+        if (bswap) {
+            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
+            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
+        } else {
+            tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
+        }
         break;
     case 3:
         /* TODO: use block store -
          * check that data_reg2 > data_reg or the other way */
-        tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
-        tcg_out_st32_12(s, COND_AL, data_reg2, addr_reg, 4);
+        if (bswap) {
+            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg2);
+            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
+            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
+            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 4);
+        } else {
+            tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
+            tcg_out_st32_12(s, COND_AL, data_reg2, addr_reg, 4);
+        }
         break;
     }
 #endif
@@ -1637,29 +1727,29 @@ static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_setcond2_i32, { "r", "r", "r", "r", "r" } },
 
 #if TARGET_LONG_BITS == 32
-    { INDEX_op_qemu_ld8u, { "r", "x" } },
-    { INDEX_op_qemu_ld8s, { "r", "x" } },
-    { INDEX_op_qemu_ld16u, { "r", "x" } },
-    { INDEX_op_qemu_ld16s, { "r", "x" } },
-    { INDEX_op_qemu_ld32, { "r", "x" } },
-    { INDEX_op_qemu_ld64, { "d", "r", "x" } },
-
-    { INDEX_op_qemu_st8, { "x", "x" } },
-    { INDEX_op_qemu_st16, { "x", "x" } },
-    { INDEX_op_qemu_st32, { "x", "x" } },
-    { INDEX_op_qemu_st64, { "x", "D", "x" } },
+    { 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, { "L", "L", "l" } },
+
+    { INDEX_op_qemu_st8, { "s", "s" } },
+    { INDEX_op_qemu_st16, { "s", "s" } },
+    { INDEX_op_qemu_st32, { "s", "s" } },
+    { INDEX_op_qemu_st64, { "s", "S", "s" } },
 #else
-    { INDEX_op_qemu_ld8u, { "r", "x", "X" } },
-    { INDEX_op_qemu_ld8s, { "r", "x", "X" } },
-    { INDEX_op_qemu_ld16u, { "r", "x", "X" } },
-    { INDEX_op_qemu_ld16s, { "r", "x", "X" } },
-    { INDEX_op_qemu_ld32, { "r", "x", "X" } },
-    { INDEX_op_qemu_ld64, { "d", "r", "x", "X" } },
-
-    { INDEX_op_qemu_st8, { "x", "x", "X" } },
-    { INDEX_op_qemu_st16, { "x", "x", "X" } },
-    { INDEX_op_qemu_st32, { "x", "x", "X" } },
-    { INDEX_op_qemu_st64, { "x", "D", "x", "X" } },
+    { 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, { "L", "L", "l", "l" } },
+
+    { INDEX_op_qemu_st8, { "s", "s", "s" } },
+    { INDEX_op_qemu_st16, { "s", "s", "s" } },
+    { INDEX_op_qemu_st32, { "s", "s", "s" } },
+    { INDEX_op_qemu_st64, { "s", "S", "s", "s" } },
 #endif
 
     { INDEX_op_bswap16_i32, { "r", "r" } },
commit e854b6d39c879bf36c1cf42f1dbfa0da89b06e75
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: use ext* ops in qemu_ld
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 13fdbb8..d019ca7 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -499,6 +499,12 @@ static inline void tcg_out_ext8s(TCGContext *s, int cond,
     }
 }
 
+static inline void tcg_out_ext8u(TCGContext *s, int cond,
+                                 int rd, int rn)
+{
+    tcg_out_dat_imm(s, cond, ARITH_AND, rd, rn, 0xff);
+}
+
 static inline void tcg_out_ext16s(TCGContext *s, int cond,
                                   int rd, int rn)
 {
@@ -1017,16 +1023,10 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 
     switch (opc) {
     case 0 | 4:
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                        TCG_REG_R0, 0, TCG_REG_R0, SHIFT_IMM_LSL(24));
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                        data_reg, 0, TCG_REG_R0, SHIFT_IMM_ASR(24));
+        tcg_out_ext8s(s, COND_AL, data_reg, TCG_REG_R0);
         break;
     case 1 | 4:
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                        TCG_REG_R0, 0, TCG_REG_R0, SHIFT_IMM_LSL(16));
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                        data_reg, 0, TCG_REG_R0, SHIFT_IMM_ASR(16));
+        tcg_out_ext16s(s, COND_AL, data_reg, TCG_REG_R0);
         break;
     case 0:
     case 1:
@@ -1191,14 +1191,11 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
 # if TARGET_LONG_BITS == 32
     switch (opc) {
     case 0:
-        tcg_out_dat_imm(s, COND_AL, ARITH_AND, TCG_REG_R1, data_reg, 0xff);
+        tcg_out_ext8u(s, COND_AL, TCG_REG_R1, data_reg);
         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
         break;
     case 1:
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                        TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(16));
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                        TCG_REG_R1, 0, TCG_REG_R1, SHIFT_IMM_LSR(16));
+        tcg_out_ext16u(s, COND_AL, TCG_REG_R1, data_reg);
         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
         break;
     case 2:
@@ -1227,14 +1224,11 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
     }
     switch (opc) {
     case 0:
-        tcg_out_dat_imm(s, COND_AL, ARITH_AND, TCG_REG_R2, data_reg, 0xff);
+        tcg_out_ext8u(s, COND_AL, TCG_REG_R2, data_reg);
         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
         break;
     case 1:
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                        TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(16));
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                        TCG_REG_R2, 0, TCG_REG_R2, SHIFT_IMM_LSR(16));
+        tcg_out_ext16u(s, COND_AL, TCG_REG_R2, data_reg);
         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
         break;
     case 2:
commit 7e0d95628d358dd3696ec69351e332347d80f0dd
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: remove conditional argument for qemu_ld/st
    
    While it make sense to pass a conditional argument to tcg_out_*()
    functions as the ARM architecture allows that, it doesn't make sense
    for qemu_ld/st functions. These functions use comparison instructions
    and conditional execution already, so it is not possible to use a
    second level of conditional execution.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 5bef306..13fdbb8 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -904,8 +904,7 @@ static void *qemu_st_helpers[4] = {
 
 #define TLB_SHIFT	(CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
 
-static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
-                const TCGArg *args, int opc)
+static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 {
     int addr_reg, data_reg, data_reg2;
 #ifdef CONFIG_SOFTMMU
@@ -1001,32 +1000,32 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
 
     /* TODO: move this code to where the constants pool will be */
     if (addr_reg != TCG_REG_R0) {
-        tcg_out_dat_reg(s, cond, ARITH_MOV,
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                         TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0));
     }
 # if TARGET_LONG_BITS == 32
-    tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R1, 0, mem_index);
+    tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R1, 0, mem_index);
 # else
     if (addr_reg2 != TCG_REG_R1) {
-        tcg_out_dat_reg(s, cond, ARITH_MOV,
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                         TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
     }
-    tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R2, 0, mem_index);
+    tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
 # endif
-    tcg_out_bl(s, cond, (tcg_target_long) qemu_ld_helpers[s_bits] -
+    tcg_out_bl(s, COND_AL, (tcg_target_long) qemu_ld_helpers[s_bits] -
                     (tcg_target_long) s->code_ptr);
 
     switch (opc) {
     case 0 | 4:
-        tcg_out_dat_reg(s, cond, ARITH_MOV,
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                         TCG_REG_R0, 0, TCG_REG_R0, SHIFT_IMM_LSL(24));
-        tcg_out_dat_reg(s, cond, ARITH_MOV,
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                         data_reg, 0, TCG_REG_R0, SHIFT_IMM_ASR(24));
         break;
     case 1 | 4:
-        tcg_out_dat_reg(s, cond, ARITH_MOV,
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                         TCG_REG_R0, 0, TCG_REG_R0, SHIFT_IMM_LSL(16));
-        tcg_out_dat_reg(s, cond, ARITH_MOV,
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                         data_reg, 0, TCG_REG_R0, SHIFT_IMM_ASR(16));
         break;
     case 0:
@@ -1034,17 +1033,17 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
     case 2:
     default:
         if (data_reg != TCG_REG_R0) {
-            tcg_out_dat_reg(s, cond, ARITH_MOV,
+            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                             data_reg, 0, TCG_REG_R0, SHIFT_IMM_LSL(0));
         }
         break;
     case 3:
         if (data_reg != TCG_REG_R0) {
-            tcg_out_dat_reg(s, cond, ARITH_MOV,
+            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                             data_reg, 0, TCG_REG_R0, SHIFT_IMM_LSL(0));
         }
         if (data_reg2 != TCG_REG_R1) {
-            tcg_out_dat_reg(s, cond, ARITH_MOV,
+            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                             data_reg2, 0, TCG_REG_R1, SHIFT_IMM_LSL(0));
         }
         break;
@@ -1099,8 +1098,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
 #endif
 }
 
-static inline void tcg_out_qemu_st(TCGContext *s, int cond,
-                const TCGArg *args, int opc)
+static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
 {
     int addr_reg, data_reg, data_reg2;
 #ifdef CONFIG_SOFTMMU
@@ -1187,85 +1185,85 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
 
     /* TODO: move this code to where the constants pool will be */
     if (addr_reg != TCG_REG_R0) {
-        tcg_out_dat_reg(s, cond, ARITH_MOV,
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                         TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0));
     }
 # if TARGET_LONG_BITS == 32
     switch (opc) {
     case 0:
-        tcg_out_dat_imm(s, cond, ARITH_AND, TCG_REG_R1, data_reg, 0xff);
-        tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R2, 0, mem_index);
+        tcg_out_dat_imm(s, COND_AL, ARITH_AND, TCG_REG_R1, data_reg, 0xff);
+        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
         break;
     case 1:
-        tcg_out_dat_reg(s, cond, ARITH_MOV,
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                         TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(16));
-        tcg_out_dat_reg(s, cond, ARITH_MOV,
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                         TCG_REG_R1, 0, TCG_REG_R1, SHIFT_IMM_LSR(16));
-        tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R2, 0, mem_index);
+        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
         break;
     case 2:
         if (data_reg != TCG_REG_R1) {
-            tcg_out_dat_reg(s, cond, ARITH_MOV,
+            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                             TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(0));
         }
-        tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R2, 0, mem_index);
+        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
         break;
     case 3:
         if (data_reg != TCG_REG_R1) {
-            tcg_out_dat_reg(s, cond, ARITH_MOV,
+            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                             TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(0));
         }
         if (data_reg2 != TCG_REG_R2) {
-            tcg_out_dat_reg(s, cond, ARITH_MOV,
+            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                             TCG_REG_R2, 0, data_reg2, SHIFT_IMM_LSL(0));
         }
-        tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R3, 0, mem_index);
+        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
         break;
     }
 # else
     if (addr_reg2 != TCG_REG_R1) {
-        tcg_out_dat_reg(s, cond, ARITH_MOV,
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                         TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
     }
     switch (opc) {
     case 0:
-        tcg_out_dat_imm(s, cond, ARITH_AND, TCG_REG_R2, data_reg, 0xff);
-        tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R3, 0, mem_index);
+        tcg_out_dat_imm(s, COND_AL, ARITH_AND, TCG_REG_R2, data_reg, 0xff);
+        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
         break;
     case 1:
-        tcg_out_dat_reg(s, cond, ARITH_MOV,
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                         TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(16));
-        tcg_out_dat_reg(s, cond, ARITH_MOV,
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                         TCG_REG_R2, 0, TCG_REG_R2, SHIFT_IMM_LSR(16));
-        tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R3, 0, mem_index);
+        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
         break;
     case 2:
         if (data_reg != TCG_REG_R2) {
-            tcg_out_dat_reg(s, cond, ARITH_MOV,
+            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                             TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
         }
-        tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R3, 0, mem_index);
+        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
         break;
     case 3:
-        tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R8, 0, mem_index);
-        tcg_out32(s, (cond << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */
+        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R8, 0, mem_index);
+        tcg_out32(s, (COND_AL << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */
         if (data_reg != TCG_REG_R2) {
-            tcg_out_dat_reg(s, cond, ARITH_MOV,
+            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                             TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
         }
         if (data_reg2 != TCG_REG_R3) {
-            tcg_out_dat_reg(s, cond, ARITH_MOV,
+            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                             TCG_REG_R3, 0, data_reg2, SHIFT_IMM_LSL(0));
         }
         break;
     }
 # endif
 
-    tcg_out_bl(s, cond, (tcg_target_long) qemu_st_helpers[s_bits] -
+    tcg_out_bl(s, COND_AL, (tcg_target_long) qemu_st_helpers[s_bits] -
                     (tcg_target_long) s->code_ptr);
 # if TARGET_LONG_BITS == 64
     if (opc == 3)
-        tcg_out_dat_imm(s, cond, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
+        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
 # endif
 
     *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
@@ -1545,35 +1543,35 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
 
     case INDEX_op_qemu_ld8u:
-        tcg_out_qemu_ld(s, COND_AL, args, 0);
+        tcg_out_qemu_ld(s, args, 0);
         break;
     case INDEX_op_qemu_ld8s:
-        tcg_out_qemu_ld(s, COND_AL, args, 0 | 4);
+        tcg_out_qemu_ld(s, args, 0 | 4);
         break;
     case INDEX_op_qemu_ld16u:
-        tcg_out_qemu_ld(s, COND_AL, args, 1);
+        tcg_out_qemu_ld(s, args, 1);
         break;
     case INDEX_op_qemu_ld16s:
-        tcg_out_qemu_ld(s, COND_AL, args, 1 | 4);
+        tcg_out_qemu_ld(s, args, 1 | 4);
         break;
     case INDEX_op_qemu_ld32:
-        tcg_out_qemu_ld(s, COND_AL, args, 2);
+        tcg_out_qemu_ld(s, args, 2);
         break;
     case INDEX_op_qemu_ld64:
-        tcg_out_qemu_ld(s, COND_AL, args, 3);
+        tcg_out_qemu_ld(s, args, 3);
         break;
 
     case INDEX_op_qemu_st8:
-        tcg_out_qemu_st(s, COND_AL, args, 0);
+        tcg_out_qemu_st(s, args, 0);
         break;
     case INDEX_op_qemu_st16:
-        tcg_out_qemu_st(s, COND_AL, args, 1);
+        tcg_out_qemu_st(s, args, 1);
         break;
     case INDEX_op_qemu_st32:
-        tcg_out_qemu_st(s, COND_AL, args, 2);
+        tcg_out_qemu_st(s, args, 2);
         break;
     case INDEX_op_qemu_st64:
-        tcg_out_qemu_st(s, COND_AL, args, 3);
+        tcg_out_qemu_st(s, args, 3);
         break;
 
     case INDEX_op_bswap16_i32:
commit 244b1e81f6afc2ddc866a6dbad42ccafd10c246b
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: add bswap ops
    
    Add an bswap16 and bswap32 ops, either using the rev and rev16
    instructions on ARMv6+ or shifts and logical operations on previous
    ARM versions. In both cases the result use less instructions than
    the pure TCG version.
    
    These ops are also needed by the qemu_ld/st functions.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index efcefe2..5bef306 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -527,6 +527,38 @@ static inline void tcg_out_ext16u(TCGContext *s, int cond,
     }
 }
 
+static inline void tcg_out_bswap16(TCGContext *s, int cond, int rd, int rn)
+{
+    if (use_armv6_instructions) {
+        /* rev16 */
+        tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
+    } else {
+        tcg_out_dat_reg(s, cond, ARITH_MOV,
+                        TCG_REG_R8, 0, rn, SHIFT_IMM_LSL(24));
+        tcg_out_dat_reg(s, cond, ARITH_MOV,
+                        TCG_REG_R8, 0, TCG_REG_R8, SHIFT_IMM_LSR(16));
+        tcg_out_dat_reg(s, cond, ARITH_ORR,
+                        rd, TCG_REG_R8, rn, SHIFT_IMM_LSR(8));
+    }
+}
+
+static inline void tcg_out_bswap32(TCGContext *s, int cond, int rd, int rn)
+{
+    if (use_armv6_instructions) {
+        /* rev */
+        tcg_out32(s, 0x06bf0f30 | (cond << 28) | (rd << 12) | rn);
+    } else {
+        tcg_out_dat_reg(s, cond, ARITH_EOR,
+                        TCG_REG_R8, rn, rn, SHIFT_IMM_ROR(16));
+        tcg_out_dat_imm(s, cond, ARITH_BIC,
+                        TCG_REG_R8, TCG_REG_R8, 0xff | 0x800);
+        tcg_out_dat_reg(s, cond, ARITH_MOV,
+                        rd, 0, rn, SHIFT_IMM_ROR(8));
+        tcg_out_dat_reg(s, cond, ARITH_EOR,
+                        rd, rd, TCG_REG_R8, SHIFT_IMM_LSR(8));
+    }
+}
+
 static inline void tcg_out_ld32_12(TCGContext *s, int cond,
                 int rd, int rn, tcg_target_long im)
 {
@@ -1544,6 +1576,13 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         tcg_out_qemu_st(s, COND_AL, args, 3);
         break;
 
+    case INDEX_op_bswap16_i32:
+        tcg_out_bswap16(s, COND_AL, args[0], args[1]);
+        break;
+    case INDEX_op_bswap32_i32:
+        tcg_out_bswap32(s, COND_AL, args[0], args[1]);
+        break;
+
     case INDEX_op_ext8s_i32:
         tcg_out_ext8s(s, COND_AL, args[0], args[1]);
         break;
@@ -1631,6 +1670,9 @@ static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_qemu_st64, { "x", "D", "x", "X" } },
 #endif
 
+    { INDEX_op_bswap16_i32, { "r", "r" } },
+    { INDEX_op_bswap32_i32, { "r", "r" } },
+
     { INDEX_op_ext8s_i32, { "r", "r" } },
     { INDEX_op_ext16s_i32, { "r", "r" } },
     { INDEX_op_ext16u_i32, { "r", "r" } },
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 1f6d665..d8d7d94 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -62,8 +62,8 @@ enum {
 #define TCG_TARGET_HAS_ext16s_i32
 #undef TCG_TARGET_HAS_ext8u_i32       /* and r0, r1, #0xff */
 #define TCG_TARGET_HAS_ext16u_i32
-// #define TCG_TARGET_HAS_bswap16_i32
-// #define TCG_TARGET_HAS_bswap32_i32
+#define TCG_TARGET_HAS_bswap16_i32
+#define TCG_TARGET_HAS_bswap32_i32
 #define TCG_TARGET_HAS_not_i32
 #define TCG_TARGET_HAS_neg_i32
 #define TCG_TARGET_HAS_rot_i32
commit 9517094f720097b51854ef458ffb1971720dddfa
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: add ext16u op
    
    Add an ext16u op, either using the uxth instruction on ARMv6+ or two
    shifts on previous ARM versions. In both cases the result use the same
    number or less instructions than the pure TCG version.
    
    Also move all sign extension code to separate functions, so that they
    can be reused in other parts of the code.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 602fdf2..efcefe2 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -485,6 +485,48 @@ static inline void tcg_out_smull32(TCGContext *s,
     }
 }
 
+static inline void tcg_out_ext8s(TCGContext *s, int cond,
+                                 int rd, int rn)
+{
+    if (use_armv6_instructions) {
+        /* sxtb */
+        tcg_out32(s, 0x06af0070 | (cond << 28) | (rd << 12) | rn);
+    } else {
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                        rd, 0, rn, SHIFT_IMM_LSL(24));
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                        rd, 0, rd, SHIFT_IMM_ASR(24));
+    }
+}
+
+static inline void tcg_out_ext16s(TCGContext *s, int cond,
+                                  int rd, int rn)
+{
+    if (use_armv6_instructions) {
+        /* sxth */
+        tcg_out32(s, 0x06bf0070 | (cond << 28) | (rd << 12) | rn);
+    } else {
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                        rd, 0, rn, SHIFT_IMM_LSL(16));
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                        rd, 0, rd, SHIFT_IMM_ASR(16));
+    }
+}
+
+static inline void tcg_out_ext16u(TCGContext *s, int cond,
+                                  int rd, int rn)
+{
+    if (use_armv6_instructions) {
+        /* uxth */
+        tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | rn);
+    } else {
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                        rd, 0, rn, SHIFT_IMM_LSL(16));
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                        rd, 0, rd, SHIFT_IMM_LSR(16));
+    }
+}
+
 static inline void tcg_out_ld32_12(TCGContext *s, int cond,
                 int rd, int rn, tcg_target_long im)
 {
@@ -1503,26 +1545,13 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
 
     case INDEX_op_ext8s_i32:
-        if (use_armv6_instructions) {
-            /* sxtb */
-            tcg_out32(s, 0xe6af0070 | (args[0] << 12) | args[1]);
-        } else {
-            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                            args[0], 0, args[1], SHIFT_IMM_LSL(24));
-            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                            args[0], 0, args[0], SHIFT_IMM_ASR(24));
-        }
+        tcg_out_ext8s(s, COND_AL, args[0], args[1]);
         break;
     case INDEX_op_ext16s_i32:
-        if (use_armv6_instructions) {
-            /* sxth */
-            tcg_out32(s, 0xe6bf0070 | (args[0] << 12) | args[1]);
-        } else {
-            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                            args[0], 0, args[1], SHIFT_IMM_LSL(16));
-            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                            args[0], 0, args[0], SHIFT_IMM_ASR(16));
-        }
+        tcg_out_ext16s(s, COND_AL, args[0], args[1]);
+        break;
+    case INDEX_op_ext16u_i32:
+        tcg_out_ext16u(s, COND_AL, args[0], args[1]);
         break;
 
     default:
@@ -1604,6 +1633,7 @@ static const TCGTargetOpDef arm_op_defs[] = {
 
     { INDEX_op_ext8s_i32, { "r", "r" } },
     { INDEX_op_ext16s_i32, { "r", "r" } },
+    { INDEX_op_ext16u_i32, { "r", "r" } },
 
     { -1 },
 };
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index bc08f91..1f6d665 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -60,8 +60,8 @@ enum {
 /* optional instructions */
 #define TCG_TARGET_HAS_ext8s_i32
 #define TCG_TARGET_HAS_ext16s_i32
-// #define TCG_TARGET_HAS_ext8u_i32
-// #define TCG_TARGET_HAS_ext16u_i32
+#undef TCG_TARGET_HAS_ext8u_i32       /* and r0, r1, #0xff */
+#define TCG_TARGET_HAS_ext16u_i32
 // #define TCG_TARGET_HAS_bswap16_i32
 // #define TCG_TARGET_HAS_bswap32_i32
 #define TCG_TARGET_HAS_not_i32
commit 293579e55c40d78353ecd3e48d67f744ba579c12
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: add rotation ops
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 2eaab04..602fdf2 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1394,11 +1394,28 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
     case INDEX_op_sar_i32:
         c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ASR(args[2] & 0x1f) :
                 SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args[2]);
+        goto gen_shift32;
+    case INDEX_op_rotr_i32:
+        c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ROR(args[2] & 0x1f) :
+                SHIFT_IMM_LSL(0) : SHIFT_REG_ROR(args[2]);
         /* Fall through.  */
     gen_shift32:
         tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1], c);
         break;
 
+    case INDEX_op_rotl_i32:
+        if (const_args[2]) {
+            tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
+                            ((0x20 - args[2]) & 0x1f) ?
+                            SHIFT_IMM_ROR((0x20 - args[2]) & 0x1f) :
+                            SHIFT_IMM_LSL(0));
+        } else {
+            tcg_out_dat_imm(s, COND_AL, ARITH_RSB, TCG_REG_R8, args[1], 0x20);
+            tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
+                            SHIFT_REG_ROR(TCG_REG_R8));
+        }
+        break;
+
     case INDEX_op_brcond_i32:
         if (const_args[1]) {
             int rot;
@@ -1547,6 +1564,8 @@ static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_shl_i32, { "r", "r", "ri" } },
     { INDEX_op_shr_i32, { "r", "r", "ri" } },
     { INDEX_op_sar_i32, { "r", "r", "ri" } },
+    { INDEX_op_rotl_i32, { "r", "r", "ri" } },
+    { INDEX_op_rotr_i32, { "r", "r", "ri" } },
 
     { INDEX_op_brcond_i32, { "r", "rI" } },
     { INDEX_op_setcond_i32, { "r", "r", "rI" } },
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 334edfa..bc08f91 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -66,7 +66,7 @@ enum {
 // #define TCG_TARGET_HAS_bswap32_i32
 #define TCG_TARGET_HAS_not_i32
 #define TCG_TARGET_HAS_neg_i32
-// #define TCG_TARGET_HAS_rot_i32
+#define TCG_TARGET_HAS_rot_i32
 #define TCG_TARGET_HAS_andc_i32
 // #define TCG_TARGET_HAS_orc_i32
 // #define TCG_TARGET_HAS_eqv_i32
commit 23401b58a4a47e964b838339f718b2993bd9345a
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: use the blx instruction when possible
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index b768bdf..2eaab04 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -357,6 +357,11 @@ static inline void tcg_out_bl(TCGContext *s, int cond, int32_t offset)
                     (((offset - 8) >> 2) & 0x00ffffff));
 }
 
+static inline void tcg_out_blx(TCGContext *s, int cond, int rn)
+{
+    tcg_out32(s, (cond << 28) | 0x012fff30 | rn);
+}
+
 static inline void tcg_out_dat_reg(TCGContext *s,
                 int cond, int opc, int rd, int rn, int rm, int shift)
 {
@@ -778,10 +783,13 @@ static inline void tcg_out_call(TCGContext *s, int cond, uint32_t addr)
 
 static inline void tcg_out_callr(TCGContext *s, int cond, int arg)
 {
-    /* TODO: on ARMv5 and ARMv6 replace with tcg_out_blx(s, cond, arg);  */
-    tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
-                    TCG_REG_PC, SHIFT_IMM_LSL(0));
-    tcg_out_bx(s, cond, arg);
+    if (use_armv5_instructions) {
+        tcg_out_blx(s, cond, arg);
+    } else {
+        tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
+                        TCG_REG_PC, SHIFT_IMM_LSL(0));
+        tcg_out_bx(s, cond, arg);
+    }
 }
 
 static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
commit 8f7f749f216af458ea96573c4057f13023e3268d
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: sxtb and sxth are available starting with ARMv6
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 24526ca..b768bdf 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1478,7 +1478,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
 
     case INDEX_op_ext8s_i32:
-        if (use_armv7_instructions) {
+        if (use_armv6_instructions) {
             /* sxtb */
             tcg_out32(s, 0xe6af0070 | (args[0] << 12) | args[1]);
         } else {
@@ -1489,7 +1489,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         }
         break;
     case INDEX_op_ext16s_i32:
-        if (use_armv7_instructions) {
+        if (use_armv6_instructions) {
             /* sxth */
             tcg_out32(s, 0xe6bf0070 | (args[0] << 12) | args[1]);
         } else {
commit ac34fb5c5d46398ede6e16d4fd1fd26af8185335
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: add variables to define the allowed instructions set
    
    Use a set of variables to define the allowed ARM instructions, depending
    on the __ARM_ARCH_*__ GCC defines.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index ee5f723..24526ca 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -22,6 +22,51 @@
  * THE SOFTWARE.
  */
 
+#if defined(__ARM_ARCH_7__) ||  \
+    defined(__ARM_ARCH_7A__) || \
+    defined(__ARM_ARCH_7EM__) || \
+    defined(__ARM_ARCH_7M__) || \
+    defined(__ARM_ARCH_7R__)
+#define USE_ARMV7_INSTRUCTIONS
+#endif
+
+#if defined(USE_ARMV7_INSTRUCTIONS) || \
+    defined(__ARM_ARCH_6J__) || \
+    defined(__ARM_ARCH_6K__) || \
+    defined(__ARM_ARCH_6T2__) || \
+    defined(__ARM_ARCH_6Z__) || \
+    defined(__ARM_ARCH_6ZK__)
+#define USE_ARMV6_INSTRUCTIONS
+#endif
+
+#if defined(USE_ARMV6_INSTRUCTIONS) || \
+    defined(__ARM_ARCH_5T__) || \
+    defined(__ARM_ARCH_5TE__) || \
+    defined(__ARM_ARCH_5TEJ__)
+#define USE_ARMV5_INSTRUCTIONS
+#endif
+
+#ifdef USE_ARMV5_INSTRUCTIONS
+static const int use_armv5_instructions = 1;
+#else
+static const int use_armv5_instructions = 0;
+#endif
+#undef USE_ARMV5_INSTRUCTIONS
+
+#ifdef USE_ARMV6_INSTRUCTIONS
+static const int use_armv6_instructions = 1;
+#else
+static const int use_armv6_instructions = 0;
+#endif
+#undef USE_ARMV6_INSTRUCTIONS
+
+#ifdef USE_ARMV7_INSTRUCTIONS
+static const int use_armv7_instructions = 1;
+#else
+static const int use_armv7_instructions = 0;
+#endif
+#undef USE_ARMV7_INSTRUCTIONS
+
 #ifndef NDEBUG
 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
     "%r0",
@@ -361,27 +406,27 @@ static inline void tcg_out_movi32(TCGContext *s,
                 tcg_out_dat_imm(s, cond, ARITH_ADD, rd, 15, offset) :
                 tcg_out_dat_imm(s, cond, ARITH_SUB, rd, 15, -offset);
 
-#ifdef __ARM_ARCH_7A__
-    /* use movw/movt */
-    /* movw */
-    tcg_out32(s, (cond << 28) | 0x03000000 | (rd << 12)
-              | ((arg << 4) & 0x000f0000) | (arg & 0xfff));
-    if (arg & 0xffff0000)
-        /* movt */
-        tcg_out32(s, (cond << 28) | 0x03400000 | (rd << 12)
-                  | ((arg >> 12) & 0x000f0000) | ((arg >> 16) & 0xfff));
-#else
-    tcg_out_dat_imm(s, cond, ARITH_MOV, rd, 0, arg & 0xff);
-    if (arg & 0x0000ff00)
-        tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
-                        ((arg >>  8) & 0xff) | 0xc00);
-    if (arg & 0x00ff0000)
-        tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
-                        ((arg >> 16) & 0xff) | 0x800);
-    if (arg & 0xff000000)
-        tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
-                        ((arg >> 24) & 0xff) | 0x400);
-#endif
+    if (use_armv7_instructions) {
+        /* use movw/movt */
+        /* movw */
+        tcg_out32(s, (cond << 28) | 0x03000000 | (rd << 12)
+                  | ((arg << 4) & 0x000f0000) | (arg & 0xfff));
+        if (arg & 0xffff0000)
+            /* movt */
+            tcg_out32(s, (cond << 28) | 0x03400000 | (rd << 12)
+                      | ((arg >> 12) & 0x000f0000) | ((arg >> 16) & 0xfff));
+    } else {
+        tcg_out_dat_imm(s, cond, ARITH_MOV, rd, 0, arg & 0xff);
+        if (arg & 0x0000ff00)
+            tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
+                            ((arg >>  8) & 0xff) | 0xc00);
+        if (arg & 0x00ff0000)
+            tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
+                            ((arg >> 16) & 0xff) | 0x800);
+        if (arg & 0xff000000)
+            tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
+                            ((arg >> 24) & 0xff) | 0x400);
+        }
 }
 
 static inline void tcg_out_mul32(TCGContext *s,
@@ -1433,26 +1478,26 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
 
     case INDEX_op_ext8s_i32:
-#ifdef __ARM_ARCH_7A__
-        /* sxtb */
-        tcg_out32(s, 0xe6af0070 | (args[0] << 12) | args[1]);
-#else
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                        args[0], 0, args[1], SHIFT_IMM_LSL(24));
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                        args[0], 0, args[0], SHIFT_IMM_ASR(24));
-#endif
+        if (use_armv7_instructions) {
+            /* sxtb */
+            tcg_out32(s, 0xe6af0070 | (args[0] << 12) | args[1]);
+        } else {
+            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                            args[0], 0, args[1], SHIFT_IMM_LSL(24));
+            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                            args[0], 0, args[0], SHIFT_IMM_ASR(24));
+        }
         break;
     case INDEX_op_ext16s_i32:
-#ifdef __ARM_ARCH_7A__
-        /* sxth */
-        tcg_out32(s, 0xe6bf0070 | (args[0] << 12) | args[1]);
-#else
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                        args[0], 0, args[1], SHIFT_IMM_LSL(16));
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                        args[0], 0, args[0], SHIFT_IMM_ASR(16));
-#endif
+        if (use_armv7_instructions) {
+            /* sxth */
+            tcg_out32(s, 0xe6bf0070 | (args[0] << 12) | args[1]);
+        } else {
+            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                            args[0], 0, args[1], SHIFT_IMM_LSL(16));
+            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+                            args[0], 0, args[0], SHIFT_IMM_ASR(16));
+        }
         break;
 
     default:
commit 2488b41bb2d03c96ffdd69a0c16b585e90697951
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: align 64-bit arguments in function calls
    
    As specified by the "Procedure Call Standard for the ARM Architecture".
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index a0027b5..334edfa 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -54,6 +54,7 @@ enum {
 /* used for function call generation */
 #define TCG_REG_CALL_STACK		TCG_REG_R13
 #define TCG_TARGET_STACK_ALIGN		8
+#define TCG_TARGET_CALL_ALIGN_ARGS	1
 #define TCG_TARGET_CALL_STACK_OFFSET	0
 
 /* optional instructions */
commit c8d80cef55522ca68618d5aa3153fd4b8f053573
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: replace integer values by registers enum
    
    The TCG ARM backends uses integer values to refer to both immediate
    values and register number. This makes the code difficult to read.
    
    The patch below replaces all (if I haven't miss any ;-) integer values
    representing register number by TCG_REG_* enum values.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index e923330..ee5f723 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -397,7 +397,7 @@ static inline void tcg_out_mul32(TCGContext *s,
         tcg_out32(s, (cond << 28) | ( 8 << 16) | (0 << 12) |
                         (rs << 8) | 0x90 | rm);
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        rd, 0, 8, SHIFT_IMM_LSL(0));
+                        rd, 0, TCG_REG_R8, SHIFT_IMM_LSL(0));
     }
 }
 
@@ -694,12 +694,13 @@ static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
         tcg_abort();
 #else
         if (cond == COND_AL) {
-            tcg_out_ld32_12(s, COND_AL, 15, 15, -4);
+            tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
             tcg_out32(s, addr); /* XXX: This is l->u.value, can we use it? */
         } else {
             tcg_out_movi32(s, cond, TCG_REG_R8, val - 8);
             tcg_out_dat_reg(s, cond, ARITH_ADD,
-                            15, 15, TCG_REG_R8, SHIFT_IMM_LSL(0));
+                            TCG_REG_PC, TCG_REG_PC,
+                            TCG_REG_R8, SHIFT_IMM_LSL(0));
         }
 #endif
     }
@@ -717,12 +718,13 @@ static inline void tcg_out_call(TCGContext *s, int cond, uint32_t addr)
         tcg_abort();
 #else
         if (cond == COND_AL) {
-            tcg_out_dat_imm(s, cond, ARITH_ADD, 14, 15, 4);
-            tcg_out_ld32_12(s, COND_AL, 15, 15, -4);
+            tcg_out_dat_imm(s, cond, ARITH_ADD, TCG_REG_R14, TCG_REG_PC, 4);
+            tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
             tcg_out32(s, addr); /* XXX: This is l->u.value, can we use it? */
         } else {
             tcg_out_movi32(s, cond, TCG_REG_R9, addr);
-            tcg_out_dat_imm(s, cond, ARITH_MOV, 14, 0, 15);
+            tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
+                            TCG_REG_PC, SHIFT_IMM_LSL(0));
             tcg_out_bx(s, cond, TCG_REG_R9);
         }
 #endif
@@ -732,7 +734,8 @@ static inline void tcg_out_call(TCGContext *s, int cond, uint32_t addr)
 static inline void tcg_out_callr(TCGContext *s, int cond, int arg)
 {
     /* TODO: on ARMv5 and ARMv6 replace with tcg_out_blx(s, cond, arg);  */
-    tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, 15, SHIFT_IMM_LSL(0));
+    tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
+                    TCG_REG_PC, SHIFT_IMM_LSL(0));
     tcg_out_bx(s, cond, arg);
 }
 
@@ -743,7 +746,7 @@ static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
     if (l->has_value)
         tcg_out_goto(s, cond, l->u.value);
     else if (cond == COND_AL) {
-        tcg_out_ld32_12(s, COND_AL, 15, 15, -4);
+        tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
         tcg_out_reloc(s, s->code_ptr, R_ARM_ABS32, label_index, 31337);
         s->code_ptr += 4;
     } else {
@@ -807,12 +810,12 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
 #  if CPU_TLB_BITS > 8
 #   error
 #  endif
-    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                    8, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
+    tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_R8,
+                    0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
     tcg_out_dat_imm(s, COND_AL, ARITH_AND,
-                    0, 8, CPU_TLB_SIZE - 1);
-    tcg_out_dat_reg(s, COND_AL, ARITH_ADD,
-                    0, TCG_AREG0, 0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
+                    TCG_REG_R0, TCG_REG_R8, CPU_TLB_SIZE - 1);
+    tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_AREG0,
+                    TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
     /* In the
      *  ldr r1 [r0, #(offsetof(CPUState, tlb_table[mem_index][0].addr_read))]
      * below, the offset is likely to exceed 12 bits if mem_index != 0 and
@@ -821,13 +824,13 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
      * before.
      */
     if (mem_index)
-        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 0, 0,
+        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
                         (mem_index << (TLB_SHIFT & 1)) |
                         ((16 - (TLB_SHIFT >> 1)) << 8));
-    tcg_out_ld32_12(s, COND_AL, 1, 0,
+    tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R0,
                     offsetof(CPUState, tlb_table[0][0].addr_read));
-    tcg_out_dat_reg(s, COND_AL, ARITH_CMP,
-                    0, 1, 8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
+    tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
+                    TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
     /* Check alignment.  */
     if (s_bits)
         tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
@@ -835,34 +838,34 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
 #  if TARGET_LONG_BITS == 64
     /* XXX: possibly we could use a block data load or writeback in
      * the first access.  */
-    tcg_out_ld32_12(s, COND_EQ, 1, 0,
+    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
                     offsetof(CPUState, tlb_table[0][0].addr_read) + 4);
-    tcg_out_dat_reg(s, COND_EQ, ARITH_CMP,
-                    0, 1, addr_reg2, SHIFT_IMM_LSL(0));
+    tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
+                    TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
 #  endif
-    tcg_out_ld32_12(s, COND_EQ, 1, 0,
+    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
                     offsetof(CPUState, tlb_table[0][0].addend));
 
     switch (opc) {
     case 0:
-        tcg_out_ld8_r(s, COND_EQ, data_reg, addr_reg, 1);
+        tcg_out_ld8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
         break;
     case 0 | 4:
-        tcg_out_ld8s_r(s, COND_EQ, data_reg, addr_reg, 1);
+        tcg_out_ld8s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
         break;
     case 1:
-        tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, 1);
+        tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
         break;
     case 1 | 4:
-        tcg_out_ld16s_r(s, COND_EQ, data_reg, addr_reg, 1);
+        tcg_out_ld16s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
         break;
     case 2:
     default:
-        tcg_out_ld32_r(s, COND_EQ, data_reg, addr_reg, 1);
+        tcg_out_ld32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
         break;
     case 3:
-        tcg_out_ld32_rwb(s, COND_EQ, data_reg, 1, addr_reg);
-        tcg_out_ld32_12(s, COND_EQ, data_reg2, 1, 4);
+        tcg_out_ld32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
+        tcg_out_ld32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
         break;
     }
 
@@ -870,16 +873,18 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
     tcg_out_b(s, COND_EQ, 8);
 
     /* TODO: move this code to where the constants pool will be */
-    if (addr_reg)
+    if (addr_reg != TCG_REG_R0) {
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        0, 0, addr_reg, SHIFT_IMM_LSL(0));
+                        TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0));
+    }
 # if TARGET_LONG_BITS == 32
-    tcg_out_dat_imm(s, cond, ARITH_MOV, 1, 0, mem_index);
+    tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R1, 0, mem_index);
 # else
-    if (addr_reg2 != 1)
+    if (addr_reg2 != TCG_REG_R1) {
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        1, 0, addr_reg2, SHIFT_IMM_LSL(0));
-    tcg_out_dat_imm(s, cond, ARITH_MOV, 2, 0, mem_index);
+                        TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
+    }
+    tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R2, 0, mem_index);
 # endif
     tcg_out_bl(s, cond, (tcg_target_long) qemu_ld_helpers[s_bits] -
                     (tcg_target_long) s->code_ptr);
@@ -887,31 +892,34 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
     switch (opc) {
     case 0 | 4:
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        0, 0, 0, SHIFT_IMM_LSL(24));
+                        TCG_REG_R0, 0, TCG_REG_R0, SHIFT_IMM_LSL(24));
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        data_reg, 0, 0, SHIFT_IMM_ASR(24));
+                        data_reg, 0, TCG_REG_R0, SHIFT_IMM_ASR(24));
         break;
     case 1 | 4:
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        0, 0, 0, SHIFT_IMM_LSL(16));
+                        TCG_REG_R0, 0, TCG_REG_R0, SHIFT_IMM_LSL(16));
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        data_reg, 0, 0, SHIFT_IMM_ASR(16));
+                        data_reg, 0, TCG_REG_R0, SHIFT_IMM_ASR(16));
         break;
     case 0:
     case 1:
     case 2:
     default:
-        if (data_reg)
+        if (data_reg != TCG_REG_R0) {
             tcg_out_dat_reg(s, cond, ARITH_MOV,
-                            data_reg, 0, 0, SHIFT_IMM_LSL(0));
+                            data_reg, 0, TCG_REG_R0, SHIFT_IMM_LSL(0));
+        }
         break;
     case 3:
-        if (data_reg != 0)
+        if (data_reg != TCG_REG_R0) {
             tcg_out_dat_reg(s, cond, ARITH_MOV,
-                            data_reg, 0, 0, SHIFT_IMM_LSL(0));
-        if (data_reg2 != 1)
+                            data_reg, 0, TCG_REG_R0, SHIFT_IMM_LSL(0));
+        }
+        if (data_reg2 != TCG_REG_R1) {
             tcg_out_dat_reg(s, cond, ARITH_MOV,
-                            data_reg2, 0, 1, SHIFT_IMM_LSL(0));
+                            data_reg2, 0, TCG_REG_R1, SHIFT_IMM_LSL(0));
+        }
         break;
     }
 
@@ -926,9 +934,9 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
             i = ctz32(offset) & ~1;
             rot = ((32 - i) << 7) & 0xf00;
 
-            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 8, addr_reg,
+            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R8, addr_reg,
                             ((offset >> i) & 0xff) | rot);
-            addr_reg = 8;
+            addr_reg = TCG_REG_R8;
             offset &= ~(0xff << i);
         }
     }
@@ -995,11 +1003,11 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
      *  add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
      */
     tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                    8, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
+                    TCG_REG_R8, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
     tcg_out_dat_imm(s, COND_AL, ARITH_AND,
-                    0, 8, CPU_TLB_SIZE - 1);
-    tcg_out_dat_reg(s, COND_AL, ARITH_ADD,
-                    0, TCG_AREG0, 0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
+                    TCG_REG_R0, TCG_REG_R8, CPU_TLB_SIZE - 1);
+    tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0,
+                    TCG_AREG0, TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
     /* In the
      *  ldr r1 [r0, #(offsetof(CPUState, tlb_table[mem_index][0].addr_write))]
      * below, the offset is likely to exceed 12 bits if mem_index != 0 and
@@ -1008,13 +1016,13 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
      * before.
      */
     if (mem_index)
-        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 0, 0,
+        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
                         (mem_index << (TLB_SHIFT & 1)) |
                         ((16 - (TLB_SHIFT >> 1)) << 8));
-    tcg_out_ld32_12(s, COND_AL, 1, 0,
+    tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R0,
                     offsetof(CPUState, tlb_table[0][0].addr_write));
-    tcg_out_dat_reg(s, COND_AL, ARITH_CMP,
-                    0, 1, 8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
+    tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
+                    TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
     /* Check alignment.  */
     if (s_bits)
         tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
@@ -1022,29 +1030,28 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
 #  if TARGET_LONG_BITS == 64
     /* XXX: possibly we could use a block data load or writeback in
      * the first access.  */
-    tcg_out_ld32_12(s, COND_EQ, 1, 0,
-                    offsetof(CPUState, tlb_table[0][0].addr_write)
-                    + 4);
-    tcg_out_dat_reg(s, COND_EQ, ARITH_CMP,
-                    0, 1, addr_reg2, SHIFT_IMM_LSL(0));
+    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
+                    offsetof(CPUState, tlb_table[0][0].addr_write) + 4);
+    tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
+                    TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
 #  endif
-    tcg_out_ld32_12(s, COND_EQ, 1, 0,
+    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
                     offsetof(CPUState, tlb_table[0][0].addend));
 
     switch (opc) {
     case 0:
-        tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, 1);
+        tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
         break;
     case 1:
-        tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, 1);
+        tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
         break;
     case 2:
     default:
-        tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, 1);
+        tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
         break;
     case 3:
-        tcg_out_st32_rwb(s, COND_EQ, data_reg, 1, addr_reg);
-        tcg_out_st32_12(s, COND_EQ, data_reg2, 1, 4);
+        tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
+        tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
         break;
     }
 
@@ -1052,69 +1059,77 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
     tcg_out_b(s, COND_EQ, 8);
 
     /* TODO: move this code to where the constants pool will be */
-    if (addr_reg)
+    if (addr_reg != TCG_REG_R0) {
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        0, 0, addr_reg, SHIFT_IMM_LSL(0));
+                        TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0));
+    }
 # if TARGET_LONG_BITS == 32
     switch (opc) {
     case 0:
-        tcg_out_dat_imm(s, cond, ARITH_AND, 1, data_reg, 0xff);
-        tcg_out_dat_imm(s, cond, ARITH_MOV, 2, 0, mem_index);
+        tcg_out_dat_imm(s, cond, ARITH_AND, TCG_REG_R1, data_reg, 0xff);
+        tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R2, 0, mem_index);
         break;
     case 1:
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        1, 0, data_reg, SHIFT_IMM_LSL(16));
+                        TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(16));
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        1, 0, 1, SHIFT_IMM_LSR(16));
-        tcg_out_dat_imm(s, cond, ARITH_MOV, 2, 0, mem_index);
+                        TCG_REG_R1, 0, TCG_REG_R1, SHIFT_IMM_LSR(16));
+        tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R2, 0, mem_index);
         break;
     case 2:
-        if (data_reg != 1)
+        if (data_reg != TCG_REG_R1) {
             tcg_out_dat_reg(s, cond, ARITH_MOV,
-                            1, 0, data_reg, SHIFT_IMM_LSL(0));
-        tcg_out_dat_imm(s, cond, ARITH_MOV, 2, 0, mem_index);
+                            TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(0));
+        }
+        tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R2, 0, mem_index);
         break;
     case 3:
-        if (data_reg != 1)
+        if (data_reg != TCG_REG_R1) {
             tcg_out_dat_reg(s, cond, ARITH_MOV,
-                            1, 0, data_reg, SHIFT_IMM_LSL(0));
-        if (data_reg2 != 2)
+                            TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(0));
+        }
+        if (data_reg2 != TCG_REG_R2) {
             tcg_out_dat_reg(s, cond, ARITH_MOV,
-                            2, 0, data_reg2, SHIFT_IMM_LSL(0));
-        tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
+                            TCG_REG_R2, 0, data_reg2, SHIFT_IMM_LSL(0));
+        }
+        tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R3, 0, mem_index);
         break;
     }
 # else
-    if (addr_reg2 != 1)
+    if (addr_reg2 != TCG_REG_R1) {
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        1, 0, addr_reg2, SHIFT_IMM_LSL(0));
+                        TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
+    }
     switch (opc) {
     case 0:
-        tcg_out_dat_imm(s, cond, ARITH_AND, 2, data_reg, 0xff);
-        tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
+        tcg_out_dat_imm(s, cond, ARITH_AND, TCG_REG_R2, data_reg, 0xff);
+        tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R3, 0, mem_index);
         break;
     case 1:
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        2, 0, data_reg, SHIFT_IMM_LSL(16));
+                        TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(16));
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        2, 0, 2, SHIFT_IMM_LSR(16));
-        tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
+                        TCG_REG_R2, 0, TCG_REG_R2, SHIFT_IMM_LSR(16));
+        tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R3, 0, mem_index);
         break;
     case 2:
-        if (data_reg != 2)
+        if (data_reg != TCG_REG_R2) {
             tcg_out_dat_reg(s, cond, ARITH_MOV,
-                            2, 0, data_reg, SHIFT_IMM_LSL(0));
-        tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
+                            TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
+        }
+        tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R3, 0, mem_index);
         break;
     case 3:
-        tcg_out_dat_imm(s, cond, ARITH_MOV, 8, 0, mem_index);
+        tcg_out_dat_imm(s, cond, ARITH_MOV, TCG_REG_R8, 0, mem_index);
         tcg_out32(s, (cond << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */
-        if (data_reg != 2)
+        if (data_reg != TCG_REG_R2) {
             tcg_out_dat_reg(s, cond, ARITH_MOV,
-                            2, 0, data_reg, SHIFT_IMM_LSL(0));
-        if (data_reg2 != 3)
+                            TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
+        }
+        if (data_reg2 != TCG_REG_R3) {
             tcg_out_dat_reg(s, cond, ARITH_MOV,
-                            3, 0, data_reg2, SHIFT_IMM_LSL(0));
+                            TCG_REG_R3, 0, data_reg2, SHIFT_IMM_LSL(0));
+        }
         break;
     }
 # endif
@@ -1123,7 +1138,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
                     (tcg_target_long) s->code_ptr);
 # if TARGET_LONG_BITS == 64
     if (opc == 3)
-        tcg_out_dat_imm(s, cond, ARITH_ADD, 13, 13, 0x10);
+        tcg_out_dat_imm(s, cond, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
 # endif
 
     *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
@@ -1137,9 +1152,9 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
             i = ctz32(offset) & ~1;
             rot = ((32 - i) << 7) & 0xf00;
 
-            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 8, addr_reg,
+            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R8, addr_reg,
                             ((offset >> i) & 0xff) | rot);
-            addr_reg = 8;
+            addr_reg = TCG_REG_R8;
             offset &= ~(0xff << i);
         }
     }
@@ -1176,9 +1191,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         {
             uint8_t *ld_ptr = s->code_ptr;
             if (args[0] >> 8)
-                tcg_out_ld32_12(s, COND_AL, 0, 15, 0);
+                tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
             else
-                tcg_out_dat_imm(s, COND_AL, ARITH_MOV, 0, 0, args[0]);
+                tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R0, 0, args[0]);
             tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
             if (args[0] >> 8) {
                 *ld_ptr = (uint8_t) (s->code_ptr - ld_ptr) - 8;
@@ -1193,7 +1208,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
             s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
             tcg_out_b(s, COND_AL, 8);
 #else
-            tcg_out_ld32_12(s, COND_AL, 15, 15, -4);
+            tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
             s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
             tcg_out32(s, 0);
 #endif
@@ -1204,12 +1219,12 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
             if (c > 0xfff || c < -0xfff) {
                 tcg_out_movi32(s, COND_AL, TCG_REG_R0,
                                 (tcg_target_long) (s->tb_next + args[0]));
-                tcg_out_ld32_12(s, COND_AL, 15, TCG_REG_R0, 0);
+                tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
             } else
-                tcg_out_ld32_12(s, COND_AL, 15, 15, c);
+                tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, c);
 #else
-            tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, 15, 0);
-            tcg_out_ld32_12(s, COND_AL, 15, TCG_REG_R0, 0);
+            tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
+            tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
             tcg_out32(s, (tcg_target_long) (s->tb_next + args[0]));
 #endif
         }
@@ -1335,8 +1350,8 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         if (const_args[1]) {
             int rot;
             rot = encode_imm(args[1]);
-            tcg_out_dat_imm(s, COND_AL, ARITH_CMP,
-                            0, args[0], rotl(args[1], rot) | (rot << 7));
+            tcg_out_dat_imm(s, COND_AL, ARITH_CMP, 0,
+                            args[0], rotl(args[1], rot) | (rot << 7));
         } else {
             tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
                             args[0], args[1], SHIFT_IMM_LSL(0));
@@ -1362,8 +1377,8 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         if (const_args[2]) {
             int rot;
             rot = encode_imm(args[2]);
-            tcg_out_dat_imm(s, COND_AL, ARITH_CMP,
-                            0, args[1], rotl(args[2], rot) | (rot << 7));
+            tcg_out_dat_imm(s, COND_AL, ARITH_CMP, 0,
+                            args[1], rotl(args[2], rot) | (rot << 7));
         } else {
             tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
                             args[1], args[2], SHIFT_IMM_LSL(0));
commit f694a27ed7281ce29f2b86235f79ef16ff759b7e
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: remove store signed functions
    
    Store signed functions doesn't make sense, and are not used. Remove
    them.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 35f6c47..e923330 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -499,7 +499,7 @@ static inline void tcg_out_ld16u_8(TCGContext *s, int cond,
                         (((-im) & 0xf0) << 4) | ((-im) & 0xf));
 }
 
-static inline void tcg_out_st16u_8(TCGContext *s, int cond,
+static inline void tcg_out_st16_8(TCGContext *s, int cond,
                 int rd, int rn, tcg_target_long im)
 {
     if (im >= 0)
@@ -519,7 +519,7 @@ static inline void tcg_out_ld16u_r(TCGContext *s, int cond,
                     (rn << 16) | (rd << 12) | rm);
 }
 
-static inline void tcg_out_st16u_r(TCGContext *s, int cond,
+static inline void tcg_out_st16_r(TCGContext *s, int cond,
                 int rd, int rn, int rm)
 {
     tcg_out32(s, (cond << 28) | 0x018000b0 |
@@ -539,19 +539,6 @@ static inline void tcg_out_ld16s_8(TCGContext *s, int cond,
                         (((-im) & 0xf0) << 4) | ((-im) & 0xf));
 }
 
-static inline void tcg_out_st16s_8(TCGContext *s, int cond,
-                int rd, int rn, tcg_target_long im)
-{
-    if (im >= 0)
-        tcg_out32(s, (cond << 28) | 0x01c000f0 |
-                        (rn << 16) | (rd << 12) |
-                        ((im & 0xf0) << 4) | (im & 0xf));
-    else
-        tcg_out32(s, (cond << 28) | 0x014000f0 |
-                        (rn << 16) | (rd << 12) |
-                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
-}
-
 static inline void tcg_out_ld16s_r(TCGContext *s, int cond,
                 int rd, int rn, int rm)
 {
@@ -559,13 +546,6 @@ static inline void tcg_out_ld16s_r(TCGContext *s, int cond,
                     (rn << 16) | (rd << 12) | rm);
 }
 
-static inline void tcg_out_st16s_r(TCGContext *s, int cond,
-                int rd, int rn, int rm)
-{
-    tcg_out32(s, (cond << 28) | 0x018000f0 |
-                    (rn << 16) | (rd << 12) | rm);
-}
-
 static inline void tcg_out_ld8_12(TCGContext *s, int cond,
                 int rd, int rn, tcg_target_long im)
 {
@@ -615,19 +595,6 @@ static inline void tcg_out_ld8s_8(TCGContext *s, int cond,
                         (((-im) & 0xf0) << 4) | ((-im) & 0xf));
 }
 
-static inline void tcg_out_st8s_8(TCGContext *s, int cond,
-                int rd, int rn, tcg_target_long im)
-{
-    if (im >= 0)
-        tcg_out32(s, (cond << 28) | 0x01c000d0 |
-                        (rn << 16) | (rd << 12) |
-                        ((im & 0xf0) << 4) | (im & 0xf));
-    else
-        tcg_out32(s, (cond << 28) | 0x014000d0 |
-                        (rn << 16) | (rd << 12) |
-                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
-}
-
 static inline void tcg_out_ld8s_r(TCGContext *s, int cond,
                 int rd, int rn, int rm)
 {
@@ -635,13 +602,6 @@ static inline void tcg_out_ld8s_r(TCGContext *s, int cond,
                     (rn << 16) | (rd << 12) | rm);
 }
 
-static inline void tcg_out_st8s_r(TCGContext *s, int cond,
-                int rd, int rn, int rm)
-{
-    tcg_out32(s, (cond << 28) | 0x018000d0 |
-                    (rn << 16) | (rd << 12) | rm);
-}
-
 static inline void tcg_out_ld32u(TCGContext *s, int cond,
                 int rd, int rn, int32_t offset)
 {
@@ -682,14 +642,14 @@ static inline void tcg_out_ld16s(TCGContext *s, int cond,
         tcg_out_ld16s_8(s, cond, rd, rn, offset);
 }
 
-static inline void tcg_out_st16u(TCGContext *s, int cond,
+static inline void tcg_out_st16(TCGContext *s, int cond,
                 int rd, int rn, int32_t offset)
 {
     if (offset > 0xff || offset < -0xff) {
         tcg_out_movi32(s, cond, TCG_REG_R8, offset);
-        tcg_out_st16u_r(s, cond, rd, rn, TCG_REG_R8);
+        tcg_out_st16_r(s, cond, rd, rn, TCG_REG_R8);
     } else
-        tcg_out_st16u_8(s, cond, rd, rn, offset);
+        tcg_out_st16_8(s, cond, rd, rn, offset);
 }
 
 static inline void tcg_out_ld8u(TCGContext *s, int cond,
@@ -712,7 +672,7 @@ static inline void tcg_out_ld8s(TCGContext *s, int cond,
         tcg_out_ld8s_8(s, cond, rd, rn, offset);
 }
 
-static inline void tcg_out_st8u(TCGContext *s, int cond,
+static inline void tcg_out_st8(TCGContext *s, int cond,
                 int rd, int rn, int32_t offset)
 {
     if (offset > 0xfff || offset < -0xfff) {
@@ -1075,14 +1035,8 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
     case 0:
         tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, 1);
         break;
-    case 0 | 4:
-        tcg_out_st8s_r(s, COND_EQ, data_reg, addr_reg, 1);
-        break;
     case 1:
-        tcg_out_st16u_r(s, COND_EQ, data_reg, addr_reg, 1);
-        break;
-    case 1 | 4:
-        tcg_out_st16s_r(s, COND_EQ, data_reg, addr_reg, 1);
+        tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, 1);
         break;
     case 2:
     default:
@@ -1193,14 +1147,8 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
     case 0:
         tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0);
         break;
-    case 0 | 4:
-        tcg_out_st8s_8(s, COND_AL, data_reg, addr_reg, 0);
-        break;
     case 1:
-        tcg_out_st16u_8(s, COND_AL, data_reg, addr_reg, 0);
-        break;
-    case 1 | 4:
-        tcg_out_st16s_8(s, COND_AL, data_reg, addr_reg, 0);
+        tcg_out_st16_8(s, COND_AL, data_reg, addr_reg, 0);
         break;
     case 2:
     default:
@@ -1299,10 +1247,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         tcg_out_ld32u(s, COND_AL, args[0], args[1], args[2]);
         break;
     case INDEX_op_st8_i32:
-        tcg_out_st8u(s, COND_AL, args[0], args[1], args[2]);
+        tcg_out_st8(s, COND_AL, args[0], args[1], args[2]);
         break;
     case INDEX_op_st16_i32:
-        tcg_out_st16u(s, COND_AL, args[0], args[1], args[2]);
+        tcg_out_st16(s, COND_AL, args[0], args[1], args[2]);
         break;
     case INDEX_op_st_i32:
         tcg_out_st32(s, COND_AL, args[0], args[1], args[2]);
commit e4a7d5e88c361040a64a0f298d666a273dc6db85
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: explicitely list clobbered/reserved regs
    
    Instead of writing very compact code, declare all registers that are
    clobbered or reserved one by one. This makes the code easier to read.
    
    Also declare all the 16 registers to TCG, and mark pc as reserved.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index e86ed9a..35f6c47 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -39,6 +39,7 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
     "%r12",
     "%r13",
     "%r14",
+    "%pc",
 };
 #endif
 
@@ -1580,15 +1581,19 @@ void tcg_target_init(TCGContext *s)
         tcg_abort();
 #endif
 
-    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0,
-                    ((2 << TCG_REG_R14) - 1) & ~(1 << TCG_REG_R8));
+    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
     tcg_regset_set32(tcg_target_call_clobber_regs, 0,
-                    ((2 << TCG_REG_R3) - 1) |
-                    (1 << TCG_REG_R12) | (1 << TCG_REG_R14));
+                     (1 << TCG_REG_R0) |
+                     (1 << TCG_REG_R1) |
+                     (1 << TCG_REG_R2) |
+                     (1 << TCG_REG_R3) |
+                     (1 << TCG_REG_R12) |
+                     (1 << TCG_REG_R14));
 
     tcg_regset_clear(s->reserved_regs);
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R8);
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
 
     tcg_add_target_add_op_defs(arm_op_defs);
 }
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 6d58de8..a0027b5 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -44,9 +44,10 @@ enum {
     TCG_REG_R12,
     TCG_REG_R13,
     TCG_REG_R14,
+    TCG_REG_PC,
 };
 
-#define TCG_TARGET_NB_REGS 15
+#define TCG_TARGET_NB_REGS 16
 
 #define TCG_CT_CONST_ARM 0x100
 
commit 39221a82be8d224e935bdba10ce108a1a808a52f
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Apr 9 20:52:48 2010 +0200

    tcg/arm: remove SAVE_LR code
    
    There is no need to save the LR register (r14) before a call to a
    subroutine. According to the "Procedure Call Standard for the ARM
    Architecture", it is the job of the callee to save this register.
    Moreover, this register is already saved in the prologue/epilogue.
    
    This patch removes the disabled SAVE_LR code, as there is no need to
    reenable later.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index f0f669d..e86ed9a 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -748,10 +748,6 @@ static inline void tcg_out_call(TCGContext *s, int cond, uint32_t addr)
 {
     int32_t val;
 
-#ifdef SAVE_LR
-    tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R8, 0, 14, SHIFT_IMM_LSL(0));
-#endif
-
     val = addr - (tcg_target_long) s->code_ptr;
     if (val < 0x01fffffd && val > -0x01fffffd)
         tcg_out_bl(s, cond, val);
@@ -770,23 +766,13 @@ static inline void tcg_out_call(TCGContext *s, int cond, uint32_t addr)
         }
 #endif
     }
-
-#ifdef SAVE_LR
-    tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, TCG_REG_R8, SHIFT_IMM_LSL(0));
-#endif
 }
 
 static inline void tcg_out_callr(TCGContext *s, int cond, int arg)
 {
-#ifdef SAVE_LR
-    tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R8, 0, 14, SHIFT_IMM_LSL(0));
-#endif
     /* TODO: on ARMv5 and ARMv6 replace with tcg_out_blx(s, cond, arg);  */
     tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, 15, SHIFT_IMM_LSL(0));
     tcg_out_bx(s, cond, arg);
-#ifdef SAVE_LR
-    tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, TCG_REG_R8, SHIFT_IMM_LSL(0));
-#endif
 }
 
 static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
@@ -922,10 +908,6 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
     label_ptr = (void *) s->code_ptr;
     tcg_out_b(s, COND_EQ, 8);
 
-# ifdef SAVE_LR
-    tcg_out_dat_reg(s, cond, ARITH_MOV, 8, 0, 14, SHIFT_IMM_LSL(0));
-# endif
-
     /* TODO: move this code to where the constants pool will be */
     if (addr_reg)
         tcg_out_dat_reg(s, cond, ARITH_MOV,
@@ -972,10 +954,6 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
         break;
     }
 
-# ifdef SAVE_LR
-    tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, 8, SHIFT_IMM_LSL(0));
-# endif
-
     *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
 #else /* !CONFIG_SOFTMMU */
     if (GUEST_BASE) {
@@ -1186,10 +1164,6 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
     }
 # endif
 
-# ifdef SAVE_LR
-    tcg_out_dat_reg(s, cond, ARITH_MOV, 8, 0, 14, SHIFT_IMM_LSL(0));
-# endif
-
     tcg_out_bl(s, cond, (tcg_target_long) qemu_st_helpers[s_bits] -
                     (tcg_target_long) s->code_ptr);
 # if TARGET_LONG_BITS == 64
@@ -1197,10 +1171,6 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
         tcg_out_dat_imm(s, cond, ARITH_ADD, 13, 13, 0x10);
 # endif
 
-# ifdef SAVE_LR
-    tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, 8, SHIFT_IMM_LSL(0));
-# endif
-
     *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
 #else /* !CONFIG_SOFTMMU */
     if (GUEST_BASE) {
@@ -1254,15 +1224,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
 
     switch (opc) {
     case INDEX_op_exit_tb:
-#ifdef SAVE_LR
-        if (args[0] >> 8)
-            tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, 15, 0);
-        else
-            tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R0, 0, args[0]);
-        tcg_out_dat_reg(s, COND_AL, ARITH_MOV, 15, 0, 14, SHIFT_IMM_LSL(0));
-        if (args[0] >> 8)
-            tcg_out32(s, args[0]);
-#else
         {
             uint8_t *ld_ptr = s->code_ptr;
             if (args[0] >> 8)
@@ -1275,7 +1236,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
                 tcg_out32(s, args[0]);
             }
         }
-#endif
         break;
     case INDEX_op_goto_tb:
         if (s->tb_jmp_offset) {
@@ -1627,9 +1587,6 @@ void tcg_target_init(TCGContext *s)
                     (1 << TCG_REG_R12) | (1 << TCG_REG_R14));
 
     tcg_regset_clear(s->reserved_regs);
-#ifdef SAVE_LR
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R14);
-#endif
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R8);
 
commit d6fa4b77fb8f27ac84cf23fb1e15016673d98a47
Author: M. Mohan Kumar <mohan at in.ibm.com>
Date:   Mon Apr 12 10:01:33 2010 +0530

    Check for invalid initrd file
    
    When qemu is invoked with an invalid initrd file, it crashes. Following
    patch prints a error message and exits if an invalid initrd is
    specified. Includes changes suggested by JV.
    
    Signed-off-by: M. Mohan Kumar <mohan at in.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/pc.c b/hw/pc.c
index 69e597f..b797f21 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -658,6 +658,12 @@ static void load_linux(void *fw_cfg,
 	}
 
 	initrd_size = get_image_size(initrd_filename);
+        if (initrd_size < 0) {
+            fprintf(stderr, "qemu: error reading initrd %s\n",
+                    initrd_filename);
+            exit(1);
+        }
+
         initrd_addr = (initrd_max-initrd_size) & ~4095;
 
         initrd_data = qemu_malloc(initrd_size);
commit f1dc58e07decfa21f6141d6c441008d4b8b83331
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Mar 31 15:21:49 2010 -0300

    Monitor: Convert do_screen_dump() to QObject
    
    Trivial, as it never fails, doesn't have output nor return
    any data.
    
    Note that it's also available under QMP, as kvm-autotest
    needs this.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/monitor.c b/monitor.c
index 072bea4..ba60f97 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1164,9 +1164,10 @@ static int do_change(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return ret;
 }
 
-static void do_screen_dump(Monitor *mon, const QDict *qdict)
+static int do_screen_dump(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     vga_hw_screen_dump(qdict_get_str(qdict, "filename"));
+    return 0;
 }
 
 static void do_logfile(Monitor *mon, const QDict *qdict)
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 62fa346..5ea5748 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -199,7 +199,8 @@ ETEXI
         .args_type  = "filename:F",
         .params     = "filename",
         .help       = "save screen into PPM image 'filename'",
-        .mhandler.cmd = do_screen_dump,
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = do_screen_dump,
     },
 
 STEXI
commit db11571f090c5e72b5da5772fe3ba6557aacd572
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Mar 24 17:24:37 2010 -0300

    QMP: Improve RTC_CHANGE event description
    
    Some people might think that this event is emitted whenever the
    time changes, be more specific.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
index a94e9b4..c084a47 100644
--- a/QMP/qmp-events.txt
+++ b/QMP/qmp-events.txt
@@ -41,7 +41,7 @@ Example:
 RTC_CHANGE
 ----------
 
-Emitted when the RTC time changes.
+Emitted when the guest changes the RTC time.
 
 Data:
 
commit 908bb9497bcb5543930cc345326afff939a6ffa4
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 31 17:46:59 2010 +0200

    virtio-blk: Fix use after free in error case
    
    virtio_blk_req_complete frees the request, so we can't access it any more when
    calling bdrv_mon_event. Use the pointer that was copied earlier.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 9915840..01d77b8 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -65,7 +65,7 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
     VirtIOBlock *s = req->dev;
 
     if (action == BLOCK_ERR_IGNORE) {
-        bdrv_mon_event(req->dev->bs, BDRV_ACTION_IGNORE, is_read);
+        bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, is_read);
         return 0;
     }
 
@@ -73,11 +73,11 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
             || action == BLOCK_ERR_STOP_ANY) {
         req->next = s->rq;
         s->rq = req;
-        bdrv_mon_event(req->dev->bs, BDRV_ACTION_STOP, is_read);
+        bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
         vm_stop(0);
     } else {
         virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
-        bdrv_mon_event(req->dev->bs, BDRV_ACTION_REPORT, is_read);
+        bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read);
     }
 
     return 1;
commit 5369e3c0b8997210a2558191d8451775f7643683
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Mar 26 09:07:11 2010 +0100

    monitor: Convert do_set_link() to QObject, QError
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/net.c b/net.c
index cdba8f3..378edfc 100644
--- a/net.c
+++ b/net.c
@@ -1271,7 +1271,7 @@ void do_info_network(Monitor *mon)
     }
 }
 
-void do_set_link(Monitor *mon, const QDict *qdict)
+int do_set_link(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     VLANState *vlan;
     VLANClientState *vc = NULL;
@@ -1289,8 +1289,8 @@ void do_set_link(Monitor *mon, const QDict *qdict)
 done:
 
     if (!vc) {
-        monitor_printf(mon, "could not find network device '%s'\n", name);
-        return;
+        qerror_report(QERR_DEVICE_NOT_FOUND, name);
+        return -1;
     }
 
     vc->link_down = !up;
@@ -1298,6 +1298,7 @@ done:
     if (vc->info->link_status_changed) {
         vc->info->link_status_changed(vc);
     }
+    return 0;
 }
 
 void net_cleanup(void)
diff --git a/net.h b/net.h
index 9f3c82f..b83f615 100644
--- a/net.h
+++ b/net.h
@@ -118,7 +118,7 @@ int qemu_find_nic_model(NICInfo *nd, const char * const *models,
                         const char *default_model);
 
 void do_info_network(Monitor *mon);
-void do_set_link(Monitor *mon, const QDict *qdict);
+int do_set_link(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 /* NIC info */
 
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 7b7dcf5..62fa346 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -989,7 +989,8 @@ ETEXI
         .args_type  = "name:s,up:b",
         .params     = "name on|off",
         .help       = "change the link status of a network adapter",
-        .mhandler.cmd = do_set_link,
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = do_set_link,
     },
 
 STEXI
commit c9b26a4cbe1e3ce71521b8a1ff0483f4cc4fa4bf
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Mar 26 09:07:10 2010 +0100

    monitor: Use argument type 'b' for set_link
    
    Second argument is now "on" or "off" instead of "up" or "down".
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/net.c b/net.c
index e00fac9..cdba8f3 100644
--- a/net.c
+++ b/net.c
@@ -1276,7 +1276,7 @@ void do_set_link(Monitor *mon, const QDict *qdict)
     VLANState *vlan;
     VLANClientState *vc = NULL;
     const char *name = qdict_get_str(qdict, "name");
-    const char *up_or_down = qdict_get_str(qdict, "up_or_down");
+    int up = qdict_get_bool(qdict, "up");
 
     QTAILQ_FOREACH(vlan, &vlans, next) {
         QTAILQ_FOREACH(vc, &vlan->clients, next) {
@@ -1293,13 +1293,7 @@ done:
         return;
     }
 
-    if (strcmp(up_or_down, "up") == 0)
-        vc->link_down = 0;
-    else if (strcmp(up_or_down, "down") == 0)
-        vc->link_down = 1;
-    else
-        monitor_printf(mon, "invalid link status '%s'; only 'up' or 'down' "
-                       "valid\n", up_or_down);
+    vc->link_down = !up;
 
     if (vc->info->link_status_changed) {
         vc->info->link_status_changed(vc);
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 8c9a41c..7b7dcf5 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -986,16 +986,16 @@ ETEXI
 
     {
         .name       = "set_link",
-        .args_type  = "name:s,up_or_down:s",
-        .params     = "name up|down",
+        .args_type  = "name:s,up:b",
+        .params     = "name on|off",
         .help       = "change the link status of a network adapter",
         .mhandler.cmd = do_set_link,
     },
 
 STEXI
- at item set_link @var{name} [up|down]
+ at item set_link @var{name} [on|off]
 @findex set_link
-Set link @var{name} up or down.
+Switch link @var{name} on (i.e. up) or off (i.e. down).
 ETEXI
 
     {
commit 942cd1f2889dbc74db850218b270bc5b41656dfd
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Mar 26 09:07:09 2010 +0100

    monitor: New argument type 'b'
    
    This is a boolean value.  Human monitor accepts "on" or "off".
    Consistent with option parsing (see parse_option_bool()).
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/monitor.c b/monitor.c
index 57eb746..072bea4 100644
--- a/monitor.c
+++ b/monitor.c
@@ -85,6 +85,8 @@
  *
  * '?'          optional type (for all types, except '/')
  * '.'          other form of optional type (for 'i' and 'l')
+ * 'b'          boolean
+ *              user mode accepts "on" or "off"
  * '-'          optional parameter (eg. '-f')
  *
  */
@@ -3757,6 +3759,29 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon,
                 qdict_put(qdict, key, qfloat_from_double(val));
             }
             break;
+        case 'b':
+            {
+                const char *beg;
+                int val;
+
+                while (qemu_isspace(*p)) {
+                    p++;
+                }
+                beg = p;
+                while (qemu_isgraph(*p)) {
+                    p++;
+                }
+                if (p - beg == 2 && !memcmp(beg, "on", p - beg)) {
+                    val = 1;
+                } else if (p - beg == 3 && !memcmp(beg, "off", p - beg)) {
+                    val = 0;
+                } else {
+                    monitor_printf(mon, "Expected 'on' or 'off'\n");
+                    goto fail;
+                }
+                qdict_put(qdict, key, qbool_from_int(val));
+            }
+            break;
         case '-':
             {
                 const char *tmp = p;
@@ -4238,6 +4263,12 @@ static int check_arg(const CmdArgs *cmd_args, QDict *args)
                 return -1;
             }
             break;
+        case 'b':
+            if (qobject_type(value) != QTYPE_QBOOL) {
+                qerror_report(QERR_INVALID_PARAMETER_TYPE, name, "bool");
+                return -1;
+            }
+            break;
         case '-':
             if (qobject_type(value) != QTYPE_QINT &&
                 qobject_type(value) != QTYPE_QBOOL) {
commit ee9545dad4004b92a93554a92cbb3e1b0e1c949d
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Mar 26 09:07:08 2010 +0100

    monitor: Rename argument type 'b' to 'f'
    
    To make 'b' available for boolean argument.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/monitor.c b/monitor.c
index 5ddf97a..57eb746 100644
--- a/monitor.c
+++ b/monitor.c
@@ -74,7 +74,7 @@
  * 'l'          target long (32 or 64 bit)
  * 'M'          just like 'l', except in user mode the value is
  *              multiplied by 2^20 (think Mebibyte)
- * 'b'          double
+ * 'f'          double
  *              user mode accepts an optional G, g, M, m, K, k suffix,
  *              which multiplies the value by 2^30 for suffixes G and
  *              g, 2^20 for M and m, 2^10 for K and k
@@ -3714,7 +3714,7 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon,
                 qdict_put(qdict, key, qint_from_int(val));
             }
             break;
-        case 'b':
+        case 'f':
         case 'T':
             {
                 double val;
@@ -3730,7 +3730,7 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon,
                 if (get_double(mon, &val, &p) < 0) {
                     goto fail;
                 }
-                if (c == 'b' && *p) {
+                if (c == 'f' && *p) {
                     switch (*p) {
                     case 'K': case 'k':
                         val *= 1 << 10; p++; break;
@@ -4231,7 +4231,7 @@ static int check_arg(const CmdArgs *cmd_args, QDict *args)
                 return -1;
             }
             break;
-        case 'b':
+        case 'f':
         case 'T':
             if (qobject_type(value) != QTYPE_QINT && qobject_type(value) != QTYPE_QFLOAT) {
                 qerror_report(QERR_INVALID_PARAMETER_TYPE, name, "number");
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 31087bd..8c9a41c 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -804,7 +804,7 @@ ETEXI
 
     {
         .name       = "migrate_set_speed",
-        .args_type  = "value:b",
+        .args_type  = "value:f",
         .params     = "value",
         .help       = "set maximum speed (in bytes) for migrations",
         .user_print = monitor_user_noop,
commit ae82d3242d9db904f8ab81a5c7d796ae2eb46f04
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu Mar 25 17:22:40 2010 +0100

    monitor: New commands netdev_add, netdev_del
    
    Monitor commands to go with -netdev.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/net.c b/net.c
index 1840dd7..e00fac9 100644
--- a/net.c
+++ b/net.c
@@ -1194,6 +1194,61 @@ void net_host_device_remove(Monitor *mon, const QDict *qdict)
     qemu_del_vlan_client(vc);
 }
 
+/**
+ * do_netdev_add(): Add a host network device
+ *
+ * Argument qdict contains
+ * - "type": the device type, "tap", "user", ...
+ * - "id": the device's ID (must be unique)
+ * - device options
+ *
+ * Example:
+ *
+ * { "type": "user", "id": "netdev1", "hostname": "a-guest" }
+ */
+int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    QemuOpts *opts;
+    int res;
+
+    opts = qemu_opts_from_qdict(&qemu_netdev_opts, qdict);
+    if (!opts) {
+        return -1;
+    }
+
+    res = net_client_init(mon, opts, 1);
+    return res;
+}
+
+/**
+ * do_netdev_del(): Delete a host network device
+ *
+ * Argument qdict contains
+ * - "id": the device's ID
+ *
+ * Example:
+ *
+ * { "id": "netdev1" }
+ */
+int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    const char *id = qdict_get_str(qdict, "id");
+    VLANClientState *vc;
+
+    vc = qemu_find_netdev(id);
+    if (!vc || vc->info->type == NET_CLIENT_TYPE_NIC) {
+        qerror_report(QERR_DEVICE_NOT_FOUND, id);
+        return -1;
+    }
+    if (vc->peer) {
+        qerror_report(QERR_DEVICE_IN_USE, id);
+        return -1;
+    }
+    qemu_del_vlan_client(vc);
+    qemu_opts_del(qemu_opts_find(&qemu_netdev_opts, id));
+    return 0;
+}
+
 void do_info_network(Monitor *mon)
 {
     VLANState *vlan;
diff --git a/net.h b/net.h
index 20be8d7..9f3c82f 100644
--- a/net.h
+++ b/net.h
@@ -164,6 +164,8 @@ void net_check_clients(void);
 void net_cleanup(void);
 void net_host_device_add(Monitor *mon, const QDict *qdict);
 void net_host_device_remove(Monitor *mon, const QDict *qdict);
+int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
 #define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index d290b4b..31087bd 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -914,6 +914,36 @@ STEXI
 Remove host VLAN client.
 ETEXI
 
+    {
+        .name       = "netdev_add",
+        .args_type  = "netdev:O",
+        .params     = "[user|tap|socket],id=str[,prop=value][,...]",
+        .help       = "add host network device",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = do_netdev_add,
+    },
+
+STEXI
+ at item netdev_add
+ at findex netdev_add
+Add host network device.
+ETEXI
+
+    {
+        .name       = "netdev_del",
+        .args_type  = "id:s",
+        .params     = "id",
+        .help       = "remove host network device",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = do_netdev_del,
+    },
+
+STEXI
+ at item netdev_del
+ at findex netdev_del
+Remove host network device.
+ETEXI
+
 #ifdef CONFIG_SLIRP
     {
         .name       = "hostfwd_add",
commit 5124eb5927d4d90adc5640e5d36a589bfadd1828
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu Mar 25 17:22:39 2010 +0100

    error: New QERR_DEVICE_IN_USE
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qerror.c b/qerror.c
index 97e8d4a..8d885cd 100644
--- a/qerror.c
+++ b/qerror.c
@@ -69,6 +69,10 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Device '%(device)' could not be initialized",
     },
     {
+        .error_fmt = QERR_DEVICE_IN_USE,
+        .desc      = "Device '%(device)' is in use",
+    },
+    {
         .error_fmt = QERR_DEVICE_LOCKED,
         .desc      = "Device '%(device)' is locked",
     },
diff --git a/qerror.h b/qerror.h
index 5625d54..bae08c0 100644
--- a/qerror.h
+++ b/qerror.h
@@ -67,6 +67,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_DEVICE_INIT_FAILED \
     "{ 'class': 'DeviceInitFailed', 'data': { 'device': %s } }"
 
+#define QERR_DEVICE_IN_USE \
+    "{ 'class': 'DeviceInUse', 'data': { 'device': %s } }"
+
 #define QERR_DEVICE_LOCKED \
     "{ 'class': 'DeviceLocked', 'data': { 'device': %s } }"
 
commit 5294e2c774f120e10b44652ac143abda356f44eb
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu Mar 25 17:22:38 2010 +0100

    error: Convert net_client_init() to QError
    
    The conversion is shallow: client type init() methods aren't
    converted.  Converting them is a big job for relatively little
    practical benefit, so leave it for later.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/net.c b/net.c
index 96e10b1..1840dd7 100644
--- a/net.c
+++ b/net.c
@@ -1065,18 +1065,12 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
     int i;
 
     type = qemu_opt_get(opts, "type");
+    if (!type) {
+        qerror_report(QERR_MISSING_PARAMETER, "type");
+        return -1;
+    }
 
-    if (!is_netdev) {
-        if (!type) {
-            error_report("No type specified for -net");
-            return -1;
-        }
-    } else {
-        if (!type) {
-            error_report("No type specified for -netdev");
-            return -1;
-        }
-
+    if (is_netdev) {
         if (strcmp(type, "tap") != 0 &&
 #ifdef CONFIG_SLIRP
             strcmp(type, "user") != 0 &&
@@ -1085,21 +1079,21 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
             strcmp(type, "vde") != 0 &&
 #endif
             strcmp(type, "socket") != 0) {
-            error_report("The '%s' network backend type is not valid with -netdev",
-                         type);
+            qerror_report(QERR_INVALID_PARAMETER_VALUE, "type",
+                          "a netdev backend type");
             return -1;
         }
 
         if (qemu_opt_get(opts, "vlan")) {
-            error_report("The 'vlan' parameter is not valid with -netdev");
+            qerror_report(QERR_INVALID_PARAMETER, "vlan");
             return -1;
         }
         if (qemu_opt_get(opts, "name")) {
-            error_report("The 'name' parameter is not valid with -netdev");
+            qerror_report(QERR_INVALID_PARAMETER, "name");
             return -1;
         }
         if (!qemu_opts_id(opts)) {
-            error_report("The id= parameter is required with -netdev");
+            qerror_report(QERR_MISSING_PARAMETER, "id");
             return -1;
         }
     }
@@ -1125,14 +1119,18 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
             }
 
             if (net_client_types[i].init) {
-                return net_client_types[i].init(opts, mon, name, vlan);
-            } else {
-                return 0;
+                if (net_client_types[i].init(opts, mon, name, vlan) < 0) {
+                    /* TODO push error reporting into init() methods */
+                    qerror_report(QERR_DEVICE_INIT_FAILED, type);
+                    return -1;
+                }
             }
+            return 0;
         }
     }
 
-    error_report("Invalid -net type '%s'", type);
+    qerror_report(QERR_INVALID_PARAMETER_VALUE, "type",
+                  "a network client type");
     return -1;
 }
 
commit db716e9c16737d2575143d88a73ed1dec8dec0fb
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu Mar 25 17:22:37 2010 +0100

    error: Convert qemu_opts_validate() to QError
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qemu-option.c b/qemu-option.c
index 394c763..1ffc497 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -877,8 +877,7 @@ int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
             }
         }
         if (desc[i].name == NULL) {
-            fprintf(stderr, "option \"%s\" is not valid for %s\n",
-                    opt->name, opts->list->name);
+            qerror_report(QERR_INVALID_PARAMETER, opt->name);
             return -1;
         }
 
commit e17ba87c52fc7d4ccfd5074428ce19f1b876ba30
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu Mar 25 17:22:36 2010 +0100

    error: Use QERR_INVALID_PARAMETER_VALUE instead of QERR_INVALID_PARAMETER
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 5ca126b..d3bf0fa 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -207,7 +207,7 @@ DeviceState *qdev_device_add(QemuOpts *opts)
     /* find driver */
     info = qdev_find_info(NULL, driver);
     if (!info || info->no_user) {
-        qerror_report(QERR_INVALID_PARAMETER, "driver");
+        qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
         error_printf_unless_qmp("Try with argument '?' for a list.\n");
         return NULL;
     }
diff --git a/monitor.c b/monitor.c
index e5f6b1c..5ddf97a 100644
--- a/monitor.c
+++ b/monitor.c
@@ -970,7 +970,8 @@ static int do_cpu_set(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     int index = qdict_get_int(qdict, "index");
     if (mon_set_cpu(index) < 0) {
-        qerror_report(QERR_INVALID_PARAMETER, "index");
+        qerror_report(QERR_INVALID_PARAMETER_VALUE, "index",
+                      "a CPU number");
         return -1;
     }
     return 0;
@@ -2405,7 +2406,8 @@ static int do_getfd(Monitor *mon, const QDict *qdict, QObject **ret_data)
     }
 
     if (qemu_isdigit(fdname[0])) {
-        qerror_report(QERR_INVALID_PARAMETER, "fdname");
+        qerror_report(QERR_INVALID_PARAMETER_VALUE, "fdname",
+                      "a name not starting with a digit");
         return -1;
     }
 
commit c389c43ee517fbfb8b18ebb520fb4c707e10646e
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu Mar 25 17:22:35 2010 +0100

    error: Drop extra messages after qemu_opts_set() and qemu_opts_parse()
    
    Both functions report errors nicely enough now, no need for additional
    messages.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index eb3701b..343fd17 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -56,8 +56,6 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
 
     opts = qemu_opts_parse(&qemu_net_opts, opts_str ? opts_str : "", 0);
     if (!opts) {
-        monitor_printf(mon, "parsing network options '%s' failed\n",
-                       opts_str ? opts_str : "");
         return NULL;
     }
 
diff --git a/net.c b/net.c
index b66ec7d..96e10b1 100644
--- a/net.c
+++ b/net.c
@@ -1169,8 +1169,6 @@ void net_host_device_add(Monitor *mon, const QDict *qdict)
 
     opts = qemu_opts_parse(&qemu_net_opts, opts_str ? opts_str : "", 0);
     if (!opts) {
-        monitor_printf(mon, "parsing network options '%s' failed\n",
-                       opts_str ? opts_str : "");
         return;
     }
 
diff --git a/qemu-config.c b/qemu-config.c
index 150157c..d4a2f43 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -472,7 +472,6 @@ int qemu_config_parse(FILE *fp, const char *fname)
                 goto out;
             }
             if (qemu_opt_set(opts, arg, value) != 0) {
-                error_report("failed to set \"%s\" for %s", arg, group);
                 goto out;
             }
             continue;
diff --git a/vl.c b/vl.c
index 4fb55b8..2f6c167 100644
--- a/vl.c
+++ b/vl.c
@@ -663,8 +663,6 @@ QemuOpts *drive_add(const char *file, const char *fmt, ...)
 
     opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0);
     if (!opts) {
-        fprintf(stderr, "%s: huh? duplicate? (%s)\n",
-                __FUNCTION__, optstr);
         return NULL;
     }
     if (file)
@@ -3072,7 +3070,6 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_mon:
                 opts = qemu_opts_parse(&qemu_mon_opts, optarg, 1);
                 if (!opts) {
-                    fprintf(stderr, "parse error: %s\n", optarg);
                     exit(1);
                 }
                 default_monitor = 0;
@@ -3080,7 +3077,6 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_chardev:
                 opts = qemu_opts_parse(&qemu_chardev_opts, optarg, 1);
                 if (!opts) {
-                    fprintf(stderr, "parse error: %s\n", optarg);
                     exit(1);
                 }
                 break;
@@ -3278,7 +3274,6 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_rtc:
                 opts = qemu_opts_parse(&qemu_rtc_opts, optarg, 0);
                 if (!opts) {
-                    fprintf(stderr, "parse error: %s\n", optarg);
                     exit(1);
                 }
                 configure_rtc(opts);
commit c64f27d4f44192579087caa3ec4bd6552caef169
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu Mar 25 17:22:34 2010 +0100

    error: Convert qemu_opts_set() to QError
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qemu-option.c b/qemu-option.c
index 12ce322..394c763 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -176,7 +176,7 @@ static int parse_option_bool(const char *name, const char *value, int *ret)
         } else if (!strcmp(value, "off")) {
             *ret = 0;
         } else {
-            fprintf(stderr, "Option '%s': Use 'on' or 'off'\n", name);
+            qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "'on' or 'off'");
             return -1;
         }
     } else {
@@ -193,12 +193,12 @@ static int parse_option_number(const char *name, const char *value, uint64_t *re
     if (value != NULL) {
         number = strtoull(value, &postfix, 0);
         if (*postfix != '\0') {
-            fprintf(stderr, "Option '%s' needs a number as parameter\n", name);
+            qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
             return -1;
         }
         *ret = number;
     } else {
-        fprintf(stderr, "Option '%s' needs a parameter\n", name);
+        qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
         return -1;
     }
     return 0;
@@ -226,13 +226,13 @@ static int parse_option_size(const char *name, const char *value, uint64_t *ret)
             *ret = (uint64_t) sizef;
             break;
         default:
-            fprintf(stderr, "Option '%s' needs size as parameter\n", name);
-            fprintf(stderr, "You may use k, M, G or T suffixes for "
+            qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
+            error_printf_unless_qmp("You may use k, M, G or T suffixes for "
                     "kilobytes, megabytes, gigabytes and terabytes.\n");
             return -1;
         }
     } else {
-        fprintf(stderr, "Option '%s' needs a parameter\n", name);
+        qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
         return -1;
     }
     return 0;
@@ -581,8 +581,7 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
         if (i == 0) {
             /* empty list -> allow any */;
         } else {
-            fprintf(stderr, "option \"%s\" is not valid for %s\n",
-                    name, opts->list->name);
+            qerror_report(QERR_INVALID_PARAMETER, name);
             return -1;
         }
     }
@@ -598,8 +597,6 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
         opt->str = qemu_strdup(value);
     }
     if (qemu_opt_parse(opt) < 0) {
-        fprintf(stderr, "Failed to parse \"%s\" for \"%s.%s\"\n", opt->str,
-                opts->list->name, opt->name);
         qemu_opt_del(opt);
         return -1;
     }
commit 985a3e52f0a21edb7b2564f6c103ffee1dc382f6
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu Mar 25 17:22:33 2010 +0100

    error: New QERR_INVALID_PARAMETER_VALUE
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qerror.c b/qerror.c
index 9fb817e..97e8d4a 100644
--- a/qerror.c
+++ b/qerror.c
@@ -121,6 +121,10 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Invalid parameter type, expected: %(expected)",
     },
     {
+        .error_fmt = QERR_INVALID_PARAMETER_VALUE,
+        .desc      = "Parameter '%(name)' expects %(expected)",
+    },
+    {
         .error_fmt = QERR_INVALID_PASSWORD,
         .desc      = "Password incorrect",
     },
diff --git a/qerror.h b/qerror.h
index 870cdc3..5625d54 100644
--- a/qerror.h
+++ b/qerror.h
@@ -106,6 +106,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_INVALID_PARAMETER_TYPE \
     "{ 'class': 'InvalidParameterType', 'data': { 'name': %s,'expected': %s } }"
 
+#define QERR_INVALID_PARAMETER_VALUE \
+    "{ 'class': 'InvalidParameterValue', 'data': { 'name': %s, 'expected': %s } }"
+
 #define QERR_INVALID_PASSWORD \
     "{ 'class': 'InvalidPassword', 'data': {} }"
 
commit 975b63a4ee43870ffd96ce358ce597e42fbe1e1e
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu Mar 25 17:22:32 2010 +0100

    error: Convert qemu_opts_create() to QError
    
    Fixes device_add to report duplicate ID properly in QMP, as
    DuplicateId instead of UndefinedError.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qemu-option.c b/qemu-option.c
index f83d07c..12ce322 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -30,6 +30,7 @@
 #include "qemu-error.h"
 #include "qemu-objects.h"
 #include "qemu-option.h"
+#include "qerror.h"
 
 /*
  * Extracts the name of an option from the parameter string (p points at the
@@ -643,8 +644,7 @@ QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exist
         opts = qemu_opts_find(list, id);
         if (opts != NULL) {
             if (fail_if_exists) {
-                fprintf(stderr, "tried to create id \"%s\" twice for \"%s\"\n",
-                        id, list->name);
+                qerror_report(QERR_DUPLICATE_ID, id, list->name);
                 return NULL;
             } else {
                 return opts;
commit 7bc8401712d70dc12f230fb69cdb38511fd021b1
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu Mar 25 17:22:31 2010 +0100

    error: New QERR_DUPLICATE_ID
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qerror.c b/qerror.c
index 4520b0d..9fb817e 100644
--- a/qerror.c
+++ b/qerror.c
@@ -97,6 +97,10 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Device '%(device)' has no child bus",
     },
     {
+        .error_fmt = QERR_DUPLICATE_ID,
+        .desc      = "Duplicate ID '%(id)' for %(object)",
+    },
+    {
         .error_fmt = QERR_FD_NOT_FOUND,
         .desc      = "File descriptor named '%(name)' not found",
     },
diff --git a/qerror.h b/qerror.h
index a2664ab..870cdc3 100644
--- a/qerror.h
+++ b/qerror.h
@@ -88,6 +88,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_DEVICE_NO_BUS \
     "{ 'class': 'DeviceNoBus', 'data': { 'device': %s } }"
 
+#define QERR_DUPLICATE_ID \
+    "{ 'class': 'DuplicateId', 'data': { 'id': %s, 'object': %s } }"
+
 #define QERR_FD_NOT_FOUND \
     "{ 'class': 'FdNotFound', 'data': { 'name': %s } }"
 
commit 9d494c4b4e7cd2b30b988f3f28c34917c5ae53f5
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu Mar 25 17:22:30 2010 +0100

    error: Put error definitions back in alphabetical order
    
    Add suitable comments to help keerp them in order.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qerror.c b/qerror.c
index eaa1deb..4520b0d 100644
--- a/qerror.c
+++ b/qerror.c
@@ -38,6 +38,10 @@ static const QType qerror_type = {
  * for example:
  *
  * "running out of foo: %(foo)%%"
+ *
+ * Please keep the entries in alphabetical order.
+ * Use "sed -n '/^static.*qerror_table\[\]/,/^};/s/QERR_/&/gp' qerror.c | sort -c"
+ * to check.
  */
 static const QErrorStringTable qerror_table[] = {
     {
@@ -65,10 +69,6 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Device '%(device)' could not be initialized",
     },
     {
-        .error_fmt = QERR_DEVICE_NOT_ENCRYPTED,
-        .desc      = "Device '%(device)' is not encrypted",
-    },
-    {
         .error_fmt = QERR_DEVICE_LOCKED,
         .desc      = "Device '%(device)' is locked",
     },
@@ -81,6 +81,10 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Device '%(device)' has not been activated by the guest",
     },
     {
+        .error_fmt = QERR_DEVICE_NOT_ENCRYPTED,
+        .desc      = "Device '%(device)' is not encrypted",
+    },
+    {
         .error_fmt = QERR_DEVICE_NOT_FOUND,
         .desc      = "Device '%(device)' not found",
     },
diff --git a/qerror.h b/qerror.h
index dd298d4..a2664ab 100644
--- a/qerror.h
+++ b/qerror.h
@@ -46,6 +46,8 @@ QError *qobject_to_qerror(const QObject *obj);
 
 /*
  * QError class list
+ * Please keep the definitions in alphabetical order.
+ * Use "grep '^#define QERR_' qerror.h | sort -c" to check.
  */
 #define QERR_BAD_BUS_FOR_DEVICE \
     "{ 'class': 'BadBusForDevice', 'data': { 'device': %s, 'bad_bus_type': %s } }"
@@ -62,9 +64,6 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_DEVICE_ENCRYPTED \
     "{ 'class': 'DeviceEncrypted', 'data': { 'device': %s } }"
 
-#define QERR_DEVICE_NOT_ENCRYPTED \
-    "{ 'class': 'DeviceNotEncrypted', 'data': { 'device': %s } }"
-
 #define QERR_DEVICE_INIT_FAILED \
     "{ 'class': 'DeviceInitFailed', 'data': { 'device': %s } }"
 
@@ -77,6 +76,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_DEVICE_NOT_ACTIVE \
     "{ 'class': 'DeviceNotActive', 'data': { 'device': %s } }"
 
+#define QERR_DEVICE_NOT_ENCRYPTED \
+    "{ 'class': 'DeviceNotEncrypted', 'data': { 'device': %s } }"
+
 #define QERR_DEVICE_NOT_FOUND \
     "{ 'class': 'DeviceNotFound', 'data': { 'device': %s } }"
 
commit 17a38eaa2fdbb9add961e974fdb1b0ca8260813c
Author: Markus Armbruster <armbru at redhat.com>
Date:   Mon Mar 22 11:38:14 2010 +0100

    monitor: convert do_device_del() to QObject, QError
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 0612dc0..5ca126b 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -799,15 +799,15 @@ int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return 0;
 }
 
-void do_device_del(Monitor *mon, const QDict *qdict)
+int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     const char *id = qdict_get_str(qdict, "id");
     DeviceState *dev;
 
     dev = qdev_find_recursive(main_system_bus, id);
     if (NULL == dev) {
-        error_report("Device '%s' not found", id);
-        return;
+        qerror_report(QERR_DEVICE_NOT_FOUND, id);
+        return -1;
     }
-    qdev_unplug(dev);
+    return qdev_unplug(dev);
 }
diff --git a/hw/qdev.h b/hw/qdev.h
index 9475705..40373c8 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -176,7 +176,7 @@ void qbus_free(BusState *bus);
 void do_info_qtree(Monitor *mon);
 void do_info_qdm(Monitor *mon);
 int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
-void do_device_del(Monitor *mon, const QDict *qdict);
+int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 /*** qdev-properties.c ***/
 
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 5308f36..d290b4b 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -589,7 +589,8 @@ ETEXI
         .args_type  = "id:s",
         .params     = "device",
         .help       = "remove device",
-        .mhandler.cmd = do_device_del,
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = do_device_del,
     },
 
 STEXI
commit cc601cb785bbbd1a017d05d69763cd2c2e1ca3a4
Author: Markus Armbruster <armbru at redhat.com>
Date:   Mon Mar 22 11:38:13 2010 +0100

    qdev: Convert qdev_unplug() to QError
    
    Note: our device unplug methods don't need conversion work, because
    they can't currently fail.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 17a46a7..0612dc0 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -287,8 +287,7 @@ int qdev_init(DeviceState *dev)
 int qdev_unplug(DeviceState *dev)
 {
     if (!dev->parent_bus->allow_hotplug) {
-        error_report("Bus %s does not support hotplugging",
-                     dev->parent_bus->name);
+        qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
         return -1;
     }
     assert(dev->info->unplug != NULL);
commit 07a5d95a3b32820662194d353da9c098adddde77
Author: Ryan Harper <ryanh at us.ibm.com>
Date:   Thu Mar 25 09:32:58 2010 -0500

    Add qerror message if the 'change' target filename can't be opened
    
    Currently when using the change command to switch the file in the cd drive
    the command doesn't complain if the file doesn't exit or can't be opened
    and the drive keeps the existing image.  This patch adds a qerror_report
    call to print a message out indicating the failure.  This error message
    can be used to catch failures.
    
    Current behavior:
    
    QEMU 0.12.50 monitor - type 'help' for more information
    (qemu) info block
    ide0-hd0: type=hd removable=0 file=/dev/null ro=0 drv=host_device encrypted=0
    ide1-cd0: type=cdrom removable=1 locked=0 [not inserted]
    floppy0: type=floppy removable=1 locked=0 [not inserted]
    sd0: type=floppy removable=1 locked=0 [not inserted]
    (qemu) change ide1-cd0 /home/rharper/work/isos/Fedora-9-i386-DVD.iso
    (qemu) info block
    ide0-hd0: type=hd removable=0 file=/dev/null ro=0 drv=host_device encrypted=0
    ide1-cd0: type=cdrom removable=1 locked=0
    file=/home/rharper/work/isos/Fedora-9-i386-DVD.iso ro=0 drv=raw encrypted=0
    floppy0: type=floppy removable=1 locked=0 [not inserted]
    sd0: type=floppy removable=1 locked=0 [not inserted]
    (qemu) change ide1-cd0 /tmp/non_existent_file.iso
    (qemu) info block
    ide0-hd0: type=hd removable=0 file=/dev/null ro=0 drv=host_device encrypted=0
    ide1-cd0: type=cdrom removable=1 locked=0 [not inserted]
    floppy0: type=floppy removable=1 locked=0 [not inserted]
    sd0: type=floppy removable=1 locked=0 [not inserted]
    (qemu)
    
    With patch:
    QEMU 0.12.50 monitor - type 'help' for more information
    (qemu) change ide1-cd0 /tmp/non_existent_file.iso
    Could not open '/tmp/non_existent_file.iso'
    (qemu)
    
    Signed-off-by: Ryan Harper <ryanh at us.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/monitor.c b/monitor.c
index 5659991..e5f6b1c 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1097,6 +1097,7 @@ static int do_change_block(Monitor *mon, const char *device,
         return -1;
     }
     if (bdrv_open2(bs, filename, BDRV_O_RDWR, drv) < 0) {
+        qerror_report(QERR_OPEN_FILE_FAILED, filename);
         return -1;
     }
     return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
commit 7107944a7b72ec31366c30d747fb91dee07ebc88
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 18 14:27:46 2010 +0000

    slirp: fix unused return value, spotted by clang
    
    Fix clang errors like:
      CC    slirp/cksum.o
    /src/qemu/slirp/cksum.c:78:3: error: expression result unused [-Wunused-value]
                    REDUCE;
    /src/qemu/slirp/cksum.c:45:66: note: instantiated from:
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/slirp/cksum.c b/slirp/cksum.c
index a044ec1..c3b45f7 100644
--- a/slirp/cksum.c
+++ b/slirp/cksum.c
@@ -42,7 +42,8 @@
  */
 
 #define ADDCARRY(x)  (x > 65535 ? x -= 65535 : x)
-#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
+#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1];        \
+        (void)ADDCARRY(sum);}
 
 int cksum(struct mbuf *m, int len)
 {
commit 156aa8981a26ea6a71028edf85410b02e6f23654
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 18 14:27:44 2010 +0000

    i386-dis: Fix unused return value, spotted by clang
    
    Fix clang erros like:
      CC    libdis/i386-dis.o
    /src/qemu/i386-dis.c:3323:7: error: expression result unused [-Wunused-value]
          FETCH_DATA (the_info, codep + 1);
    /src/qemu/i386-dis.c:285:6: note: instantiated from:
       ? 1 : fetch_data ((info), (addr)))
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/i386-dis.c b/i386-dis.c
index ec079a9..c4a81c9 100644
--- a/i386-dis.c
+++ b/i386-dis.c
@@ -155,7 +155,8 @@
 
 #include <setjmp.h>
 
-static int fetch_data (struct disassemble_info *, bfd_byte *);
+static int fetch_data2(struct disassemble_info *, bfd_byte *);
+static int fetch_data(struct disassemble_info *, bfd_byte *);
 static void ckprefix (void);
 static const char *prefix_name (int, int);
 static int print_insn (bfd_vma, disassemble_info *);
@@ -280,12 +281,8 @@ static int used_prefixes;
 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
    on error.  */
-#define FETCH_DATA(info, addr) \
-  ((addr) <= ((struct dis_private *) (info->private_data))->max_fetched \
-   ? 1 : fetch_data ((info), (addr)))
-
 static int
-fetch_data (struct disassemble_info *info, bfd_byte *addr)
+fetch_data2(struct disassemble_info *info, bfd_byte *addr)
 {
   int status;
   struct dis_private *priv = (struct dis_private *) info->private_data;
@@ -313,6 +310,17 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
   return 1;
 }
 
+static int
+fetch_data(struct disassemble_info *info, bfd_byte *addr)
+{
+    if (addr <= ((struct dis_private *) (info->private_data))->max_fetched) {
+        return 1;
+    } else {
+        return fetch_data2(info, addr);
+    }
+}
+
+
 #define XX { NULL, 0 }
 
 #define Eb { OP_E, b_mode }
@@ -3320,7 +3328,7 @@ ckprefix (void)
   rex_used = 0;
   while (1)
     {
-      FETCH_DATA (the_info, codep + 1);
+      fetch_data(the_info, codep + 1);
       newrex = 0;
       switch (*codep)
 	{
@@ -3684,7 +3692,7 @@ print_insn (bfd_vma pc, disassemble_info *info)
   insn_codep = codep;
   sizeflag = priv.orig_sizeflag;
 
-  FETCH_DATA (info, codep + 1);
+  fetch_data(info, codep + 1);
   two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
 
   if (((prefixes & PREFIX_FWAIT)
@@ -3706,7 +3714,7 @@ print_insn (bfd_vma pc, disassemble_info *info)
   if (*codep == 0x0f)
     {
       unsigned char threebyte;
-      FETCH_DATA (info, codep + 2);
+      fetch_data(info, codep + 2);
       threebyte = *++codep;
       dp = &dis386_twobyte[threebyte];
       need_modrm = twobyte_has_modrm[*codep];
@@ -3717,7 +3725,7 @@ print_insn (bfd_vma pc, disassemble_info *info)
       codep++;
       if (dp->name == NULL && dp->op[0].bytemode == IS_3BYTE_OPCODE)
 	{
-	  FETCH_DATA (info, codep + 2);
+          fetch_data(info, codep + 2);
 	  op = *codep++;
 	  switch (threebyte)
 	    {
@@ -3802,7 +3810,7 @@ print_insn (bfd_vma pc, disassemble_info *info)
     }
   else if (need_modrm)
     {
-      FETCH_DATA (info, codep + 1);
+      fetch_data(info, codep + 1);
       modrm.mod = (*codep >> 6) & 3;
       modrm.reg = (*codep >> 3) & 7;
       modrm.rm = *codep & 7;
@@ -4968,7 +4976,7 @@ OP_E (int bytemode, int sizeflag)
       if (base == 4)
 	{
 	  havesib = 1;
-	  FETCH_DATA (the_info, codep + 1);
+          fetch_data(the_info, codep + 1);
 	  index = (*codep >> 3) & 7;
 	  if (address_mode == mode_64bit || index != 0x4)
 	    /* When INDEX == 0x4 in 32 bit mode, SCALE is ignored.  */
@@ -4993,7 +5001,7 @@ OP_E (int bytemode, int sizeflag)
 	    }
 	  break;
 	case 1:
-	  FETCH_DATA (the_info, codep + 1);
+          fetch_data (the_info, codep + 1);
 	  disp = *codep++;
 	  if ((disp & 0x80) != 0)
 	    disp -= 0x100;
@@ -5104,7 +5112,7 @@ OP_E (int bytemode, int sizeflag)
 	    }
 	  break;
 	case 1:
-	  FETCH_DATA (the_info, codep + 1);
+          fetch_data(the_info, codep + 1);
 	  disp = *codep++;
 	  if ((disp & 0x80) != 0)
 	    disp -= 0x100;
@@ -5226,7 +5234,7 @@ get64 (void)
   unsigned int a;
   unsigned int b;
 
-  FETCH_DATA (the_info, codep + 8);
+  fetch_data(the_info, codep + 8);
   a = *codep++ & 0xff;
   a |= (*codep++ & 0xff) << 8;
   a |= (*codep++ & 0xff) << 16;
@@ -5248,7 +5256,7 @@ get32 (void)
 {
   bfd_signed_vma x = 0;
 
-  FETCH_DATA (the_info, codep + 4);
+  fetch_data(the_info, codep + 4);
   x = *codep++ & (bfd_signed_vma) 0xff;
   x |= (*codep++ & (bfd_signed_vma) 0xff) << 8;
   x |= (*codep++ & (bfd_signed_vma) 0xff) << 16;
@@ -5261,7 +5269,7 @@ get32s (void)
 {
   bfd_signed_vma x = 0;
 
-  FETCH_DATA (the_info, codep + 4);
+  fetch_data(the_info, codep + 4);
   x = *codep++ & (bfd_signed_vma) 0xff;
   x |= (*codep++ & (bfd_signed_vma) 0xff) << 8;
   x |= (*codep++ & (bfd_signed_vma) 0xff) << 16;
@@ -5277,7 +5285,7 @@ get16 (void)
 {
   int x = 0;
 
-  FETCH_DATA (the_info, codep + 2);
+  fetch_data(the_info, codep + 2);
   x = *codep++ & 0xff;
   x |= (*codep++ & 0xff) << 8;
   return x;
@@ -5418,7 +5426,7 @@ OP_I (int bytemode, int sizeflag)
   switch (bytemode)
     {
     case b_mode:
-      FETCH_DATA (the_info, codep + 1);
+      fetch_data(the_info, codep + 1);
       op = *codep++;
       mask = 0xff;
       break;
@@ -5480,7 +5488,7 @@ OP_I64 (int bytemode, int sizeflag)
   switch (bytemode)
     {
     case b_mode:
-      FETCH_DATA (the_info, codep + 1);
+      fetch_data(the_info, codep + 1);
       op = *codep++;
       mask = 0xff;
       break;
@@ -5524,7 +5532,7 @@ OP_sI (int bytemode, int sizeflag)
   switch (bytemode)
     {
     case b_mode:
-      FETCH_DATA (the_info, codep + 1);
+      fetch_data(the_info, codep + 1);
       op = *codep++;
       if ((op & 0x80) != 0)
 	op -= 0x100;
@@ -5570,7 +5578,7 @@ OP_J (int bytemode, int sizeflag)
   switch (bytemode)
     {
     case b_mode:
-      FETCH_DATA (the_info, codep + 1);
+      fetch_data(the_info, codep + 1);
       disp = *codep++;
       if ((disp & 0x80) != 0)
 	disp -= 0x100;
@@ -6092,7 +6100,7 @@ OP_3DNowSuffix (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
 {
   const char *mnemonic;
 
-  FETCH_DATA (the_info, codep + 1);
+  fetch_data(the_info, codep + 1);
   /* AMD 3DNow! instructions are specified by an opcode suffix in the
      place where an 8-bit immediate would normally go.  ie. the last
      byte of the instruction.  */
@@ -6128,7 +6136,7 @@ OP_SIMD_Suffix (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
 {
   unsigned int cmp_type;
 
-  FETCH_DATA (the_info, codep + 1);
+  fetch_data(the_info, codep + 1);
   obufp = obuf + strlen (obuf);
   cmp_type = *codep++ & 0xff;
   if (cmp_type < 8)
commit 7b13448f05882b98c836c32329b1aca347abeb52
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 18 14:26:51 2010 +0000

    PPC: avoid function pointer type mismatch, spotted by clang
    
    Fixes clang errors:
      CC    ppc-softmmu/translate.o
    /src/qemu/target-ppc/translate.c:3748:13: error: comparison of distinct pointer types ('void (*)(void *, int, int)' and 'void *')
            if (likely(read_cb != SPR_NOACCESS)) {
    /src/qemu/target-ppc/translate.c:3748:28: note: instantiated from:
            if (likely(read_cb != SPR_NOACCESS)) {
    /src/qemu/target-ppc/translate.c:3903:13: error: comparison of distinct pointer types ('void (*)(void *, int, int)' and 'void *')
            if (likely(write_cb != SPR_NOACCESS)) {
    /src/qemu/target-ppc/translate.c:3903:29: note: instantiated from:
            if (likely(write_cb != SPR_NOACCESS)) {
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 0af7e4f..3869c24 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3719,16 +3719,14 @@ static void gen_mfmsr(DisasContext *ctx)
 #endif
 }
 
-#if 1
-#define SPR_NOACCESS ((void *)(-1UL))
-#else
-static void spr_noaccess (void *opaque, int sprn)
+static void spr_noaccess(void *opaque, int gprn, int sprn)
 {
+#if 0
     sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
     printf("ERROR: try to access SPR %d !\n", sprn);
+#endif
 }
 #define SPR_NOACCESS (&spr_noaccess)
-#endif
 
 /* mfspr */
 static inline void gen_op_mfspr(DisasContext *ctx)
commit 8c0d577eb5e5255333e43bd4b89dc3a266f03685
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 18 14:22:14 2010 +0000

    kvm: avoid collision with dprintf macro in stdio.h, spotted by clang
    
    Fixes clang errors:
      CC    i386-softmmu/kvm.o
    /src/qemu/target-i386/kvm.c:40:9: error: 'dprintf' macro redefined
    In file included from /src/qemu/target-i386/kvm.c:21:
    In file included from /src/qemu/qemu-common.h:27:
    In file included from /usr/include/stdio.h:910:
    /usr/include/bits/stdio2.h:189:12: note: previous definition is here
      CC    i386-softmmu/kvm-all.o
    /src/qemu/kvm-all.c:39:9: error: 'dprintf' macro redefined
    In file included from /src/qemu/kvm-all.c:23:
    In file included from /src/qemu/qemu-common.h:27:
    In file included from /usr/include/stdio.h:910:
    /usr/include/bits/stdio2.h:189:12: note: previous definition is here
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/kvm-all.c b/kvm-all.c
index 7aa5e57..065fd6a 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -33,10 +33,10 @@
 //#define DEBUG_KVM
 
 #ifdef DEBUG_KVM
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
     do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
 #else
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
     do { } while (0)
 #endif
 
@@ -173,11 +173,11 @@ int kvm_init_vcpu(CPUState *env)
     long mmap_size;
     int ret;
 
-    dprintf("kvm_init_vcpu\n");
+    DPRINTF("kvm_init_vcpu\n");
 
     ret = kvm_vm_ioctl(s, KVM_CREATE_VCPU, env->cpu_index);
     if (ret < 0) {
-        dprintf("kvm_create_vcpu failed\n");
+        DPRINTF("kvm_create_vcpu failed\n");
         goto err;
     }
 
@@ -186,7 +186,7 @@ int kvm_init_vcpu(CPUState *env)
 
     mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
     if (mmap_size < 0) {
-        dprintf("KVM_GET_VCPU_MMAP_SIZE failed\n");
+        DPRINTF("KVM_GET_VCPU_MMAP_SIZE failed\n");
         goto err;
     }
 
@@ -194,7 +194,7 @@ int kvm_init_vcpu(CPUState *env)
                         env->kvm_fd, 0);
     if (env->kvm_run == MAP_FAILED) {
         ret = -errno;
-        dprintf("mmap'ing vcpu state failed\n");
+        DPRINTF("mmap'ing vcpu state failed\n");
         goto err;
     }
 
@@ -325,7 +325,7 @@ static int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
         d.slot = mem->slot;
 
         if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) {
-            dprintf("ioctl failed %d\n", errno);
+            DPRINTF("ioctl failed %d\n", errno);
             ret = -1;
             break;
         }
@@ -768,12 +768,12 @@ int kvm_cpu_exec(CPUState *env)
     struct kvm_run *run = env->kvm_run;
     int ret;
 
-    dprintf("kvm_cpu_exec()\n");
+    DPRINTF("kvm_cpu_exec()\n");
 
     do {
 #ifndef CONFIG_IOTHREAD
         if (env->exit_request) {
-            dprintf("interrupt exit requested\n");
+            DPRINTF("interrupt exit requested\n");
             ret = 0;
             break;
         }
@@ -792,13 +792,13 @@ int kvm_cpu_exec(CPUState *env)
 
         if (ret == -EINTR || ret == -EAGAIN) {
             cpu_exit(env);
-            dprintf("io window exit\n");
+            DPRINTF("io window exit\n");
             ret = 0;
             break;
         }
 
         if (ret < 0) {
-            dprintf("kvm run failed %s\n", strerror(-ret));
+            DPRINTF("kvm run failed %s\n", strerror(-ret));
             abort();
         }
 
@@ -807,7 +807,7 @@ int kvm_cpu_exec(CPUState *env)
         ret = 0; /* exit loop */
         switch (run->exit_reason) {
         case KVM_EXIT_IO:
-            dprintf("handle_io\n");
+            DPRINTF("handle_io\n");
             ret = kvm_handle_io(run->io.port,
                                 (uint8_t *)run + run->io.data_offset,
                                 run->io.direction,
@@ -815,7 +815,7 @@ int kvm_cpu_exec(CPUState *env)
                                 run->io.count);
             break;
         case KVM_EXIT_MMIO:
-            dprintf("handle_mmio\n");
+            DPRINTF("handle_mmio\n");
             cpu_physical_memory_rw(run->mmio.phys_addr,
                                    run->mmio.data,
                                    run->mmio.len,
@@ -823,24 +823,24 @@ int kvm_cpu_exec(CPUState *env)
             ret = 1;
             break;
         case KVM_EXIT_IRQ_WINDOW_OPEN:
-            dprintf("irq_window_open\n");
+            DPRINTF("irq_window_open\n");
             break;
         case KVM_EXIT_SHUTDOWN:
-            dprintf("shutdown\n");
+            DPRINTF("shutdown\n");
             qemu_system_reset_request();
             ret = 1;
             break;
         case KVM_EXIT_UNKNOWN:
-            dprintf("kvm_exit_unknown\n");
+            DPRINTF("kvm_exit_unknown\n");
             break;
         case KVM_EXIT_FAIL_ENTRY:
-            dprintf("kvm_exit_fail_entry\n");
+            DPRINTF("kvm_exit_fail_entry\n");
             break;
         case KVM_EXIT_EXCEPTION:
-            dprintf("kvm_exit_exception\n");
+            DPRINTF("kvm_exit_exception\n");
             break;
         case KVM_EXIT_DEBUG:
-            dprintf("kvm_exit_debug\n");
+            DPRINTF("kvm_exit_debug\n");
 #ifdef KVM_CAP_SET_GUEST_DEBUG
             if (kvm_arch_debug(&run->debug.arch)) {
                 gdb_set_stop_cpu(env);
@@ -853,7 +853,7 @@ int kvm_cpu_exec(CPUState *env)
 #endif /* KVM_CAP_SET_GUEST_DEBUG */
             break;
         default:
-            dprintf("kvm_arch_handle_exit\n");
+            DPRINTF("kvm_arch_handle_exit\n");
             ret = kvm_arch_handle_exit(env, run);
             break;
         }
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index f77e488..5513472 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -34,10 +34,10 @@
 //#define DEBUG_KVM
 
 #ifdef DEBUG_KVM
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
     do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
 #else
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
     do { } while (0)
 #endif
 
@@ -957,7 +957,7 @@ int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
             struct kvm_interrupt intr;
             intr.irq = irq;
             /* FIXME: errors */
-            dprintf("injected interrupt %d\n", irq);
+            DPRINTF("injected interrupt %d\n", irq);
             kvm_vcpu_ioctl(env, KVM_INTERRUPT, &intr);
         }
     }
@@ -971,7 +971,7 @@ int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
     else
         run->request_interrupt_window = 0;
 
-    dprintf("setting tpr\n");
+    DPRINTF("setting tpr\n");
     run->cr8 = cpu_get_apic_tpr(env);
 
     return 0;
@@ -1009,7 +1009,7 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
 
     switch (run->exit_reason) {
     case KVM_EXIT_HLT:
-        dprintf("handle_hlt\n");
+        DPRINTF("handle_hlt\n");
         ret = kvm_handle_halt(env);
         break;
     }
commit 6ad6135dcaec584958179bb57a954d3f8d890919
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 18 14:22:14 2010 +0000

    Fix harmless if statements with empty body, spotted by clang
    
    These clang errors are harmless but worth fixing:
      CC    ppc-softmmu/usb-ohci.o
    /src/qemu/hw/usb-ohci.c:1104:59: error: if statement has empty body [-Wempty-body]
                              ohci->ctrl_head, ohci->ctrl_cur);
    /src/qemu/hw/usb-ohci.c:1371:57: error: if statement has empty body [-Wempty-body]
            DPRINTF("usb-ohci: port %d: SUSPEND\n", portnum);
      CC    sparc64-softmmu/translate.o
    /src/qemu/target-sparc/translate.c:3173:37: error: if statement has empty body [-Wempty-body]
                                        ; // XXX
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 034acd8..7cd5ca0 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1099,9 +1099,10 @@ static void ohci_sof(OHCIState *ohci)
 static void ohci_process_lists(OHCIState *ohci, int completion)
 {
     if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) {
-        if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head)
-          DPRINTF("usb-ohci: head %x, cur %x\n",
-                          ohci->ctrl_head, ohci->ctrl_cur);
+        if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) {
+            DPRINTF("usb-ohci: head %x, cur %x\n",
+                    ohci->ctrl_head, ohci->ctrl_cur);
+        }
         if (!ohci_service_ed_list(ohci, ohci->ctrl_head, completion)) {
             ohci->ctrl_cur = 0;
             ohci->status &= ~OHCI_STATUS_CLF;
@@ -1367,8 +1368,9 @@ static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
 
     ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES);
 
-    if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS))
+    if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) {
         DPRINTF("usb-ohci: port %d: SUSPEND\n", portnum);
+    }
 
     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) {
         DPRINTF("usb-ohci: port %d: RESET\n", portnum);
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 4f25278..b54c520 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -3169,8 +3169,9 @@ static void disas_sparc_insn(DisasContext * dc)
                                 break;
                             case 0xf: /* V9 sir, nop if user */
 #if !defined(CONFIG_USER_ONLY)
-                                if (supervisor(dc))
+                                if (supervisor(dc)) {
                                     ; // XXX
+                                }
 #endif
                                 break;
                             case 0x13: /* Graphics Status */
commit 676d9b9b883691cf99e298291dbc2ad7956516b9
Author: Artyom Tarasenko <atar4qemu at googlemail.com>
Date:   Sun Apr 18 00:34:03 2010 +0200

    sparc32 use empty_slot for missing RAM v1
    
    use empty_slot device for the RAM which is not installed
    
    Models without ECC don't trap when missing ram is accessed.
    
    v0->v1 compile only once and fix indentation
    
    Signed-off-by: Artyom Tarasenko <atar4qemu at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index ab1af88..f4d2faf 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -140,6 +140,7 @@ hw-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
 
 hw-obj-$(CONFIG_M48T59) += m48t59.o
 hw-obj-$(CONFIG_ESCC) += escc.o
+hw-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
 
 hw-obj-$(CONFIG_SERIAL) += serial.o
 hw-obj-$(CONFIG_PARALLEL) += parallel.o
diff --git a/default-configs/sparc-softmmu.mak b/default-configs/sparc-softmmu.mak
index 54899ff..becf880 100644
--- a/default-configs/sparc-softmmu.mak
+++ b/default-configs/sparc-softmmu.mak
@@ -7,3 +7,4 @@ CONFIG_M48T59=y
 CONFIG_PTIMER=y
 CONFIG_FDC=y
 CONFIG_VIRTIO_PCI=y
+CONFIG_EMPTY_SLOT=y
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 90e661d..9a79120 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -36,6 +36,7 @@
 #include "isa.h"
 #include "fw_cfg.h"
 #include "escc.h"
+#include "empty_slot.h"
 #include "qdev-addr.h"
 #include "loader.h"
 #include "elf.h"
@@ -820,6 +821,10 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size,
 
     /* set up devices */
     ram_init(0, RAM_size, hwdef->max_mem);
+    /* models without ECC don't trap when missing ram is accessed */
+    if (!hwdef->ecc_base) {
+        empty_slot_init(RAM_size, hwdef->max_mem - RAM_size);
+    }
 
     prom_init(hwdef->slavio_base, bios_name);
 
commit da9fcfa54486797a5f261b43ad0c0b2f8dc47181
Author: Artyom Tarasenko <atar4qemu at googlemail.com>
Date:   Sat Apr 17 01:10:04 2010 +0200

    create empty_slot device
    
    The empty_slot device emulates known to a bus but not connected devices.
    
    Signed-off-by: Artyom Tarasenko <atar4qemu at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/empty_slot.c b/hw/empty_slot.c
new file mode 100644
index 0000000..ac1f6eb
--- /dev/null
+++ b/hw/empty_slot.c
@@ -0,0 +1,92 @@
+/*
+ * QEMU Empty Slot
+ *
+ * The empty_slot device emulates known to a bus but not connected devices.
+ *
+ * Copyright (c) 2010 Artyom Tarasenko
+ *
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
+ * version.
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "empty_slot.h"
+
+//#define DEBUG_EMPTY_SLOT
+
+#ifdef DEBUG_EMPTY_SLOT
+#define DPRINTF(fmt, ...)                                       \
+    do { printf("empty_slot: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do {} while (0)
+#endif
+
+typedef struct EmptySlot {
+    SysBusDevice busdev;
+    uint64_t size;
+} EmptySlot;
+
+static uint32_t empty_slot_readl(void *opaque, target_phys_addr_t addr)
+{
+    DPRINTF("read from " TARGET_FMT_plx "\n", addr);
+    return 0;
+}
+
+static void empty_slot_writel(void *opaque, target_phys_addr_t addr,
+                              uint32_t val)
+{
+    DPRINTF("write 0x%x to " TARGET_FMT_plx "\n", val, addr);
+}
+
+CPUReadMemoryFunc * const empty_slot_read[3] = {
+    empty_slot_readl,
+    empty_slot_readl,
+    empty_slot_readl,
+};
+
+static CPUWriteMemoryFunc * const empty_slot_write[3] = {
+    empty_slot_writel,
+    empty_slot_writel,
+    empty_slot_writel,
+};
+
+void empty_slot_init(target_phys_addr_t addr, uint64_t slot_size)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    EmptySlot *e;
+
+    dev = qdev_create(NULL, "empty_slot");
+    s = sysbus_from_qdev(dev);
+    e = FROM_SYSBUS(EmptySlot, s);
+    e->size = slot_size;
+
+    qdev_init_nofail(dev);
+
+    sysbus_mmio_map(s, 0, addr);
+}
+
+static int empty_slot_init1(SysBusDevice *dev)
+{
+    EmptySlot *s = FROM_SYSBUS(EmptySlot, dev);
+    ram_addr_t empty_slot_offset;
+
+    empty_slot_offset = cpu_register_io_memory(empty_slot_read,
+                                               empty_slot_write, s);
+    sysbus_init_mmio(dev, s->size, empty_slot_offset | IO_MEM_RAM);
+    return 0;
+}
+
+static SysBusDeviceInfo empty_slot_info = {
+    .init = empty_slot_init1,
+    .qdev.name  = "empty_slot",
+    .qdev.size  = sizeof(EmptySlot),
+};
+
+static void empty_slot_register_devices(void)
+{
+    sysbus_register_withprop(&empty_slot_info);
+}
+
+device_init(empty_slot_register_devices);
diff --git a/hw/empty_slot.h b/hw/empty_slot.h
new file mode 100644
index 0000000..78dc91d
--- /dev/null
+++ b/hw/empty_slot.h
@@ -0,0 +1,2 @@
+/* empty_slot.c */
+void empty_slot_init(target_phys_addr_t addr, uint64_t slot_size);
commit 3c83eb4f17ffa981cb60b965087769b808062a3a
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Apr 18 08:45:03 2010 +0000

    Fix harmless if statements with empty body, spotted by clang
    
    These clang errors are harmless but worth fixing:
      CC    libhw64/fdc.o
    /src/qemu/hw/fdc.c:998:74: error: if statement has empty body [-Wempty-body]
            FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval);
      CC    libhw64/cuda.o
    /src/qemu/hw/cuda.c:320:66: error: if statement has empty body [-Wempty-body]
            CUDA_DPRINTF("read: reg=0x%x val=%02x\n", (int)addr, val);
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/cuda.c b/hw/cuda.c
index 83ae68a..50950d9 100644
--- a/hw/cuda.c
+++ b/hw/cuda.c
@@ -316,8 +316,10 @@ static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr)
         val = s->anh;
         break;
     }
-    if (addr != 13 || val != 0)
+    if (addr != 13 || val != 0) {
         CUDA_DPRINTF("read: reg=0x%x val=%02x\n", (int)addr, val);
+    }
+
     return val;
 }
 
diff --git a/hw/fdc.c b/hw/fdc.c
index 93a7f1d..c4ca9e9 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -994,8 +994,9 @@ static uint32_t fdctrl_read_dir(FDCtrl *fdctrl)
 #endif
         )
         retval |= FD_DIR_DSKCHG;
-    if (retval != 0)
+    if (retval != 0) {
         FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval);
+    }
 
     return retval;
 }
commit 606257c6f2dbbaa63f462e557f15a5f7364967a6
Author: malc <av1474 at comtv.ru>
Date:   Sun Apr 18 08:46:29 2010 +0400

    tcg/ppc: Remove redundant comparison from brcond2
    
    Signed-off-by: malc <av1474 at comtv.ru>

diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index d559214..2b85928 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -1106,10 +1106,9 @@ static void tcg_out_cr7eq_from_cond (TCGContext *s, const TCGArg *args,
     case TCG_COND_GEU:
         op = (b->bit1 != b->bit2) ? CRANDC : CRAND;
         tcg_out_cmp (s, b->cond2, args[1], args[3], const_args[3], 5);
-        tcg_out_cmp (s, TCG_COND_EQ, args[1], args[3], const_args[3], 6);
         tcg_out_cmp (s, tcg_unsigned_cond (cond), args[0], args[2],
                      const_args[2], 7);
-        tcg_out32 (s, op | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, b->bit2));
+        tcg_out32 (s, op | BT (7, CR_EQ) | BA (5, CR_EQ) | BB (7, b->bit2));
         tcg_out32 (s, CROR | BT (7, CR_EQ) | BA (5, b->bit1) | BB (7, CR_EQ));
         break;
     default:
commit 2d8ebcf94ee461dea9eb363be7becb769d9a962f
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Apr 17 16:25:10 2010 +0000

    Fix --enable-profiler compilation.
    
    There's a header file inclusion ordering problem between cpu-all.h
    and qemu-timer.h, such that cpu_get_real_ticks is not defined when
    we attempt to use it in profile_getclock.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpu-all.h b/cpu-all.h
index 3004d0f..7b1594c 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -943,18 +943,6 @@ void dump_exec_info(FILE *f,
 int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
                         uint8_t *buf, int len, int is_write);
 
-/* profiling */
-#ifdef CONFIG_PROFILER
-static inline int64_t profile_getclock(void)
-{
-    return cpu_get_real_ticks();
-}
-
-extern int64_t qemu_time, qemu_time_start;
-extern int64_t tlb_flush_time;
-extern int64_t dev_time;
-#endif
-
 void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
                         uint64_t mcg_status, uint64_t addr, uint64_t misc);
 
diff --git a/qemu-timer.h b/qemu-timer.h
index d2e15f4..62da887 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -236,4 +236,15 @@ static inline int can_do_io(CPUState *env)
 }
 #endif
 
+#ifdef CONFIG_PROFILER
+static inline int64_t profile_getclock(void)
+{
+    return cpu_get_real_ticks();
+}
+
+extern int64_t qemu_time, qemu_time_start;
+extern int64_t tlb_flush_time;
+extern int64_t dev_time;
+#endif
+
 #endif
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 6db96d0..54f7fa9 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -47,6 +47,7 @@
 #include "qemu-common.h"
 #include "cache-utils.h"
 #include "host-utils.h"
+#include "qemu-timer.h"
 
 /* Note: the long term plan is to reduce the dependancies on the QEMU
    CPU definitions. Currently they are used for qemu_ld/st
commit 42a8aa8393b931c92662578bc6b0b82c54fe63f8
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Apr 17 16:25:08 2010 +0000

    target-sparc: Free instruction temporaries.
    
    Rather than creating new temporaries for constants, use the
    ones created in disas_sparc_insn.  Remember the temps created
    there so that they can be freed at the end of the function.
    
    Profile data collected by TCG while booting sparc-test kernel:
    
    -avg temps/TB    70.61 max=421
    +avg temps/TB    62.75 max=66
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index addb1e1..4f25278 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -49,7 +49,7 @@ static TCGv cpu_y;
 #ifndef CONFIG_USER_ONLY
 static TCGv cpu_tbr;
 #endif
-static TCGv cpu_cond, cpu_src1, cpu_src2, cpu_dst, cpu_addr, cpu_val;
+static TCGv cpu_cond, cpu_dst, cpu_addr, cpu_val;
 #ifdef TARGET_SPARC64
 static TCGv_i32 cpu_xcc, cpu_asi, cpu_fprs;
 static TCGv cpu_gsr;
@@ -1631,12 +1631,13 @@ static inline TCGv get_src1(unsigned int insn, TCGv def)
     unsigned int rs1;
 
     rs1 = GET_FIELD(insn, 13, 17);
-    if (rs1 == 0)
-        r_rs1 = tcg_const_tl(0); // XXX how to free?
-    else if (rs1 < 8)
+    if (rs1 == 0) {
+        tcg_gen_movi_tl(def, 0);
+    } else if (rs1 < 8) {
         r_rs1 = cpu_gregs[rs1];
-    else
+    } else {
         tcg_gen_ld_tl(def, cpu_regwptr, (rs1 - 8) * sizeof(target_ulong));
+    }
     return r_rs1;
 }
 
@@ -1645,20 +1646,17 @@ static inline TCGv get_src2(unsigned int insn, TCGv def)
     TCGv r_rs2 = def;
 
     if (IS_IMM) { /* immediate */
-        target_long simm;
-
-        simm = GET_FIELDs(insn, 19, 31);
-        r_rs2 = tcg_const_tl(simm); // XXX how to free?
+        target_long simm = GET_FIELDs(insn, 19, 31);
+        tcg_gen_movi_tl(def, simm);
     } else { /* register */
-        unsigned int rs2;
-
-        rs2 = GET_FIELD(insn, 27, 31);
-        if (rs2 == 0)
-            r_rs2 = tcg_const_tl(0); // XXX how to free?
-        else if (rs2 < 8)
+        unsigned int rs2 = GET_FIELD(insn, 27, 31);
+        if (rs2 == 0) {
+            tcg_gen_movi_tl(def, 0);
+        } else if (rs2 < 8) {
             r_rs2 = cpu_gregs[rs2];
-        else
+        } else {
             tcg_gen_ld_tl(def, cpu_regwptr, (rs2 - 8) * sizeof(target_ulong));
+        }
     }
     return r_rs2;
 }
@@ -1701,6 +1699,7 @@ static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_ptr cpu_env)
 static void disas_sparc_insn(DisasContext * dc)
 {
     unsigned int insn, opc, rs1, rs2, rd;
+    TCGv cpu_src1, cpu_src2, cpu_tmp1, cpu_tmp2;
     target_long simm;
 
     if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
@@ -1710,8 +1709,8 @@ static void disas_sparc_insn(DisasContext * dc)
 
     rd = GET_FIELD(insn, 2, 6);
 
-    cpu_src1 = tcg_temp_new(); // const
-    cpu_src2 = tcg_temp_new(); // const
+    cpu_tmp1 = cpu_src1 = tcg_temp_new();
+    cpu_tmp2 = cpu_src2 = tcg_temp_new();
 
     switch (opc) {
     case 0:                     /* branches/sethi */
@@ -4601,7 +4600,7 @@ static void disas_sparc_insn(DisasContext * dc)
         dc->npc = dc->npc + 4;
     }
  jmp_insn:
-    return;
+    goto egress;
  illegal_insn:
     {
         TCGv_i32 r_const;
@@ -4612,7 +4611,7 @@ static void disas_sparc_insn(DisasContext * dc)
         tcg_temp_free_i32(r_const);
         dc->is_br = 1;
     }
-    return;
+    goto egress;
  unimp_flush:
     {
         TCGv_i32 r_const;
@@ -4623,7 +4622,7 @@ static void disas_sparc_insn(DisasContext * dc)
         tcg_temp_free_i32(r_const);
         dc->is_br = 1;
     }
-    return;
+    goto egress;
 #if !defined(CONFIG_USER_ONLY)
  priv_insn:
     {
@@ -4635,19 +4634,19 @@ static void disas_sparc_insn(DisasContext * dc)
         tcg_temp_free_i32(r_const);
         dc->is_br = 1;
     }
-    return;
+    goto egress;
 #endif
  nfpu_insn:
     save_state(dc, cpu_cond);
     gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
     dc->is_br = 1;
-    return;
+    goto egress;
 #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
  nfq_insn:
     save_state(dc, cpu_cond);
     gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
     dc->is_br = 1;
-    return;
+    goto egress;
 #endif
 #ifndef TARGET_SPARC64
  ncp_insn:
@@ -4660,8 +4659,11 @@ static void disas_sparc_insn(DisasContext * dc)
         tcg_temp_free(r_const);
         dc->is_br = 1;
     }
-    return;
+    goto egress;
 #endif
+ egress:
+    tcg_temp_free(cpu_tmp1);
+    tcg_temp_free(cpu_tmp2);
 }
 
 static inline void gen_intermediate_code_internal(TranslationBlock * tb,
commit 058ed88cc115e6b8323a39d7f05e6cf91b19b35e
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Apr 17 16:25:06 2010 +0000

    target-sparc: Fix TARGET_{PHYS,VIRT}_ADDR_SPACE_BITS.
    
    The 32 and 64-bit definitions were swapped in the ifdef.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 580f4d4..0e7f390 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -7,18 +7,18 @@
 #define TARGET_LONG_BITS 32
 #define TARGET_FPREGS 32
 #define TARGET_PAGE_BITS 12 /* 4k */
+#define TARGET_PHYS_ADDR_SPACE_BITS 36
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+#else
+#define TARGET_LONG_BITS 64
+#define TARGET_FPREGS 64
+#define TARGET_PAGE_BITS 13 /* 8k */
 #define TARGET_PHYS_ADDR_SPACE_BITS 41
 # ifdef TARGET_ABI32
 #  define TARGET_VIRT_ADDR_SPACE_BITS 32
 # else
 #  define TARGET_VIRT_ADDR_SPACE_BITS 44
 # endif
-#else
-#define TARGET_LONG_BITS 64
-#define TARGET_FPREGS 64
-#define TARGET_PAGE_BITS 13 /* 8k */
-#define TARGET_PHYS_ADDR_SPACE_BITS 36
-#define TARGET_VIRT_ADDR_SPACE_BITS 32
 #endif
 
 #define CPUState struct CPUSPARCState
commit cca1d527efaa8ce65b4a78f936af82cc7cc96e82
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Apr 17 16:25:04 2010 +0000

    Sparc: fix PC/NPC during FPU traps
    
    All FPU instructions can trap, so save PC/NPC state before
    executing them.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 2c07385..addb1e1 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2155,6 +2155,7 @@ static void disas_sparc_insn(DisasContext * dc)
                 rs1 = GET_FIELD(insn, 13, 17);
                 rs2 = GET_FIELD(insn, 27, 31);
                 xop = GET_FIELD(insn, 18, 26);
+                save_state(dc, cpu_cond);
                 switch (xop) {
                 case 0x1: /* fmovs */
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);
@@ -2468,6 +2469,7 @@ static void disas_sparc_insn(DisasContext * dc)
                 rs1 = GET_FIELD(insn, 13, 17);
                 rs2 = GET_FIELD(insn, 27, 31);
                 xop = GET_FIELD(insn, 18, 26);
+                save_state(dc, cpu_cond);
 #ifdef TARGET_SPARC64
                 if ((xop & 0x11f) == 0x005) { // V9 fmovsr
                     int l1;
commit 655feed5d9889a0391023ee518bcba4dbd09438c
Author: malc <av1474 at comtv.ru>
Date:   Sat Apr 17 07:59:26 2010 +0400

    tcg: Add missing static qualifier
    
    Build breaks otherwise when USE_LIVENESS_ANALYSIS is not defined.
    
    Signed-off-by: malc <av1474 at comtv.ru>

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 3294743..6db96d0 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1278,7 +1278,7 @@ static void tcg_liveness_analysis(TCGContext *s)
 }
 #else
 /* dummy liveness analysis */
-void tcg_liveness_analysis(TCGContext *s)
+static void tcg_liveness_analysis(TCGContext *s)
 {
     int nb_ops;
     nb_ops = gen_opc_ptr - gen_opc_buf;
commit efe72c8de7b5f07bf8348d51ed4bb4f004e50748
Author: malc <av1474 at comtv.ru>
Date:   Sat Apr 17 07:58:08 2010 +0400

    tcg/ppc: Fix signed versions of brcond2
    
    Thanks to: Alexander Graff, Thomas Gleixner and Andreas Faerber.
    
    Signed-off-by: malc <av1474 at comtv.ru>

diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 6f044d6..d559214 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -1107,7 +1107,8 @@ static void tcg_out_cr7eq_from_cond (TCGContext *s, const TCGArg *args,
         op = (b->bit1 != b->bit2) ? CRANDC : CRAND;
         tcg_out_cmp (s, b->cond2, args[1], args[3], const_args[3], 5);
         tcg_out_cmp (s, TCG_COND_EQ, args[1], args[3], const_args[3], 6);
-        tcg_out_cmp (s, cond, args[0], args[2], const_args[2], 7);
+        tcg_out_cmp (s, tcg_unsigned_cond (cond), args[0], args[2],
+                     const_args[2], 7);
         tcg_out32 (s, op | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, b->bit2));
         tcg_out32 (s, CROR | BT (7, CR_EQ) | BA (5, b->bit1) | BB (7, CR_EQ));
         break;
commit a491cf58dbe320511b1d3d053870baba2c7f0384
Author: Arnaud Lacombe <lacombar at gmail.com>
Date:   Tue Apr 13 21:25:25 2010 -0400

    Fix format strings
    
    This fix the following build failure:
    
      CC    libdis-user/microblaze-dis.o
    cc1: warnings being treated as errors
    microblaze-dis.c: In function 'print_insn_microblaze':
    microblaze-dis.c:829: warning: format '%04x' expects type 'unsigned int',
    but argument 4 has type 'long unsigned int'
    microblaze-dis.c:962: warning: format '%04x' expects type 'unsigned int',
    but argument 4 has type 'long unsigned int'
    
    Reported-at: http://www.monstr.eu/wiki/doku.php?id=log:2010-04-13_12_10_00
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/microblaze-dis.c b/microblaze-dis.c
index b26572f..9235fd8 100644
--- a/microblaze-dis.c
+++ b/microblaze-dis.c
@@ -826,7 +826,7 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
   prev_insn_vma = curr_insn_vma;
 
   if (op->name == 0) {
-    fprintf (stream, ".short 0x%04x", inst);
+    fprintf (stream, ".short 0x%04lx", inst);
   }
   else
     {
@@ -959,7 +959,7 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
      break;
   default:
 	  /* if the disassembler lags the instruction set */
-	  fprintf (stream, "\tundecoded operands, inst is 0x%04x", inst);
+	  fprintf (stream, "\tundecoded operands, inst is 0x%04lx", inst);
 	  break;
 	}
     }


More information about the Spice-commits mailing list