[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