[packages/qemu-kvm] - updated to 1.2.0 - removed obsolete Fix_save-restore_of_in-kernel_i8259,enable_architectural_PMU_c

qboosh qboosh at pld-linux.org
Mon Nov 5 20:20:54 CET 2012


commit a95b7932884e3f5d67db5f78de3f1cc602782d98
Author: Jakub Bogusz <qboosh at pld-linux.org>
Date:   Mon Nov 5 20:20:51 2012 +0100

    - updated to 1.2.0
    - removed obsolete Fix_save-restore_of_in-kernel_i8259,enable_architectural_PMU_cpuid_leaf,virtio-scsi_support,cflags,1.0.1 patches
    - added fixes patch (fixes mips emu build after kvm-specific acpi changes)

 Fix_save-restore_of_in-kernel_i8259.patch |   87 --
 enable_architectural_PMU_cpuid_leaf.patch |   37 -
 qemu-1.0.1.patch                          | 2131 -----------------------------
 qemu-kvm-cflags.patch                     |   13 -
 qemu-kvm-fixes.patch                      |   10 +
 qemu-kvm.spec                             |  100 +-
 qemu_virtio-scsi_support.patch            | 1652 ----------------------
 7 files changed, 83 insertions(+), 3947 deletions(-)
---
diff --git a/qemu-kvm.spec b/qemu-kvm.spec
index 907f86c..4925fb5 100644
--- a/qemu-kvm.spec
+++ b/qemu-kvm.spec
@@ -5,12 +5,12 @@
 Summary:	QEMU CPU Emulator
 Summary(pl.UTF-8):	QEMU - emulator procesora
 Name:		qemu-kvm
-Version:	1.0
-Release:	8
-License:	GPL
+Version:	1.2.0
+Release:	1
+License:	GPL v2+
 Group:		Applications/Emulators
 Source0:	http://downloads.sourceforge.net/kvm/%{name}-%{version}.tar.gz
-# Source0-md5:	00a825db46a70ba8ef9fc95da9cc7c1e
+# Source0-md5:	d7b18b673c48abfee65a9c0245df0415
 Source1:	http://www.linuxtogo.org/~kevin/SeaBIOS/bios.bin-1.6.3
 # Source1-md5:	9d3b8a7fbd65e5250b9d005a79ffaf34
 Source2:	qemu.binfmt
@@ -28,13 +28,7 @@ Source10:	ksmtuned.conf
 Source11:	qemu-guest-agent.service
 Source12:	99-qemu-guest-agent.rules
 Patch0:		%{name}-whitelist.patch
-Patch1:		Fix_save-restore_of_in-kernel_i8259.patch
-# Feature patches, should be in 1.1 before release
-Patch2:		enable_architectural_PMU_cpuid_leaf.patch
-Patch3:		qemu_virtio-scsi_support.patch
-Patch4:		qemu-kvm-cflags.patch
-# Update to qemu 1.0.1
-Patch100:	qemu-1.0.1.patch
+Patch1:		%{name}-fixes.patch
 URL:		http://www.linux-kvm.org/
 BuildRequires:	SDL-devel >= 1.2.1
 BuildRequires:	alsa-lib-devel
@@ -306,6 +300,23 @@ dobrą szybkość emulacji dzięki użyciu translacji dynamicznej.
 
 Ten pakiet zawiera emulator systemu z procesorem MIPS.
 
+%package system-or32
+Summary:	QEMU system emulator for OpenRISC
+Summary(pl.UTF-8):	QEMU - emulator systemu z procesorem OpenRISC
+Group:		Development/Tools
+Requires:	%{name}-common = %{version}-%{release}
+
+%description system-or32
+QEMU is a generic and open source processor emulator which achieves a
+good emulation speed by using dynamic translation.
+
+This package provides the system emulator with OpenRISC CPU.
+
+%description system-or32 -l pl.UTF-8
+QEMU to ogólny, mający otwarte źródła emulator procesora, osiągający
+dobrą szybkość emulacji dzięki użyciu translacji dynamicznej.
+
+Ten pakiet zawiera emulator systemu z procesorem OpenRISC.
 
 %package system-ppc
 Summary:	QEMU system emulator for PowerPC
@@ -379,6 +390,24 @@ dobrą szybkość emulacji dzięki użyciu translacji dynamicznej.
 
 Ten pakiet zawiera emulator systemu z procesorem SPARC/SPARC64.
 
+%package system-unicore32
+Summary:	QEMU system emulator for UniCore32
+Summary(pl.UTF-8):	QEMU - emulator systemu z procesorem UniCore32
+Group:		Development/Tools
+Requires:	%{name}-common = %{version}-%{release}
+
+%description system-unicore32
+QEMU is a generic and open source processor emulator which achieves a
+good emulation speed by using dynamic translation.
+
+This package provides the system emulator with UniCore32 CPU.
+
+%description system-unicore32 -l pl.UTF-8
+QEMU to ogólny, mający otwarte źródła emulator procesora, osiągający
+dobrą szybkość emulacji dzięki użyciu translacji dynamicznej.
+
+Ten pakiet zawiera emulator systemu z procesorem UniCore32.
+
 %package system-x86
 Summary:	QEMU system emulator for x86
 Summary(pl.UTF-8):	QEMU - emulator systemu z procesorem x86
@@ -450,13 +479,7 @@ Ten pakiet nie musi być zainstalowany w systemie hosta.
 %prep
 %setup -q
 %patch0 -p1
-
 %patch1 -p1
-%patch2 -p1
-%patch3 -p1
-%patch4 -p1
-
-%patch100 -p1
 
 cp -a %{SOURCE1} pc-bios/bios.bin
 
@@ -478,11 +501,9 @@ ln -s ../error.h qapi/error.h
 	--enable-vnc-sasl \
 	--enable-vnc-jpeg \
 	--enable-vnc-png \
-	--enable-vnc-thread \
 	--enable-curses \
 	--enable-bluez \
-	--enable-kvm-device-assignment \
-	--enable-kvm-pit \
+	--enable-kvm \
 	--enable-system \
 	--enable-user \
 	--enable-mixemu \
@@ -498,9 +519,14 @@ ln -s ../error.h qapi/error.h
 	%{__enable_disable spice} \
 	--disable-strip
 
-%{__make} V=99
+# note: CONFIG_QEMU_HELPERDIR is used when compiling, libexecdir when installing;
+# --libexecdir in configure is nop
+%{__make} \
+	V=99 \
+	CONFIG_QEMU_HELPERDIR="%{_libdir}"
 cp -a x86_64-softmmu/qemu-system-x86_64 qemu-kvm
-%{__make} clean V=99
+%{__make} clean \
+	V=99
 %endif
 
 ./configure \
@@ -516,7 +542,6 @@ cp -a x86_64-softmmu/qemu-system-x86_64 qemu-kvm
 	--enable-vnc-sasl \
 	--enable-vnc-jpeg \
 	--enable-vnc-png \
-	--enable-vnc-thread \
 	--enable-curses \
 	--enable-bluez \
 	--disable-kvm \
@@ -537,7 +562,11 @@ cp -a x86_64-softmmu/qemu-system-x86_64 qemu-kvm
 %endif
 	--disable-strip
 
-%{__make} V=99
+# note: CONFIG_QEMU_HELPERDIR is used when compiling, libexecdir when installing;
+# --libexecdir in configure is nop
+%{__make} \
+	V=99 \
+	CONFIG_QEMU_HELPERDIR="%{_libdir}"
 
 %{__cc} %{SOURCE7} %{rpmcflags} -o ksmctl
 
@@ -549,7 +578,8 @@ install -d $RPM_BUILD_ROOT{%{systemdunitdir},/usr/lib/binfmt.d} \
 
 %{__make} install \
 	V=99 \
-	DESTDIR=$RPM_BUILD_ROOT
+	DESTDIR=$RPM_BUILD_ROOT \
+	libexecdir=%{_libdir}
 
 install -d $RPM_BUILD_ROOT%{_sysconfdir}
 cat <<'EOF' > $RPM_BUILD_ROOT%{_sysconfdir}/qemu-ifup
@@ -570,7 +600,7 @@ install -p %{SOURCE10} $RPM_BUILD_ROOT%{_sysconfdir}/ksmtuned.conf
 %ifarch %{ix86} %{x8664}
 install qemu-kvm $RPM_BUILD_ROOT%{_bindir}/qemu-system-x86_64
 ln -s qemu-system-x86_64 $RPM_BUILD_ROOT%{_bindir}/qemu-kvm
-install kvm/kvm_stat $RPM_BUILD_ROOT%{_bindir}
+install scripts/kvm/kvm_stat $RPM_BUILD_ROOT%{_bindir}
 install -p %{SOURCE3} $RPM_BUILD_ROOT/etc/modules-load.d/kvm.conf
 install -p %{SOURCE4} $RPM_BUILD_ROOT%{_sysconfdir}/udev/rules.d
 %endif
@@ -603,6 +633,7 @@ done < %{SOURCE2}
 
 # already packaged
 %{__rm} $RPM_BUILD_ROOT%{_docdir}/qemu/qemu-{doc,tech}.html
+%{__rm} $RPM_BUILD_ROOT%{_docdir}/qemu/qmp-commands.txt
 
 %clean
 rm -rf $RPM_BUILD_ROOT
@@ -652,7 +683,7 @@ fi
 
 %files common
 %defattr(644,root,root,755)
-%doc README qemu-doc.html qemu-tech.html
+%doc README qemu-doc.html qemu-tech.html QMP/qmp-commands.txt
 %attr(755,root,root) %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/qemu-ifup
 %dir %{_sysconfdir}/qemu
 %attr(755,root,root) %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/qemu/target-*.conf
@@ -662,13 +693,19 @@ fi
 %{systemdunitdir}/ksm.service
 %{systemdunitdir}/ksmtuned.service
 %attr(755,root,root) %{_bindir}/qemu-nbd
+%attr(755,root,root) %{_bindir}/virtfs-proxy-helper
+%attr(755,root,root) %{_bindir}/vscclient
+%attr(755,root,root) %{_libdir}/qemu-bridge-helper
 %attr(755,root,root) %{_sbindir}/ksmctl
 %attr(755,root,root) %{_sbindir}/ksmtuned
 %{_mandir}/man1/qemu.1*
+%{_mandir}/man1/virtfs-proxy-helper.1*
 %{_mandir}/man8/qemu-nbd.8*
 
 %dir %{_datadir}/qemu
+%{_datadir}/qemu/cpus-*.conf
 %{_datadir}/qemu/keymaps
+%{_datadir}/qemu/qemu-icon.bmp
 # various bios images
 %{_datadir}/qemu/*.bin
 %{_datadir}/qemu/*.rom
@@ -696,6 +733,7 @@ fi
 %attr(755,root,root) %{_bindir}/qemu-microblazeel
 %attr(755,root,root) %{_bindir}/qemu-mips
 %attr(755,root,root) %{_bindir}/qemu-mipsel
+%attr(755,root,root) %{_bindir}/qemu-or32
 %attr(755,root,root) %{_bindir}/qemu-ppc
 %attr(755,root,root) %{_bindir}/qemu-ppc64
 %attr(755,root,root) %{_bindir}/qemu-ppc64abi32
@@ -740,6 +778,10 @@ fi
 %attr(755,root,root) %{_bindir}/qemu-system-mips64
 %attr(755,root,root) %{_bindir}/qemu-system-mips64el
 
+%files system-or32
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_bindir}/qemu-system-or32
+
 %files system-ppc
 %defattr(644,root,root,755)
 %attr(755,root,root) %{_bindir}/qemu-system-ppc
@@ -760,6 +802,10 @@ fi
 %attr(755,root,root) %{_bindir}/qemu-system-sparc
 %attr(755,root,root) %{_bindir}/qemu-system-sparc64
 
+%files system-unicore32
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_bindir}/qemu-system-unicore32
+
 %files system-x86
 %defattr(644,root,root,755)
 %ifarch %{ix86} %{x8664}
diff --git a/Fix_save-restore_of_in-kernel_i8259.patch b/Fix_save-restore_of_in-kernel_i8259.patch
deleted file mode 100644
index d475baf..0000000
--- a/Fix_save-restore_of_in-kernel_i8259.patch
+++ /dev/null
@@ -1,87 +0,0 @@
-As the qemu-kvm version of the i8259 contains KVM bits, it still has to
-be compiled per target. This unbreaks migration of the i8259.
-
-Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
----
-
-Not sure if anyone bothers (no one should actually use qemu-kvm for
-targets != x86), but let's avoid needless breakages of other targets
-requiring the i8259.
-
- Makefile.objs   |    2 +-
- Makefile.target |    8 ++++----
- hw/i8259.c      |    2 --
- 3 files changed, 5 insertions(+), 7 deletions(-)
-
-diff --git a/Makefile.objs b/Makefile.objs
-index 13afd19..77237e1 100644
---- a/Makefile.objs
-+++ b/Makefile.objs
-@@ -223,7 +223,7 @@ hw-obj-$(CONFIG_APPLESMC) += applesmc.o
- hw-obj-$(CONFIG_SMARTCARD) += usb-ccid.o ccid-card-passthru.o
- hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
- hw-obj-$(CONFIG_USB_REDIR) += usb-redir.o
--hw-obj-$(CONFIG_I8259) += i8259.o
-+# hw-obj-$(CONFIG_I8259) += i8259.o
- 
- # PPC devices
- hw-obj-$(CONFIG_PREP_PCI) += prep_pci.o
-diff --git a/Makefile.target b/Makefile.target
-index 0b610ad..29eaa68 100644
---- a/Makefile.target
-+++ b/Makefile.target
-@@ -236,7 +236,7 @@ obj-$(CONFIG_IVSHMEM) += ivshmem.o
- 
- # Hardware support
- obj-i386-y += vga.o
--obj-i386-y += mc146818rtc.o pc.o
-+obj-i386-y += mc146818rtc.o pc.o i8259.o
- obj-i386-y += cirrus_vga.o sga.o apic.o ioapic.o piix_pci.o
- obj-i386-y += vmport.o
- obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
-@@ -255,7 +255,7 @@ obj-i386-$(CONFIG_KVM_DEVICE_ASSIGNMENT) += device-assignment.o
- obj-ppc-y = ppc.o ppc_booke.o
- obj-ppc-y += vga.o
- # PREP target
--obj-ppc-y += mc146818rtc.o
-+obj-ppc-y += mc146818rtc.o i8254.o i8259.o
- obj-ppc-y += ppc_prep.o
- # OldWorld PowerMac
- obj-ppc-y += ppc_oldworld.o
-@@ -311,7 +311,7 @@ obj-mips-y += acpi.o acpi_piix4.o
- obj-mips-y += mips_addr.o mips_timer.o mips_int.o
- obj-mips-y += vga.o
- obj-mips-y += jazz_led.o
--obj-mips-y += gt64xxx.o mc146818rtc.o
-+obj-mips-y += gt64xxx.o mc146818rtc.o i8259.o
- obj-mips-y += cirrus_vga.o
- obj-mips-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o
- 
-@@ -392,7 +392,7 @@ obj-m68k-y += m68k-semi.o dummy_m68k.o
- 
- obj-s390x-y = s390-virtio-bus.o s390-virtio.o
- 
--obj-alpha-y = mc146818rtc.o
-+obj-alpha-y = mc146818rtc.o i8254.o i8259.o
- obj-alpha-y += vga.o cirrus_vga.o
- obj-alpha-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
- 
-diff --git a/hw/i8259.c b/hw/i8259.c
-index fa63e83..a9ea9c9 100644
---- a/hw/i8259.c
-+++ b/hw/i8259.c
-@@ -697,8 +697,6 @@ static int kvm_kernel_pic_load_from_user(PicState *s)
-     return 0;
- }
- 
--extern void apic_set_irq_delivered(void);
--
- static void kvm_i8259_set_irq(void *opaque, int irq, int level)
- {
-     int pic_ret;
--- 
-1.7.3.4
---
-To unsubscribe from this list: send the line "unsubscribe kvm" in
-the body of a message to majordomo at vger.kernel.org
-More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff --git a/enable_architectural_PMU_cpuid_leaf.patch b/enable_architectural_PMU_cpuid_leaf.patch
deleted file mode 100644
index f0a7415..0000000
--- a/enable_architectural_PMU_cpuid_leaf.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-commit a0fa82085e175bf8ce6d69a3f83695f81af2a649
-Author: Gleb Natapov <gleb at redhat.com>
-Date:   Thu Dec 15 12:44:05 2011 +0200
-
-    enable architectural PMU cpuid leaf for kvm
-    
-    Signed-off-by: Gleb Natapov <gleb at redhat.com>
-    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
-
-diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
-index 0b3af90..91a104b 100644
---- a/target-i386/cpuid.c
-+++ b/target-i386/cpuid.c
-@@ -1180,10 +1180,19 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
-         break;
-     case 0xA:
-         /* Architectural Performance Monitoring Leaf */
--        *eax = 0;
--        *ebx = 0;
--        *ecx = 0;
--        *edx = 0;
-+        if (kvm_enabled()) {
-+            KVMState *s = env->kvm_state;
-+
-+            *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX);
-+            *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX);
-+            *ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX);
-+            *edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX);
-+        } else {
-+            *eax = 0;
-+            *ebx = 0;
-+            *ecx = 0;
-+            *edx = 0;
-+        }
-         break;
-     case 0xD:
-         /* Processor Extended State */
diff --git a/qemu-1.0.1.patch b/qemu-1.0.1.patch
deleted file mode 100644
index 225eaad..0000000
--- a/qemu-1.0.1.patch
+++ /dev/null
@@ -1,2131 +0,0 @@
-diff -urN qemu-1.0/block/rbd.c qemu-1.0.1/block/rbd.c
---- qemu-1.0/block/rbd.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/block/rbd.c	2012-02-17 20:45:39.000000000 +0100
-@@ -808,7 +808,7 @@
-     } while (snap_count == -ERANGE);
- 
-     if (snap_count <= 0) {
--        return snap_count;
-+        goto done;
-     }
- 
-     sn_tab = g_malloc0(snap_count * sizeof(QEMUSnapshotInfo));
-@@ -827,6 +827,7 @@
-     }
-     rbd_snap_list_end(snaps);
- 
-+ done:
-     *psn_tab = sn_tab;
-     return snap_count;
- }
-diff -urN qemu-1.0/configure qemu-1.0.1/configure
---- qemu-1.0/configure	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/configure	2012-02-17 20:45:39.000000000 +0100
-@@ -1116,7 +1116,7 @@
- 
- if test "$pie" = ""; then
-   case "$cpu-$targetos" in
--    i386-Linux|x86_64-Linux)
-+    i386-Linux|x86_64-Linux|i386-OpenBSD|x86_64-OpenBSD)
-       ;;
-     *)
-       pie="no"
-diff -urN qemu-1.0/console.c qemu-1.0.1/console.c
---- qemu-1.0/console.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/console.c	2012-02-17 20:45:39.000000000 +0100
-@@ -186,7 +186,9 @@
-         consoles[0]->hw_screen_dump(consoles[0]->hw, filename);
-     }
- 
--    console_select(previous_active_console->index);
-+    if (previous_active_console) {
-+        console_select(previous_active_console->index);
-+    }
- }
- 
- void vga_hw_text_update(console_ch_t *chardata)
-diff -urN qemu-1.0/coroutine-ucontext.c qemu-1.0.1/coroutine-ucontext.c
---- qemu-1.0/coroutine-ucontext.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/coroutine-ucontext.c	2012-02-17 20:45:39.000000000 +0100
-@@ -35,6 +35,10 @@
-     POOL_MAX_SIZE = 64,
- };
- 
-+/** Free list to speed up creation */
-+static QLIST_HEAD(, Coroutine) pool = QLIST_HEAD_INITIALIZER(pool);
-+static unsigned int pool_size;
-+
- typedef struct {
-     Coroutine base;
-     void *stack;
-@@ -48,10 +52,6 @@
-     /** Currently executing coroutine */
-     Coroutine *current;
- 
--    /** Free list to speed up creation */
--    QLIST_HEAD(, Coroutine) pool;
--    unsigned int pool_size;
--
-     /** The default coroutine */
-     CoroutineUContext leader;
- } CoroutineThreadState;
-@@ -75,7 +75,6 @@
-     if (!s) {
-         s = g_malloc0(sizeof(*s));
-         s->current = &s->leader.base;
--        QLIST_INIT(&s->pool);
-         pthread_setspecific(thread_state_key, s);
-     }
-     return s;
-@@ -84,14 +83,19 @@
- static void qemu_coroutine_thread_cleanup(void *opaque)
- {
-     CoroutineThreadState *s = opaque;
-+
-+    g_free(s);
-+}
-+
-+static void __attribute__((destructor)) coroutine_cleanup(void)
-+{
-     Coroutine *co;
-     Coroutine *tmp;
- 
--    QLIST_FOREACH_SAFE(co, &s->pool, pool_next, tmp) {
-+    QLIST_FOREACH_SAFE(co, &pool, pool_next, tmp) {
-         g_free(DO_UPCAST(CoroutineUContext, base, co)->stack);
-         g_free(co);
-     }
--    g_free(s);
- }
- 
- static void __attribute__((constructor)) coroutine_init(void)
-@@ -169,13 +173,12 @@
- 
- Coroutine *qemu_coroutine_new(void)
- {
--    CoroutineThreadState *s = coroutine_get_thread_state();
-     Coroutine *co;
- 
--    co = QLIST_FIRST(&s->pool);
-+    co = QLIST_FIRST(&pool);
-     if (co) {
-         QLIST_REMOVE(co, pool_next);
--        s->pool_size--;
-+        pool_size--;
-     } else {
-         co = coroutine_new();
-     }
-@@ -184,13 +187,12 @@
- 
- void qemu_coroutine_delete(Coroutine *co_)
- {
--    CoroutineThreadState *s = coroutine_get_thread_state();
-     CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_);
- 
--    if (s->pool_size < POOL_MAX_SIZE) {
--        QLIST_INSERT_HEAD(&s->pool, &co->base, pool_next);
-+    if (pool_size < POOL_MAX_SIZE) {
-+        QLIST_INSERT_HEAD(&pool, &co->base, pool_next);
-         co->base.caller = NULL;
--        s->pool_size++;
-+        pool_size++;
-         return;
-     }
- 
-diff -urN qemu-1.0/cpu-common.h qemu-1.0.1/cpu-common.h
---- qemu-1.0/cpu-common.h	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/cpu-common.h	2012-02-17 20:45:39.000000000 +0100
-@@ -172,6 +172,7 @@
- #define IO_MEM_ROM         (1 << IO_MEM_SHIFT) /* hardcoded offset */
- #define IO_MEM_UNASSIGNED  (2 << IO_MEM_SHIFT)
- #define IO_MEM_NOTDIRTY    (3 << IO_MEM_SHIFT)
-+#define IO_MEM_SUBPAGE_RAM (4 << IO_MEM_SHIFT)
- 
- /* Acts like a ROM when read and like a device when written.  */
- #define IO_MEM_ROMD        (1)
-diff -urN qemu-1.0/cutils.c qemu-1.0.1/cutils.c
---- qemu-1.0/cutils.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/cutils.c	2012-02-17 20:45:39.000000000 +0100
-@@ -217,7 +217,10 @@
- {
-     assert(qiov->nalloc != -1);
- 
-+    qemu_iovec_reset(qiov);
-     g_free(qiov->iov);
-+    qiov->nalloc = 0;
-+    qiov->iov = NULL;
- }
- 
- void qemu_iovec_reset(QEMUIOVector *qiov)
-diff -urN qemu-1.0/exec.c qemu-1.0.1/exec.c
---- qemu-1.0/exec.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/exec.c	2012-02-17 20:45:39.000000000 +0100
-@@ -3570,6 +3570,63 @@
-     &subpage_writel,
- };
- 
-+static uint32_t subpage_ram_readb(void *opaque, target_phys_addr_t addr)
-+{
-+    ram_addr_t raddr = addr;
-+    void *ptr = qemu_get_ram_ptr(raddr);
-+    return ldub_p(ptr);
-+}
-+
-+static void subpage_ram_writeb(void *opaque, target_phys_addr_t addr,
-+                               uint32_t value)
-+{
-+    ram_addr_t raddr = addr;
-+    void *ptr = qemu_get_ram_ptr(raddr);
-+    stb_p(ptr, value);
-+}
-+
-+static uint32_t subpage_ram_readw(void *opaque, target_phys_addr_t addr)
-+{
-+    ram_addr_t raddr = addr;
-+    void *ptr = qemu_get_ram_ptr(raddr);
-+    return lduw_p(ptr);
-+}
-+
-+static void subpage_ram_writew(void *opaque, target_phys_addr_t addr,
-+                               uint32_t value)
-+{
-+    ram_addr_t raddr = addr;
-+    void *ptr = qemu_get_ram_ptr(raddr);
-+    stw_p(ptr, value);
-+}
-+
-+static uint32_t subpage_ram_readl(void *opaque, target_phys_addr_t addr)
-+{
-+    ram_addr_t raddr = addr;
-+    void *ptr = qemu_get_ram_ptr(raddr);
-+    return ldl_p(ptr);
-+}
-+
-+static void subpage_ram_writel(void *opaque, target_phys_addr_t addr,
-+                               uint32_t value)
-+{
-+    ram_addr_t raddr = addr;
-+    void *ptr = qemu_get_ram_ptr(raddr);
-+    stl_p(ptr, value);
-+}
-+
-+static CPUReadMemoryFunc * const subpage_ram_read[] = {
-+    &subpage_ram_readb,
-+    &subpage_ram_readw,
-+    &subpage_ram_readl,
-+};
-+
-+static CPUWriteMemoryFunc * const subpage_ram_write[] = {
-+    &subpage_ram_writeb,
-+    &subpage_ram_writew,
-+    &subpage_ram_writel,
-+};
-+
- static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
-                              ram_addr_t memory, ram_addr_t region_offset)
- {
-@@ -3583,8 +3640,9 @@
-     printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
-            mmio, start, end, idx, eidx, memory);
- #endif
--    if ((memory & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
--        memory = IO_MEM_UNASSIGNED;
-+    if ((memory & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
-+        memory = IO_MEM_SUBPAGE_RAM;
-+    }
-     memory = (memory >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
-     for (; idx <= eidx; idx++) {
-         mmio->sub_io_index[idx] = memory;
-@@ -3817,6 +3875,9 @@
-     cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read,
-                                  notdirty_mem_write, NULL,
-                                  DEVICE_NATIVE_ENDIAN);
-+    cpu_register_io_memory_fixed(IO_MEM_SUBPAGE_RAM, subpage_ram_read,
-+                                 subpage_ram_write, NULL,
-+                                 DEVICE_NATIVE_ENDIAN);
-     for (i=0; i<5; i++)
-         io_mem_used[i] = 1;
- 
-diff -urN qemu-1.0/fsdev/file-op-9p.h qemu-1.0.1/fsdev/file-op-9p.h
---- qemu-1.0/fsdev/file-op-9p.h	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/fsdev/file-op-9p.h	2012-02-17 20:45:39.000000000 +0100
-@@ -74,7 +74,7 @@
- } FsContext;
- 
- typedef struct V9fsPath {
--    int16_t size;
-+    uint16_t size;
-     char *data;
- } V9fsPath;
- 
-@@ -112,10 +112,10 @@
-     ssize_t (*pwritev)(FsContext *, V9fsFidOpenState *,
-                        const struct iovec *, int, off_t);
-     int (*mkdir)(FsContext *, V9fsPath *, const char *, FsCred *);
--    int (*fstat)(FsContext *, V9fsFidOpenState *, struct stat *);
-+    int (*fstat)(FsContext *, int, V9fsFidOpenState *, struct stat *);
-     int (*rename)(FsContext *, const char *, const char *);
-     int (*truncate)(FsContext *, V9fsPath *, off_t);
--    int (*fsync)(FsContext *, V9fsFidOpenState *, int);
-+    int (*fsync)(FsContext *, int, V9fsFidOpenState *, int);
-     int (*statfs)(FsContext *s, V9fsPath *path, struct statfs *stbuf);
-     ssize_t (*lgetxattr)(FsContext *, V9fsPath *,
-                          const char *, void *, size_t);
-diff -urN qemu-1.0/fsdev/qemu-fsdev.c qemu-1.0.1/fsdev/qemu-fsdev.c
---- qemu-1.0/fsdev/qemu-fsdev.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/fsdev/qemu-fsdev.c	2012-02-17 20:45:39.000000000 +0100
-@@ -23,7 +23,9 @@
- 
- static FsDriverTable FsDrivers[] = {
-     { .name = "local", .ops = &local_ops},
-+#ifdef CONFIG_OPEN_BY_HANDLE
-     { .name = "handle", .ops = &handle_ops},
-+#endif
-     { .name = "synth", .ops = &synth_ops},
- };
- 
-diff -urN qemu-1.0/hw/9pfs/cofile.c qemu-1.0.1/hw/9pfs/cofile.c
---- qemu-1.0/hw/9pfs/cofile.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/9pfs/cofile.c	2012-02-17 20:45:39.000000000 +0100
-@@ -71,7 +71,7 @@
-     }
-     v9fs_co_run_in_worker(
-         {
--            err = s->ops->fstat(&s->ctx, &fidp->fs, stbuf);
-+            err = s->ops->fstat(&s->ctx, fidp->fid_type, &fidp->fs, stbuf);
-             if (err < 0) {
-                 err = -errno;
-             }
-@@ -192,7 +192,7 @@
-     }
-     v9fs_co_run_in_worker(
-         {
--            err = s->ops->fsync(&s->ctx, &fidp->fs, datasync);
-+            err = s->ops->fsync(&s->ctx, fidp->fid_type, &fidp->fs, datasync);
-             if (err < 0) {
-                 err = -errno;
-             }
-diff -urN qemu-1.0/hw/9pfs/virtio-9p.c qemu-1.0.1/hw/9pfs/virtio-9p.c
---- qemu-1.0/hw/9pfs/virtio-9p.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/9pfs/virtio-9p.c	2012-02-17 20:45:39.000000000 +0100
-@@ -23,6 +23,7 @@
- #include "virtio-9p-xattr.h"
- #include "virtio-9p-coth.h"
- #include "trace.h"
-+#include "migration.h"
- 
- int open_fd_hw;
- int total_open_fd;
-@@ -373,6 +374,19 @@
-      * Don't free the fid if it is in reclaim list
-      */
-     if (!fidp->ref && fidp->clunked) {
-+        if (fidp->fid == pdu->s->root_fid) {
-+            /*
-+             * if the clunked fid is root fid then we
-+             * have unmounted the fs on the client side.
-+             * delete the migration blocker. Ideally, this
-+             * should be hooked to transport close notification
-+             */
-+            if (pdu->s->migration_blocker) {
-+                migrate_del_blocker(pdu->s->migration_blocker);
-+                error_free(pdu->s->migration_blocker);
-+                pdu->s->migration_blocker = NULL;
-+            }
-+        }
-         free_fid(pdu, fidp);
-     }
- }
-@@ -509,6 +523,30 @@
-     return 0;
- }
- 
-+static void virtfs_reset(V9fsPDU *pdu)
-+{
-+    V9fsState *s = pdu->s;
-+    V9fsFidState *fidp = NULL;
-+
-+    /* Free all fids */
-+    while (s->fid_list) {
-+        fidp = s->fid_list;
-+        s->fid_list = fidp->next;
-+
-+        if (fidp->ref) {
-+            fidp->clunked = 1;
-+        } else {
-+            free_fid(pdu, fidp);
-+        }
-+    }
-+    if (fidp) {
-+        /* One or more unclunked fids found... */
-+        error_report("9pfs:%s: One or more uncluncked fids "
-+                     "found during reset", __func__);
-+    }
-+    return;
-+}
-+
- #define P9_QID_TYPE_DIR         0x80
- #define P9_QID_TYPE_SYMLINK     0x02
- 
-@@ -636,40 +674,6 @@
-                              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;
-@@ -705,12 +709,6 @@
-             *valp = le64_to_cpu(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);
-@@ -789,12 +787,6 @@
-             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);
-@@ -1105,42 +1097,6 @@
-     stat_to_qid(stbuf, &v9lstat->qid);
- }
- 
--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;
-@@ -1182,6 +1138,8 @@
-     pdu_unmarshal(pdu, offset, "ds", &s->msize, &version);
-     trace_v9fs_version(pdu->tag, pdu->id, s->msize, version.data);
- 
-+    virtfs_reset(pdu);
-+
-     if (!strcmp(version.data, "9P2000.u")) {
-         s->proto_version = V9FS_PROTO_2000U;
-     } else if (!strcmp(version.data, "9P2000.L")) {
-@@ -1235,6 +1193,11 @@
-     err = offset;
-     trace_v9fs_attach_return(pdu->tag, pdu->id,
-                              qid.type, qid.version, qid.path);
-+    s->root_fid = fid;
-+    /* disable migration */
-+    error_set(&s->migration_blocker, QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION,
-+              s->ctx.fs_root, s->tag);
-+    migrate_add_blocker(s->migration_blocker);
- out:
-     put_fid(pdu, fidp);
- out_nofid:
-@@ -1731,8 +1694,8 @@
-     complete_pdu(s, pdu, err);
- }
- 
--static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu,
--                           V9fsFidState *fidp, int64_t off, int32_t max_count)
-+static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
-+                           uint64_t off, uint32_t max_count)
- {
-     size_t offset = 7;
-     int read_count;
-@@ -1756,7 +1719,7 @@
- }
- 
- static int v9fs_do_readdir_with_stat(V9fsPDU *pdu,
--                                     V9fsFidState *fidp, int32_t max_count)
-+                                     V9fsFidState *fidp, uint32_t max_count)
- {
-     V9fsPath path;
-     V9fsStat v9stat;
-@@ -1816,14 +1779,46 @@
-     return count;
- }
- 
-+/*
-+ * Create a QEMUIOVector for a sub-region of PDU iovecs
-+ *
-+ * @qiov:       uninitialized QEMUIOVector
-+ * @skip:       number of bytes to skip from beginning of PDU
-+ * @size:       number of bytes to include
-+ * @is_write:   true - write, false - read
-+ *
-+ * The resulting QEMUIOVector has heap-allocated iovecs and must be cleaned up
-+ * with qemu_iovec_destroy().
-+ */
-+static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu,
-+                                    uint64_t skip, size_t size,
-+                                    bool is_write)
-+{
-+    QEMUIOVector elem;
-+    struct iovec *iov;
-+    unsigned int niov;
-+
-+    if (is_write) {
-+        iov = pdu->elem.out_sg;
-+        niov = pdu->elem.out_num;
-+    } else {
-+        iov = pdu->elem.in_sg;
-+        niov = pdu->elem.in_num;
-+    }
-+
-+    qemu_iovec_init_external(&elem, iov, niov);
-+    qemu_iovec_init(qiov, niov);
-+    qemu_iovec_copy(qiov, &elem, skip, size);
-+}
-+
- static void v9fs_read(void *opaque)
- {
-     int32_t fid;
--    int64_t off;
-+    uint64_t off;
-     ssize_t err = 0;
-     int32_t count = 0;
-     size_t offset = 7;
--    int32_t max_count;
-+    uint32_t max_count;
-     V9fsFidState *fidp;
-     V9fsPDU *pdu = opaque;
-     V9fsState *s = pdu->s;
-@@ -1850,21 +1845,21 @@
-         err += pdu_marshal(pdu, offset, "d", count);
-         err += count;
-     } else if (fidp->fid_type == P9_FID_FILE) {
--        int32_t cnt;
-+        QEMUIOVector qiov_full;
-+        QEMUIOVector qiov;
-         int32_t len;
--        struct iovec *sg;
--        struct iovec iov[128]; /* FIXME: bad, bad, bad */
- 
--        sg = iov;
--        pdu_marshal(pdu, offset + 4, "v", sg, &cnt);
--        sg = cap_sg(sg, max_count, &cnt);
-+        v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset + 4, max_count, false);
-+        qemu_iovec_init(&qiov, qiov_full.niov);
-         do {
-+            qemu_iovec_reset(&qiov);
-+            qemu_iovec_copy(&qiov, &qiov_full, count, qiov_full.size - count);
-             if (0) {
--                print_sg(sg, cnt);
-+                print_sg(qiov.iov, qiov.niov);
-             }
-             /* Loop in case of EINTR */
-             do {
--                len = v9fs_co_preadv(pdu, fidp, sg, cnt, off);
-+                len = v9fs_co_preadv(pdu, fidp, qiov.iov, qiov.niov, off);
-                 if (len >= 0) {
-                     off   += len;
-                     count += len;
-@@ -1875,11 +1870,12 @@
-                 err = len;
-                 goto out;
-             }
--            sg = adjust_sg(sg, len, &cnt);
-         } while (count < max_count && len > 0);
-         err = offset;
-         err += pdu_marshal(pdu, offset, "d", count);
-         err += count;
-+        qemu_iovec_destroy(&qiov);
-+        qemu_iovec_destroy(&qiov_full);
-     } else if (fidp->fid_type == P9_FID_XATTR) {
-         err = v9fs_xattr_read(s, pdu, fidp, off, max_count);
-     } else {
-@@ -1966,8 +1962,9 @@
-     V9fsFidState *fidp;
-     ssize_t retval = 0;
-     size_t offset = 7;
--    int64_t initial_offset;
--    int32_t count, max_count;
-+    uint64_t initial_offset;
-+    int32_t count;
-+    uint32_t max_count;
-     V9fsPDU *pdu = opaque;
-     V9fsState *s = pdu->s;
- 
-@@ -2005,7 +2002,7 @@
- }
- 
- static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
--                            int64_t off, int32_t count,
-+                            uint64_t off, uint32_t count,
-                             struct iovec *sg, int cnt)
- {
-     int i, to_copy;
-@@ -2050,22 +2047,22 @@
- 
- static void v9fs_write(void *opaque)
- {
--    int cnt;
-     ssize_t err;
-     int32_t fid;
--    int64_t off;
--    int32_t count;
-+    uint64_t off;
-+    uint32_t count;
-     int32_t len = 0;
-     int32_t total = 0;
-     size_t offset = 7;
-     V9fsFidState *fidp;
--    struct iovec iov[128]; /* FIXME: bad, bad, bad */
--    struct iovec *sg = iov;
-     V9fsPDU *pdu = opaque;
-     V9fsState *s = pdu->s;
-+    QEMUIOVector qiov_full;
-+    QEMUIOVector qiov;
- 
--    pdu_unmarshal(pdu, offset, "dqdv", &fid, &off, &count, sg, &cnt);
--    trace_v9fs_write(pdu->tag, pdu->id, fid, off, count, cnt);
-+    offset += pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &count);
-+    v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset, count, true);
-+    trace_v9fs_write(pdu->tag, pdu->id, fid, off, count, qiov_full.niov);
- 
-     fidp = get_fid(pdu, fid);
-     if (fidp == NULL) {
-@@ -2081,20 +2078,23 @@
-         /*
-          * setxattr operation
-          */
--        err = v9fs_xattr_write(s, pdu, fidp, off, count, sg, cnt);
-+        err = v9fs_xattr_write(s, pdu, fidp, off, count,
-+                               qiov_full.iov, qiov_full.niov);
-         goto out;
-     } else {
-         err = -EINVAL;
-         goto out;
-     }
--    sg = cap_sg(sg, count, &cnt);
-+    qemu_iovec_init(&qiov, qiov_full.niov);
-     do {
-+        qemu_iovec_reset(&qiov);
-+        qemu_iovec_copy(&qiov, &qiov_full, total, qiov_full.size - total);
-         if (0) {
--            print_sg(sg, cnt);
-+            print_sg(qiov.iov, qiov.niov);
-         }
-         /* Loop in case of EINTR */
-         do {
--            len = v9fs_co_pwritev(pdu, fidp, sg, cnt, off);
-+            len = v9fs_co_pwritev(pdu, fidp, qiov.iov, qiov.niov, off);
-             if (len >= 0) {
-                 off   += len;
-                 total += len;
-@@ -2103,16 +2103,20 @@
-         if (len < 0) {
-             /* IO error return the error */
-             err = len;
--            goto out;
-+            goto out_qiov;
-         }
--        sg = adjust_sg(sg, len, &cnt);
-     } while (total < count && len > 0);
-+
-+    offset = 7;
-     offset += pdu_marshal(pdu, offset, "d", total);
-     err = offset;
-     trace_v9fs_write_return(pdu->tag, pdu->id, total, err);
-+out_qiov:
-+    qemu_iovec_destroy(&qiov);
- out:
-     put_fid(pdu, fidp);
- out_nofid:
-+    qemu_iovec_destroy(&qiov_full);
-     complete_pdu(s, pdu, err);
- }
- 
-diff -urN qemu-1.0/hw/9pfs/virtio-9p-device.c qemu-1.0.1/hw/9pfs/virtio-9p-device.c
---- qemu-1.0/hw/9pfs/virtio-9p-device.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/9pfs/virtio-9p-device.c	2012-02-17 20:45:39.000000000 +0100
-@@ -33,13 +33,15 @@
- 
- static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
- {
-+    int len;
-     struct virtio_9p_config *cfg;
-     V9fsState *s = to_virtio_9p(vdev);
- 
--    cfg = g_malloc0(sizeof(struct virtio_9p_config) +
--                        s->tag_len);
--    stw_raw(&cfg->tag_len, s->tag_len);
--    memcpy(cfg->tag, s->tag, s->tag_len);
-+    len = strlen(s->tag);
-+    cfg = g_malloc0(sizeof(struct virtio_9p_config) + len);
-+    stw_raw(&cfg->tag_len, len);
-+    /* We don't copy the terminating null to config space */
-+    memcpy(cfg->tag, s->tag, len);
-     memcpy(config, cfg, s->config_size);
-     g_free(cfg);
- }
-@@ -96,20 +98,18 @@
-     }
- 
-     len = strlen(conf->tag);
--    if (len > MAX_TAG_LEN) {
-+    if (len > MAX_TAG_LEN - 1) {
-         fprintf(stderr, "mount tag '%s' (%d bytes) is longer than "
--                "maximum (%d bytes)", conf->tag, len, MAX_TAG_LEN);
-+                "maximum (%d bytes)", conf->tag, len, MAX_TAG_LEN - 1);
-         exit(1);
-     }
--    /* s->tag is non-NULL terminated string */
--    s->tag = g_malloc(len);
--    memcpy(s->tag, conf->tag, len);
--    s->tag_len = len;
-+
-+    s->tag = strdup(conf->tag);
-     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->config_size = sizeof(struct virtio_9p_config) + len;
-     s->vdev.get_config = virtio_9p_get_config;
-     s->fid_list = NULL;
-     qemu_co_rwlock_init(&s->rename_lock);
-@@ -176,7 +176,8 @@
-         DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
-         DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
-         DEFINE_PROP_END_OF_LIST(),
--    }
-+    },
-+    .qdev.reset = virtio_pci_reset,
- };
- 
- static void virtio_9p_register_devices(void)
-diff -urN qemu-1.0/hw/9pfs/virtio-9p.h qemu-1.0.1/hw/9pfs/virtio-9p.h
---- qemu-1.0/hw/9pfs/virtio-9p.h	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/9pfs/virtio-9p.h	2012-02-17 20:45:39.000000000 +0100
-@@ -156,7 +156,7 @@
- 
- typedef struct V9fsString
- {
--    int16_t size;
-+    uint16_t size;
-     char *data;
- } V9fsString;
- 
-@@ -246,8 +246,7 @@
-     V9fsFidState *fid_list;
-     FileOperations *ops;
-     FsContext ctx;
--    uint16_t tag_len;
--    uint8_t *tag;
-+    char *tag;
-     size_t config_size;
-     enum p9_proto_version proto_version;
-     int32_t msize;
-@@ -256,6 +255,8 @@
-      * on rename.
-      */
-     CoRwlock rename_lock;
-+    int32_t root_fid;
-+    Error *migration_blocker;
- } V9fsState;
- 
- typedef struct V9fsStatState {
-diff -urN qemu-1.0/hw/9pfs/virtio-9p-handle.c qemu-1.0.1/hw/9pfs/virtio-9p-handle.c
---- qemu-1.0/hw/9pfs/virtio-9p-handle.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/9pfs/virtio-9p-handle.c	2012-02-17 20:45:39.000000000 +0100
-@@ -45,7 +45,6 @@
-     int handle_bytes;
- };
- 
--#ifdef CONFIG_OPEN_BY_HANDLE
- static inline int name_to_handle(int dirfd, const char *name,
-                                  struct file_handle *fh, int *mnt_id, int flags)
- {
-@@ -56,38 +55,6 @@
- {
-     return open_by_handle_at(mountfd, (struct file_handle *)fh, flags);
- }
--#else
--
--struct rpl_file_handle {
--    unsigned int handle_bytes;
--    int handle_type;
--    unsigned char handle[0];
--};
--#define file_handle rpl_file_handle
--
--#ifndef AT_REMOVEDIR
--#define AT_REMOVEDIR    0x200
--#endif
--#ifndef AT_EMPTY_PATH
--#define AT_EMPTY_PATH   0x1000  /* Allow empty relative pathname */
--#endif
--#ifndef O_PATH
--#define O_PATH    010000000
--#endif
--
--static inline int name_to_handle(int dirfd, const char *name,
--                                 struct file_handle *fh, int *mnt_id, int flags)
--{
--    errno = ENOSYS;
--    return -1;
--}
--
--static inline int open_by_handle(int mountfd, const char *fh, int flags)
--{
--    errno = ENOSYS;
--    return -1;
--}
--#endif
- 
- static int handle_update_file_cred(int dirfd, const char *name, FsCred *credp)
- {
-@@ -288,10 +255,17 @@
-     return ret;
- }
- 
--static int handle_fstat(FsContext *fs_ctx, V9fsFidOpenState *fs,
--                        struct stat *stbuf)
-+static int handle_fstat(FsContext *fs_ctx, int fid_type,
-+                        V9fsFidOpenState *fs, struct stat *stbuf)
- {
--    return fstat(fs->fd, stbuf);
-+    int fd;
-+
-+    if (fid_type == P9_FID_DIR) {
-+        fd = dirfd(fs->dir);
-+    } else {
-+        fd = fs->fd;
-+    }
-+    return fstat(fd, stbuf);
- }
- 
- static int handle_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
-@@ -428,12 +402,21 @@
-     return -1;
- }
- 
--static int handle_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync)
-+static int handle_fsync(FsContext *ctx, int fid_type,
-+                        V9fsFidOpenState *fs, int datasync)
- {
-+    int fd;
-+
-+    if (fid_type == P9_FID_DIR) {
-+        fd = dirfd(fs->dir);
-+    } else {
-+        fd = fs->fd;
-+    }
-+
-     if (datasync) {
--        return qemu_fdatasync(fs->fd);
-+        return qemu_fdatasync(fd);
-     } else {
--        return fsync(fs->fd);
-+        return fsync(fd);
-     }
- }
- 
-diff -urN qemu-1.0/hw/9pfs/virtio-9p-local.c qemu-1.0.1/hw/9pfs/virtio-9p-local.c
---- qemu-1.0/hw/9pfs/virtio-9p-local.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/9pfs/virtio-9p-local.c	2012-02-17 20:45:39.000000000 +0100
-@@ -366,11 +366,18 @@
-     return err;
- }
- 
--static int local_fstat(FsContext *fs_ctx,
-+static int local_fstat(FsContext *fs_ctx, int fid_type,
-                        V9fsFidOpenState *fs, struct stat *stbuf)
- {
--    int err;
--    err = fstat(fs->fd, stbuf);
-+    int err, fd;
-+
-+    if (fid_type == P9_FID_DIR) {
-+        fd = dirfd(fs->dir);
-+    } else {
-+        fd = fs->fd;
-+    }
-+
-+    err = fstat(fd, stbuf);
-     if (err) {
-         return err;
-     }
-@@ -381,19 +388,19 @@
-         mode_t tmp_mode;
-         dev_t tmp_dev;
- 
--        if (fgetxattr(fs->fd, "user.virtfs.uid",
-+        if (fgetxattr(fd, "user.virtfs.uid",
-                       &tmp_uid, sizeof(uid_t)) > 0) {
-             stbuf->st_uid = tmp_uid;
-         }
--        if (fgetxattr(fs->fd, "user.virtfs.gid",
-+        if (fgetxattr(fd, "user.virtfs.gid",
-                       &tmp_gid, sizeof(gid_t)) > 0) {
-             stbuf->st_gid = tmp_gid;
-         }
--        if (fgetxattr(fs->fd, "user.virtfs.mode",
-+        if (fgetxattr(fd, "user.virtfs.mode",
-                       &tmp_mode, sizeof(mode_t)) > 0) {
-             stbuf->st_mode = tmp_mode;
-         }
--        if (fgetxattr(fs->fd, "user.virtfs.rdev",
-+        if (fgetxattr(fd, "user.virtfs.rdev",
-                       &tmp_dev, sizeof(dev_t)) > 0) {
-                 stbuf->st_rdev = tmp_dev;
-         }
-@@ -592,12 +599,21 @@
-     return remove(rpath(ctx, path, buffer));
- }
- 
--static int local_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync)
-+static int local_fsync(FsContext *ctx, int fid_type,
-+                       V9fsFidOpenState *fs, int datasync)
- {
-+    int fd;
-+
-+    if (fid_type == P9_FID_DIR) {
-+        fd = dirfd(fs->dir);
-+    } else {
-+        fd = fs->fd;
-+    }
-+
-     if (datasync) {
--        return qemu_fdatasync(fs->fd);
-+        return qemu_fdatasync(fd);
-     } else {
--        return fsync(fs->fd);
-+        return fsync(fd);
-     }
- }
- 
-diff -urN qemu-1.0/hw/9pfs/virtio-9p-synth.c qemu-1.0.1/hw/9pfs/virtio-9p-synth.c
---- qemu-1.0/hw/9pfs/virtio-9p-synth.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/9pfs/virtio-9p-synth.c	2012-02-17 20:45:39.000000000 +0100
-@@ -166,7 +166,7 @@
-     return 0;
- }
- 
--static int v9fs_synth_fstat(FsContext *fs_ctx,
-+static int v9fs_synth_fstat(FsContext *fs_ctx, int fid_type,
-                             V9fsFidOpenState *fs, struct stat *stbuf)
- {
-     V9fsSynthOpenState *synth_open = fs->private;
-@@ -414,7 +414,8 @@
-     return -1;
- }
- 
--static int v9fs_synth_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync)
-+static int v9fs_synth_fsync(FsContext *ctx, int fid_type,
-+                            V9fsFidOpenState *fs, int datasync)
- {
-     errno = ENOSYS;
-     return 0;
-diff -urN qemu-1.0/hw/e1000.c qemu-1.0.1/hw/e1000.c
---- qemu-1.0/hw/e1000.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/e1000.c	2012-02-17 20:45:39.000000000 +0100
-@@ -466,6 +466,8 @@
-             bytes = split_size;
-             if (tp->size + bytes > msh)
-                 bytes = msh - tp->size;
-+
-+            bytes = MIN(sizeof(tp->data) - tp->size, bytes);
-             pci_dma_read(&s->dev, addr, tp->data + tp->size, bytes);
-             if ((sz = tp->size + bytes) >= hdr && tp->size < hdr)
-                 memmove(tp->header, tp->data, hdr);
-@@ -481,6 +483,7 @@
-         // context descriptor TSE is not set, while data descriptor TSE is set
-         DBGOUT(TXERR, "TCP segmentaion Error\n");
-     } else {
-+        split_size = MIN(sizeof(tp->data) - tp->size, split_size);
-         pci_dma_read(&s->dev, addr, tp->data + tp->size, split_size);
-         tp->size += split_size;
-     }
-diff -urN qemu-1.0/hw/mips_malta.c qemu-1.0.1/hw/mips_malta.c
---- qemu-1.0/hw/mips_malta.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/mips_malta.c	2012-02-17 20:45:39.000000000 +0100
-@@ -47,6 +47,7 @@
- #include "mc146818rtc.h"
- #include "blockdev.h"
- #include "exec-memory.h"
-+#include "sysbus.h"             /* SysBusDevice */
- 
- //#define DEBUG_BOARD_INIT
- 
-@@ -72,6 +73,11 @@
-     SerialState *uart;
- } MaltaFPGAState;
- 
-+typedef struct {
-+    SysBusDevice busdev;
-+    qemu_irq *i8259;
-+} MaltaState;
-+
- static ISADevice *pit;
- 
- static struct _loaderparams {
-@@ -775,7 +781,7 @@
-     int64_t kernel_entry;
-     PCIBus *pci_bus;
-     CPUState *env;
--    qemu_irq *i8259 = NULL, *isa_irq;
-+    qemu_irq *isa_irq;
-     qemu_irq *cpu_exit_irq;
-     int piix4_devfn;
-     i2c_bus *smbus;
-@@ -787,6 +793,11 @@
-     int fl_sectors = 0;
-     int be;
- 
-+    DeviceState *dev = qdev_create(NULL, "mips-malta");
-+    MaltaState *s = DO_UPCAST(MaltaState, busdev.qdev, dev);
-+
-+    qdev_init_nofail(dev);
-+
-     /* Make sure the first 3 serial ports are associated with a device. */
-     for(i = 0; i < 3; i++) {
-         if (!serial_hds[i]) {
-@@ -932,7 +943,7 @@
-      * qemu_irq_proxy() adds an extra bit of indirection, allowing us
-      * to resolve the isa_irq -> i8259 dependency after i8259 is initialized.
-      */
--    isa_irq = qemu_irq_proxy(&i8259, 16);
-+    isa_irq = qemu_irq_proxy(&s->i8259, 16);
- 
-     /* Northbridge */
-     pci_bus = gt64120_register(isa_irq);
-@@ -944,9 +955,9 @@
- 
-     /* Interrupt controller */
-     /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
--    i8259 = i8259_init(env->irq[2]);
-+    s->i8259 = i8259_init(env->irq[2]);
- 
--    isa_bus_irqs(i8259);
-+    isa_bus_irqs(s->i8259);
-     pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
-     usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
-     smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_get_irq(9),
-@@ -990,6 +1001,20 @@
-     }
- }
- 
-+static int mips_malta_sysbus_device_init(SysBusDevice *sysbusdev)
-+{
-+    return 0;
-+}
-+
-+static SysBusDeviceInfo mips_malta_device = {
-+    .init = mips_malta_sysbus_device_init,
-+    .qdev.name  = "mips-malta",
-+    .qdev.size  = sizeof(MaltaState),
-+    .qdev.props = (Property[]) {
-+        DEFINE_PROP_END_OF_LIST(),
-+    }
-+};
-+
- static QEMUMachine mips_malta_machine = {
-     .name = "malta",
-     .desc = "MIPS Malta Core LV",
-@@ -998,9 +1023,15 @@
-     .is_default = 1,
- };
- 
-+static void mips_malta_device_init(void)
-+{
-+    sysbus_register_withprop(&mips_malta_device);
-+}
-+
- static void mips_malta_machine_init(void)
- {
-     qemu_register_machine(&mips_malta_machine);
- }
- 
-+device_init(mips_malta_device_init);
- machine_init(mips_malta_machine_init);
-diff -urN qemu-1.0/hw/pc_piix.c qemu-1.0.1/hw/pc_piix.c
---- qemu-1.0/hw/pc_piix.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/pc_piix.c	2012-02-17 20:45:39.000000000 +0100
-@@ -306,6 +306,14 @@
-     .is_default = 1,
- };
- 
-+static QEMUMachine pc_machine_v0_15 = {
-+    .name = "pc-0.15",
-+    .desc = "Standard PC",
-+    .init = pc_init_pci,
-+    .max_cpus = 255,
-+    .is_default = 1,
-+};
-+
- static QEMUMachine pc_machine_v0_14 = {
-     .name = "pc-0.14",
-     .desc = "Standard PC",
-@@ -320,6 +328,22 @@
-             .driver   = "qxl-vga",
-             .property = "revision",
-             .value    = stringify(2),
-+        },{
-+            .driver   = "virtio-blk-pci",
-+            .property = "event_idx",
-+            .value    = "off",
-+        },{
-+            .driver   = "virtio-serial-pci",
-+            .property = "event_idx",
-+            .value    = "off",
-+        },{
-+            .driver   = "virtio-net-pci",
-+            .property = "event_idx",
-+            .value    = "off",
-+        },{
-+            .driver   = "virtio-balloon-pci",
-+            .property = "event_idx",
-+            .value    = "off",
-         },
-         { /* end of list */ }
-     },
-@@ -360,6 +384,10 @@
-             .property = "event_idx",
-             .value    = "off",
-         },{
-+            .driver   = "virtio-balloon-pci",
-+            .property = "event_idx",
-+            .value    = "off",
-+        },{
-             .driver   = "AC97",
-             .property = "use_broken_id",
-             .value    = stringify(1),
-@@ -407,6 +435,10 @@
-             .property = "event_idx",
-             .value    = "off",
-         },{
-+            .driver   = "virtio-balloon-pci",
-+            .property = "event_idx",
-+            .value    = "off",
-+        },{
-             .driver   = "AC97",
-             .property = "use_broken_id",
-             .value    = stringify(1),
-@@ -462,6 +494,10 @@
-             .property = "event_idx",
-             .value    = "off",
-         },{
-+            .driver   = "virtio-balloon-pci",
-+            .property = "event_idx",
-+            .value    = "off",
-+        },{
-             .driver   = "AC97",
-             .property = "use_broken_id",
-             .value    = stringify(1),
-@@ -529,6 +565,10 @@
-             .property = "event_idx",
-             .value    = "off",
-         },{
-+            .driver   = "virtio-balloon-pci",
-+            .property = "event_idx",
-+            .value    = "off",
-+        },{
-             .driver   = "AC97",
-             .property = "use_broken_id",
-             .value    = stringify(1),
-@@ -557,6 +597,7 @@
- static void pc_machine_init(void)
- {
-     qemu_register_machine(&pc_machine_v1_0);
-+    qemu_register_machine(&pc_machine_v0_15);
-     qemu_register_machine(&pc_machine_v0_14);
-     qemu_register_machine(&pc_machine_v0_13);
-     qemu_register_machine(&pc_machine_v0_12);
-diff -urN qemu-1.0/hw/ppce500_spin.c qemu-1.0.1/hw/ppce500_spin.c
---- qemu-1.0/hw/ppce500_spin.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/ppce500_spin.c	2012-02-17 20:45:39.000000000 +0100
-@@ -112,6 +112,7 @@
- 
-     env->halted = 0;
-     env->exception_index = -1;
-+    env->stopped = 0;
-     qemu_cpu_kick(env);
- }
- 
-diff -urN qemu-1.0/hw/spapr.c qemu-1.0.1/hw/spapr.c
---- qemu-1.0/hw/spapr.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/spapr.c	2012-02-17 20:45:39.000000000 +0100
-@@ -351,6 +351,8 @@
-         fprintf(stderr, "Couldn't set up RTAS device tree properties\n");
-     }
- 
-+    spapr_populate_chosen_stdout(fdt, spapr->vio_bus);
-+
-     _FDT((fdt_pack(fdt)));
- 
-     cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
-diff -urN qemu-1.0/hw/spapr_pci.c qemu-1.0.1/hw/spapr_pci.c
---- qemu-1.0/hw/spapr_pci.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/spapr_pci.c	2012-02-17 20:45:39.000000000 +0100
-@@ -454,7 +454,7 @@
-         reg[0].size = 0;
- 
-         n = 0;
--        for (i = 0; i < PCI_NUM_REGIONS; ++i) {
-+        for (i = 0; i < ARRAY_SIZE(bars); ++i) {
-             if (0 == dev->io_regions[i].size) {
-                 continue;
-             }
-diff -urN qemu-1.0/hw/spapr_vio.c qemu-1.0.1/hw/spapr_vio.c
---- qemu-1.0/hw/spapr_vio.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/spapr_vio.c	2012-02-17 20:45:39.000000000 +0100
-@@ -749,21 +749,95 @@
- device_init(spapr_vio_register_devices)
- 
- #ifdef CONFIG_FDT
-+static int compare_reg(const void *p1, const void *p2)
-+{
-+    VIOsPAPRDevice const *dev1, *dev2;
-+
-+    dev1 = (VIOsPAPRDevice *)*(DeviceState **)p1;
-+    dev2 = (VIOsPAPRDevice *)*(DeviceState **)p2;
-+
-+    if (dev1->reg < dev2->reg) {
-+        return -1;
-+    }
-+    if (dev1->reg == dev2->reg) {
-+        return 0;
-+    }
-+
-+    /* dev1->reg > dev2->reg */
-+    return 1;
-+}
-+
- int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
- {
--    DeviceState *qdev;
--    int ret = 0;
-+    DeviceState *qdev, **qdevs;
-+    int i, num, ret = 0;
-+
-+    /* Count qdevs on the bus list */
-+    num = 0;
-+    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
-+        num++;
-+    }
- 
-+    /* Copy out into an array of pointers */
-+    qdevs = g_malloc(sizeof(qdev) * num);
-+    num = 0;
-     QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
--        VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
-+        qdevs[num++] = qdev;
-+    }
-+
-+    /* Sort the array */
-+    qsort(qdevs, num, sizeof(qdev), compare_reg);
-+
-+    /* Hack alert. Give the devices to libfdt in reverse order, we happen
-+     * to know that will mean they are in forward order in the tree. */
-+    for (i = num - 1; i >= 0; i--) {
-+        VIOsPAPRDevice *dev = (VIOsPAPRDevice *)(qdevs[i]);
- 
-         ret = vio_make_devnode(dev, fdt);
- 
-         if (ret < 0) {
--            return ret;
-+            goto out;
-         }
-     }
- 
--    return 0;
-+    ret = 0;
-+out:
-+    free(qdevs);
-+
-+    return ret;
-+}
-+
-+int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus)
-+{
-+    VIOsPAPRDevice *dev;
-+    char *name, *path;
-+    int ret, offset;
-+
-+    dev = spapr_vty_get_default(bus);
-+    if (!dev)
-+        return 0;
-+
-+    offset = fdt_path_offset(fdt, "/chosen");
-+    if (offset < 0) {
-+        return offset;
-+    }
-+
-+    name = vio_format_dev_name(dev);
-+    if (!name) {
-+        return -ENOMEM;
-+    }
-+
-+    if (asprintf(&path, "/vdevice/%s", name) < 0) {
-+        path = NULL;
-+        ret = -ENOMEM;
-+        goto out;
-+    }
-+
-+    ret = fdt_setprop_string(fdt, offset, "linux,stdout-path", path);
-+out:
-+    free(name);
-+    free(path);
-+
-+    return ret;
- }
- #endif /* CONFIG_FDT */
-diff -urN qemu-1.0/hw/spapr_vio.h qemu-1.0.1/hw/spapr_vio.h
---- qemu-1.0/hw/spapr_vio.h	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/spapr_vio.h	2012-02-17 20:45:39.000000000 +0100
-@@ -83,6 +83,7 @@
- extern VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg);
- extern void spapr_vio_bus_register_withprop(VIOsPAPRDeviceInfo *info);
- extern int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt);
-+extern int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus);
- 
- extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode);
- 
-@@ -108,6 +109,8 @@
- void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd);
- void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg);
- 
-+VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus);
-+
- int spapr_tce_set_bypass(uint32_t unit, uint32_t enable);
- void spapr_vio_quiesce(void);
- 
-diff -urN qemu-1.0/hw/spapr_vty.c qemu-1.0.1/hw/spapr_vty.c
---- qemu-1.0/hw/spapr_vty.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/spapr_vty.c	2012-02-17 20:45:39.000000000 +0100
-@@ -156,24 +156,53 @@
-     },
- };
- 
-+VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
-+{
-+    VIOsPAPRDevice *sdev, *selected;
-+    DeviceState *iter;
-+
-+    /*
-+     * To avoid the console bouncing around we want one VTY to be
-+     * the "default". We haven't really got anything to go on, so
-+     * arbitrarily choose the one with the lowest reg value.
-+     */
-+
-+    selected = NULL;
-+    QTAILQ_FOREACH(iter, &bus->bus.children, sibling) {
-+        /* Only look at VTY devices */
-+        if (iter->info != &spapr_vty.qdev) {
-+            continue;
-+        }
-+
-+        sdev = DO_UPCAST(VIOsPAPRDevice, qdev, iter);
-+
-+        /* First VTY we've found, so it is selected for now */
-+        if (!selected) {
-+            selected = sdev;
-+            continue;
-+        }
-+
-+        /* Choose VTY with lowest reg value */
-+        if (sdev->reg < selected->reg) {
-+            selected = sdev;
-+        }
-+    }
-+
-+    return selected;
-+}
-+
- static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
- {
-     VIOsPAPRDevice *sdev;
- 
-     sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
-     if (!sdev && reg == 0) {
--        DeviceState *qdev;
--
-         /* Hack for kernel early debug, which always specifies reg==0.
--         * We search all VIO devices, and grab the first available vty
--         * device.  This attempts to mimic existing PowerVM behaviour
-+         * We search all VIO devices, and grab the vty with the lowest
-+         * reg.  This attempts to mimic existing PowerVM behaviour
-          * (early debug does work there, despite having no vty with
-          * reg==0. */
--        QTAILQ_FOREACH(qdev, &spapr->vio_bus->bus.children, sibling) {
--            if (qdev->info == &spapr_vty.qdev) {
--                return DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
--            }
--        }
-+        return spapr_vty_get_default(spapr->vio_bus);
-     }
- 
-     return sdev;
-diff -urN qemu-1.0/hw/usb-msd.c qemu-1.0.1/hw/usb-msd.c
---- qemu-1.0/hw/usb-msd.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/usb-msd.c	2012-02-17 20:45:39.000000000 +0100
-@@ -278,6 +278,18 @@
-     MSDState *s = (MSDState *)dev;
- 
-     DPRINTF("Reset\n");
-+    if (s->req) {
-+        scsi_req_cancel(s->req);
-+    }
-+    assert(s->req == NULL);
-+
-+    if (s->packet) {
-+        USBPacket *p = s->packet;
-+        s->packet = NULL;
-+        p->result = USB_RET_STALL;
-+        usb_packet_complete(dev, p);
-+    }
-+
-     s->mode = USB_MSDM_CBW;
- }
- 
-diff -urN qemu-1.0/hw/usb-ohci.c qemu-1.0.1/hw/usb-ohci.c
---- qemu-1.0/hw/usb-ohci.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/usb-ohci.c	2012-02-17 20:45:39.000000000 +0100
-@@ -1025,10 +1025,10 @@
-         if (ret == len) {
-             td.cbp = 0;
-         } else {
--            td.cbp += ret;
-             if ((td.cbp & 0xfff) + ret > 0xfff) {
--                td.cbp &= 0xfff;
--                td.cbp |= td.be & ~0xfff;
-+                td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff);
-+            } else {
-+                td.cbp += ret;
-             }
-         }
-         td.flags |= OHCI_TD_T1;
-diff -urN qemu-1.0/hw/virtio-pci.c qemu-1.0.1/hw/virtio-pci.c
---- qemu-1.0/hw/virtio-pci.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/virtio-pci.c	2012-02-17 20:45:39.000000000 +0100
-@@ -266,7 +266,7 @@
-     proxy->ioeventfd_started = false;
- }
- 
--static void virtio_pci_reset(DeviceState *d)
-+void virtio_pci_reset(DeviceState *d)
- {
-     VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev);
-     virtio_pci_stop_ioeventfd(proxy);
-diff -urN qemu-1.0/hw/virtio-pci.h qemu-1.0.1/hw/virtio-pci.h
---- qemu-1.0/hw/virtio-pci.h	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/hw/virtio-pci.h	2012-02-17 20:45:39.000000000 +0100
-@@ -45,6 +45,7 @@
- } VirtIOPCIProxy;
- 
- void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
-+void virtio_pci_reset(DeviceState *d);
- 
- /* Virtio ABI version, if we increment this, we break the guest driver. */
- #define VIRTIO_PCI_ABI_VERSION          0
-diff -urN qemu-1.0/Makefile.objs qemu-1.0.1/Makefile.objs
---- qemu-1.0/Makefile.objs	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/Makefile.objs	2012-02-17 20:45:39.000000000 +0100
-@@ -310,8 +310,8 @@
- 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o
- 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
- 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o cofs.o codir.o cofile.o
--9pfs-nested-$(CONFIG_VIRTFS) += coxattr.o virtio-9p-handle.o
--9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-synth.o
-+9pfs-nested-$(CONFIG_VIRTFS) += coxattr.o virtio-9p-synth.o
-+9pfs-nested-$(CONFIG_OPEN_BY_HANDLE) +=  virtio-9p-handle.o
- 
- hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y))
- $(addprefix 9pfs/, $(9pfs-nested-y)): QEMU_CFLAGS+=$(GLIB_CFLAGS)
-diff -urN qemu-1.0/ppc64.ld qemu-1.0.1/ppc64.ld
---- qemu-1.0/ppc64.ld	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/ppc64.ld	2012-02-17 20:45:39.000000000 +0100
-@@ -54,8 +54,20 @@
-       *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
-       *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
-     }
--  .rel.plt        : { *(.rel.plt) }
--  .rela.plt       : { *(.rela.plt) }
-+  .rel.plt      :
-+  {
-+    *(.rel.plt)
-+    PROVIDE (__rel_iplt_start = .);
-+    *(.rel.iplt)
-+    PROVIDE (__rel_iplt_end = .);
-+  }
-+  .rela.plt       :
-+  {
-+    *(.rela.plt)
-+    PROVIDE (__rela_iplt_start = .);
-+    *(.rela.iplt)
-+    PROVIDE (__rela_iplt_end = .);
-+  }
-   .rela.tocbss	  : { *(.rela.tocbss) }
-   .init           :
-   {
-diff -urN qemu-1.0/ppc.ld qemu-1.0.1/ppc.ld
---- qemu-1.0/ppc.ld	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/ppc.ld	2012-02-17 20:45:39.000000000 +0100
-@@ -49,8 +49,20 @@
-   .rela.sbss2     : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) }
-   .rel.bss        : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
-   .rela.bss       : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
--  .rel.plt        : { *(.rel.plt) }
--  .rela.plt       : { *(.rela.plt) }
-+  .rel.plt      :
-+  {
-+    *(.rel.plt)
-+    PROVIDE (__rel_iplt_start = .);
-+    *(.rel.iplt)
-+    PROVIDE (__rel_iplt_end = .);
-+  }
-+  .rela.plt       :
-+  {
-+    *(.rela.plt)
-+    PROVIDE (__rela_iplt_start = .);
-+    *(.rela.iplt)
-+    PROVIDE (__rela_iplt_end = .);
-+  }
-   .init           :
-   {
-     KEEP (*(.init))
-diff -urN qemu-1.0/qemu-img.c qemu-1.0.1/qemu-img.c
---- qemu-1.0/qemu-img.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/qemu-img.c	2012-02-17 20:45:39.000000000 +0100
-@@ -1420,6 +1420,8 @@
-      */
-     if (!unsafe) {
-         uint64_t num_sectors;
-+        uint64_t old_backing_num_sectors;
-+        uint64_t new_backing_num_sectors;
-         uint64_t sector;
-         int n;
-         uint8_t * buf_old;
-@@ -1430,6 +1432,8 @@
-         buf_new = qemu_blockalign(bs, IO_BUF_SIZE);
- 
-         bdrv_get_geometry(bs, &num_sectors);
-+        bdrv_get_geometry(bs_old_backing, &old_backing_num_sectors);
-+        bdrv_get_geometry(bs_new_backing, &new_backing_num_sectors);
- 
-         local_progress = (float)100 /
-             (num_sectors / MIN(num_sectors, IO_BUF_SIZE / 512));
-@@ -1448,16 +1452,36 @@
-                 continue;
-             }
- 
--            /* Read old and new backing file */
--            ret = bdrv_read(bs_old_backing, sector, buf_old, n);
--            if (ret < 0) {
--                error_report("error while reading from old backing file");
--                goto out;
-+            /*
-+             * Read old and new backing file and take into consideration that
-+             * backing files may be smaller than the COW image.
-+             */
-+            if (sector >= old_backing_num_sectors) {
-+                memset(buf_old, 0, n * BDRV_SECTOR_SIZE);
-+            } else {
-+                if (sector + n > old_backing_num_sectors) {
-+                    n = old_backing_num_sectors - sector;
-+                }
-+
-+                ret = bdrv_read(bs_old_backing, sector, buf_old, n);
-+                if (ret < 0) {
-+                    error_report("error while reading from old backing file");
-+                    goto out;
-+                }
-             }
--            ret = bdrv_read(bs_new_backing, sector, buf_new, n);
--            if (ret < 0) {
--                error_report("error while reading from new backing file");
--                goto out;
-+
-+            if (sector >= new_backing_num_sectors) {
-+                memset(buf_new, 0, n * BDRV_SECTOR_SIZE);
-+            } else {
-+                if (sector + n > new_backing_num_sectors) {
-+                    n = new_backing_num_sectors - sector;
-+                }
-+
-+                ret = bdrv_read(bs_new_backing, sector, buf_new, n);
-+                if (ret < 0) {
-+                    error_report("error while reading from new backing file");
-+                    goto out;
-+                }
-             }
- 
-             /* If they differ, we need to write to the COW file */
-diff -urN qemu-1.0/qemu-img-cmds.hx qemu-1.0.1/qemu-img-cmds.hx
---- qemu-1.0/qemu-img-cmds.hx	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/qemu-img-cmds.hx	2012-02-17 20:45:39.000000000 +0100
-@@ -24,13 +24,13 @@
- DEF("commit", img_commit,
-     "commit [-f fmt] [-t cache] filename")
- STEXI
-- at item commit [-f @var{fmt}] @var{filename}
-+ at item commit [-f @var{fmt}] [-t @var{cache}] @var{filename}
- ETEXI
- 
- DEF("convert", img_convert,
-     "convert [-c] [-p] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_name] [-S sparse_size] filename [filename2 [...]] output_filename")
- STEXI
-- at item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
-+ at item convert [-c] [-p] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
- ETEXI
- 
- DEF("info", img_info,
-@@ -48,7 +48,7 @@
- DEF("rebase", img_rebase,
-     "rebase [-f fmt] [-t cache] [-p] [-u] -b backing_file [-F backing_fmt] filename")
- STEXI
-- at item rebase [-f @var{fmt}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
-+ at item rebase [-f @var{fmt}] [-t @var{cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
- ETEXI
- 
- DEF("resize", img_resize,
-diff -urN qemu-1.0/qemu-img.texi qemu-1.0.1/qemu-img.texi
---- qemu-1.0/qemu-img.texi	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/qemu-img.texi	2012-02-17 20:45:39.000000000 +0100
-@@ -45,6 +45,10 @@
- for qemu-img to create a sparse image during conversion. This value is rounded
- down to the nearest 512 bytes. You may use the common size suffixes like
- @code{k} for kilobytes.
-+ at item -t @var{cache}
-+specifies the cache mode that should be used with the (destination) file. See
-+the documentation of the emulator's @code{-drive cache=...} option for allowed
-+values.
- @end table
- 
- Parameters to snapshot subcommand:
-@@ -87,11 +91,11 @@
- The size can also be specified using the @var{size} option with @code{-o},
- it doesn't need to be specified separately in this case.
- 
-- at item commit [-f @var{fmt}] @var{filename}
-+ at item commit [-f @var{fmt}] [-t @var{cache}] @var{filename}
- 
- Commit the changes recorded in @var{filename} in its base image.
- 
-- at item convert [-c] [-p] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
-+ at item convert [-c] [-p] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
- 
- Convert the disk image @var{filename} or a snapshot @var{snapshot_name} to disk image @var{output_filename}
- using format @var{output_fmt}. It can be optionally compressed (@code{-c}
-@@ -121,7 +125,7 @@
- 
- List, apply, create or delete snapshots in image @var{filename}.
- 
-- at item rebase [-f @var{fmt}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
-+ at item rebase [-f @var{fmt}] [-t @var{cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
- 
- Changes the backing file of an image. Only the formats @code{qcow2} and
- @code{qed} support changing the backing file.
-diff -urN qemu-1.0/qerror.c qemu-1.0.1/qerror.c
---- qemu-1.0/qerror.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/qerror.c	2012-02-17 20:45:39.000000000 +0100
-@@ -235,6 +235,11 @@
-                      "supported by this qemu version: %(feature)",
-     },
-     {
-+        .error_fmt = QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION,
-+        .desc      = "Migration is disabled when VirtFS export path '%(path)' "
-+                     "is mounted in the guest using mount_tag '%(tag)'",
-+    },
-+    {
-         .error_fmt = QERR_VNC_SERVER_FAILED,
-         .desc      = "Could not start VNC server on %(target)",
-     },
-diff -urN qemu-1.0/qerror.h qemu-1.0.1/qerror.h
---- qemu-1.0/qerror.h	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/qerror.h	2012-02-17 20:45:39.000000000 +0100
-@@ -192,6 +192,9 @@
- #define QERR_UNKNOWN_BLOCK_FORMAT_FEATURE \
-     "{ 'class': 'UnknownBlockFormatFeature', 'data': { 'device': %s, 'format': %s, 'feature': %s } }"
- 
-+#define QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION \
-+    "{ 'class': 'VirtFSFeatureBlocksMigration', 'data': { 'path': %s, 'tag': %s } }"
-+
- #define QERR_VNC_SERVER_FAILED \
-     "{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }"
- 
-diff -urN qemu-1.0/target-cris/cpu.h qemu-1.0.1/target-cris/cpu.h
---- qemu-1.0/target-cris/cpu.h	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/target-cris/cpu.h	2012-02-17 20:45:39.000000000 +0100
-@@ -67,6 +67,8 @@
- #define Q_FLAG 0x80000000
- #define M_FLAG 0x40000000
- #define PFIX_FLAG 0x800      /* CRISv10 Only.  */
-+#define F_FLAG_V10 0x400
-+#define P_FLAG_V10 0x200
- #define S_FLAG 0x200
- #define R_FLAG 0x100
- #define P_FLAG 0x80
-diff -urN qemu-1.0/target-cris/helper.c qemu-1.0.1/target-cris/helper.c
---- qemu-1.0/target-cris/helper.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/target-cris/helper.c	2012-02-17 20:45:39.000000000 +0100
-@@ -157,6 +157,7 @@
- 	/* Now that we are in kernel mode, load the handlers address.  */
- 	env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4);
- 	env->locked_irq = 1;
-+	env->pregs[PR_CCS] |= F_FLAG_V10; /* set F.  */
- 
- 	qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n", 
- 		      __func__, env->pc, ex_vec, 
-diff -urN qemu-1.0/target-cris/translate_v10.c qemu-1.0.1/target-cris/translate_v10.c
---- qemu-1.0/target-cris/translate_v10.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/target-cris/translate_v10.c	2012-02-17 20:45:39.000000000 +0100
-@@ -62,6 +62,65 @@
-     t_gen_raise_exception(EXCP_BREAK);
- }
- 
-+static void gen_store_v10_conditional(DisasContext *dc, TCGv addr, TCGv val,
-+                       unsigned int size, int mem_index)
-+{
-+    int l1 = gen_new_label();
-+    TCGv taddr = tcg_temp_local_new();
-+    TCGv tval = tcg_temp_local_new();
-+    TCGv t1 = tcg_temp_local_new();
-+    dc->postinc = 0;
-+    cris_evaluate_flags(dc);
-+
-+    tcg_gen_mov_tl(taddr, addr);
-+    tcg_gen_mov_tl(tval, val);
-+
-+    /* Store only if F flag isn't set */
-+    tcg_gen_andi_tl(t1, cpu_PR[PR_CCS], F_FLAG_V10);
-+    tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
-+    if (size == 1) {
-+        tcg_gen_qemu_st8(tval, taddr, mem_index);
-+    } else if (size == 2) {
-+        tcg_gen_qemu_st16(tval, taddr, mem_index);
-+    } else {
-+        tcg_gen_qemu_st32(tval, taddr, mem_index);
-+    }
-+    gen_set_label(l1);
-+    tcg_gen_shri_tl(t1, t1, 1);  /* shift F to P position */
-+    tcg_gen_or_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], t1); /*P=F*/
-+    tcg_temp_free(t1);
-+    tcg_temp_free(tval);
-+    tcg_temp_free(taddr);
-+}
-+
-+static void gen_store_v10(DisasContext *dc, TCGv addr, TCGv val,
-+                       unsigned int size)
-+{
-+    int mem_index = cpu_mmu_index(dc->env);
-+
-+    /* If we get a fault on a delayslot we must keep the jmp state in
-+       the cpu-state to be able to re-execute the jmp.  */
-+    if (dc->delayed_branch == 1) {
-+        cris_store_direct_jmp(dc);
-+    }
-+
-+    /* Conditional writes. We only support the kind were X is known
-+       at translation time.  */
-+    if (dc->flagx_known && dc->flags_x) {
-+        gen_store_v10_conditional(dc, addr, val, size, mem_index);
-+        return;
-+    }
-+
-+    if (size == 1) {
-+        tcg_gen_qemu_st8(val, addr, mem_index);
-+    } else if (size == 2) {
-+        tcg_gen_qemu_st16(val, addr, mem_index);
-+    } else {
-+        tcg_gen_qemu_st32(val, addr, mem_index);
-+    }
-+}
-+
-+
- /* Prefix flag and register are used to handle the more complex
-    addressing modes.  */
- static void cris_set_prefix(DisasContext *dc)
-@@ -313,7 +372,8 @@
-     if (set) {
-         tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags);
-     } else {
--        tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags);
-+        tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS],
-+                        ~(flags|F_FLAG_V10|P_FLAG_V10));
-     }
- 
-     dc->flags_uptodate = 1;
-@@ -723,7 +783,7 @@
-     LOG_DIS("move.%d $r%d, [$r%d]\n", dc->size, dc->src, dc->dst);
-     addr = tcg_temp_new();
-     crisv10_prepare_memaddr(dc, addr, size);
--    gen_store(dc, addr, cpu_R[dc->dst], size);
-+    gen_store_v10(dc, addr, cpu_R[dc->dst], size);
-     insn_len += crisv10_post_memaddr(dc, size);
- 
-     return insn_len;
-@@ -767,10 +827,10 @@
-         t0 = tcg_temp_new();
-         cris_evaluate_flags(dc);
-         tcg_gen_andi_tl(t0, cpu_PR[PR_CCS], ~PFIX_FLAG);
--        gen_store(dc, addr, t0, size);
-+        gen_store_v10(dc, addr, t0, size);
-         tcg_temp_free(t0);
-     } else {
--        gen_store(dc, addr, cpu_PR[dc->dst], size);
-+        gen_store_v10(dc, addr, cpu_PR[dc->dst], size);
-     }
-     t0 = tcg_temp_new();
-     insn_len += crisv10_post_memaddr(dc, size);
-@@ -793,9 +853,9 @@
-     tcg_gen_mov_tl(t0, addr);
-     for (i = dc->dst; i >= 0; i--) {
-         if ((pfix && dc->mode == CRISV10_MODE_AUTOINC) && dc->src == i) {
--            gen_store(dc, addr, t0, 4);
-+            gen_store_v10(dc, addr, t0, 4);
-         } else {
--            gen_store(dc, addr, cpu_R[i], 4);
-+            gen_store_v10(dc, addr, cpu_R[i], 4);
-         }
-         tcg_gen_addi_tl(addr, addr, 4);
-     }
-diff -urN qemu-1.0/target-i386/translate.c qemu-1.0.1/target-i386/translate.c
---- qemu-1.0/target-i386/translate.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/target-i386/translate.c	2012-02-17 20:45:39.000000000 +0100
-@@ -4870,20 +4870,23 @@
-             tcg_gen_sub_tl(t2, cpu_regs[R_EAX], t0);
-             gen_extu(ot, t2);
-             tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1);
-+            label2 = gen_new_label();
-             if (mod == 3) {
--                label2 = gen_new_label();
-                 gen_op_mov_reg_v(ot, R_EAX, t0);
-                 tcg_gen_br(label2);
-                 gen_set_label(label1);
-                 gen_op_mov_reg_v(ot, rm, t1);
--                gen_set_label(label2);
-             } else {
--                tcg_gen_mov_tl(t1, t0);
-+                /* perform no-op store cycle like physical cpu; must be
-+                   before changing accumulator to ensure idempotency if
-+                   the store faults and the instruction is restarted */
-+                gen_op_st_v(ot + s->mem_index, t0, a0);
-                 gen_op_mov_reg_v(ot, R_EAX, t0);
-+                tcg_gen_br(label2);
-                 gen_set_label(label1);
--                /* always store */
-                 gen_op_st_v(ot + s->mem_index, t1, a0);
-             }
-+            gen_set_label(label2);
-             tcg_gen_mov_tl(cpu_cc_src, t0);
-             tcg_gen_mov_tl(cpu_cc_dst, t2);
-             s->cc_op = CC_OP_SUBB + ot;
-diff -urN qemu-1.0/target-ppc/kvm.c qemu-1.0.1/target-ppc/kvm.c
---- qemu-1.0/target-ppc/kvm.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/target-ppc/kvm.c	2012-02-17 20:45:39.000000000 +0100
-@@ -504,7 +504,7 @@
- 
- int kvm_arch_process_async_events(CPUState *env)
- {
--    return 0;
-+    return env->halted;
- }
- 
- static int kvmppc_handle_halt(CPUState *env)
-@@ -838,12 +838,18 @@
-     int fd;
-     void *table;
- 
-+    /* Must set fd to -1 so we don't try to munmap when called for
-+     * destroying the table, which the upper layers -will- do
-+     */
-+    *pfd = -1;
-     if (!cap_spapr_tce) {
-         return NULL;
-     }
- 
-     fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE, &args);
-     if (fd < 0) {
-+        fprintf(stderr, "KVM: Failed to create TCE table for liobn 0x%x\n",
-+                liobn);
-         return NULL;
-     }
- 
-@@ -852,6 +858,8 @@
- 
-     table = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
-     if (table == MAP_FAILED) {
-+        fprintf(stderr, "KVM: Failed to map TCE table for liobn 0x%x\n",
-+                liobn);
-         close(fd);
-         return NULL;
-     }
-@@ -871,8 +879,8 @@
-     len = (window_size / SPAPR_VIO_TCE_PAGE_SIZE)*sizeof(VIOsPAPR_RTCE);
-     if ((munmap(table, len) < 0) ||
-         (close(fd) < 0)) {
--        fprintf(stderr, "KVM: Unexpected error removing KVM SPAPR TCE "
--                "table: %s", strerror(errno));
-+        fprintf(stderr, "KVM: Unexpected error removing TCE table: %s",
-+                strerror(errno));
-         /* Leak the table */
-     }
- 
-diff -urN qemu-1.0/target-s390x/kvm.c qemu-1.0.1/target-s390x/kvm.c
---- qemu-1.0/target-s390x/kvm.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/target-s390x/kvm.c	2012-02-17 20:45:39.000000000 +0100
-@@ -185,9 +185,6 @@
-         return;
-     }
- 
--    s390_add_running_cpu(env);
--    qemu_cpu_kick(env);
--
-     kvmint.type = type;
-     kvmint.parm = parm;
-     kvmint.parm64 = parm64;
-diff -urN qemu-1.0/target-s390x/op_helper.c qemu-1.0.1/target-s390x/op_helper.c
---- qemu-1.0/target-s390x/op_helper.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/target-s390x/op_helper.c	2012-02-17 20:45:39.000000000 +0100
-@@ -636,6 +636,9 @@
-         case 0x700:
-             cc = helper_xc(l, get_address(0, b1, d1), get_address(0, b2, d2));
-             break;
-+        case 0xc00:
-+            helper_tr(l, get_address(0, b1, d1), get_address(0, b2, d2));
-+            break;
-         default:
-             goto abort;
-             break;
-diff -urN qemu-1.0/target-sh4/translate.c qemu-1.0.1/target-sh4/translate.c
---- qemu-1.0/target-sh4/translate.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/target-sh4/translate.c	2012-02-17 20:45:39.000000000 +0100
-@@ -1652,18 +1652,10 @@
- 	}
- 	return;
-     case 0x00a3:		/* ocbp @Rn */
--	{
--	    TCGv dummy = tcg_temp_new();
--	    tcg_gen_qemu_ld32s(dummy, REG(B11_8), ctx->memidx);
--	    tcg_temp_free(dummy);
--	}
--	return;
-     case 0x00b3:		/* ocbwb @Rn */
--	{
--	    TCGv dummy = tcg_temp_new();
--	    tcg_gen_qemu_ld32s(dummy, REG(B11_8), ctx->memidx);
--	    tcg_temp_free(dummy);
--	}
-+        /* These instructions are supposed to do nothing in case of
-+           a cache miss. Given that we only partially emulate caches
-+           it is safe to simply ignore them. */
- 	return;
-     case 0x0083:		/* pref @Rn */
- 	return;
-diff -urN qemu-1.0/trace-events qemu-1.0.1/trace-events
---- qemu-1.0/trace-events	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/trace-events	2012-02-17 20:45:39.000000000 +0100
-@@ -579,11 +579,11 @@
- v9fs_lcreate_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int32_t iounit) "tag %d id %d qid={type %d version %d path %"PRId64"} iounit %d"
- v9fs_fsync(uint16_t tag, uint8_t id, int32_t fid, int datasync) "tag %d id %d fid %d datasync %d"
- v9fs_clunk(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
--v9fs_read(uint16_t tag, uint8_t id, int32_t fid, int64_t off, int32_t max_count) "tag %d id %d fid %d off %"PRId64" max_count %d"
-+v9fs_read(uint16_t tag, uint8_t id, int32_t fid, uint64_t off, uint32_t max_count) "tag %d id %d fid %d off %"PRIu64" max_count %u"
- v9fs_read_return(uint16_t tag, uint8_t id, int32_t count, ssize_t err) "tag %d id %d count %d err %zd"
--v9fs_readdir(uint16_t tag, uint8_t id, int32_t fid, int64_t offset, int32_t max_count) "tag %d id %d fid %d offset %"PRId64" max_count %d"
--v9fs_readdir_return(uint16_t tag, uint8_t id, int32_t count, ssize_t retval) "tag %d id %d count %d retval %zd"
--v9fs_write(uint16_t tag, uint8_t id, int32_t fid, int64_t off, int32_t count, int cnt) "tag %d id %d fid %d off %"PRId64" count %d cnt %d"
-+v9fs_readdir(uint16_t tag, uint8_t id, int32_t fid, uint64_t offset, uint32_t max_count) "tag %d id %d fid %d offset %"PRIu64" max_count %u"
-+v9fs_readdir_return(uint16_t tag, uint8_t id, uint32_t count, ssize_t retval) "tag %d id %d count %u retval %zd"
-+v9fs_write(uint16_t tag, uint8_t id, int32_t fid, uint64_t off, uint32_t count, int cnt) "tag %d id %d fid %d off %"PRIu64" count %u cnt %d"
- v9fs_write_return(uint16_t tag, uint8_t id, int32_t total, ssize_t err) "tag %d id %d total %d err %zd"
- v9fs_create(uint16_t tag, uint8_t id, int32_t fid, char* name, int32_t perm, int8_t mode) "tag %d id %d fid %d name %s perm %d mode %d"
- v9fs_create_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int iounit) "tag %d id %d qid={type %d version %d path %"PRId64"} iounit %d"
-diff -urN qemu-1.0/usb-linux.c qemu-1.0.1/usb-linux.c
---- qemu-1.0/usb-linux.c	2011-12-01 21:07:34.000000000 +0100
-+++ qemu-1.0.1/usb-linux.c	2012-02-17 20:45:39.000000000 +0100
-@@ -116,6 +116,7 @@
-     USBDevice dev;
-     int       fd;
-     int       hub_fd;
-+    int       hub_port;
- 
-     uint8_t   descr[8192];
-     int       descr_len;
-@@ -434,7 +435,7 @@
- {
- #ifdef USBDEVFS_CLAIM_PORT
-     char *h, hub_name[64], line[1024];
--    int hub_addr, portnr, ret;
-+    int hub_addr, ret;
- 
-     snprintf(hub_name, sizeof(hub_name), "%d-%s",
-              s->match.bus_num, s->match.port);
-@@ -442,13 +443,13 @@
-     /* try strip off last ".$portnr" to get hub */
-     h = strrchr(hub_name, '.');
-     if (h != NULL) {
--        portnr = atoi(h+1);
-+        s->hub_port = atoi(h+1);
-         *h = '\0';
-     } else {
-         /* no dot in there -> it is the root hub */
-         snprintf(hub_name, sizeof(hub_name), "usb%d",
-                  s->match.bus_num);
--        portnr = atoi(s->match.port);
-+        s->hub_port = atoi(s->match.port);
-     }
- 
-     if (!usb_host_read_file(line, sizeof(line), "devnum",
-@@ -469,20 +470,32 @@
-         return -1;
-     }
- 
--    ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &portnr);
-+    ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &s->hub_port);
-     if (ret < 0) {
-         close(s->hub_fd);
-         s->hub_fd = -1;
-         return -1;
-     }
- 
--    trace_usb_host_claim_port(s->match.bus_num, hub_addr, portnr);
-+    trace_usb_host_claim_port(s->match.bus_num, hub_addr, s->hub_port);
-     return 0;
- #else
-     return -1;
- #endif
- }
- 
-+static void usb_host_release_port(USBHostDevice *s)
-+{
-+    if (s->hub_fd == -1) {
-+        return;
-+    }
-+#ifdef USBDEVFS_RELEASE_PORT
-+    ioctl(s->hub_fd, USBDEVFS_RELEASE_PORT, &s->hub_port);
-+#endif
-+    close(s->hub_fd);
-+    s->hub_fd = -1;
-+}
-+
- static int usb_host_disconnect_ifaces(USBHostDevice *dev, int nb_interfaces)
- {
-     /* earlier Linux 2.4 do not support that */
-@@ -635,10 +648,8 @@
- {
-     USBHostDevice *s = (USBHostDevice *)dev;
- 
-+    usb_host_release_port(s);
-     usb_host_close(s);
--    if (s->hub_fd != -1) {
--        close(s->hub_fd);
--    }
-     QTAILQ_REMOVE(&hostdevs, s, next);
-     qemu_remove_exit_notifier(&s->exit);
- }
-@@ -1141,15 +1152,18 @@
-     length = s->descr_len - 18;
-     i = 0;
- 
--    if (descriptors[i + 1] != USB_DT_CONFIG ||
--        descriptors[i + 5] != s->configuration) {
--        fprintf(stderr, "invalid descriptor data - configuration %d\n",
--                s->configuration);
--        return 1;
--    }
--    i += descriptors[i];
--
-     while (i < length) {
-+        if (descriptors[i + 1] != USB_DT_CONFIG) {
-+            fprintf(stderr, "invalid descriptor data\n");
-+            return 1;
-+        } else if (descriptors[i + 5] != s->configuration) {
-+            DPRINTF("not requested configuration %d\n", s->configuration);
-+            i += (descriptors[i + 3] << 8) + descriptors[i + 2];
-+            continue;
-+        }
-+
-+        i += descriptors[i];
-+
-         if (descriptors[i + 1] != USB_DT_INTERFACE ||
-             (descriptors[i + 1] == USB_DT_INTERFACE &&
-              descriptors[i + 4] == 0)) {
-@@ -1399,6 +1413,7 @@
- {
-     USBHostDevice *s = container_of(n, USBHostDevice, exit);
- 
-+    usb_host_release_port(s);
-     if (s->fd != -1) {
-         usb_host_do_reset(s);;
-     }
diff --git a/qemu-kvm-cflags.patch b/qemu-kvm-cflags.patch
deleted file mode 100644
index 248c79c..0000000
--- a/qemu-kvm-cflags.patch
+++ /dev/null
@@ -1,13 +0,0 @@
---- qemu-kvm-1.0/configure~	2012-02-22 11:45:58.440892282 +0100
-+++ qemu-kvm-1.0/configure	2012-02-23 10:24:12.692463270 +0100
-@@ -2781,10 +2781,6 @@
- # End of CC checks
- # After here, no more $cc or $ld runs
- 
--if test "$debug" = "no" ; then
--  CFLAGS="-O2 $CFLAGS"
--fi
--
- # Consult white-list to determine whether to enable werror
- # by default.  Only enable by default for git builds
- z_version=`cut -f3 -d. $source_path/VERSION`
diff --git a/qemu-kvm-fixes.patch b/qemu-kvm-fixes.patch
new file mode 100644
index 0000000..497dee6
--- /dev/null
+++ b/qemu-kvm-fixes.patch
@@ -0,0 +1,10 @@
+--- qemu-kvm-1.2.0/hw/mips/Makefile.objs.orig	2012-09-06 10:31:27.000000000 +0200
++++ qemu-kvm-1.2.0/hw/mips/Makefile.objs	2012-11-04 14:45:03.810503326 +0100
+@@ -1,6 +1,7 @@
+ obj-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
+ obj-y += mips_addr.o mips_timer.o mips_int.o
+ obj-y += gt64xxx.o mc146818rtc.o
++obj-y += acpi.o acpi_piix4.o
+ obj-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o
+ 
+ obj-y := $(addprefix ../,$(obj-y))
diff --git a/qemu_virtio-scsi_support.patch b/qemu_virtio-scsi_support.patch
deleted file mode 100644
index 59f6876..0000000
--- a/qemu_virtio-scsi_support.patch
+++ /dev/null
@@ -1,1652 +0,0 @@
-diff -ruNp qemu-kvm-1.0/default-configs/pci.mak qemu-kvm-1.0.virtio-scsi/default-configs/pci.mak
---- qemu-kvm-1.0/default-configs/pci.mak	2011-12-04 04:38:06.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/default-configs/pci.mak	2012-02-07 14:44:53.424905251 -0600
-@@ -1,5 +1,6 @@
- CONFIG_PCI=y
- CONFIG_VIRTIO_PCI=y
-+CONFIG_VIRTIO_SCSI=y
- CONFIG_VIRTIO=y
- CONFIG_USB_UHCI=y
- CONFIG_USB_OHCI=y
-diff -ruNp qemu-kvm-1.0/default-configs/s390x-softmmu.mak qemu-kvm-1.0.virtio-scsi/default-configs/s390x-softmmu.mak
---- qemu-kvm-1.0/default-configs/s390x-softmmu.mak	2011-12-04 04:38:06.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/default-configs/s390x-softmmu.mak	2012-02-07 14:44:53.424905251 -0600
-@@ -1 +1,2 @@
- CONFIG_VIRTIO=y
-+CONFIG_VIRTIO_SCSI=y
-diff -ruNp qemu-kvm-1.0/dma.h qemu-kvm-1.0.virtio-scsi/dma.h
---- qemu-kvm-1.0/dma.h	2011-12-04 04:38:06.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/dma.h	2012-02-07 14:44:53.425905267 -0600
-@@ -17,6 +17,13 @@
- 
- typedef struct ScatterGatherEntry ScatterGatherEntry;
- 
-+struct QEMUSGList {
-+    ScatterGatherEntry *sg;
-+    int nsg;
-+    int nalloc;
-+    size_t size;
-+};
-+
- #if defined(TARGET_PHYS_ADDR_BITS)
- typedef target_phys_addr_t dma_addr_t;
- 
-@@ -32,13 +39,6 @@ struct ScatterGatherEntry {
-     dma_addr_t len;
- };
- 
--struct QEMUSGList {
--    ScatterGatherEntry *sg;
--    int nsg;
--    int nalloc;
--    dma_addr_t size;
--};
--
- void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint);
- void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len);
- void qemu_sglist_destroy(QEMUSGList *qsg);
-@@ -58,4 +58,10 @@ BlockDriverAIOCB *dma_bdrv_read(BlockDri
- BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
-                                  QEMUSGList *sg, uint64_t sector,
-                                  BlockDriverCompletionFunc *cb, void *opaque);
-+uint64_t dma_buf_read(uint8_t *ptr, int32_t len, QEMUSGList *sg);
-+uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
-+
-+void dma_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie,
-+                    QEMUSGList *sg, enum BlockAcctType type);
-+
- #endif
-diff -ruNp qemu-kvm-1.0/dma-helpers.c qemu-kvm-1.0.virtio-scsi/dma-helpers.c
---- qemu-kvm-1.0/dma-helpers.c	2011-12-04 04:38:06.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/dma-helpers.c	2012-02-07 14:44:53.424905251 -0600
-@@ -196,3 +196,39 @@ BlockDriverAIOCB *dma_bdrv_write(BlockDr
- {
-     return dma_bdrv_io(bs, sg, sector, bdrv_aio_writev, cb, opaque, true);
- }
-+
-+
-+static uint64_t dma_buf_rw(uint8_t *ptr, int32_t len, QEMUSGList *sg, bool to_dev)
-+{
-+    uint64_t resid;
-+    int sg_cur_index;
-+
-+    resid = sg->size;
-+    sg_cur_index = 0;
-+    len = MIN(len, resid);
-+    while (len > 0) {
-+        ScatterGatherEntry entry = sg->sg[sg_cur_index++];
-+        cpu_physical_memory_rw(entry.base, ptr, MIN(len, entry.len), !to_dev);
-+        ptr += entry.len;
-+        len -= entry.len;
-+        resid -= entry.len;
-+    }
-+
-+    return resid;
-+}
-+
-+uint64_t dma_buf_read(uint8_t *ptr, int32_t len, QEMUSGList *sg)
-+{
-+    return dma_buf_rw(ptr, len, sg, 0);
-+}
-+
-+uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg)
-+{
-+    return dma_buf_rw(ptr, len, sg, 1);
-+}
-+
-+void dma_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie,
-+                    QEMUSGList *sg, enum BlockAcctType type)
-+{
-+    bdrv_acct_start(bs, cookie, sg->size, type);
-+}
-diff -ruNp qemu-kvm-1.0/hw/esp.c qemu-kvm-1.0.virtio-scsi/hw/esp.c
---- qemu-kvm-1.0/hw/esp.c	2011-12-04 04:38:06.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/esp.c	2012-02-07 14:44:53.425905267 -0600
-@@ -389,7 +389,8 @@ static void esp_do_dma(ESPState *s)
-     esp_dma_done(s);
- }
- 
--static void esp_command_complete(SCSIRequest *req, uint32_t status)
-+static void esp_command_complete(SCSIRequest *req, uint32_t status,
-+                                 int32_t resid)
- {
-     ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
- 
-diff -ruNp qemu-kvm-1.0/hw/ide/ahci.c qemu-kvm-1.0.virtio-scsi/hw/ide/ahci.c
---- qemu-kvm-1.0/hw/ide/ahci.c	2011-12-04 04:38:06.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/ide/ahci.c	2012-02-07 14:44:53.426905283 -0600
-@@ -425,55 +425,6 @@ static void ahci_reg_init(AHCIState *s)
-     }
- }
- 
--static uint32_t read_from_sglist(uint8_t *buffer, uint32_t len,
--                                 QEMUSGList *sglist)
--{
--    uint32_t i = 0;
--    uint32_t total = 0, once;
--    ScatterGatherEntry *cur_prd;
--    uint32_t sgcount;
--
--    cur_prd = sglist->sg;
--    sgcount = sglist->nsg;
--    for (i = 0; len && sgcount; i++) {
--        once = MIN(cur_prd->len, len);
--        cpu_physical_memory_read(cur_prd->base, buffer, once);
--        cur_prd++;
--        sgcount--;
--        len -= once;
--        buffer += once;
--        total += once;
--    }
--
--    return total;
--}
--
--static uint32_t write_to_sglist(uint8_t *buffer, uint32_t len,
--                                QEMUSGList *sglist)
--{
--    uint32_t i = 0;
--    uint32_t total = 0, once;
--    ScatterGatherEntry *cur_prd;
--    uint32_t sgcount;
--
--    DPRINTF(-1, "total: 0x%x bytes\n", len);
--
--    cur_prd = sglist->sg;
--    sgcount = sglist->nsg;
--    for (i = 0; len && sgcount; i++) {
--        once = MIN(cur_prd->len, len);
--        DPRINTF(-1, "write 0x%x bytes to 0x%lx\n", once, (long)cur_prd->base);
--        cpu_physical_memory_write(cur_prd->base, buffer, once);
--        cur_prd++;
--        sgcount--;
--        len -= once;
--        buffer += once;
--        total += once;
--    }
--
--    return total;
--}
--
- static void check_cmd(AHCIState *s, int port)
- {
-     AHCIPortRegs *pr = &s->dev[port].port_regs;
-@@ -794,9 +745,8 @@ static void process_ncq_command(AHCIStat
-             DPRINTF(port, "tag %d aio read %"PRId64"\n",
-                     ncq_tfs->tag, ncq_tfs->lba);
- 
--            bdrv_acct_start(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct,
--                            (ncq_tfs->sector_count-1) * BDRV_SECTOR_SIZE,
--                            BDRV_ACCT_READ);
-+            dma_acct_start(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct,
-+                           &ncq_tfs->sglist, BDRV_ACCT_READ);
-             ncq_tfs->aiocb = dma_bdrv_read(ncq_tfs->drive->port.ifs[0].bs,
-                                            &ncq_tfs->sglist, ncq_tfs->lba,
-                                            ncq_cb, ncq_tfs);
-@@ -808,9 +758,8 @@ static void process_ncq_command(AHCIStat
-             DPRINTF(port, "tag %d aio write %"PRId64"\n",
-                     ncq_tfs->tag, ncq_tfs->lba);
- 
--            bdrv_acct_start(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct,
--                            (ncq_tfs->sector_count-1) * BDRV_SECTOR_SIZE,
--                            BDRV_ACCT_WRITE);
-+            dma_acct_start(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct,
-+                           &ncq_tfs->sglist, BDRV_ACCT_WRITE);
-             ncq_tfs->aiocb = dma_bdrv_write(ncq_tfs->drive->port.ifs[0].bs,
-                                             &ncq_tfs->sglist, ncq_tfs->lba,
-                                             ncq_cb, ncq_tfs);
-@@ -1015,12 +964,12 @@ static int ahci_start_transfer(IDEDMA *d
-             is_write ? "writ" : "read", size, is_atapi ? "atapi" : "ata",
-             has_sglist ? "" : "o");
- 
--    if (is_write && has_sglist && (s->data_ptr < s->data_end)) {
--        read_from_sglist(s->data_ptr, size, &s->sg);
--    }
--
--    if (!is_write && has_sglist && (s->data_ptr < s->data_end)) {
--        write_to_sglist(s->data_ptr, size, &s->sg);
-+    if (has_sglist && size) {
-+        if (is_write) {
-+            dma_buf_write(s->data_ptr, size, &s->sg);
-+        } else {
-+            dma_buf_read(s->data_ptr, size, &s->sg);
-+        }
-     }
- 
-     /* update number of transferred bytes */
-@@ -1059,14 +1008,9 @@ static int ahci_dma_prepare_buf(IDEDMA *
- {
-     AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
-     IDEState *s = &ad->port.ifs[0];
--    int i;
- 
-     ahci_populate_sglist(ad, &s->sg);
--
--    s->io_buffer_size = 0;
--    for (i = 0; i < s->sg.nsg; i++) {
--        s->io_buffer_size += s->sg.sg[i].len;
--    }
-+    s->io_buffer_size = s->sg.size;
- 
-     DPRINTF(ad->port_no, "len=%#x\n", s->io_buffer_size);
-     return s->io_buffer_size != 0;
-@@ -1084,9 +1028,9 @@ static int ahci_dma_rw_buf(IDEDMA *dma,
-     }
- 
-     if (is_write) {
--        write_to_sglist(p, l, &s->sg);
-+        dma_buf_read(p, l, &s->sg);
-     } else {
--        read_from_sglist(p, l, &s->sg);
-+        dma_buf_write(p, l, &s->sg);
-     }
- 
-     /* update number of transferred bytes */
-diff -ruNp qemu-kvm-1.0/hw/lsi53c895a.c qemu-kvm-1.0.virtio-scsi/hw/lsi53c895a.c
---- qemu-kvm-1.0/hw/lsi53c895a.c	2011-12-04 04:38:06.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/lsi53c895a.c	2012-02-07 14:44:53.427905299 -0600
-@@ -699,7 +699,7 @@ static int lsi_queue_req(LSIState *s, SC
- }
- 
-  /* Callback to indicate that the SCSI layer has completed a command.  */
--static void lsi_command_complete(SCSIRequest *req, uint32_t status)
-+static void lsi_command_complete(SCSIRequest *req, uint32_t status, int32_t resid)
- {
-     LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
-     int out;
-diff -ruNp qemu-kvm-1.0/hw/pci.h qemu-kvm-1.0.virtio-scsi/hw/pci.h
---- qemu-kvm-1.0/hw/pci.h	2011-12-04 04:38:06.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/pci.h	2012-02-07 14:44:53.427905299 -0600
-@@ -76,6 +76,7 @@
- #define PCI_DEVICE_ID_VIRTIO_BLOCK       0x1001
- #define PCI_DEVICE_ID_VIRTIO_BALLOON     0x1002
- #define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
-+#define PCI_DEVICE_ID_VIRTIO_SCSI        0x1004
- 
- #define FMT_PCIBUS                      PRIx64
- 
-diff -ruNp qemu-kvm-1.0/hw/s390-virtio-bus.c qemu-kvm-1.0.virtio-scsi/hw/s390-virtio-bus.c
---- qemu-kvm-1.0/hw/s390-virtio-bus.c	2011-12-04 04:38:06.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/s390-virtio-bus.c	2012-02-07 14:44:53.428905315 -0600
-@@ -158,6 +158,18 @@ static int s390_virtio_serial_init(VirtI
-     return r;
- }
- 
-+static int s390_virtio_scsi_init(VirtIOS390Device *dev)
-+{
-+    VirtIODevice *vdev;
-+
-+    vdev = virtio_scsi_init((DeviceState *)dev, &dev->scsi);
-+    if (!vdev) {
-+        return -1;
-+    }
-+
-+    return s390_virtio_device_init(dev, vdev);
-+}
-+
- static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)
- {
-     ram_addr_t token_off;
-@@ -370,6 +382,17 @@ static VirtIOS390DeviceInfo s390_virtio_
-     },
- };
- 
-+static VirtIOS390DeviceInfo s390_virtio_scsi = {
-+    .init = s390_virtio_scsi_init,
-+    .qdev.name = "virtio-scsi-s390",
-+    .qdev.alias = "virtio-scsi",
-+    .qdev.size = sizeof(VirtIOS390Device),
-+    .qdev.props = (Property[]) {
-+        DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOS390Device, host_features, scsi),
-+        DEFINE_PROP_END_OF_LIST(),
-+    },
-+};
-+
- static int s390_virtio_busdev_init(DeviceState *dev, DeviceInfo *info)
- {
-     VirtIOS390DeviceInfo *_info = (VirtIOS390DeviceInfo *)info;
-@@ -392,6 +415,7 @@ static void s390_virtio_register(void)
-     s390_virtio_bus_register_withprop(&s390_virtio_serial);
-     s390_virtio_bus_register_withprop(&s390_virtio_blk);
-     s390_virtio_bus_register_withprop(&s390_virtio_net);
-+    s390_virtio_bus_register_withprop(&s390_virtio_scsi);
- }
- device_init(s390_virtio_register);
- 
-diff -ruNp qemu-kvm-1.0/hw/s390-virtio-bus.h qemu-kvm-1.0.virtio-scsi/hw/s390-virtio-bus.h
---- qemu-kvm-1.0/hw/s390-virtio-bus.h	2011-12-04 04:38:06.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/s390-virtio-bus.h	2012-02-07 14:44:53.428905315 -0600
-@@ -19,6 +19,7 @@
- 
- #include "virtio-net.h"
- #include "virtio-serial.h"
-+#include "virtio-scsi.h"
- 
- #define VIRTIO_DEV_OFFS_TYPE		0	/* 8 bits */
- #define VIRTIO_DEV_OFFS_NUM_VQ		1	/* 8 bits */
-@@ -47,6 +48,7 @@ typedef struct VirtIOS390Device {
-     uint32_t host_features;
-     virtio_serial_conf serial;
-     virtio_net_conf net;
-+    VirtIOSCSIConf scsi;
- } VirtIOS390Device;
- 
- typedef struct VirtIOS390Bus {
-diff -ruNp qemu-kvm-1.0/hw/scsi-bus.c qemu-kvm-1.0.virtio-scsi/hw/scsi-bus.c
---- qemu-kvm-1.0/hw/scsi-bus.c	2011-12-04 04:38:06.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/scsi-bus.c	2012-02-07 14:44:53.428905315 -0600
-@@ -5,6 +5,7 @@
- #include "qdev.h"
- #include "blockdev.h"
- #include "trace.h"
-+#include "dma.h"
- 
- static char *scsibus_get_fw_dev_path(DeviceState *dev);
- static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
-@@ -50,6 +51,7 @@ static void scsi_dma_restart_bh(void *op
-                 scsi_req_continue(req);
-                 break;
-             case SCSI_XFER_NONE:
-+                assert(!req->sg);
-                 scsi_req_dequeue(req);
-                 scsi_req_enqueue(req);
-                 break;
-@@ -512,6 +514,8 @@ SCSIRequest *scsi_req_new(SCSIDevice *d,
-     }
- 
-     req->cmd = cmd;
-+    req->resid = req->cmd.xfer;
-+
-     switch (buf[0]) {
-     case INQUIRY:
-         trace_scsi_inquiry(d->id, lun, tag, cmd.buf[1], cmd.buf[2]);
-@@ -624,15 +628,25 @@ void scsi_req_build_sense(SCSIRequest *r
-     req->sense_len = 18;
- }
- 
--int32_t scsi_req_enqueue(SCSIRequest *req)
-+static void scsi_req_enqueue_internal(SCSIRequest *req)
- {
--    int32_t rc;
--
-     assert(!req->enqueued);
-     scsi_req_ref(req);
-+    if (req->bus->info->get_sg_list) {
-+        req->sg = req->bus->info->get_sg_list(req);
-+    } else {
-+        req->sg = NULL;
-+    }
-     req->enqueued = true;
-     QTAILQ_INSERT_TAIL(&req->dev->requests, req, next);
-+}
-+
-+int32_t scsi_req_enqueue(SCSIRequest *req)
-+{
-+    int32_t rc;
- 
-+    assert (!req->retry);
-+    scsi_req_enqueue_internal(req);
-     scsi_req_ref(req);
-     rc = req->ops->send_command(req, req->cmd.buf);
-     scsi_req_unref(req);
-@@ -1254,12 +1268,32 @@ void scsi_req_continue(SCSIRequest *req)
-    Once it completes, calling scsi_req_continue will restart I/O.  */
- void scsi_req_data(SCSIRequest *req, int len)
- {
-+    uint8_t *buf;
-     if (req->io_canceled) {
-         trace_scsi_req_data_canceled(req->dev->id, req->lun, req->tag, len);
--    } else {
--        trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
-+        return;
-+    }
-+    trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
-+    assert(req->cmd.mode != SCSI_XFER_NONE);
-+    if (!req->sg) {
-+        req->resid -= len;
-         req->bus->info->transfer_data(req, len);
-+        return;
-+    }
-+
-+    /* If the device calls scsi_req_data and the HBA specified a
-+     * scatter/gather list, the transfer has to happen in a single
-+     * step.  */
-+    assert(!req->dma_started);
-+    req->dma_started = true;
-+
-+    buf = scsi_req_get_buf(req);
-+    if (req->cmd.mode == SCSI_XFER_FROM_DEV) {
-+        req->resid = dma_buf_read(buf, len, req->sg);
-+    } else {
-+        req->resid = dma_buf_write(buf, len, req->sg);
-     }
-+    scsi_req_continue(req);
- }
- 
- void scsi_req_print(SCSIRequest *req)
-@@ -1318,7 +1352,7 @@ void scsi_req_complete(SCSIRequest *req,
- 
-     scsi_req_ref(req);
-     scsi_req_dequeue(req);
--    req->bus->info->complete(req, req->status);
-+    req->bus->info->complete(req, req->status, req->resid);
-     scsi_req_unref(req);
- }
- 
-@@ -1393,3 +1427,100 @@ SCSIDevice *scsi_device_find(SCSIBus *bu
-     }
-     return target_dev;
- }
-+
-+
-+/* SCSI request list.  For simplicity, pv points to the whole device */
-+
-+static void put_scsi_requests(QEMUFile *f, void *pv, size_t size)
-+{
-+    SCSIDevice *s = pv;
-+    SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
-+    SCSIRequest *req;
-+
-+    QTAILQ_FOREACH(req, &s->requests, next) {
-+        assert(!req->io_canceled);
-+        assert(req->status == -1);
-+        assert(req->retry);
-+        assert(req->enqueued);
-+
-+        qemu_put_sbyte(f, 1);
-+        qemu_put_buffer(f, req->cmd.buf, sizeof(req->cmd.buf));
-+        qemu_put_be32s(f, &req->tag);
-+        qemu_put_be32s(f, &req->lun);
-+        if (bus->info->save_request) {
-+            bus->info->save_request(f, req);
-+        }
-+        if (req->ops->save_request) {
-+            req->ops->save_request(f, req);
-+        }
-+    }
-+    qemu_put_sbyte(f, 0);
-+}
-+
-+static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
-+{
-+    SCSIDevice *s = pv;
-+    SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
-+
-+    while (qemu_get_sbyte(f)) {
-+        uint8_t buf[SCSI_CMD_BUF_SIZE];
-+        uint32_t tag;
-+        uint32_t lun;
-+        SCSIRequest *req;
-+
-+        qemu_get_buffer(f, buf, sizeof(buf));
-+        qemu_get_be32s(f, &tag);
-+        qemu_get_be32s(f, &lun);
-+        req = scsi_req_new(s, tag, lun, buf, NULL);
-+        if (bus->info->load_request) {
-+            req->hba_private = bus->info->load_request(f, req);
-+        }
-+        if (req->ops->load_request) {
-+            req->ops->load_request(f, req);
-+        }
-+
-+        /* Just restart it later.  */
-+        req->retry = true;
-+        scsi_req_enqueue_internal(req);
-+
-+        /* At this point, the request will be kept alive by the reference
-+         * added by scsi_req_enqueue_internal, so we can release our reference.
-+         * The HBA of course will add its own reference in the load_request
-+         * callback if it needs to hold on the SCSIRequest.
-+         */
-+        scsi_req_unref(req);
-+    }
-+
-+    return 0;
-+}
-+
-+const VMStateInfo vmstate_info_scsi_requests = {
-+    .name = "scsi-requests",
-+    .get  = get_scsi_requests,
-+    .put  = put_scsi_requests,
-+};
-+
-+const VMStateDescription vmstate_scsi_device = {
-+    .name = "SCSIDevice",
-+    .version_id = 1,
-+    .minimum_version_id = 1,
-+    .minimum_version_id_old = 1,
-+    .fields = (VMStateField[]) {
-+        VMSTATE_UINT8(unit_attention.key, SCSIDevice),
-+        VMSTATE_UINT8(unit_attention.asc, SCSIDevice),
-+        VMSTATE_UINT8(unit_attention.ascq, SCSIDevice),
-+        VMSTATE_BOOL(sense_is_ua, SCSIDevice),
-+        VMSTATE_UINT8_ARRAY(sense, SCSIDevice, SCSI_SENSE_BUF_SIZE),
-+        VMSTATE_UINT32(sense_len, SCSIDevice),
-+        {
-+            .name         = "requests",
-+            .version_id   = 0,
-+            .field_exists = NULL,
-+            .size         = 0,   /* ouch */
-+            .info         = &vmstate_info_scsi_requests,
-+            .flags        = VMS_SINGLE,
-+            .offset       = 0,
-+        },
-+        VMSTATE_END_OF_LIST()
-+    }
-+};
-diff -ruNp qemu-kvm-1.0/hw/scsi-disk.c qemu-kvm-1.0.virtio-scsi/hw/scsi-disk.c
---- qemu-kvm-1.0/hw/scsi-disk.c	2011-12-04 04:38:06.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/scsi-disk.c	2012-02-07 14:44:53.429905331 -0600
-@@ -38,6 +38,7 @@ do { fprintf(stderr, "scsi-disk: " fmt ,
- #include "sysemu.h"
- #include "blockdev.h"
- #include "block_int.h"
-+#include "dma.h"
- 
- #ifdef __linux
- #include <scsi/sg.h>
-@@ -110,12 +111,12 @@ static void scsi_cancel_io(SCSIRequest *
-     r->req.aiocb = NULL;
- }
- 
--static uint32_t scsi_init_iovec(SCSIDiskReq *r)
-+static uint32_t scsi_init_iovec(SCSIDiskReq *r, size_t size)
- {
-     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
- 
-     if (!r->iov.iov_base) {
--        r->buflen = SCSI_DMA_BUF_SIZE;
-+        r->buflen = size;
-         r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
-     }
-     r->iov.iov_len = MIN(r->sector_count * 512, r->buflen);
-@@ -123,6 +124,56 @@ static uint32_t scsi_init_iovec(SCSIDisk
-     return r->qiov.size / 512;
- }
- 
-+static void scsi_disk_save_request(QEMUFile *f, SCSIRequest *req)
-+{
-+    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
-+
-+    qemu_put_be64s(f, &r->sector);
-+    qemu_put_be32s(f, &r->sector_count);
-+    qemu_put_be32s(f, &r->buflen);
-+    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
-+        qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
-+    }
-+}
-+
-+static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req)
-+{
-+    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
-+
-+    qemu_get_be64s(f, &r->sector);
-+    qemu_get_be32s(f, &r->sector_count);
-+    qemu_get_be32s(f, &r->buflen);
-+    if (r->buflen) {
-+        scsi_init_iovec(r, r->buflen);
-+        if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
-+            qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
-+        }
-+    }
-+
-+    qemu_iovec_init_external(&r->qiov, &r->iov, 1);
-+}
-+
-+static void scsi_dma_complete(void * opaque, int ret)
-+{
-+    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
-+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
-+
-+    bdrv_acct_done(s->qdev.conf.bs, &r->acct);
-+
-+    if (ret) {
-+        if (scsi_handle_rw_error(r, -ret)) {
-+            goto done;
-+        }
-+    }
-+
-+    r->sector += r->sector_count;
-+    r->sector_count = 0;
-+    scsi_req_complete(&r->req, GOOD);
-+
-+done:
-+    scsi_req_unref(&r->req);
-+}
-+
- static void scsi_read_complete(void * opaque, int ret)
- {
-     SCSIDiskReq *r = (SCSIDiskReq *)opaque;
-@@ -213,10 +264,17 @@ static void scsi_read_data(SCSIRequest *
-         return;
-     }
- 
--    n = scsi_init_iovec(r);
--    bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
--    r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
--                              scsi_read_complete, r);
-+    if (r->req.sg) {
-+        dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_READ);
-+	r->req.resid -= r->req.sg->size;
-+        r->req.aiocb = dma_bdrv_read(s->qdev.conf.bs, r->req.sg, r->sector,
-+                                     scsi_dma_complete, r);
-+    } else {
-+        n = scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
-+        bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
-+        r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
-+                                      scsi_read_complete, r);
-+    }
-     if (r->req.aiocb == NULL) {
-         scsi_read_complete(r, -EIO);
-     }
-@@ -290,7 +348,7 @@ static void scsi_write_complete(void * o
-     if (r->sector_count == 0) {
-         scsi_req_complete(&r->req, GOOD);
-     } else {
--        scsi_init_iovec(r);
-+        scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
-         DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, r->qiov.size);
-         scsi_req_data(&r->req, r->qiov.size);
-     }
-@@ -318,21 +376,29 @@ static void scsi_write_data(SCSIRequest
-         return;
-     }
- 
--    n = r->qiov.size / 512;
--    if (n) {
--        if (s->tray_open) {
--            scsi_write_complete(r, -ENOMEDIUM);
--            return;
--        }
-+    if (!r->req.sg && !r->qiov.size) {
-+        /* Called for the first time.  Ask the driver to send us more data.  */
-+        scsi_write_complete(r, 0);
-+        return;
-+    }
-+    if (s->tray_open) {
-+        scsi_write_complete(r, -ENOMEDIUM);
-+        return;
-+    }
-+
-+    if (r->req.sg) {
-+        dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_WRITE);
-+	r->req.resid -= r->req.sg->size;
-+        r->req.aiocb = dma_bdrv_write(s->qdev.conf.bs, r->req.sg, r->sector,
-+                                      scsi_dma_complete, r);
-+    } else {
-+        n = r->qiov.size / 512;
-         bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
-         r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, r->sector, &r->qiov, n,
-                                        scsi_write_complete, r);
--        if (r->req.aiocb == NULL) {
--            scsi_write_complete(r, -ENOMEM);
--        }
--    } else {
--        /* Called for the first time.  Ask the driver to send us more data.  */
--        scsi_write_complete(r, 0);
-+    }
-+    if (r->req.aiocb == NULL) {
-+        scsi_write_complete(r, -ENOMEM);
-     }
- }
- 
-@@ -1601,6 +1667,8 @@ static const SCSIReqOps scsi_disk_reqops
-     .write_data   = scsi_write_data,
-     .cancel_io    = scsi_cancel_io,
-     .get_buf      = scsi_get_buf,
-+    .load_request = scsi_disk_load_request,
-+    .save_request = scsi_disk_save_request,
- };
- 
- static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
-@@ -1729,6 +1797,22 @@ static SCSIRequest *scsi_block_new_reque
-     DEFINE_PROP_STRING("ver",  SCSIDiskState, version),         \
-     DEFINE_PROP_STRING("serial",  SCSIDiskState, serial)
- 
-+static const VMStateDescription vmstate_scsi_disk_state = {
-+    .name = "scsi-disk",
-+    .version_id = 1,
-+    .minimum_version_id = 1,
-+    .minimum_version_id_old = 1,
-+    .fields = (VMStateField[]) {
-+        VMSTATE_SCSI_DEVICE(qdev, SCSIDiskState),
-+        VMSTATE_BOOL(media_changed, SCSIDiskState),
-+        VMSTATE_BOOL(media_event, SCSIDiskState),
-+        VMSTATE_BOOL(eject_request, SCSIDiskState),
-+        VMSTATE_BOOL(tray_open, SCSIDiskState),
-+        VMSTATE_BOOL(tray_locked, SCSIDiskState),
-+        VMSTATE_END_OF_LIST()
-+    }
-+};
-+
- static SCSIDeviceInfo scsi_disk_info[] = {
-     {
-         .qdev.name    = "scsi-hd",
-@@ -1736,6 +1820,7 @@ static SCSIDeviceInfo scsi_disk_info[] =
-         .qdev.desc    = "virtual SCSI disk",
-         .qdev.size    = sizeof(SCSIDiskState),
-         .qdev.reset   = scsi_disk_reset,
-+        .qdev.vmsd    = &vmstate_scsi_disk_state,
-         .init         = scsi_hd_initfn,
-         .destroy      = scsi_destroy,
-         .alloc_req    = scsi_new_request,
-@@ -1751,6 +1836,7 @@ static SCSIDeviceInfo scsi_disk_info[] =
-         .qdev.desc    = "virtual SCSI CD-ROM",
-         .qdev.size    = sizeof(SCSIDiskState),
-         .qdev.reset   = scsi_disk_reset,
-+        .qdev.vmsd    = &vmstate_scsi_disk_state,
-         .init         = scsi_cd_initfn,
-         .destroy      = scsi_destroy,
-         .alloc_req    = scsi_new_request,
-@@ -1766,6 +1852,7 @@ static SCSIDeviceInfo scsi_disk_info[] =
-         .qdev.desc    = "SCSI block device passthrough",
-         .qdev.size    = sizeof(SCSIDiskState),
-         .qdev.reset   = scsi_disk_reset,
-+        .qdev.vmsd    = &vmstate_scsi_disk_state,
-         .init         = scsi_block_initfn,
-         .destroy      = scsi_destroy,
-         .alloc_req    = scsi_block_new_request,
-@@ -1780,6 +1867,7 @@ static SCSIDeviceInfo scsi_disk_info[] =
-         .qdev.desc    = "virtual SCSI disk or CD-ROM (legacy)",
-         .qdev.size    = sizeof(SCSIDiskState),
-         .qdev.reset   = scsi_disk_reset,
-+        .qdev.vmsd    = &vmstate_scsi_disk_state,
-         .init         = scsi_disk_initfn,
-         .destroy      = scsi_destroy,
-         .alloc_req    = scsi_new_request,
-diff -ruNp qemu-kvm-1.0/hw/scsi-generic.c qemu-kvm-1.0.virtio-scsi/hw/scsi-generic.c
---- qemu-kvm-1.0/hw/scsi-generic.c	2011-12-04 04:38:06.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/scsi-generic.c	2012-02-07 14:44:53.430905347 -0600
-@@ -59,6 +59,28 @@ typedef struct SCSIGenericReq {
-     sg_io_hdr_t io_header;
- } SCSIGenericReq;
- 
-+static void scsi_generic_save_request(QEMUFile *f, SCSIRequest *req)
-+{
-+    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
-+
-+    qemu_put_sbe32s(f, &r->buflen);
-+    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
-+        assert(!r->req.sg);
-+        qemu_put_buffer(f, r->buf, r->req.cmd.xfer);
-+    }
-+}
-+
-+static void scsi_generic_load_request(QEMUFile *f, SCSIRequest *req)
-+{
-+    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
-+
-+    qemu_get_sbe32s(f, &r->buflen);
-+    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
-+        assert(!r->req.sg);
-+        qemu_get_buffer(f, r->buf, r->req.cmd.xfer);
-+    }
-+}
-+
- static void scsi_free_request(SCSIRequest *req)
- {
-     SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
-@@ -450,6 +472,8 @@ const SCSIReqOps scsi_generic_req_ops =
-     .write_data   = scsi_write_data,
-     .cancel_io    = scsi_cancel_io,
-     .get_buf      = scsi_get_buf,
-+    .load_request = scsi_generic_load_request,
-+    .save_request = scsi_generic_save_request,
- };
- 
- static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
-@@ -467,6 +491,7 @@ static SCSIDeviceInfo scsi_generic_info
-     .qdev.desc    = "pass through generic scsi device (/dev/sg*)",
-     .qdev.size    = sizeof(SCSIDevice),
-     .qdev.reset   = scsi_generic_reset,
-+    .qdev.vmsd    = &vmstate_scsi_device,
-     .init         = scsi_generic_initfn,
-     .destroy      = scsi_destroy,
-     .alloc_req    = scsi_new_request,
-diff -ruNp qemu-kvm-1.0/hw/scsi.h qemu-kvm-1.0.virtio-scsi/hw/scsi.h
---- qemu-kvm-1.0/hw/scsi.h	2011-12-04 04:38:06.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/scsi.h	2012-02-07 14:44:53.430905347 -0600
-@@ -47,8 +47,11 @@ struct SCSIRequest {
-     uint32_t          tag;
-     uint32_t          lun;
-     uint32_t          status;
-+    size_t            resid;
-     SCSICommand       cmd;
-     BlockDriverAIOCB  *aiocb;
-+    QEMUSGList        *sg;
-+    bool              dma_started;
-     uint8_t sense[SCSI_SENSE_BUF_SIZE];
-     uint32_t sense_len;
-     bool enqueued;
-@@ -78,6 +81,16 @@ struct SCSIDevice
-     uint64_t max_lba;
- };
- 
-+extern const VMStateDescription vmstate_scsi_device;
-+
-+#define VMSTATE_SCSI_DEVICE(_field, _state) {                        \
-+    .name       = (stringify(_field)),                               \
-+    .size       = sizeof(SCSIDevice),                                \
-+    .vmsd       = &vmstate_scsi_device,                              \
-+    .flags      = VMS_STRUCT,                                        \
-+    .offset     = vmstate_offset_value(_state, _field, SCSIDevice),  \
-+}
-+
- /* cdrom.c */
- int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
- int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
-@@ -91,6 +104,9 @@ struct SCSIReqOps {
-     void (*write_data)(SCSIRequest *req);
-     void (*cancel_io)(SCSIRequest *req);
-     uint8_t *(*get_buf)(SCSIRequest *req);
-+
-+    void (*save_request)(QEMUFile *f, SCSIRequest *req);
-+    void (*load_request)(QEMUFile *f, SCSIRequest *req);
- };
- 
- typedef int (*scsi_qdev_initfn)(SCSIDevice *dev);
-@@ -107,8 +123,12 @@ struct SCSIBusInfo {
-     int tcq;
-     int max_channel, max_target, max_lun;
-     void (*transfer_data)(SCSIRequest *req, uint32_t arg);
--    void (*complete)(SCSIRequest *req, uint32_t arg);
-+    void (*complete)(SCSIRequest *req, uint32_t arg, int32_t len);
-     void (*cancel)(SCSIRequest *req);
-+    QEMUSGList *(*get_sg_list)(SCSIRequest *req);
-+
-+    void (*save_request)(QEMUFile *f, SCSIRequest *req);
-+    void *(*load_request)(QEMUFile *f, SCSIRequest *req);
- };
- 
- struct SCSIBus {
-diff -ruNp qemu-kvm-1.0/hw/spapr_vscsi.c qemu-kvm-1.0.virtio-scsi/hw/spapr_vscsi.c
---- qemu-kvm-1.0/hw/spapr_vscsi.c	2011-12-04 04:38:06.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/spapr_vscsi.c	2012-02-07 14:44:53.430905347 -0600
-@@ -494,7 +494,7 @@ static void vscsi_transfer_data(SCSIRequ
- }
- 
- /* Callback to indicate that the SCSI layer has completed a transfer.  */
--static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status)
-+static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status, int32_t resid)
- {
-     VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
-     vscsi_req *req = sreq->hba_private;
-diff -ruNp qemu-kvm-1.0/hw/usb-msd.c qemu-kvm-1.0.virtio-scsi/hw/usb-msd.c
---- qemu-kvm-1.0/hw/usb-msd.c	2012-02-07 14:44:04.881123501 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/usb-msd.c	2012-02-07 14:44:53.431905363 -0600
-@@ -223,7 +223,7 @@ static void usb_msd_transfer_data(SCSIRe
-     }
- }
- 
--static void usb_msd_command_complete(SCSIRequest *req, uint32_t status)
-+static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, int32_t resid)
- {
-     MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
-     USBPacket *p = s->packet;
-diff -ruNp qemu-kvm-1.0/hw/virtio.h qemu-kvm-1.0.virtio-scsi/hw/virtio.h
---- qemu-kvm-1.0/hw/virtio.h	2011-12-04 04:38:06.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/virtio.h	2012-02-07 14:44:53.433905395 -0600
-@@ -199,6 +199,8 @@ VirtIODevice *virtio_net_init(DeviceStat
- typedef struct virtio_serial_conf virtio_serial_conf;
- VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *serial);
- VirtIODevice *virtio_balloon_init(DeviceState *dev);
-+typedef struct VirtIOSCSIConf VirtIOSCSIConf;
-+VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *conf);
- #ifdef CONFIG_LINUX
- VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
- #endif
-@@ -208,6 +210,7 @@ void virtio_net_exit(VirtIODevice *vdev)
- void virtio_blk_exit(VirtIODevice *vdev);
- void virtio_serial_exit(VirtIODevice *vdev);
- void virtio_balloon_exit(VirtIODevice *vdev);
-+void virtio_scsi_exit(VirtIODevice *vdev);
- 
- #define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
- 	DEFINE_PROP_BIT("indirect_desc", _state, _field, \
-diff -ruNp qemu-kvm-1.0/hw/virtio-pci.c qemu-kvm-1.0.virtio-scsi/hw/virtio-pci.c
---- qemu-kvm-1.0/hw/virtio-pci.c	2012-02-07 14:44:04.850123002 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/virtio-pci.c	2012-02-07 14:44:53.432905379 -0600
-@@ -19,6 +19,7 @@
- #include "virtio-blk.h"
- #include "virtio-net.h"
- #include "virtio-serial.h"
-+#include "virtio-scsi.h"
- #include "pci.h"
- #include "qemu-error.h"
- #include "msix.h"
-@@ -855,6 +856,32 @@ static int virtio_balloon_exit_pci(PCIDe
-     return virtio_exit_pci(pci_dev);
- }
- 
-+static int virtio_scsi_init_pci(PCIDevice *pci_dev)
-+{
-+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-+    VirtIODevice *vdev;
-+
-+    vdev = virtio_scsi_init(&pci_dev->qdev, &proxy->scsi);
-+    if (!vdev) {
-+        return -EINVAL;
-+    }
-+
-+    vdev->nvectors = proxy->nvectors;
-+    virtio_init_pci(proxy, vdev);
-+
-+    /* make the actual value visible */
-+    proxy->nvectors = vdev->nvectors;
-+    return 0;
-+}
-+
-+static int virtio_scsi_exit_pci(PCIDevice *pci_dev)
-+{
-+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-+
-+    virtio_scsi_exit(proxy->vdev);
-+    return virtio_exit_pci(pci_dev);
-+}
-+
- static PCIDeviceInfo virtio_info[] = {
-     {
-         .qdev.name = "virtio-blk-pci",
-@@ -940,6 +967,21 @@ static PCIDeviceInfo virtio_info[] = {
-         },
-         .qdev.reset = virtio_pci_reset,
-     },{
-+        .qdev.name = "virtio-scsi-pci",
-+        .qdev.alias = "virtio-scsi",
-+        .qdev.size = sizeof(VirtIOPCIProxy),
-+        .init      = virtio_scsi_init_pci,
-+        .exit      = virtio_scsi_exit_pci,
-+        .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
-+        .device_id = PCI_DEVICE_ID_VIRTIO_SCSI,
-+        .class_id  = PCI_CLASS_STORAGE_SCSI,
-+        .revision  = 0x00,
-+        .qdev.props = (Property[]) {
-+            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
-+            DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOPCIProxy, host_features, scsi),
-+            DEFINE_PROP_END_OF_LIST(),
-+        },
-+    }, {
-         /* end of list */
-     }
- };
-diff -ruNp qemu-kvm-1.0/hw/virtio-pci.h qemu-kvm-1.0.virtio-scsi/hw/virtio-pci.h
---- qemu-kvm-1.0/hw/virtio-pci.h	2012-02-07 14:44:04.850123002 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/virtio-pci.h	2012-02-07 14:44:53.432905379 -0600
-@@ -17,6 +17,7 @@
- 
- #include "virtio-net.h"
- #include "virtio-serial.h"
-+#include "virtio-scsi.h"
- 
- /* Performance improves when virtqueue kick processing is decoupled from the
-  * vcpu thread using ioeventfd for some devices. */
-@@ -40,6 +41,7 @@ typedef struct {
- #endif
-     virtio_serial_conf serial;
-     virtio_net_conf net;
-+    VirtIOSCSIConf scsi;
-     bool ioeventfd_disabled;
-     bool ioeventfd_started;
- } VirtIOPCIProxy;
-diff -ruNp qemu-kvm-1.0/hw/virtio-scsi.c qemu-kvm-1.0.virtio-scsi/hw/virtio-scsi.c
---- qemu-kvm-1.0/hw/virtio-scsi.c	1969-12-31 18:00:00.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/virtio-scsi.c	2012-02-07 14:44:53.432905379 -0600
-@@ -0,0 +1,607 @@
-+/*
-+ * Virtio SCSI HBA
-+ *
-+ * Copyright IBM, Corp. 2010
-+ * Copyright Red Hat, Inc. 2011
-+ *
-+ * Authors:
-+ *   Stefan Hajnoczi    <stefanha at linux.vnet.ibm.com>
-+ *   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 "virtio-scsi.h"
-+#include <hw/scsi.h>
-+#include <hw/scsi-defs.h>
-+
-+#define VIRTIO_SCSI_VQ_SIZE     128
-+#define VIRTIO_SCSI_CDB_SIZE    32
-+#define VIRTIO_SCSI_SENSE_SIZE  96
-+#define VIRTIO_SCSI_MAX_CHANNEL	0
-+#define VIRTIO_SCSI_MAX_TARGET  255
-+#define VIRTIO_SCSI_MAX_LUN     16383
-+
-+/* Response codes */
-+#define VIRTIO_SCSI_S_OK                       0
-+#define VIRTIO_SCSI_S_OVERRUN                  1
-+#define VIRTIO_SCSI_S_ABORTED                  2
-+#define VIRTIO_SCSI_S_BAD_TARGET               3
-+#define VIRTIO_SCSI_S_RESET                    4
-+#define VIRTIO_SCSI_S_BUSY                     5
-+#define VIRTIO_SCSI_S_TRANSPORT_FAILURE        6
-+#define VIRTIO_SCSI_S_TARGET_FAILURE           7
-+#define VIRTIO_SCSI_S_NEXUS_FAILURE            8
-+#define VIRTIO_SCSI_S_FAILURE                  9
-+#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED       10
-+#define VIRTIO_SCSI_S_FUNCTION_REJECTED        11
-+#define VIRTIO_SCSI_S_INCORRECT_LUN            12
-+
-+/* Controlq type codes.  */
-+#define VIRTIO_SCSI_T_TMF                      0
-+#define VIRTIO_SCSI_T_AN_QUERY                 1
-+#define VIRTIO_SCSI_T_AN_SUBSCRIBE             2
-+
-+/* Valid TMF subtypes.  */
-+#define VIRTIO_SCSI_T_TMF_ABORT_TASK           0
-+#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET       1
-+#define VIRTIO_SCSI_T_TMF_CLEAR_ACA            2
-+#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET       3
-+#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET      4
-+#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET   5
-+#define VIRTIO_SCSI_T_TMF_QUERY_TASK           6
-+#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET       7
-+
-+/* Events.  */
-+#define VIRTIO_SCSI_T_EVENTS_MISSED            0x80000000
-+#define VIRTIO_SCSI_T_NO_EVENT                 0
-+#define VIRTIO_SCSI_T_TRANSPORT_RESET          1
-+#define VIRTIO_SCSI_T_ASYNC_NOTIFY             2
-+
-+/* SCSI command request, followed by data-out */
-+typedef struct {
-+    uint8_t lun[8];              /* Logical Unit Number */
-+    uint64_t tag;                /* Command identifier */
-+    uint8_t task_attr;           /* Task attribute */
-+    uint8_t prio;
-+    uint8_t crn;
-+    uint8_t cdb[];
-+} QEMU_PACKED VirtIOSCSICmdReq;
-+
-+/* Response, followed by sense data and data-in */
-+typedef struct {
-+    uint32_t sense_len;          /* Sense data length */
-+    uint32_t resid;              /* Residual bytes in data buffer */
-+    uint16_t status_qualifier;   /* Status qualifier */
-+    uint8_t status;              /* Command completion status */
-+    uint8_t response;            /* Response values */
-+    uint8_t sense[];
-+} QEMU_PACKED VirtIOSCSICmdResp;
-+
-+/* Task Management Request */
-+typedef struct {
-+    uint32_t type;
-+    uint32_t subtype;
-+    uint8_t lun[8];
-+    uint64_t tag;
-+} QEMU_PACKED VirtIOSCSICtrlTMFReq;
-+
-+typedef struct {
-+    uint8_t response;
-+} QEMU_PACKED VirtIOSCSICtrlTMFResp;
-+
-+/* Asynchronous notification query/subscription */
-+typedef struct {
-+    uint32_t type;
-+    uint8_t lun[8];
-+    uint32_t event_requested;
-+} QEMU_PACKED VirtIOSCSICtrlANReq;
-+
-+typedef struct {
-+    uint32_t event_actual;
-+    uint8_t response;
-+} QEMU_PACKED VirtIOSCSICtrlANResp;
-+
-+typedef struct {
-+    uint32_t event;
-+    uint8_t lun[8];
-+    uint32_t reason;
-+} QEMU_PACKED VirtIOSCSIEvent;
-+
-+typedef struct {
-+    uint32_t num_queues;
-+    uint32_t seg_max;
-+    uint32_t max_sectors;
-+    uint32_t cmd_per_lun;
-+    uint32_t event_info_size;
-+    uint32_t sense_size;
-+    uint32_t cdb_size;
-+    uint16_t max_channel;
-+    uint16_t max_target;
-+    uint32_t max_lun;
-+} QEMU_PACKED VirtIOSCSIConfig;
-+
-+typedef struct {
-+    VirtIODevice vdev;
-+    DeviceState *qdev;
-+    VirtIOSCSIConf *conf;
-+
-+    SCSIBus bus;
-+    VirtQueue *ctrl_vq;
-+    VirtQueue *event_vq;
-+    VirtQueue *cmd_vq;
-+    uint32_t sense_size;
-+    uint32_t cdb_size;
-+    bool resetting;
-+} VirtIOSCSI;
-+
-+typedef struct VirtIOSCSIReq {
-+    VirtIOSCSI *dev;
-+    VirtQueue *vq;
-+    VirtQueueElement elem;
-+    QEMUSGList qsgl;
-+    SCSIRequest *sreq;
-+    union {
-+        char                  *buf;
-+        VirtIOSCSICmdReq      *cmd;
-+        VirtIOSCSICtrlTMFReq  *tmf;
-+        VirtIOSCSICtrlANReq   *an;
-+    } req;
-+    union {
-+        char                  *buf;
-+        VirtIOSCSICmdResp     *cmd;
-+        VirtIOSCSICtrlTMFResp *tmf;
-+        VirtIOSCSICtrlANResp  *an;
-+        VirtIOSCSIEvent       *event;
-+    } resp;
-+} VirtIOSCSIReq;
-+
-+static inline int virtio_scsi_get_lun(uint8_t *lun)
-+{
-+    return ((lun[2] << 8) | lun[3]) & 0x3FFF;
-+}
-+
-+static inline SCSIDevice *virtio_scsi_device_find(VirtIOSCSI *s, uint8_t *lun)
-+{
-+    if (lun[0] != 1) {
-+        return NULL;
-+    }
-+    if (lun[2] != 0 && !(lun[2] >= 0x40 && lun[2] < 0x80)) {
-+        return NULL;
-+    }
-+    return scsi_device_find(&s->bus, 0, lun[1], virtio_scsi_get_lun(lun));
-+}
-+
-+static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
-+{
-+    VirtIOSCSI *s = req->dev;
-+    VirtQueue *vq = req->vq;
-+    virtqueue_push(vq, &req->elem, req->qsgl.size + req->elem.in_sg[0].iov_len);
-+    qemu_sglist_destroy(&req->qsgl);
-+    if (req->sreq) {
-+        req->sreq->hba_private = NULL;
-+        scsi_req_unref(req->sreq);
-+    }
-+    g_free(req);
-+    virtio_notify(&s->vdev, vq);
-+}
-+
-+static void virtio_scsi_bad_req(void)
-+{
-+    error_report("wrong size for virtio-scsi headers");
-+    exit(1);
-+}
-+
-+static void qemu_sgl_init_external(QEMUSGList *qsgl, struct iovec *sg,
-+                                   target_phys_addr_t *addr, int num)
-+{
-+    memset(qsgl, 0, sizeof(*qsgl));
-+    while (num--) {
-+        qemu_sglist_add(qsgl, *(addr++), (sg++)->iov_len);
-+    }
-+}
-+
-+static void virtio_scsi_parse_req(VirtIOSCSI *s, VirtQueue *vq,
-+                                  VirtIOSCSIReq *req)
-+{
-+    assert(req->elem.out_num && req->elem.in_num);
-+    req->vq = vq;
-+    req->dev = s;
-+    req->sreq = NULL;
-+    req->req.buf = req->elem.out_sg[0].iov_base;
-+    req->resp.buf = req->elem.in_sg[0].iov_base;
-+
-+    if (req->elem.out_num > 1) {
-+        qemu_sgl_init_external(&req->qsgl, &req->elem.out_sg[1],
-+                               &req->elem.out_addr[1],
-+                               req->elem.out_num - 1);
-+    } else {
-+        qemu_sgl_init_external(&req->qsgl, &req->elem.in_sg[1],
-+                               &req->elem.in_addr[1],
-+                               req->elem.in_num - 1);
-+    }
-+}
-+
-+static VirtIOSCSIReq *virtio_scsi_pop_req(VirtIOSCSI *s, VirtQueue *vq)
-+{
-+    VirtIOSCSIReq *req;
-+    req = g_malloc(sizeof(*req));
-+    if (!virtqueue_pop(vq, &req->elem)) {
-+        g_free(req);
-+        return NULL;
-+    }
-+
-+    virtio_scsi_parse_req(s, vq, req);
-+    return req;
-+}
-+
-+static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq)
-+{
-+    VirtIOSCSIReq *req = sreq->hba_private;
-+
-+    qemu_put_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem));
-+}
-+
-+static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
-+{
-+    SCSIBus *bus = sreq->bus;
-+    VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
-+    VirtIOSCSIReq *req;
-+
-+    req = g_malloc(sizeof(*req));
-+    qemu_get_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem));
-+    virtio_scsi_parse_req(s, s->cmd_vq, req);
-+
-+    scsi_req_ref(sreq);
-+    req->sreq = sreq;
-+    if (req->sreq->cmd.mode != SCSI_XFER_NONE) {
-+        int req_mode =
-+            (req->elem.in_num > 1 ? SCSI_XFER_FROM_DEV : SCSI_XFER_TO_DEV);
-+
-+	assert (req->sreq->cmd.mode == req_mode);
-+    }
-+    return req;
-+}
-+
-+static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
-+{
-+    SCSIDevice *d = virtio_scsi_device_find(s, req->req.cmd->lun);
-+    SCSIRequest *r, *next;
-+    DeviceState *qdev;
-+    int target;
-+
-+    switch (req->req.tmf->subtype) {
-+    case VIRTIO_SCSI_T_TMF_ABORT_TASK:
-+    case VIRTIO_SCSI_T_TMF_QUERY_TASK:
-+        d = virtio_scsi_device_find(s, req->req.cmd->lun);
-+        if (!d) {
-+            goto fail;
-+        }
-+        if (d->lun != virtio_scsi_get_lun(req->req.cmd->lun)) {
-+            req->resp.tmf->response = VIRTIO_SCSI_S_INCORRECT_LUN;
-+            break;
-+        }
-+        QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
-+            if (r->tag == req->req.cmd->tag) {
-+                break;
-+            }
-+        }
-+        if (r && r->hba_private) {
-+            if (req->req.tmf->subtype == VIRTIO_SCSI_T_TMF_ABORT_TASK) {
-+                scsi_req_cancel(r);
-+            }
-+            req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
-+        } else {
-+            req->resp.tmf->response = VIRTIO_SCSI_S_OK;
-+        }
-+        break;
-+
-+    case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET:
-+        d = virtio_scsi_device_find(s, req->req.cmd->lun);
-+        if (!d) {
-+            goto fail;
-+        }
-+        if (d->lun == virtio_scsi_get_lun(req->req.cmd->lun)) {
-+            s->resetting++;
-+            qdev_reset_all(&d->qdev);
-+            s->resetting--;
-+        }
-+        break;
-+
-+    case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET:
-+    case VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET:
-+    case VIRTIO_SCSI_T_TMF_QUERY_TASK_SET:
-+        d = virtio_scsi_device_find(s, req->req.cmd->lun);
-+        if (!d) {
-+            goto fail;
-+        }
-+        if (d->lun != virtio_scsi_get_lun(req->req.cmd->lun)) {
-+            req->resp.tmf->response = VIRTIO_SCSI_S_INCORRECT_LUN;
-+            break;
-+        }
-+        req->resp.tmf->response = VIRTIO_SCSI_S_OK;
-+        QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
-+            if (r->hba_private) {
-+                if (req->req.tmf->subtype != VIRTIO_SCSI_T_TMF_QUERY_TASK) {
-+                    scsi_req_cancel(r);
-+                }
-+                req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
-+            }
-+        }
-+        break;
-+
-+    case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
-+        target = req->req.cmd->lun[1];
-+        s->resetting++;
-+        QTAILQ_FOREACH(qdev, &s->bus.qbus.children, sibling) {
-+             d = DO_UPCAST(SCSIDevice, qdev, qdev);
-+             if (d->channel == 0 && d->id == target) {
-+                qdev_reset_all(&d->qdev);
-+             }
-+        }
-+        s->resetting--;
-+        break;
-+
-+    case VIRTIO_SCSI_T_TMF_CLEAR_ACA:
-+    default:
-+        req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
-+        break;
-+    }
-+
-+    return;
-+
-+fail:
-+    req->resp.tmf->response = VIRTIO_SCSI_S_BAD_TARGET;
-+}
-+
-+static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
-+{
-+    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
-+    VirtIOSCSIReq *req;
-+
-+    while ((req = virtio_scsi_pop_req(s, vq))) {
-+        int out_size, in_size;
-+        if (req->elem.out_num < 1 || req->elem.in_num < 1) {
-+            virtio_scsi_bad_req();
-+            continue;
-+        }
-+
-+        out_size = req->elem.out_sg[0].iov_len;
-+        in_size = req->elem.in_sg[0].iov_len;
-+        if (req->req.tmf->type == VIRTIO_SCSI_T_TMF) {
-+            if (out_size < sizeof(VirtIOSCSICtrlTMFReq) ||
-+                in_size < sizeof(VirtIOSCSICtrlTMFResp)) {
-+                virtio_scsi_bad_req();
-+            }
-+            virtio_scsi_do_tmf(s, req);
-+
-+        } else if (req->req.tmf->type == VIRTIO_SCSI_T_AN_QUERY ||
-+                   req->req.tmf->type == VIRTIO_SCSI_T_AN_SUBSCRIBE) {
-+            if (out_size < sizeof(VirtIOSCSICtrlANReq) ||
-+                in_size < sizeof(VirtIOSCSICtrlANResp)) {
-+                virtio_scsi_bad_req();
-+            }
-+            req->resp.an->event_actual = 0;
-+            req->resp.an->response = VIRTIO_SCSI_S_OK;
-+        }
-+        virtio_scsi_complete_req(req);
-+    }
-+}
-+
-+static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
-+                                         int32_t resid)
-+{
-+    VirtIOSCSIReq *req = r->hba_private;
-+
-+    req->resp.cmd->response = VIRTIO_SCSI_S_OK;
-+    req->resp.cmd->status = status;
-+    if (req->resp.cmd->status == GOOD) {
-+        req->resp.cmd->resid = resid;
-+    } else {
-+       req->resp.cmd->resid = 0;
-+       scsi_req_get_sense(r, req->resp.cmd->sense, VIRTIO_SCSI_SENSE_SIZE);
-+    }
-+    virtio_scsi_complete_req(req);
-+}
-+
-+static QEMUSGList *virtio_scsi_get_sg_list(SCSIRequest *r)
-+{
-+    VirtIOSCSIReq *req = r->hba_private;
-+
-+    return &req->qsgl;
-+}
-+
-+static void virtio_scsi_request_cancelled(SCSIRequest *r)
-+{
-+    VirtIOSCSIReq *req = r->hba_private;
-+
-+    if (!req) {
-+        return;
-+    }
-+    if (req->dev->resetting) {
-+        req->resp.cmd->response = VIRTIO_SCSI_S_RESET;
-+    } else {
-+        req->resp.cmd->response = VIRTIO_SCSI_S_ABORTED;
-+    }
-+    virtio_scsi_complete_req(req);
-+}
-+
-+static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq *req)
-+{
-+    req->resp.cmd->response = VIRTIO_SCSI_S_FAILURE;
-+    virtio_scsi_complete_req(req);
-+}
-+
-+static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
-+{
-+    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
-+    VirtIOSCSIReq *req;
-+    int n;
-+
-+    while ((req = virtio_scsi_pop_req(s, vq))) {
-+        SCSIDevice *d;
-+        int out_size, in_size;
-+        if (req->elem.out_num < 1 || req->elem.in_num < 1) {
-+            virtio_scsi_bad_req();
-+        }
-+
-+        out_size = req->elem.out_sg[0].iov_len;
-+        in_size = req->elem.in_sg[0].iov_len;
-+        if (out_size < sizeof(VirtIOSCSICmdReq) + s->cdb_size ||
-+            in_size < sizeof(VirtIOSCSICmdResp) + s->sense_size) {
-+            virtio_scsi_bad_req();
-+        }
-+
-+        if (req->elem.out_num > 1 && req->elem.in_num > 1) {
-+            virtio_scsi_fail_cmd_req(req);
-+            continue;
-+        }
-+
-+        d = virtio_scsi_device_find(s, req->req.cmd->lun);
-+        if (!d) {
-+            req->resp.cmd->response = VIRTIO_SCSI_S_BAD_TARGET;
-+            virtio_scsi_complete_req(req);
-+            continue;
-+        }
-+        req->sreq = scsi_req_new(d, req->req.cmd->tag,
-+                                 virtio_scsi_get_lun(req->req.cmd->lun),
-+                                 req->req.cmd->cdb, req);
-+
-+        if (req->sreq->cmd.mode != SCSI_XFER_NONE) {
-+            int req_mode =
-+                (req->elem.in_num > 1 ? SCSI_XFER_FROM_DEV : SCSI_XFER_TO_DEV);
-+
-+            if (req->sreq->cmd.mode != req_mode ||
-+                req->sreq->cmd.xfer > req->qsgl.size) {
-+                req->resp.cmd->response = VIRTIO_SCSI_S_OVERRUN;
-+                virtio_scsi_complete_req(req);
-+                continue;
-+            }
-+        }
-+
-+        n = scsi_req_enqueue(req->sreq);
-+        if (n) {
-+            scsi_req_continue(req->sreq);
-+        }
-+    }
-+}
-+
-+static void virtio_scsi_get_config(VirtIODevice *vdev,
-+                                   uint8_t *config)
-+{
-+    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
-+    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
-+
-+    stl_raw(&scsiconf->num_queues, s->conf->num_queues);
-+    stl_raw(&scsiconf->seg_max, 128 - 2);
-+    stl_raw(&scsiconf->max_sectors, s->conf->max_sectors);
-+    stl_raw(&scsiconf->cmd_per_lun, s->conf->cmd_per_lun);
-+    stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
-+    stl_raw(&scsiconf->sense_size, s->sense_size);
-+    stl_raw(&scsiconf->cdb_size, s->cdb_size);
-+    stl_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
-+    stl_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
-+    stl_raw(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
-+}
-+
-+static void virtio_scsi_set_config(VirtIODevice *vdev,
-+                                   const uint8_t *config)
-+{
-+    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
-+    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
-+
-+    if ((uint32_t) ldl_raw(&scsiconf->sense_size) >= 65536 ||
-+        (uint32_t) ldl_raw(&scsiconf->cdb_size) >= 256) {
-+        error_report("bad data written to virtio-scsi configuration space");
-+        exit(1);
-+    }
-+
-+    s->sense_size = ldl_raw(&scsiconf->sense_size);
-+    s->cdb_size = ldl_raw(&scsiconf->cdb_size);
-+}
-+
-+static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
-+                                         uint32_t requested_features)
-+{
-+    return requested_features;
-+}
-+
-+static void virtio_scsi_reset(VirtIODevice *vdev)
-+{
-+    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
-+
-+    s->sense_size = VIRTIO_SCSI_SENSE_SIZE;
-+    s->cdb_size = VIRTIO_SCSI_CDB_SIZE;
-+}
-+
-+/* The device does not have anything to save beyond the virtio data.
-+ * Request data is saved with callbacks from SCSI devices.
-+ */
-+static void virtio_scsi_save(QEMUFile *f, void *opaque)
-+{
-+    VirtIOSCSI *s = opaque;
-+    virtio_save(&s->vdev, f);
-+}
-+
-+static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id)
-+{
-+    VirtIOSCSI *s = opaque;
-+    virtio_load(&s->vdev, f);
-+    return 0;
-+}
-+
-+static struct SCSIBusInfo virtio_scsi_scsi_info = {
-+    .tcq = true,
-+    .max_channel = VIRTIO_SCSI_MAX_CHANNEL,
-+    .max_target = VIRTIO_SCSI_MAX_TARGET,
-+    .max_lun = VIRTIO_SCSI_MAX_LUN,
-+
-+    .complete = virtio_scsi_command_complete,
-+    .cancel = virtio_scsi_request_cancelled,
-+    .get_sg_list = virtio_scsi_get_sg_list,
-+    .save_request = virtio_scsi_save_request,
-+    .load_request = virtio_scsi_load_request,
-+};
-+
-+VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
-+{
-+    VirtIOSCSI *s;
-+    static int virtio_scsi_id;
-+
-+    s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
-+                                         sizeof(VirtIOSCSIConfig),
-+                                         sizeof(VirtIOSCSI));
-+
-+    s->qdev = dev;
-+    s->conf = proxyconf;
-+
-+    /* TODO set up vdev function pointers */
-+    s->vdev.get_config = virtio_scsi_get_config;
-+    s->vdev.set_config = virtio_scsi_set_config;
-+    s->vdev.get_features = virtio_scsi_get_features;
-+    s->vdev.reset = virtio_scsi_reset;
-+
-+    s->ctrl_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
-+                                   virtio_scsi_handle_ctrl);
-+    s->event_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
-+                                   NULL);
-+    s->cmd_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
-+                                   virtio_scsi_handle_cmd);
-+
-+    scsi_bus_new(&s->bus, dev, &virtio_scsi_scsi_info);
-+    if (!dev->hotplugged) {
-+        scsi_bus_legacy_handle_cmdline(&s->bus);
-+    }
-+
-+    register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1,
-+                    virtio_scsi_save, virtio_scsi_load, s);
-+
-+    return &s->vdev;
-+}
-+
-+void virtio_scsi_exit(VirtIODevice *vdev)
-+{
-+    virtio_cleanup(vdev);
-+}
-diff -ruNp qemu-kvm-1.0/hw/virtio-scsi.h qemu-kvm-1.0.virtio-scsi/hw/virtio-scsi.h
---- qemu-kvm-1.0/hw/virtio-scsi.h	1969-12-31 18:00:00.000000000 -0600
-+++ qemu-kvm-1.0.virtio-scsi/hw/virtio-scsi.h	2012-02-07 14:44:53.432905379 -0600
-@@ -0,0 +1,36 @@
-+/*
-+ * Virtio SCSI HBA
-+ *
-+ * Copyright IBM, Corp. 2010
-+ *
-+ * Authors:
-+ *  Stefan Hajnoczi    <stefanha 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_VIRTIO_SCSI_H
-+#define _QEMU_VIRTIO_SCSI_H
-+
-+#include "virtio.h"
-+#include "net.h"
-+#include "pci.h"
-+
-+/* The ID for virtio_scsi */
-+#define VIRTIO_ID_SCSI  8
-+
-+struct VirtIOSCSIConf {
-+    uint32_t num_queues;
-+    uint32_t max_sectors;
-+    uint32_t cmd_per_lun;
-+};
-+
-+#define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _features_field, _conf_field) \
-+    DEFINE_VIRTIO_COMMON_FEATURES(_state, _features_field), \
-+    DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \
-+    DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF), \
-+    DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128)
-+
-+#endif /* _QEMU_VIRTIO_SCSI_H */
-diff -ruNp qemu-kvm-1.0/Makefile.target qemu-kvm-1.0.virtio-scsi/Makefile.target
---- qemu-kvm-1.0/Makefile.target	2012-02-07 14:44:04.965124855 -0600
-+++ qemu-kvm-1.0.virtio-scsi/Makefile.target	2012-02-07 14:44:53.126900450 -0600
-@@ -205,6 +205,7 @@ obj-y = arch_init.o cpus.o monitor.o mac
- obj-$(CONFIG_NO_PCI) += pci-stub.o
- obj-$(CONFIG_PCI) += pci.o
- obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
-+obj-$(CONFIG_VIRTIO_SCSI) += virtio-scsi.o
- obj-y += vhost_net.o
- obj-$(CONFIG_VHOST_NET) += vhost.o
- obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/qemu-kvm.git/commitdiff/a95b7932884e3f5d67db5f78de3f1cc602782d98




More information about the pld-cvs-commit mailing list