Upgrade to qemu-kvm-1.1.0
- WIP build fails, investigating - New upstream release 1.1.0 - Drop about a 100 spice + USB patches, which are all upstream
This commit is contained in:
parent
188256aae3
commit
329b588089
@ -1,132 +0,0 @@
|
||||
From 0b23c5d40ea933cfece3b4f69427f79c8a23256d Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Weil <sw@weilnetz.de>
|
||||
Date: Tue, 29 Nov 2011 06:34:48 +0100
|
||||
Subject: [PATCH 01/25] malta: Fix regression (i8259 interrupts did not work)
|
||||
|
||||
Commit 5632ae46d5bda798e971dae48ebb318ac2c3686a passes the address
|
||||
of i8259 to qemu_irq_proxy. i8259 is an auto variable with undefined
|
||||
value outside of mips_malta_init.
|
||||
|
||||
This made the interrupt proxy unusable: either QEMU crashes, or
|
||||
the interrupt handler was not called.
|
||||
|
||||
Ethernet for example no longer worked with MIPS Malta.
|
||||
|
||||
v2:
|
||||
While v1 used a static variable for i8259, this patch introduces
|
||||
a qdev for the malta machine. i8259 is now part of the device status.
|
||||
This is a minimal qdev implementation to keep the patch small.
|
||||
|
||||
Signed-off-by: Stefan Weil <sw@weilnetz.de>
|
||||
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
|
||||
(cherry picked from commit e9b40fd34ceb23461083d505a444a389c094455b)
|
||||
---
|
||||
hw/mips_malta.c | 39 +++++++++++++++++++++++++++++++++++----
|
||||
1 files changed, 35 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
|
||||
index bb49749..941b9bd 100644
|
||||
--- a/hw/mips_malta.c
|
||||
+++ b/hw/mips_malta.c
|
||||
@@ -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 @@ typedef struct {
|
||||
SerialState *uart;
|
||||
} MaltaFPGAState;
|
||||
|
||||
+typedef struct {
|
||||
+ SysBusDevice busdev;
|
||||
+ qemu_irq *i8259;
|
||||
+} MaltaState;
|
||||
+
|
||||
static ISADevice *pit;
|
||||
|
||||
static struct _loaderparams {
|
||||
@@ -775,7 +781,7 @@ void mips_malta_init (ram_addr_t ram_size,
|
||||
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 @@ void mips_malta_init (ram_addr_t ram_size,
|
||||
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 @@ void mips_malta_init (ram_addr_t ram_size,
|
||||
* 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 @@ void mips_malta_init (ram_addr_t ram_size,
|
||||
|
||||
/* 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 @@ void mips_malta_init (ram_addr_t ram_size,
|
||||
}
|
||||
}
|
||||
|
||||
+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 @@ static QEMUMachine mips_malta_machine = {
|
||||
.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);
|
||||
--
|
||||
1.7.7.5
|
||||
|
36
0001-qemu-kvm-Add-missing-default-machine-options.patch
Normal file
36
0001-qemu-kvm-Add-missing-default-machine-options.patch
Normal file
@ -0,0 +1,36 @@
|
||||
From 398b87f4ef3426569bdda2da2c9c2b89f4ba906f Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kiszka <jan.kiszka@siemens.com>
|
||||
Date: Mon, 2 Jul 2012 09:34:46 +0200
|
||||
Subject: [PATCH 01/17] qemu-kvm: Add missing default machine options
|
||||
|
||||
qemu-kvm-specific machine defaults were missing for pc-0.15 and pc-1.0.
|
||||
|
||||
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
|
||||
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
|
||||
---
|
||||
hw/pc_piix.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
|
||||
index c3fb74e..4e8a280 100644
|
||||
--- a/hw/pc_piix.c
|
||||
+++ b/hw/pc_piix.c
|
||||
@@ -393,6 +393,7 @@ static QEMUMachine pc_machine_v1_0 = {
|
||||
.desc = "Standard PC",
|
||||
.init = pc_init_pci,
|
||||
.max_cpus = 255,
|
||||
+ .default_machine_opts = "accel=kvm,kernel_irqchip=on",
|
||||
.compat_props = (GlobalProperty[]) {
|
||||
PC_COMPAT_1_0,
|
||||
{ /* end of list */ }
|
||||
@@ -407,6 +408,7 @@ static QEMUMachine pc_machine_v0_15 = {
|
||||
.desc = "Standard PC",
|
||||
.init = pc_init_pci,
|
||||
.max_cpus = 255,
|
||||
+ .default_machine_opts = "accel=kvm,kernel_irqchip=on",
|
||||
.compat_props = (GlobalProperty[]) {
|
||||
PC_COMPAT_0_15,
|
||||
{ /* end of list */ }
|
||||
--
|
||||
1.7.10.4
|
||||
|
@ -1,134 +0,0 @@
|
||||
From 2061800b85ddcc9b34b5ccbfaa87f7e8b94626a6 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Andreas=20F=C3=A4rber?= <afaerber@suse.de>
|
||||
Date: Wed, 30 Nov 2011 16:26:21 +0100
|
||||
Subject: [PATCH 02/25] exec.c: Fix subpage memory access to RAM MemoryRegion
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Commit 95c318f5e1f88d7e5bcc6deac17330fd4806a2d3 (Fix segfault in mmio
|
||||
subpage handling code.) prevented a segfault by making all subpage
|
||||
registrations over an existing memory page perform an unassigned access.
|
||||
Symptoms were writes not taking effect and reads returning zero.
|
||||
|
||||
Very small page sizes are not currently supported either,
|
||||
so subpage memory areas cannot fully be avoided.
|
||||
|
||||
Therefore change the previous fix to use a new IO_MEM_SUBPAGE_RAM
|
||||
instead of IO_MEM_UNASSIGNED. Suggested by Avi.
|
||||
|
||||
Reviewed-by: Avi Kivity <avi@redhat.com>
|
||||
Signed-off-by: Andreas Färber <afaerber@suse.de>
|
||||
Cc: Avi Kivity <avi@redhat.com>
|
||||
Cc: Gleb Natapov <gleb@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
---
|
||||
cpu-common.h | 1 +
|
||||
exec.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 64 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/cpu-common.h b/cpu-common.h
|
||||
index c9878ba..3f45428 100644
|
||||
--- a/cpu-common.h
|
||||
+++ b/cpu-common.h
|
||||
@@ -172,6 +172,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr,
|
||||
#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 --git a/exec.c b/exec.c
|
||||
index 6b92198..6c206ff 100644
|
||||
--- a/exec.c
|
||||
+++ b/exec.c
|
||||
@@ -3570,6 +3570,63 @@ static CPUWriteMemoryFunc * const subpage_write[] = {
|
||||
&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 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
|
||||
printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
|
||||
mmio, start, end, idx, eidx, memory);
|
||||
#endif
|
||||
- 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 @@ static void io_mem_init(void)
|
||||
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;
|
||||
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -0,0 +1,41 @@
|
||||
From 6f82a5ea52302bab33287b0191538be6f9138637 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kiszka <jan.kiszka@siemens.com>
|
||||
Date: Mon, 2 Jul 2012 10:05:39 +0200
|
||||
Subject: [PATCH 02/17] qemu-kvm: virtio: Do not register mask notifiers
|
||||
without in-kernel irqchip support
|
||||
|
||||
We crash if we registers mask notifiers without backing in-kernel
|
||||
irqchip. This corresponds to the check in QEMU upstream after 1.1 now.
|
||||
|
||||
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
|
||||
Acked-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
|
||||
---
|
||||
hw/virtio-pci.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
|
||||
index a0c2ca7..5b64356 100644
|
||||
--- a/hw/virtio-pci.c
|
||||
+++ b/hw/virtio-pci.c
|
||||
@@ -629,7 +629,7 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
|
||||
|
||||
/* Must unset mask notifier while guest notifier
|
||||
* is still assigned */
|
||||
- if (!assign) {
|
||||
+ if (kvm_irqchip_in_kernel() && !assign) {
|
||||
r = msix_unset_mask_notifier(&proxy->pci_dev);
|
||||
assert(r >= 0);
|
||||
}
|
||||
@@ -647,7 +647,7 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
|
||||
|
||||
/* Must set mask notifier after guest notifier
|
||||
* has been assigned */
|
||||
- if (assign) {
|
||||
+ if (kvm_irqchip_in_kernel() && assign) {
|
||||
r = msix_set_mask_notifier(&proxy->pci_dev,
|
||||
virtio_pci_mask_notifier);
|
||||
if (r < 0) {
|
||||
--
|
||||
1.7.10.4
|
||||
|
@ -1,101 +0,0 @@
|
||||
From f03969b952bc2aaf9f4445b6da28aebb0a9abde5 Mon Sep 17 00:00:00 2001
|
||||
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
|
||||
Date: Sun, 4 Dec 2011 22:35:27 +0530
|
||||
Subject: [PATCH 03/25] hw/9pfs: Improve portability to older systems
|
||||
|
||||
handle fs driver require a set of newly added syscalls. Don't
|
||||
Compile handle FS driver if those syscalls are not available.
|
||||
Instead of adding #ifdef for all those syscalls we check for
|
||||
open by handle syscall. If that is available then rest of the
|
||||
syscalls used by the driver should be available.
|
||||
|
||||
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
|
||||
---
|
||||
Makefile.objs | 4 ++--
|
||||
fsdev/qemu-fsdev.c | 2 ++
|
||||
hw/9pfs/virtio-9p-handle.c | 33 ---------------------------------
|
||||
3 files changed, 4 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/Makefile.objs b/Makefile.objs
|
||||
index d7a6539..3a699ee 100644
|
||||
--- a/Makefile.objs
|
||||
+++ b/Makefile.objs
|
||||
@@ -310,8 +310,8 @@ hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
|
||||
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 --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
|
||||
index 7fd2aa7..6684f7e 100644
|
||||
--- a/fsdev/qemu-fsdev.c
|
||||
+++ b/fsdev/qemu-fsdev.c
|
||||
@@ -23,7 +23,9 @@ static QTAILQ_HEAD(FsDriverEntry_head, FsDriverListEntry) fsdriver_entries =
|
||||
|
||||
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 --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
|
||||
index 7644ae5..a62f690 100644
|
||||
--- a/hw/9pfs/virtio-9p-handle.c
|
||||
+++ b/hw/9pfs/virtio-9p-handle.c
|
||||
@@ -45,7 +45,6 @@ struct handle_data {
|
||||
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 @@ static inline int open_by_handle(int mountfd, const char *fh, int flags)
|
||||
{
|
||||
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)
|
||||
{
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,171 +0,0 @@
|
||||
From 77a02621812952acfde887244f6f480de1b51f95 Mon Sep 17 00:00:00 2001
|
||||
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
|
||||
Date: Sun, 4 Dec 2011 22:35:28 +0530
|
||||
Subject: [PATCH 04/25] hw/9pfs: use migration blockers to prevent live
|
||||
migration when virtfs export path is mounted
|
||||
|
||||
Now when you try to migrate with VirtFS export path mounted, you get a proper QMP error:
|
||||
|
||||
(qemu) migrate tcp:localhost:4444
|
||||
Migration is disabled when VirtFS export path '/tmp/' is mounted in the guest using mount_tag 'v_tmp'
|
||||
(qemu)
|
||||
|
||||
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
|
||||
---
|
||||
hw/9pfs/virtio-9p-device.c | 22 +++++++++++-----------
|
||||
hw/9pfs/virtio-9p.c | 19 +++++++++++++++++++
|
||||
hw/9pfs/virtio-9p.h | 5 +++--
|
||||
qerror.c | 5 +++++
|
||||
qerror.h | 3 +++
|
||||
5 files changed, 41 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
|
||||
index bba4c54..c9bca8b 100644
|
||||
--- a/hw/9pfs/virtio-9p-device.c
|
||||
+++ b/hw/9pfs/virtio-9p-device.c
|
||||
@@ -33,13 +33,15 @@ static V9fsState *to_virtio_9p(VirtIODevice *vdev)
|
||||
|
||||
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 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
|
||||
}
|
||||
|
||||
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);
|
||||
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
|
||||
index 1b2fc5d..32b98dd 100644
|
||||
--- a/hw/9pfs/virtio-9p.c
|
||||
+++ b/hw/9pfs/virtio-9p.c
|
||||
@@ -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 @@ static void put_fid(V9fsPDU *pdu, V9fsFidState *fidp)
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -1235,6 +1249,11 @@ static void v9fs_attach(void *opaque)
|
||||
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:
|
||||
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
|
||||
index 7f88356..8b612da 100644
|
||||
--- a/hw/9pfs/virtio-9p.h
|
||||
+++ b/hw/9pfs/virtio-9p.h
|
||||
@@ -246,8 +246,7 @@ typedef struct V9fsState
|
||||
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 @@ typedef struct V9fsState
|
||||
* on rename.
|
||||
*/
|
||||
CoRwlock rename_lock;
|
||||
+ int32_t root_fid;
|
||||
+ Error *migration_blocker;
|
||||
} V9fsState;
|
||||
|
||||
typedef struct V9fsStatState {
|
||||
diff --git a/qerror.c b/qerror.c
|
||||
index fdf62b9..25bc91e 100644
|
||||
--- a/qerror.c
|
||||
+++ b/qerror.c
|
||||
@@ -235,6 +235,11 @@ static const QErrorStringTable qerror_table[] = {
|
||||
"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 --git a/qerror.h b/qerror.h
|
||||
index 2d3d43b..6414cd9 100644
|
||||
--- a/qerror.h
|
||||
+++ b/qerror.h
|
||||
@@ -192,6 +192,9 @@ QError *qobject_to_qerror(const QObject *obj);
|
||||
#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 } }"
|
||||
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,64 +0,0 @@
|
||||
From c554919f74e5a79f15360c4c2f417003477634cf Mon Sep 17 00:00:00 2001
|
||||
From: Deepak C Shetty <deepakcs@linux.vnet.ibm.com>
|
||||
Date: Sun, 4 Dec 2011 22:35:28 +0530
|
||||
Subject: [PATCH 05/25] hw/9pfs: Reset server state during TVERSION
|
||||
|
||||
As per the 9p rfc, during TVERSION its necessary to clean all the active
|
||||
fids, so that we start the session from a clean state. Its also needed in
|
||||
scenarios where the guest is booting off 9p, and boot fails, and client
|
||||
restarts, without any knowledge of the past, it will issue a TVERSION again
|
||||
so this ensures that we always start from a clean state.
|
||||
|
||||
Signed-off-by: Deepak C Shetty <deepakcs@linux.vnet.ibm.com>
|
||||
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
|
||||
---
|
||||
hw/9pfs/virtio-9p.c | 26 ++++++++++++++++++++++++++
|
||||
1 files changed, 26 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
|
||||
index 32b98dd..dd43209 100644
|
||||
--- a/hw/9pfs/virtio-9p.c
|
||||
+++ b/hw/9pfs/virtio-9p.c
|
||||
@@ -523,6 +523,30 @@ static int v9fs_mark_fids_unreclaim(V9fsPDU *pdu, V9fsPath *path)
|
||||
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
|
||||
|
||||
@@ -1196,6 +1220,8 @@ static void v9fs_version(void *opaque)
|
||||
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")) {
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,57 +0,0 @@
|
||||
From 64dd41bc2de392fa018c5ce804cc451b83f18b94 Mon Sep 17 00:00:00 2001
|
||||
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
|
||||
Date: Sun, 4 Dec 2011 22:35:28 +0530
|
||||
Subject: [PATCH 06/25] hw/9pfs: Add qdev.reset callback for virtio-9p-pci
|
||||
device
|
||||
|
||||
Add the device reset callback
|
||||
|
||||
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
|
||||
---
|
||||
hw/9pfs/virtio-9p-device.c | 3 ++-
|
||||
hw/virtio-pci.c | 2 +-
|
||||
hw/virtio-pci.h | 1 +
|
||||
3 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
|
||||
index c9bca8b..cd343e1 100644
|
||||
--- a/hw/9pfs/virtio-9p-device.c
|
||||
+++ b/hw/9pfs/virtio-9p-device.c
|
||||
@@ -176,7 +176,8 @@ static PCIDeviceInfo virtio_9p_info = {
|
||||
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 --git a/hw/virtio-pci.c b/hw/virtio-pci.c
|
||||
index 64c6a94..c665f5c 100644
|
||||
--- a/hw/virtio-pci.c
|
||||
+++ b/hw/virtio-pci.c
|
||||
@@ -266,7 +266,7 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
|
||||
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 --git a/hw/virtio-pci.h b/hw/virtio-pci.h
|
||||
index f8404de..344c22b 100644
|
||||
--- a/hw/virtio-pci.h
|
||||
+++ b/hw/virtio-pci.h
|
||||
@@ -45,6 +45,7 @@ typedef struct {
|
||||
} 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
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,210 +0,0 @@
|
||||
From ed6857bf98e6c8b8080be208ffe15bb678591466 Mon Sep 17 00:00:00 2001
|
||||
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
|
||||
Date: Sun, 4 Dec 2011 22:35:28 +0530
|
||||
Subject: [PATCH 07/25] hw/9pfs: Use the correct file descriptor in Fsdriver
|
||||
Callback
|
||||
|
||||
Fsdriver callback that operate on file descriptor need to
|
||||
differentiate between directory fd and file fd.
|
||||
|
||||
Based on the original patch from Sassan Panahinejad <sassan@sassan.me.uk>
|
||||
|
||||
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
|
||||
---
|
||||
fsdev/file-op-9p.h | 4 ++--
|
||||
hw/9pfs/cofile.c | 4 ++--
|
||||
hw/9pfs/virtio-9p-handle.c | 28 ++++++++++++++++++++++------
|
||||
hw/9pfs/virtio-9p-local.c | 36 ++++++++++++++++++++++++++----------
|
||||
hw/9pfs/virtio-9p-synth.c | 5 +++--
|
||||
5 files changed, 55 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
|
||||
index 1928da2..a85ecd3 100644
|
||||
--- a/fsdev/file-op-9p.h
|
||||
+++ b/fsdev/file-op-9p.h
|
||||
@@ -112,10 +112,10 @@ typedef struct FileOperations
|
||||
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 --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c
|
||||
index 586b038..b15838c 100644
|
||||
--- a/hw/9pfs/cofile.c
|
||||
+++ b/hw/9pfs/cofile.c
|
||||
@@ -71,7 +71,7 @@ int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, struct stat *stbuf)
|
||||
}
|
||||
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 @@ int v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync)
|
||||
}
|
||||
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 --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
|
||||
index a62f690..f97d898 100644
|
||||
--- a/hw/9pfs/virtio-9p-handle.c
|
||||
+++ b/hw/9pfs/virtio-9p-handle.c
|
||||
@@ -255,10 +255,17 @@ static int handle_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
|
||||
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,
|
||||
@@ -395,12 +402,21 @@ static int handle_remove(FsContext *ctx, const char *path)
|
||||
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 --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
|
||||
index 99ef0cd..371a94d 100644
|
||||
--- a/hw/9pfs/virtio-9p-local.c
|
||||
+++ b/hw/9pfs/virtio-9p-local.c
|
||||
@@ -366,11 +366,18 @@ out:
|
||||
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 @@ static int local_fstat(FsContext *fs_ctx,
|
||||
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 @@ static int local_remove(FsContext *ctx, const char *path)
|
||||
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 --git a/hw/9pfs/virtio-9p-synth.c b/hw/9pfs/virtio-9p-synth.c
|
||||
index f573616..92e0b09 100644
|
||||
--- a/hw/9pfs/virtio-9p-synth.c
|
||||
+++ b/hw/9pfs/virtio-9p-synth.c
|
||||
@@ -166,7 +166,7 @@ static int v9fs_synth_lstat(FsContext *fs_ctx,
|
||||
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 @@ static int v9fs_synth_remove(FsContext *ctx, const char *path)
|
||||
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;
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,305 +0,0 @@
|
||||
From 45d6cdff48356dc8974497ec0524f971b646dd70 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
|
||||
Date: Wed, 21 Dec 2011 12:37:22 +0530
|
||||
Subject: [PATCH 08/25] hw/9pfs: replace iovec manipulation with QEMUIOVector
|
||||
|
||||
The v9fs_read() and v9fs_write() functions rely on iovec[] manipulation
|
||||
code should be replaced with QEMUIOVector to avoid duplicating code.
|
||||
In the future it may be possible to make the code even more concise by
|
||||
using QEMUIOVector consistently across virtio and 9pfs.
|
||||
|
||||
The "v" format specifier for pdu_marshal() and pdu_unmarshal() is
|
||||
dropped since it does not actually pack/unpack anything. The specifier
|
||||
was also not implemented to update the offset variable and could only be
|
||||
used at the end of a format string, another sign that this shouldn't
|
||||
really be a format specifier. Instead, see the new
|
||||
v9fs_init_qiov_from_pdu() function.
|
||||
|
||||
This change avoids a possible iovec[] buffer overflow when indirect
|
||||
vrings are used since the number of vectors is now limited by the
|
||||
underlying VirtQueueElement and cannot be out-of-bounds.
|
||||
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
|
||||
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
|
||||
---
|
||||
hw/9pfs/virtio-9p.c | 162 +++++++++++++++++++--------------------------------
|
||||
1 files changed, 60 insertions(+), 102 deletions(-)
|
||||
|
||||
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
|
||||
index dd43209..c018916 100644
|
||||
--- a/hw/9pfs/virtio-9p.c
|
||||
+++ b/hw/9pfs/virtio-9p.c
|
||||
@@ -674,40 +674,6 @@ static size_t pdu_pack(V9fsPDU *pdu, size_t offset, const void *src,
|
||||
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;
|
||||
@@ -743,12 +709,6 @@ static size_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
|
||||
*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);
|
||||
@@ -827,12 +787,6 @@ static size_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
|
||||
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);
|
||||
@@ -1143,42 +1097,6 @@ static void stat_to_v9stat_dotl(V9fsState *s, const struct stat *stbuf,
|
||||
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;
|
||||
@@ -1861,6 +1779,38 @@ out:
|
||||
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;
|
||||
@@ -1895,21 +1845,21 @@ static void v9fs_read(void *opaque)
|
||||
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;
|
||||
@@ -1920,11 +1870,12 @@ static void v9fs_read(void *opaque)
|
||||
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 {
|
||||
@@ -2095,7 +2046,6 @@ out:
|
||||
|
||||
static void v9fs_write(void *opaque)
|
||||
{
|
||||
- int cnt;
|
||||
ssize_t err;
|
||||
int32_t fid;
|
||||
int64_t off;
|
||||
@@ -2104,13 +2054,14 @@ static void v9fs_write(void *opaque)
|
||||
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) {
|
||||
@@ -2126,20 +2077,23 @@ static void v9fs_write(void *opaque)
|
||||
/*
|
||||
* 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;
|
||||
@@ -2148,16 +2102,20 @@ static void v9fs_write(void *opaque)
|
||||
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);
|
||||
}
|
||||
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,133 +0,0 @@
|
||||
From 3d3ec7b809b91f2a71fb78fc6b5b079963383243 Mon Sep 17 00:00:00 2001
|
||||
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
|
||||
Date: Wed, 21 Dec 2011 12:37:23 +0530
|
||||
Subject: [PATCH 09/25] hw/9pfs: Use the correct signed type for different
|
||||
variables
|
||||
|
||||
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
|
||||
---
|
||||
fsdev/file-op-9p.h | 2 +-
|
||||
hw/9pfs/virtio-9p.c | 21 +++++++++++----------
|
||||
hw/9pfs/virtio-9p.h | 2 +-
|
||||
trace-events | 8 ++++----
|
||||
4 files changed, 17 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
|
||||
index a85ecd3..c823fe0 100644
|
||||
--- a/fsdev/file-op-9p.h
|
||||
+++ b/fsdev/file-op-9p.h
|
||||
@@ -74,7 +74,7 @@ typedef struct FsContext
|
||||
} FsContext;
|
||||
|
||||
typedef struct V9fsPath {
|
||||
- int16_t size;
|
||||
+ uint16_t size;
|
||||
char *data;
|
||||
} V9fsPath;
|
||||
|
||||
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
|
||||
index c018916..b3fc3d0 100644
|
||||
--- a/hw/9pfs/virtio-9p.c
|
||||
+++ b/hw/9pfs/virtio-9p.c
|
||||
@@ -1694,8 +1694,8 @@ out_nofid:
|
||||
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;
|
||||
@@ -1719,7 +1719,7 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu,
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -1814,11 +1814,11 @@ static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu,
|
||||
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;
|
||||
@@ -1962,8 +1962,9 @@ static void v9fs_readdir(void *opaque)
|
||||
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;
|
||||
|
||||
@@ -2001,7 +2002,7 @@ out_nofid:
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -2048,8 +2049,8 @@ static void v9fs_write(void *opaque)
|
||||
{
|
||||
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;
|
||||
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
|
||||
index 8b612da..19a797b 100644
|
||||
--- a/hw/9pfs/virtio-9p.h
|
||||
+++ b/hw/9pfs/virtio-9p.h
|
||||
@@ -156,7 +156,7 @@ typedef struct V9fsFidState V9fsFidState;
|
||||
|
||||
typedef struct V9fsString
|
||||
{
|
||||
- int16_t size;
|
||||
+ uint16_t size;
|
||||
char *data;
|
||||
} V9fsString;
|
||||
|
||||
diff --git a/trace-events b/trace-events
|
||||
index 962caca..e417897 100644
|
||||
--- a/trace-events
|
||||
+++ b/trace-events
|
||||
@@ -579,11 +579,11 @@ v9fs_lcreate(uint16_t tag, uint8_t id, int32_t dfid, int32_t flags, int32_t mode
|
||||
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"
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,54 +0,0 @@
|
||||
From abf80f880410ebbdd01a289c41c87153802fe900 Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Gustafsson <gson@gson.org>
|
||||
Date: Mon, 12 Dec 2011 00:46:32 +0400
|
||||
Subject: [PATCH 10/25] target-i386: fix cmpxchg instruction emulation
|
||||
|
||||
When the i386 cmpxchg instruction is executed with a memory operand
|
||||
and the comparison result is "unequal", do the memory write before
|
||||
changing the accumulator instead of the other way around, because
|
||||
otherwise the new accumulator value will incorrectly be used in the
|
||||
comparison when the instruction is restarted after a page fault.
|
||||
|
||||
This bug was originally reported on 2010-04-25 as
|
||||
https://bugs.launchpad.net/qemu/+bug/569760
|
||||
|
||||
Signed-off-by: Andreas Gustafsson <gson@gson.org>
|
||||
---
|
||||
target-i386/translate.c | 11 +++++++----
|
||||
1 files changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/target-i386/translate.c b/target-i386/translate.c
|
||||
index 1ef8d16..8321bf3 100644
|
||||
--- a/target-i386/translate.c
|
||||
+++ b/target-i386/translate.c
|
||||
@@ -4870,20 +4870,23 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
|
||||
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;
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,31 +0,0 @@
|
||||
From 6d450bfbc862d0dab0e8da10ae15698612800726 Mon Sep 17 00:00:00 2001
|
||||
From: Brad <brad@comstyle.com>
|
||||
Date: Mon, 28 Nov 2011 19:53:49 -0500
|
||||
Subject: [PATCH 11/25] configure: Enable build by default PIE / read-only
|
||||
relocation sections on OpenBSD amd64/i386.
|
||||
|
||||
Enable build by default PIE / read-only relocation sections for the QEMU
|
||||
binaries on OpenBSD amd64/i386.
|
||||
|
||||
Signed-off-by: Brad Smith <brad@comstyle.com>
|
||||
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
|
||||
---
|
||||
configure | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/configure b/configure
|
||||
index ac4840d..b113f60 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -1116,7 +1116,7 @@ fi
|
||||
|
||||
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"
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,155 +0,0 @@
|
||||
From 3e8088148bb56b84a739c2ef3c63d89188a1ad8f Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Sandstrom <Stefan.Sandstrom@axis.com>
|
||||
Date: Mon, 12 Dec 2011 11:38:31 +0100
|
||||
Subject: [PATCH 12/25] cris: Handle conditional stores on CRISv10
|
||||
|
||||
Signed-off-by: Stefan Sandstrom <Stefan.Sandstrom@axis.com>
|
||||
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||
---
|
||||
target-cris/cpu.h | 2 +
|
||||
target-cris/helper.c | 1 +
|
||||
target-cris/translate_v10.c | 72 +++++++++++++++++++++++++++++++++++++++---
|
||||
3 files changed, 69 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
|
||||
index 8ae0ce3..453afbb 100644
|
||||
--- a/target-cris/cpu.h
|
||||
+++ b/target-cris/cpu.h
|
||||
@@ -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 --git a/target-cris/helper.c b/target-cris/helper.c
|
||||
index 75f0035..5bc6d81 100644
|
||||
--- a/target-cris/helper.c
|
||||
+++ b/target-cris/helper.c
|
||||
@@ -157,6 +157,7 @@ static void do_interruptv10(CPUState *env)
|
||||
/* 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 --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
|
||||
index 637ac20..95053b6 100644
|
||||
--- a/target-cris/translate_v10.c
|
||||
+++ b/target-cris/translate_v10.c
|
||||
@@ -62,6 +62,65 @@ static inline void cris_illegal_insn(DisasContext *dc)
|
||||
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 @@ static unsigned int dec10_setclrf(DisasContext *dc)
|
||||
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 @@ static unsigned int dec10_ind_move_r_m(DisasContext *dc, unsigned int size)
|
||||
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 @@ static unsigned int dec10_ind_move_pr_m(DisasContext *dc)
|
||||
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 @@ static void dec10_movem_r_m(DisasContext *dc)
|
||||
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);
|
||||
}
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,40 +0,0 @@
|
||||
From a25808dc5baee83f36e0cdab998eb6c0024156fa Mon Sep 17 00:00:00 2001
|
||||
From: Anthony Liguori <aliguori@us.ibm.com>
|
||||
Date: Sun, 18 Dec 2011 12:59:12 -0600
|
||||
Subject: [PATCH 13/25] pc: add pc-0.15
|
||||
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
---
|
||||
hw/pc_piix.c | 9 +++++++++
|
||||
1 files changed, 9 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
|
||||
index 970f43c..9093a28 100644
|
||||
--- a/hw/pc_piix.c
|
||||
+++ b/hw/pc_piix.c
|
||||
@@ -306,6 +306,14 @@ static QEMUMachine pc_machine_v1_0 = {
|
||||
.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",
|
||||
@@ -557,6 +565,7 @@ static QEMUMachine xenfv_machine = {
|
||||
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);
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,87 +0,0 @@
|
||||
From 7e2191ae9898cc957a3d1991aff0e40f2e0f44a4 Mon Sep 17 00:00:00 2001
|
||||
From: Anthony Liguori <aliguori@us.ibm.com>
|
||||
Date: Sun, 18 Dec 2011 13:07:03 -0600
|
||||
Subject: [PATCH 14/25] pc: fix event_idx compatibility for virtio devices
|
||||
|
||||
event_idx was introduced in 0.15 and must be disabled for all virtio-pci devices
|
||||
(including virtio-balloon-pci).
|
||||
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
---
|
||||
hw/pc_piix.c | 32 ++++++++++++++++++++++++++++++++
|
||||
1 files changed, 32 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
|
||||
index 9093a28..05000e3 100644
|
||||
--- a/hw/pc_piix.c
|
||||
+++ b/hw/pc_piix.c
|
||||
@@ -328,6 +328,22 @@ static QEMUMachine pc_machine_v0_14 = {
|
||||
.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 */ }
|
||||
},
|
||||
@@ -368,6 +384,10 @@ static QEMUMachine pc_machine_v0_13 = {
|
||||
.property = "event_idx",
|
||||
.value = "off",
|
||||
},{
|
||||
+ .driver = "virtio-balloon-pci",
|
||||
+ .property = "event_idx",
|
||||
+ .value = "off",
|
||||
+ },{
|
||||
.driver = "AC97",
|
||||
.property = "use_broken_id",
|
||||
.value = stringify(1),
|
||||
@@ -415,6 +435,10 @@ static QEMUMachine pc_machine_v0_12 = {
|
||||
.property = "event_idx",
|
||||
.value = "off",
|
||||
},{
|
||||
+ .driver = "virtio-balloon-pci",
|
||||
+ .property = "event_idx",
|
||||
+ .value = "off",
|
||||
+ },{
|
||||
.driver = "AC97",
|
||||
.property = "use_broken_id",
|
||||
.value = stringify(1),
|
||||
@@ -470,6 +494,10 @@ static QEMUMachine pc_machine_v0_11 = {
|
||||
.property = "event_idx",
|
||||
.value = "off",
|
||||
},{
|
||||
+ .driver = "virtio-balloon-pci",
|
||||
+ .property = "event_idx",
|
||||
+ .value = "off",
|
||||
+ },{
|
||||
.driver = "AC97",
|
||||
.property = "use_broken_id",
|
||||
.value = stringify(1),
|
||||
@@ -537,6 +565,10 @@ static QEMUMachine pc_machine_v0_10 = {
|
||||
.property = "event_idx",
|
||||
.value = "off",
|
||||
},{
|
||||
+ .driver = "virtio-balloon-pci",
|
||||
+ .property = "event_idx",
|
||||
+ .value = "off",
|
||||
+ },{
|
||||
.driver = "AC97",
|
||||
.property = "use_broken_id",
|
||||
.value = stringify(1),
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,56 +0,0 @@
|
||||
From 9b81fbdbb0cc930aacec343c6ab37adfd60c9e76 Mon Sep 17 00:00:00 2001
|
||||
From: "Cao,Bing Bu" <mars@linux.vnet.ibm.com>
|
||||
Date: Tue, 13 Dec 2011 09:22:20 +0800
|
||||
Subject: [PATCH 15/25] Fix parse of usb device description with multiple
|
||||
configurations
|
||||
|
||||
Changed From V1:
|
||||
Use DPRINTF instead of fprintf,because it is not an error.
|
||||
|
||||
When testing ipod on QEMU by He Jie Xu<xuhj@linux.vnet.ibm.com>,qemu made a assertion.
|
||||
We found that the ipod with 2 configurations,and the usb-linux did not parse the descriptor correctly.
|
||||
The descr_len returned is the total length of the all configurations,not one configuration.
|
||||
The older version will through the other configurations instead of skip,continue parsing the descriptor of interfaces/endpoints in other configurations,then went wrong.
|
||||
|
||||
This patch will put the configuration descriptor parse in loop outside and dispel the other configurations not requested.
|
||||
|
||||
Signed-off-by: Cao,Bing Bu <mars@linux.vnet.ibm.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
usb-linux.c | 19 +++++++++++--------
|
||||
1 files changed, 11 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/usb-linux.c b/usb-linux.c
|
||||
index ab4c693..ed14bb1 100644
|
||||
--- a/usb-linux.c
|
||||
+++ b/usb-linux.c
|
||||
@@ -1141,15 +1141,18 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
|
||||
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)) {
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,40 +0,0 @@
|
||||
From f63d074313c5df917535587b50802ece7beb6e45 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 4 Jan 2012 18:13:54 +0100
|
||||
Subject: [PATCH 16/25] usb-storage: cancel I/O on reset
|
||||
|
||||
When resetting the usb-storage device we'll have to carefully cancel
|
||||
and clear any requests which might be in flight, otherwise we'll confuse
|
||||
the state machine.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/usb-msd.c | 12 ++++++++++++
|
||||
1 files changed, 12 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
|
||||
index 4c06950..3147131 100644
|
||||
--- a/hw/usb-msd.c
|
||||
+++ b/hw/usb-msd.c
|
||||
@@ -278,6 +278,18 @@ static void usb_msd_handle_reset(USBDevice *dev)
|
||||
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;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,111 +0,0 @@
|
||||
From c936f649d4a6b87cabe809170874f6b560cc0524 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 5 Jan 2012 15:49:18 +0100
|
||||
Subject: [PATCH 17/25] usb-host: properly release port on unplug & exit
|
||||
|
||||
Factor out port release into a separate function. Call release function
|
||||
in exit notifier too. Add explicit call the USBDEVFS_RELEASE_PORT
|
||||
ioctl, just closing the hub file handle seems not to be enougth. Make
|
||||
sure we release the port before resetting the device, otherwise host
|
||||
drivers will not re-attach.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
usb-linux.c | 28 ++++++++++++++++++++--------
|
||||
1 files changed, 20 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/usb-linux.c b/usb-linux.c
|
||||
index ed14bb1..749ce71 100644
|
||||
--- a/usb-linux.c
|
||||
+++ b/usb-linux.c
|
||||
@@ -116,6 +116,7 @@ typedef struct USBHostDevice {
|
||||
USBDevice dev;
|
||||
int fd;
|
||||
int hub_fd;
|
||||
+ int hub_port;
|
||||
|
||||
uint8_t descr[8192];
|
||||
int descr_len;
|
||||
@@ -434,7 +435,7 @@ static int usb_host_claim_port(USBHostDevice *s)
|
||||
{
|
||||
#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 @@ static int usb_host_claim_port(USBHostDevice *s)
|
||||
/* 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 @@ static int usb_host_claim_port(USBHostDevice *s)
|
||||
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 @@ static void usb_host_handle_destroy(USBDevice *dev)
|
||||
{
|
||||
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);
|
||||
}
|
||||
@@ -1402,6 +1413,7 @@ static void usb_host_exit_notifier(struct Notifier *n, void *data)
|
||||
{
|
||||
USBHostDevice *s = container_of(n, USBHostDevice, exit);
|
||||
|
||||
+ usb_host_release_port(s);
|
||||
if (s->fd != -1) {
|
||||
usb_host_do_reset(s);;
|
||||
}
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,40 +0,0 @@
|
||||
From 23201c64a789cf948fedcea221a4b6e197fcd628 Mon Sep 17 00:00:00 2001
|
||||
From: Andriy Gapon <avg@FreeBSD.org>
|
||||
Date: Thu, 22 Dec 2011 11:34:30 +0200
|
||||
Subject: [PATCH 18/25] usb-ohci: td.cbp incorrectly updated near page end
|
||||
|
||||
The current code that updates the cbp value after a transfer looks like this:
|
||||
td.cbp += ret;
|
||||
if ((td.cbp & 0xfff) + ret > 0xfff) {
|
||||
<handle page overflow>
|
||||
because the 'ret' value is effectively added twice the check may fire too early
|
||||
when the overflow hasn't happened yet.
|
||||
|
||||
Below is one of the possible changes that correct the behavior:
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/usb-ohci.c | 6 +++---
|
||||
1 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
|
||||
index c2981c5..c27014a 100644
|
||||
--- a/hw/usb-ohci.c
|
||||
+++ b/hw/usb-ohci.c
|
||||
@@ -1025,10 +1025,10 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
|
||||
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;
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,47 +0,0 @@
|
||||
From 37769d27270eff15d878a1c7df23407fc5f09b7f Mon Sep 17 00:00:00 2001
|
||||
From: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Sat, 7 Jan 2012 15:20:12 +0100
|
||||
Subject: [PATCH 19/25] target-sh4: ignore ocbp and ocbwb instructions
|
||||
|
||||
ocbp and ocbwb controls the writeback of a cache line to memory. They
|
||||
are supposed to do nothing in case of a cache miss. Given QEMU only
|
||||
partially emulate caches, it is safe to ignore these instructions.
|
||||
|
||||
This fixes a kernel oops when trying to access an rtl8139 NIC with
|
||||
recent versions.
|
||||
|
||||
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
|
||||
(cherry picked from commit 0cdb95549fedc73e13c147ab9dcabcc303426a07)
|
||||
---
|
||||
target-sh4/translate.c | 14 +++-----------
|
||||
1 files changed, 3 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
|
||||
index bad3577..e04a6e0 100644
|
||||
--- a/target-sh4/translate.c
|
||||
+++ b/target-sh4/translate.c
|
||||
@@ -1652,18 +1652,10 @@ static void _decode_opc(DisasContext * ctx)
|
||||
}
|
||||
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;
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,74 +0,0 @@
|
||||
From fbcf305e5adc310e6383d4ec5e844f3f8d072116 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Mon, 12 Dec 2011 22:36:01 +0100
|
||||
Subject: [PATCH 20/25] PPC: Fix linker scripts on ppc hosts
|
||||
|
||||
When compiling qemu statically with multilib on PPC, we hit the
|
||||
same issue that commit 845f2c2812d9ed24b36c02a3d06ee83aeafe8b49
|
||||
is fixing. Do the same here.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
|
||||
(cherry picked from commit 665a04ae1cbfa8004a38cf0fe99ba799c978a1fe)
|
||||
---
|
||||
ppc.ld | 16 ++++++++++++++--
|
||||
ppc64.ld | 16 ++++++++++++++--
|
||||
2 files changed, 28 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/ppc.ld b/ppc.ld
|
||||
index 69aa3f2..2a0dcad 100644
|
||||
--- a/ppc.ld
|
||||
+++ b/ppc.ld
|
||||
@@ -49,8 +49,20 @@ SECTIONS
|
||||
.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 --git a/ppc64.ld b/ppc64.ld
|
||||
index 0a7c0dd..e2dafa0 100644
|
||||
--- a/ppc64.ld
|
||||
+++ b/ppc64.ld
|
||||
@@ -54,8 +54,20 @@ SECTIONS
|
||||
*(.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 :
|
||||
{
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,34 +0,0 @@
|
||||
From 6061f16a8a119a46e61f2ddbabdb58f83e8857f7 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Date: Fri, 25 Nov 2011 12:06:22 +0100
|
||||
Subject: [PATCH 21/25] qiov: prevent double free or use-after-free
|
||||
|
||||
qemu_iovec_destroy does not clear the QEMUIOVector fully, and the data
|
||||
could thus be used after free or freed again. While I do not know any
|
||||
example in the tree, I observed this using virtio-scsi (and SCSI
|
||||
scatter/gather) when canceling DMA requests.
|
||||
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
cutils.c | 3 +++
|
||||
1 files changed, 3 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/cutils.c b/cutils.c
|
||||
index 6db6304..24b3fe3 100644
|
||||
--- a/cutils.c
|
||||
+++ b/cutils.c
|
||||
@@ -217,7 +217,10 @@ void qemu_iovec_destroy(QEMUIOVector *qiov)
|
||||
{
|
||||
assert(qiov->nalloc != -1);
|
||||
|
||||
+ qemu_iovec_reset(qiov);
|
||||
g_free(qiov->iov);
|
||||
+ qiov->nalloc = 0;
|
||||
+ qiov->iov = NULL;
|
||||
}
|
||||
|
||||
void qemu_iovec_reset(QEMUIOVector *qiov)
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,115 +0,0 @@
|
||||
From fe5c13ebf1161d0f324229cfb36cb5fb87ec6248 Mon Sep 17 00:00:00 2001
|
||||
From: Avi Kivity <avi@redhat.com>
|
||||
Date: Mon, 5 Dec 2011 19:20:12 +0200
|
||||
Subject: [PATCH 22/25] coroutine: switch per-thread free pool to a global
|
||||
pool
|
||||
|
||||
ucontext-based coroutines use a free pool to reduce allocations and
|
||||
deallocations of coroutine objects. The pool is per-thread, presumably
|
||||
to improve locality. However, as coroutines are usually allocated in
|
||||
a vcpu thread and freed in the I/O thread, the pool accounting gets
|
||||
screwed up and we end allocating and freeing a coroutine for every I/O
|
||||
request. This is expensive since large objects are allocated via the
|
||||
kernel, and are not cached by the C runtime.
|
||||
|
||||
Fix by switching to a global pool. This is safe since we're protected
|
||||
by the global mutex.
|
||||
|
||||
Signed-off-by: Avi Kivity <avi@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
coroutine-ucontext.c | 30 ++++++++++++++++--------------
|
||||
1 files changed, 16 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/coroutine-ucontext.c b/coroutine-ucontext.c
|
||||
index 2b8d3e9..3d01075 100644
|
||||
--- a/coroutine-ucontext.c
|
||||
+++ b/coroutine-ucontext.c
|
||||
@@ -35,6 +35,10 @@ enum {
|
||||
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 @@ typedef struct {
|
||||
/** 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 @@ static CoroutineThreadState *coroutine_get_thread_state(void)
|
||||
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 CoroutineThreadState *coroutine_get_thread_state(void)
|
||||
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 @@ static Coroutine *coroutine_new(void)
|
||||
|
||||
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 @@ Coroutine *qemu_coroutine_new(void)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,86 +0,0 @@
|
||||
From 5bb37d151b026759ee35f04212b11b4d625c7431 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Wed, 7 Dec 2011 12:42:10 +0100
|
||||
Subject: [PATCH 23/25] qemu-img rebase: Fix for undersized backing files
|
||||
|
||||
Backing files may be smaller than the corresponding COW file. When
|
||||
reading directly from the backing file, qemu-img rebase must consider
|
||||
this and assume zero sectors after the end of backing files.
|
||||
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
|
||||
---
|
||||
qemu-img.c | 42 +++++++++++++++++++++++++++++++++---------
|
||||
1 files changed, 33 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/qemu-img.c b/qemu-img.c
|
||||
index 8bdae66..01cc0d3 100644
|
||||
--- a/qemu-img.c
|
||||
+++ b/qemu-img.c
|
||||
@@ -1420,6 +1420,8 @@ static int img_rebase(int argc, char **argv)
|
||||
*/
|
||||
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 @@ static int img_rebase(int argc, char **argv)
|
||||
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 @@ static int img_rebase(int argc, char **argv)
|
||||
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 */
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,82 +0,0 @@
|
||||
From 8afe984ef7aa25cb2f8af51da021fdc8a242884d Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Wed, 7 Dec 2011 13:57:13 +0100
|
||||
Subject: [PATCH 24/25] Documentation: Add qemu-img -t parameter in man page
|
||||
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
|
||||
---
|
||||
qemu-img-cmds.hx | 6 +++---
|
||||
qemu-img.texi | 10 +++++++---
|
||||
2 files changed, 10 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
|
||||
index 4be00a5..49dce7c 100644
|
||||
--- a/qemu-img-cmds.hx
|
||||
+++ b/qemu-img-cmds.hx
|
||||
@@ -24,13 +24,13 @@ ETEXI
|
||||
DEF("commit", img_commit,
|
||||
"commit [-f fmt] [-t cache] filename")
|
||||
STEXI
|
||||
-@item commit [-f @var{fmt}] @var{filename}
|
||||
+@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
|
||||
-@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}
|
||||
+@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 @@ ETEXI
|
||||
DEF("rebase", img_rebase,
|
||||
"rebase [-f fmt] [-t cache] [-p] [-u] -b backing_file [-F backing_fmt] filename")
|
||||
STEXI
|
||||
-@item rebase [-f @var{fmt}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
|
||||
+@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 --git a/qemu-img.texi b/qemu-img.texi
|
||||
index 70fa321..b2ca3a5 100644
|
||||
--- a/qemu-img.texi
|
||||
+++ b/qemu-img.texi
|
||||
@@ -45,6 +45,10 @@ indicates the consecutive number of bytes that must contain only zeros
|
||||
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.
|
||||
+@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 @@ this case. @var{backing_file} will never be modified unless you use the
|
||||
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.
|
||||
|
||||
-@item commit [-f @var{fmt}] @var{filename}
|
||||
+@item commit [-f @var{fmt}] [-t @var{cache}] @var{filename}
|
||||
|
||||
Commit the changes recorded in @var{filename} in its base image.
|
||||
|
||||
-@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}
|
||||
+@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 @@ they are displayed too.
|
||||
|
||||
List, apply, create or delete snapshots in image @var{filename}.
|
||||
|
||||
-@item rebase [-f @var{fmt}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
|
||||
+@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.
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,39 +0,0 @@
|
||||
From e47c212cb5af148ab6d9dcf49bc0e054fe9c2e1d Mon Sep 17 00:00:00 2001
|
||||
From: Josh Durgin <josh.durgin@dreamhost.com>
|
||||
Date: Tue, 6 Dec 2011 17:05:10 -0800
|
||||
Subject: [PATCH 25/25] rbd: always set out parameter in qemu_rbd_snap_list
|
||||
|
||||
The caller expects psn_tab to be NULL when there are no snapshots or
|
||||
an error occurs. This results in calling g_free on an invalid address.
|
||||
|
||||
Reported-by: Oliver Francke <Oliver@filoo.de>
|
||||
Signed-off-by: Josh Durgin <josh.durgin@dreamhost.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
block/rbd.c | 3 ++-
|
||||
1 files changed, 2 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/block/rbd.c b/block/rbd.c
|
||||
index 9088c52..54a6961 100644
|
||||
--- a/block/rbd.c
|
||||
+++ b/block/rbd.c
|
||||
@@ -808,7 +808,7 @@ static int qemu_rbd_snap_list(BlockDriverState *bs,
|
||||
} 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 @@ static int qemu_rbd_snap_list(BlockDriverState *bs,
|
||||
}
|
||||
rbd_snap_list_end(snaps);
|
||||
|
||||
+ done:
|
||||
*psn_tab = sn_tab;
|
||||
return snap_count;
|
||||
}
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,37 +0,0 @@
|
||||
From d0ed2d2e8e863a9a64c9fc9c08fa68bee546ad00 Mon Sep 17 00:00:00 2001
|
||||
From: Anthony Liguori <aliguori@us.ibm.com>
|
||||
Date: Mon, 23 Jan 2012 07:30:43 -0600
|
||||
Subject: [PATCH 26/26] e1000: bounds packet size against buffer size
|
||||
|
||||
Otherwise we can write beyond the buffer and corrupt memory. This is tracked
|
||||
as CVE-2012-0029.
|
||||
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
---
|
||||
hw/e1000.c | 3 +++
|
||||
1 files changed, 3 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/hw/e1000.c b/hw/e1000.c
|
||||
index 986ed9c..e164d79 100644
|
||||
--- a/hw/e1000.c
|
||||
+++ b/hw/e1000.c
|
||||
@@ -466,6 +466,8 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
|
||||
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 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
|
||||
// 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;
|
||||
}
|
||||
--
|
||||
1.7.7.6
|
||||
|
@ -1,19 +1,19 @@
|
||||
From 34736b9b6690054152ae2b9b37f75f7ed720590a Mon Sep 17 00:00:00 2001
|
||||
From 5b79aa329a378537ec939cee75df10ca073b367f Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Mon, 21 Mar 2011 21:57:47 +0100
|
||||
Subject: [PATCH 106/118] char: Split out tcp socket close code in a separate
|
||||
Subject: [PATCH 101/114] char: Split out tcp socket close code in a separate
|
||||
function
|
||||
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
---
|
||||
qemu-char.c | 25 ++++++++++++++++---------
|
||||
1 files changed, 16 insertions(+), 9 deletions(-)
|
||||
1 file changed, 16 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/qemu-char.c b/qemu-char.c
|
||||
index 27abcb9..a5ca611 100644
|
||||
index fe1126f..78d2a69 100644
|
||||
--- a/qemu-char.c
|
||||
+++ b/qemu-char.c
|
||||
@@ -2163,6 +2163,21 @@ typedef struct {
|
||||
@@ -2141,6 +2141,21 @@ typedef struct {
|
||||
|
||||
static void tcp_chr_accept(void *opaque);
|
||||
|
||||
@ -35,7 +35,7 @@ index 27abcb9..a5ca611 100644
|
||||
static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
{
|
||||
TCPCharDriver *s = chr->opaque;
|
||||
@@ -2313,15 +2328,7 @@ static void tcp_chr_read(void *opaque)
|
||||
@@ -2291,15 +2306,7 @@ static void tcp_chr_read(void *opaque)
|
||||
len = s->max_size;
|
||||
size = tcp_chr_recv(chr, (void *)buf, len);
|
||||
if (size == 0) {
|
||||
@ -53,5 +53,5 @@ index 27abcb9..a5ca611 100644
|
||||
if (s->do_telnetopt)
|
||||
tcp_chr_process_IAC_bytes(chr, s, buf, &size);
|
||||
--
|
||||
1.7.7.5
|
||||
1.7.10.4
|
||||
|
@ -1,56 +0,0 @@
|
||||
From 01936dfd5b9fa8117fc1d63ce92198dd28422773 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Mon, 19 Dec 2011 14:59:45 +0100
|
||||
Subject: [PATCH 101/118] usb-redir: Clear iso / irq error when stopping the
|
||||
stream
|
||||
|
||||
And ignore status messages from the client which arrive after stream
|
||||
stop (the stream stop send to the client and an error status reported by
|
||||
the client my cross each other due to network latency).
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
usb-redir.c | 6 ++++--
|
||||
1 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index fb91c92..7678f1a 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -410,6 +410,7 @@ static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep)
|
||||
DPRINTF("iso stream stopped ep %02X\n", ep);
|
||||
dev->endpoint[EP2I(ep)].iso_started = 0;
|
||||
}
|
||||
+ dev->endpoint[EP2I(ep)].iso_error = 0;
|
||||
usbredir_free_bufpq(dev, ep);
|
||||
}
|
||||
|
||||
@@ -522,6 +523,7 @@ static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev,
|
||||
DPRINTF("interrupt recv stopped ep %02X\n", ep);
|
||||
dev->endpoint[EP2I(ep)].interrupt_started = 0;
|
||||
}
|
||||
+ dev->endpoint[EP2I(ep)].interrupt_error = 0;
|
||||
usbredir_free_bufpq(dev, ep);
|
||||
}
|
||||
|
||||
@@ -1029,7 +1031,7 @@ static void usbredir_iso_stream_status(void *priv, uint32_t id,
|
||||
DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status,
|
||||
ep, id);
|
||||
|
||||
- if (!dev->dev.attached) {
|
||||
+ if (!dev->dev.attached || !dev->endpoint[EP2I(ep)].iso_started) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1050,7 +1052,7 @@ static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
|
||||
DPRINTF("interrupt recv status %d ep %02X id %u\n",
|
||||
interrupt_receiving_status->status, ep, id);
|
||||
|
||||
- if (!dev->dev.attached) {
|
||||
+ if (!dev->dev.attached || !dev->endpoint[EP2I(ep)].interrupt_started) {
|
||||
return;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 61efa48e1973eaac16615c85198d9d74e36a3124 Mon Sep 17 00:00:00 2001
|
||||
From 0e725325a4f3d1eb0eaa243cc059df2774c9c098 Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Mon, 21 Mar 2011 20:31:45 +0100
|
||||
Subject: [PATCH 107/118] char: Add a QemuChrHandlers struct to initialise
|
||||
Subject: [PATCH 102/114] char: Add a QemuChrHandlers struct to initialise
|
||||
chardev handlers
|
||||
|
||||
Instead of passing each handler in the qemu_add_handlers() function,
|
||||
@ -10,10 +10,12 @@ create a struct of handlers that can be passed to the function instead.
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
---
|
||||
gdbstub.c | 9 +++++++--
|
||||
hw/cadence_uart.c | 9 +++++++--
|
||||
hw/ccid-card-passthru.c | 11 +++++++----
|
||||
hw/debugcon.c | 2 +-
|
||||
hw/escc.c | 9 +++++++--
|
||||
hw/etraxfs_ser.c | 13 +++++++++----
|
||||
hw/exynos4210_uart.c | 9 +++++++--
|
||||
hw/grlib_apbuart.c | 12 +++++++-----
|
||||
hw/ivshmem.c | 28 ++++++++++++++++++++++------
|
||||
hw/lm32_juart.c | 8 +++++++-
|
||||
@ -22,27 +24,28 @@ Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
hw/milkymist-uart.c | 8 +++++++-
|
||||
hw/pl011.c | 9 +++++++--
|
||||
hw/pxa2xx.c | 13 +++++++++----
|
||||
hw/qdev-properties.c | 2 +-
|
||||
hw/serial.c | 9 +++++++--
|
||||
hw/sh_serial.c | 12 +++++++++---
|
||||
hw/spapr_vty.c | 8 ++++++--
|
||||
hw/strongarm.c | 12 +++++++-----
|
||||
hw/syborg_serial.c | 9 +++++++--
|
||||
hw/usb-serial.c | 9 +++++++--
|
||||
hw/virtio-console.c | 11 ++++++++---
|
||||
hw/usb/dev-serial.c | 9 +++++++--
|
||||
hw/usb/redirect.c | 9 +++++++--
|
||||
hw/virtio-console.c | 9 +++++++--
|
||||
hw/xen_console.c | 16 +++++++++++-----
|
||||
hw/xilinx_uartlite.c | 11 +++++++++--
|
||||
monitor.c | 18 ++++++++++++++----
|
||||
net/slirp.c | 8 ++++++--
|
||||
qemu-char.c | 32 ++++++++++++++++++++++----------
|
||||
qemu-char.h | 13 +++++++++----
|
||||
usb-redir.c | 9 +++++++--
|
||||
27 files changed, 233 insertions(+), 83 deletions(-)
|
||||
qtest.c | 9 ++++++++-
|
||||
30 files changed, 248 insertions(+), 86 deletions(-)
|
||||
|
||||
diff --git a/gdbstub.c b/gdbstub.c
|
||||
index 640cf4e..b984e12 100644
|
||||
index 6a77a66..9e099b0 100644
|
||||
--- a/gdbstub.c
|
||||
+++ b/gdbstub.c
|
||||
@@ -2860,6 +2860,12 @@ static void gdb_sigterm_handler(int signal)
|
||||
@@ -2874,6 +2874,12 @@ static void gdb_sigterm_handler(int signal)
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -55,7 +58,7 @@ index 640cf4e..b984e12 100644
|
||||
int gdbserver_start(const char *device)
|
||||
{
|
||||
GDBState *s;
|
||||
@@ -2889,8 +2895,7 @@ int gdbserver_start(const char *device)
|
||||
@@ -2903,8 +2909,7 @@ int gdbserver_start(const char *device)
|
||||
if (!chr)
|
||||
return -1;
|
||||
|
||||
@ -65,8 +68,35 @@ index 640cf4e..b984e12 100644
|
||||
}
|
||||
|
||||
s = gdbserver_state;
|
||||
diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c
|
||||
index d98e531..8f7d64a 100644
|
||||
--- a/hw/cadence_uart.c
|
||||
+++ b/hw/cadence_uart.c
|
||||
@@ -435,6 +435,12 @@ static void cadence_uart_reset(UartState *s)
|
||||
s->rx_wpos = 0;
|
||||
}
|
||||
|
||||
+static const QemuChrHandlers cadence_uart_handlers = {
|
||||
+ .fd_can_read = uart_can_receive,
|
||||
+ .fd_read = uart_receive,
|
||||
+ .fd_event = uart_event,
|
||||
+};
|
||||
+
|
||||
static int cadence_uart_init(SysBusDevice *dev)
|
||||
{
|
||||
UartState *s = FROM_SYSBUS(UartState, dev);
|
||||
@@ -456,8 +462,7 @@ static int cadence_uart_init(SysBusDevice *dev)
|
||||
cadence_uart_reset(s);
|
||||
|
||||
if (s->chr) {
|
||||
- qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
|
||||
- uart_event, s);
|
||||
+ qemu_chr_add_handlers(s->chr, &cadence_uart_handlers, s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
|
||||
index 9f51c6c..c5bff01 100644
|
||||
index bd6c777..fb32107 100644
|
||||
--- a/hw/ccid-card-passthru.c
|
||||
+++ b/hw/ccid-card-passthru.c
|
||||
@@ -274,6 +274,12 @@ static const uint8_t *passthru_get_atr(CCIDCardState *base, uint32_t *len)
|
||||
@ -95,7 +125,7 @@ index 9f51c6c..c5bff01 100644
|
||||
} else {
|
||||
error_report("missing chardev");
|
||||
diff --git a/hw/debugcon.c b/hw/debugcon.c
|
||||
index c9ee6d9..1d3c3ca 100644
|
||||
index 14ab326..7887fd2 100644
|
||||
--- a/hw/debugcon.c
|
||||
+++ b/hw/debugcon.c
|
||||
@@ -73,7 +73,7 @@ static void debugcon_init_core(DebugconState *s)
|
||||
@ -108,7 +138,7 @@ index c9ee6d9..1d3c3ca 100644
|
||||
|
||||
static int debugcon_isa_initfn(ISADevice *dev)
|
||||
diff --git a/hw/escc.c b/hw/escc.c
|
||||
index 13c7e66..997377e 100644
|
||||
index 4d8a8e8..689f275 100644
|
||||
--- a/hw/escc.c
|
||||
+++ b/hw/escc.c
|
||||
@@ -867,6 +867,12 @@ void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
|
||||
@ -135,7 +165,7 @@ index 13c7e66..997377e 100644
|
||||
}
|
||||
s->chn[0].otherchn = &s->chn[1];
|
||||
diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
|
||||
index 298b985..29d486e 100644
|
||||
index 5f16b17..f2571c2 100644
|
||||
--- a/hw/etraxfs_ser.c
|
||||
+++ b/hw/etraxfs_ser.c
|
||||
@@ -208,6 +208,12 @@ static void etraxfs_ser_reset(DeviceState *d)
|
||||
@ -152,9 +182,9 @@ index 298b985..29d486e 100644
|
||||
{
|
||||
struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
|
||||
@@ -217,10 +223,9 @@ static int etraxfs_ser_init(SysBusDevice *dev)
|
||||
sysbus_init_mmio_region(dev, &s->mmio);
|
||||
sysbus_init_mmio(dev, &s->mmio);
|
||||
|
||||
s->chr = qdev_init_chardev(&dev->qdev);
|
||||
s->chr = qemu_char_get_next_serial();
|
||||
- if (s->chr)
|
||||
- qemu_chr_add_handlers(s->chr,
|
||||
- serial_can_receive, serial_receive,
|
||||
@ -165,12 +195,39 @@ index 298b985..29d486e 100644
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/hw/exynos4210_uart.c b/hw/exynos4210_uart.c
|
||||
index ccc4780..fefe400 100644
|
||||
--- a/hw/exynos4210_uart.c
|
||||
+++ b/hw/exynos4210_uart.c
|
||||
@@ -625,6 +625,12 @@ DeviceState *exynos4210_uart_create(target_phys_addr_t addr,
|
||||
return dev;
|
||||
}
|
||||
|
||||
+static const QemuChrHandlers exynos4210_handlers = {
|
||||
+ .fd_can_read = exynos4210_uart_can_receive,
|
||||
+ .fd_read = exynos4210_uart_receive,
|
||||
+ .fd_event = exynos4210_uart_event,
|
||||
+};
|
||||
+
|
||||
static int exynos4210_uart_init(SysBusDevice *dev)
|
||||
{
|
||||
Exynos4210UartState *s = FROM_SYSBUS(Exynos4210UartState, dev);
|
||||
@@ -636,8 +642,7 @@ static int exynos4210_uart_init(SysBusDevice *dev)
|
||||
|
||||
sysbus_init_irq(dev, &s->irq);
|
||||
|
||||
- qemu_chr_add_handlers(s->chr, exynos4210_uart_can_receive,
|
||||
- exynos4210_uart_receive, exynos4210_uart_event, s);
|
||||
+ qemu_chr_add_handlers(s->chr, &exynos4210_handlers, s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
|
||||
index c90b810..ac6c33b 100644
|
||||
index 73fc989..fd77d52 100644
|
||||
--- a/hw/grlib_apbuart.c
|
||||
+++ b/hw/grlib_apbuart.c
|
||||
@@ -144,16 +144,18 @@ static CPUWriteMemoryFunc * const grlib_apbuart_write[] = {
|
||||
NULL, NULL, grlib_apbuart_writel,
|
||||
@@ -222,15 +222,17 @@ static const MemoryRegionOps grlib_apbuart_ops = {
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
+static const QemuChrHandlers grlib_handlers = {
|
||||
@ -182,7 +239,6 @@ index c90b810..ac6c33b 100644
|
||||
static int grlib_apbuart_init(SysBusDevice *dev)
|
||||
{
|
||||
UART *uart = FROM_SYSBUS(typeof(*uart), dev);
|
||||
int uart_regs = 0;
|
||||
|
||||
- qemu_chr_add_handlers(uart->chr,
|
||||
- grlib_apbuart_can_receive,
|
||||
@ -194,10 +250,10 @@ index c90b810..ac6c33b 100644
|
||||
sysbus_init_irq(dev, &uart->irq);
|
||||
|
||||
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
|
||||
index 7b4dbf6..ee78576 100644
|
||||
index d48e5f9..2dbf86e 100644
|
||||
--- a/hw/ivshmem.c
|
||||
+++ b/hw/ivshmem.c
|
||||
@@ -276,6 +276,18 @@ static void fake_irqfd(void *opaque, const uint8_t *buf, int size) {
|
||||
@@ -279,6 +279,18 @@ static void fake_irqfd(void *opaque, const uint8_t *buf, int size) {
|
||||
msix_notify(pdev, entry->vector);
|
||||
}
|
||||
|
||||
@ -216,7 +272,7 @@ index 7b4dbf6..ee78576 100644
|
||||
static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd,
|
||||
int vector)
|
||||
{
|
||||
@@ -295,11 +307,10 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd,
|
||||
@@ -298,11 +310,10 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, int eventfd,
|
||||
s->eventfd_table[vector].pdev = &s->dev;
|
||||
s->eventfd_table[vector].vector = vector;
|
||||
|
||||
@ -231,8 +287,8 @@ index 7b4dbf6..ee78576 100644
|
||||
}
|
||||
|
||||
return chr;
|
||||
@@ -614,6 +625,12 @@ static int ivshmem_load(QEMUFile* f, void *opaque, int version_id)
|
||||
return 0;
|
||||
@@ -635,6 +646,12 @@ static void ivshmem_write_config(PCIDevice *pci_dev, uint32_t address,
|
||||
msix_write_config(pci_dev, address, val, len);
|
||||
}
|
||||
|
||||
+static const QemuChrHandlers ivshmem_server_handlers = {
|
||||
@ -244,7 +300,7 @@ index 7b4dbf6..ee78576 100644
|
||||
static int pci_ivshmem_init(PCIDevice *dev)
|
||||
{
|
||||
IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev);
|
||||
@@ -703,8 +720,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
|
||||
@@ -724,8 +741,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
|
||||
|
||||
s->eventfd_chr = g_malloc0(s->vectors * sizeof(CharDriverState *));
|
||||
|
||||
@ -255,7 +311,7 @@ index 7b4dbf6..ee78576 100644
|
||||
/* just map the file immediately, we're not using a server */
|
||||
int fd;
|
||||
diff --git a/hw/lm32_juart.c b/hw/lm32_juart.c
|
||||
index 5454aa4..1b9fa07 100644
|
||||
index f07ed39..d4daeb8 100644
|
||||
--- a/hw/lm32_juart.c
|
||||
+++ b/hw/lm32_juart.c
|
||||
@@ -110,13 +110,19 @@ static void juart_reset(DeviceState *d)
|
||||
@ -272,18 +328,18 @@ index 5454aa4..1b9fa07 100644
|
||||
{
|
||||
LM32JuartState *s = FROM_SYSBUS(typeof(*s), dev);
|
||||
|
||||
s->chr = qdev_init_chardev(&dev->qdev);
|
||||
s->chr = qemu_char_get_next_serial();
|
||||
if (s->chr) {
|
||||
- qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s);
|
||||
+ qemu_chr_add_handlers(s->chr, juart_handlers, s);
|
||||
+ qemu_chr_add_handlers(s->chr, &juart_handlers, s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c
|
||||
index 3678545..ccaf88c 100644
|
||||
index 57066e2..4ea130b 100644
|
||||
--- a/hw/lm32_uart.c
|
||||
+++ b/hw/lm32_uart.c
|
||||
@@ -242,6 +242,12 @@ static void uart_reset(DeviceState *d)
|
||||
@@ -243,6 +243,12 @@ static void uart_reset(DeviceState *d)
|
||||
s->regs[R_LSR] = LSR_THRE | LSR_TEMT;
|
||||
}
|
||||
|
||||
@ -296,20 +352,20 @@ index 3678545..ccaf88c 100644
|
||||
static int lm32_uart_init(SysBusDevice *dev)
|
||||
{
|
||||
LM32UartState *s = FROM_SYSBUS(typeof(*s), dev);
|
||||
@@ -255,7 +261,7 @@ static int lm32_uart_init(SysBusDevice *dev)
|
||||
@@ -254,7 +260,7 @@ static int lm32_uart_init(SysBusDevice *dev)
|
||||
|
||||
s->chr = qdev_init_chardev(&dev->qdev);
|
||||
s->chr = qemu_char_get_next_serial();
|
||||
if (s->chr) {
|
||||
- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
|
||||
+ qemu_chr_add_handlers(s->chr, uart_handlers, s);
|
||||
+ qemu_chr_add_handlers(s->chr, &uart_handlers, s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
|
||||
index e6b2ab0..2870683 100644
|
||||
index ec6a87f..f52fb96 100644
|
||||
--- a/hw/mcf_uart.c
|
||||
+++ b/hw/mcf_uart.c
|
||||
@@ -268,6 +268,12 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
|
||||
@@ -272,6 +272,12 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
|
||||
mcf_uart_push_byte(s, buf[0]);
|
||||
}
|
||||
|
||||
@ -322,7 +378,7 @@ index e6b2ab0..2870683 100644
|
||||
void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
|
||||
{
|
||||
mcf_uart_state *s;
|
||||
@@ -276,8 +282,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
|
||||
@@ -280,8 +286,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
|
||||
s->chr = chr;
|
||||
s->irq = irq;
|
||||
if (chr) {
|
||||
@ -333,7 +389,7 @@ index e6b2ab0..2870683 100644
|
||||
mcf_uart_reset(s);
|
||||
return s;
|
||||
diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c
|
||||
index 5404ca9..fd10e12 100644
|
||||
index 291fe3c..2dcb41c 100644
|
||||
--- a/hw/milkymist-uart.c
|
||||
+++ b/hw/milkymist-uart.c
|
||||
@@ -189,6 +189,12 @@ static void milkymist_uart_reset(DeviceState *d)
|
||||
@ -351,18 +407,18 @@ index 5404ca9..fd10e12 100644
|
||||
MilkymistUartState *s = FROM_SYSBUS(typeof(*s), dev);
|
||||
@@ -201,7 +207,7 @@ static int milkymist_uart_init(SysBusDevice *dev)
|
||||
|
||||
s->chr = qdev_init_chardev(&dev->qdev);
|
||||
s->chr = qemu_char_get_next_serial();
|
||||
if (s->chr) {
|
||||
- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
|
||||
+ qemu_chr_add_handlers(s->chr, uart_handlers, s);
|
||||
+ qemu_chr_add_handlers(s->chr, &uart_handlers, s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/hw/pl011.c b/hw/pl011.c
|
||||
index 707a161..7482246 100644
|
||||
index 8a5a8f5..b125c40 100644
|
||||
--- a/hw/pl011.c
|
||||
+++ b/hw/pl011.c
|
||||
@@ -260,6 +260,12 @@ static const VMStateDescription vmstate_pl011 = {
|
||||
@@ -256,6 +256,12 @@ static const VMStateDescription vmstate_pl011 = {
|
||||
}
|
||||
};
|
||||
|
||||
@ -374,8 +430,8 @@ index 707a161..7482246 100644
|
||||
+
|
||||
static int pl011_init(SysBusDevice *dev, const unsigned char *id)
|
||||
{
|
||||
int iomemtype;
|
||||
@@ -278,8 +284,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
|
||||
pl011_state *s = FROM_SYSBUS(pl011_state, dev);
|
||||
@@ -271,8 +277,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
|
||||
s->cr = 0x300;
|
||||
s->flags = 0x90;
|
||||
if (s->chr) {
|
||||
@ -386,10 +442,10 @@ index 707a161..7482246 100644
|
||||
vmstate_register(&dev->qdev, -1, &vmstate_pl011, s);
|
||||
return 0;
|
||||
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
|
||||
index e9a507e..24925b6 100644
|
||||
index ddaa846..81827a4 100644
|
||||
--- a/hw/pxa2xx.c
|
||||
+++ b/hw/pxa2xx.c
|
||||
@@ -1984,6 +1984,12 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
|
||||
@@ -2011,6 +2011,12 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -402,7 +458,7 @@ index e9a507e..24925b6 100644
|
||||
static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
|
||||
target_phys_addr_t base,
|
||||
qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma,
|
||||
@@ -2002,10 +2008,9 @@ static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
|
||||
@@ -2029,10 +2035,9 @@ static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
|
||||
memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000);
|
||||
memory_region_add_subregion(sysmem, base, &s->iomem);
|
||||
|
||||
@ -416,11 +472,24 @@ index e9a507e..24925b6 100644
|
||||
register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
|
||||
pxa2xx_fir_load, s);
|
||||
|
||||
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
|
||||
index b7b5597..e3c1b40 100644
|
||||
--- a/hw/qdev-properties.c
|
||||
+++ b/hw/qdev-properties.c
|
||||
@@ -551,7 +551,7 @@ static void release_chr(Object *obj, const char *name, void *opaque)
|
||||
CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
|
||||
if (*ptr) {
|
||||
- qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
|
||||
+ qemu_chr_add_handlers(*ptr, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/hw/serial.c b/hw/serial.c
|
||||
index d35c7a9..6499d4a 100644
|
||||
index a421d1e..056d823 100644
|
||||
--- a/hw/serial.c
|
||||
+++ b/hw/serial.c
|
||||
@@ -728,6 +728,12 @@ static void serial_reset(void *opaque)
|
||||
@@ -736,6 +736,12 @@ static void serial_reset(void *opaque)
|
||||
qemu_irq_lower(s->irq);
|
||||
}
|
||||
|
||||
@ -433,7 +502,7 @@ index d35c7a9..6499d4a 100644
|
||||
static void serial_init_core(SerialState *s)
|
||||
{
|
||||
if (!s->chr) {
|
||||
@@ -742,8 +748,7 @@ static void serial_init_core(SerialState *s)
|
||||
@@ -750,8 +756,7 @@ static void serial_init_core(SerialState *s)
|
||||
|
||||
qemu_register_reset(serial_reset, s);
|
||||
|
||||
@ -444,11 +513,11 @@ index d35c7a9..6499d4a 100644
|
||||
|
||||
/* Change the main reference oscillator frequency. */
|
||||
diff --git a/hw/sh_serial.c b/hw/sh_serial.c
|
||||
index a20c59e..470ce7a 100644
|
||||
index 43b0eb1..c322784 100644
|
||||
--- a/hw/sh_serial.c
|
||||
+++ b/hw/sh_serial.c
|
||||
@@ -350,6 +350,12 @@ static CPUWriteMemoryFunc * const sh_serial_writefn[] = {
|
||||
&sh_serial_write,
|
||||
@@ -350,6 +350,12 @@ static const MemoryRegionOps sh_serial_ops = {
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
+static const QemuChrHandlers sh_serial_handlers = {
|
||||
@ -457,10 +526,10 @@ index a20c59e..470ce7a 100644
|
||||
+ .fd_event = sh_serial_event,
|
||||
+};
|
||||
+
|
||||
void sh_serial_init (target_phys_addr_t base, int feat,
|
||||
void sh_serial_init(MemoryRegion *sysmem,
|
||||
target_phys_addr_t base, int feat,
|
||||
uint32_t freq, CharDriverState *chr,
|
||||
qemu_irq eri_source,
|
||||
@@ -389,9 +395,9 @@ void sh_serial_init (target_phys_addr_t base, int feat,
|
||||
@@ -394,9 +400,9 @@ void sh_serial_init(MemoryRegion *sysmem,
|
||||
|
||||
s->chr = chr;
|
||||
|
||||
@ -474,7 +543,7 @@ index a20c59e..470ce7a 100644
|
||||
s->eri = eri_source;
|
||||
s->rxi = rxi_source;
|
||||
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
|
||||
index f23cc36..0d9cd59 100644
|
||||
index c9674f3..15f61c3 100644
|
||||
--- a/hw/spapr_vty.c
|
||||
+++ b/hw/spapr_vty.c
|
||||
@@ -54,6 +54,11 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
|
||||
@ -495,15 +564,15 @@ index f23cc36..0d9cd59 100644
|
||||
|
||||
- qemu_chr_add_handlers(dev->chardev, vty_can_receive,
|
||||
- vty_receive, NULL, dev);
|
||||
+ qemu_chr_add_handlers(dev->chardev, vty_handlers, dev);
|
||||
+ qemu_chr_add_handlers(dev->chardev, &vty_handlers, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/hw/strongarm.c b/hw/strongarm.c
|
||||
index a3d9080..8a8a219 100644
|
||||
index 1b15f39..2ae2f7e 100644
|
||||
--- a/hw/strongarm.c
|
||||
+++ b/hw/strongarm.c
|
||||
@@ -1160,6 +1160,12 @@ static const MemoryRegionOps strongarm_uart_ops = {
|
||||
@@ -1199,6 +1199,12 @@ static const MemoryRegionOps strongarm_uart_ops = {
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
@ -516,7 +585,7 @@ index a3d9080..8a8a219 100644
|
||||
static int strongarm_uart_init(SysBusDevice *dev)
|
||||
{
|
||||
StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev);
|
||||
@@ -1172,11 +1178,7 @@ static int strongarm_uart_init(SysBusDevice *dev)
|
||||
@@ -1211,11 +1217,7 @@ static int strongarm_uart_init(SysBusDevice *dev)
|
||||
s->tx_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_tx, s);
|
||||
|
||||
if (s->chr) {
|
||||
@ -529,38 +598,11 @@ index a3d9080..8a8a219 100644
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
|
||||
index c83f82c..fff76da 100644
|
||||
--- a/hw/syborg_serial.c
|
||||
+++ b/hw/syborg_serial.c
|
||||
@@ -292,6 +292,12 @@ static const VMStateDescription vmstate_syborg_serial = {
|
||||
}
|
||||
};
|
||||
|
||||
+static const QemuChrHandlers syborg_serial_handlers = {
|
||||
+ .fd_can_read = syborg_serial_can_receive,
|
||||
+ .fd_read = syborg_serial_receive,
|
||||
+ .fd_event = syborg_serial_event,
|
||||
+};
|
||||
+
|
||||
static int syborg_serial_init(SysBusDevice *dev)
|
||||
{
|
||||
SyborgSerialState *s = FROM_SYSBUS(SyborgSerialState, dev);
|
||||
@@ -304,8 +310,7 @@ static int syborg_serial_init(SysBusDevice *dev)
|
||||
sysbus_init_mmio(dev, 0x1000, iomemtype);
|
||||
s->chr = qdev_init_chardev(&dev->qdev);
|
||||
if (s->chr) {
|
||||
- qemu_chr_add_handlers(s->chr, syborg_serial_can_receive,
|
||||
- syborg_serial_receive, syborg_serial_event, s);
|
||||
+ qemu_chr_add_handlers(s->chr, &syborg_serial_handlers, s);
|
||||
}
|
||||
if (s->fifo_size <= 0) {
|
||||
fprintf(stderr, "syborg_serial: fifo too small\n");
|
||||
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
|
||||
index 7dbf6df..bcf6622 100644
|
||||
--- a/hw/usb-serial.c
|
||||
+++ b/hw/usb-serial.c
|
||||
@@ -482,6 +482,12 @@ static void usb_serial_event(void *opaque, int event)
|
||||
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
|
||||
index 56743ee..af670cc 100644
|
||||
--- a/hw/usb/dev-serial.c
|
||||
+++ b/hw/usb/dev-serial.c
|
||||
@@ -475,6 +475,12 @@ static void usb_serial_event(void *opaque, int event)
|
||||
}
|
||||
}
|
||||
|
||||
@ -573,7 +615,7 @@ index 7dbf6df..bcf6622 100644
|
||||
static int usb_serial_initfn(USBDevice *dev)
|
||||
{
|
||||
USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
|
||||
@@ -493,8 +499,7 @@ static int usb_serial_initfn(USBDevice *dev)
|
||||
@@ -487,8 +493,7 @@ static int usb_serial_initfn(USBDevice *dev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -583,11 +625,38 @@ index 7dbf6df..bcf6622 100644
|
||||
usb_serial_handle_reset(dev);
|
||||
return 0;
|
||||
}
|
||||
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
|
||||
index 51c27b4..6e8180e 100644
|
||||
--- a/hw/usb/redirect.c
|
||||
+++ b/hw/usb/redirect.c
|
||||
@@ -890,6 +890,12 @@ static void usbredir_chardev_event(void *opaque, int event)
|
||||
}
|
||||
}
|
||||
|
||||
+static const QemuChrHandlers usbredir_chr_handlers = {
|
||||
+ .fd_can_read = usbredir_chardev_can_read,
|
||||
+ .fd_read = usbredir_chardev_read,
|
||||
+ .fd_event = usbredir_chardev_event,
|
||||
+};
|
||||
+
|
||||
/*
|
||||
* init + destroy
|
||||
*/
|
||||
@@ -928,8 +934,7 @@ static int usbredir_initfn(USBDevice *udev)
|
||||
|
||||
/* Let the backend know we are ready */
|
||||
qemu_chr_fe_open(dev->cs);
|
||||
- qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
|
||||
- usbredir_chardev_read, usbredir_chardev_event, dev);
|
||||
+ qemu_chr_add_handlers(dev->cs, &usbredir_chr_handlers, dev);
|
||||
|
||||
add_boot_device_path(dev->bootindex, &udev->qdev, NULL);
|
||||
return 0;
|
||||
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
|
||||
index d3351c8..6d6f3ef 100644
|
||||
index cffee3d..066590c 100644
|
||||
--- a/hw/virtio-console.c
|
||||
+++ b/hw/virtio-console.c
|
||||
@@ -95,6 +95,12 @@ static void chr_event(void *opaque, int event)
|
||||
@@ -106,6 +106,12 @@ static void chr_event(void *opaque, int event)
|
||||
}
|
||||
}
|
||||
|
||||
@ -600,27 +669,18 @@ index d3351c8..6d6f3ef 100644
|
||||
static int virtconsole_initfn(VirtIOSerialPort *port)
|
||||
{
|
||||
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
||||
@@ -107,8 +113,7 @@ static int virtconsole_initfn(VirtIOSerialPort *port)
|
||||
@@ -117,8 +123,7 @@ static int virtconsole_initfn(VirtIOSerialPort *port)
|
||||
}
|
||||
|
||||
if (vcon->chr) {
|
||||
- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
|
||||
- vcon);
|
||||
+ qemu_chr_add_handlers(vcon->chr, &chr_handlers, vcon);
|
||||
info->have_data = flush_buf;
|
||||
info->guest_open = guest_open;
|
||||
info->guest_close = guest_close;
|
||||
@@ -126,7 +131,7 @@ static int virtconsole_exitfn(VirtIOSerialPort *port)
|
||||
* Instead of closing the chardev, free it so it can be used
|
||||
* for other purposes.
|
||||
*/
|
||||
- qemu_chr_add_handlers(vcon->chr, NULL, NULL, NULL, NULL);
|
||||
+ qemu_chr_add_handlers(vcon->chr, NULL, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/hw/xen_console.c b/hw/xen_console.c
|
||||
index edcb31c..2ba74f0 100644
|
||||
index 3794b19..ee872c3 100644
|
||||
--- a/hw/xen_console.c
|
||||
+++ b/hw/xen_console.c
|
||||
@@ -212,6 +212,11 @@ out:
|
||||
@ -648,10 +708,10 @@ index edcb31c..2ba74f0 100644
|
||||
|
||||
xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
|
||||
con->ring_ref,
|
||||
@@ -248,8 +253,9 @@ static void con_disconnect(struct XenDevice *xendev)
|
||||
{
|
||||
struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
|
||||
|
||||
@@ -251,8 +256,9 @@ static void con_disconnect(struct XenDevice *xendev)
|
||||
if (!xendev->dev) {
|
||||
return;
|
||||
}
|
||||
- if (con->chr)
|
||||
- qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
|
||||
+ if (con->chr) {
|
||||
@ -661,7 +721,7 @@ index edcb31c..2ba74f0 100644
|
||||
|
||||
if (con->sring) {
|
||||
diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
|
||||
index ceb7b4d..69f7191 100644
|
||||
index aa0170d..6ca45dc 100644
|
||||
--- a/hw/xilinx_uartlite.c
|
||||
+++ b/hw/xilinx_uartlite.c
|
||||
@@ -195,6 +195,12 @@ static void uart_event(void *opaque, int event)
|
||||
@ -678,9 +738,9 @@ index ceb7b4d..69f7191 100644
|
||||
{
|
||||
struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev);
|
||||
@@ -206,8 +212,9 @@ static int xilinx_uartlite_init(SysBusDevice *dev)
|
||||
sysbus_init_mmio_region(dev, &s->mmio);
|
||||
sysbus_init_mmio(dev, &s->mmio);
|
||||
|
||||
s->chr = qdev_init_chardev(&dev->qdev);
|
||||
s->chr = qemu_char_get_next_serial();
|
||||
- if (s->chr)
|
||||
- qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
|
||||
+ if (s->chr) {
|
||||
@ -690,10 +750,10 @@ index ceb7b4d..69f7191 100644
|
||||
}
|
||||
|
||||
diff --git a/monitor.c b/monitor.c
|
||||
index f956eb7..a82fda3 100644
|
||||
index 71f4392..116accb 100644
|
||||
--- a/monitor.c
|
||||
+++ b/monitor.c
|
||||
@@ -4882,6 +4882,18 @@ static void sortcmdlist(void)
|
||||
@@ -4601,6 +4601,18 @@ static void sortcmdlist(void)
|
||||
* End:
|
||||
*/
|
||||
|
||||
@ -712,7 +772,7 @@ index f956eb7..a82fda3 100644
|
||||
void monitor_init(CharDriverState *chr, int flags)
|
||||
{
|
||||
static int is_first_init = 1;
|
||||
@@ -4904,12 +4916,10 @@ void monitor_init(CharDriverState *chr, int flags)
|
||||
@@ -4623,12 +4635,10 @@ void monitor_init(CharDriverState *chr, int flags)
|
||||
if (monitor_ctrl_mode(mon)) {
|
||||
mon->mc = g_malloc0(sizeof(MonitorControl));
|
||||
/* Control mode requires special handlers */
|
||||
@ -728,10 +788,10 @@ index f956eb7..a82fda3 100644
|
||||
|
||||
QLIST_INSERT_HEAD(&mon_list, mon, entry);
|
||||
diff --git a/net/slirp.c b/net/slirp.c
|
||||
index 6646ecb..05405ff 100644
|
||||
index 96f5032..aa8ed08 100644
|
||||
--- a/net/slirp.c
|
||||
+++ b/net/slirp.c
|
||||
@@ -576,6 +576,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
|
||||
@@ -577,6 +577,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
|
||||
slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
|
||||
}
|
||||
|
||||
@ -743,7 +803,7 @@ index 6646ecb..05405ff 100644
|
||||
static int slirp_guestfwd(SlirpState *s, const char *config_str,
|
||||
int legacy_format)
|
||||
{
|
||||
@@ -632,8 +637,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
|
||||
@@ -633,8 +638,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
|
||||
fwd->port = port;
|
||||
fwd->slirp = s->slirp;
|
||||
|
||||
@ -754,10 +814,10 @@ index 6646ecb..05405ff 100644
|
||||
|
||||
fail_syntax:
|
||||
diff --git a/qemu-char.c b/qemu-char.c
|
||||
index a5ca611..d2a99a6 100644
|
||||
index 78d2a69..86bdabf 100644
|
||||
--- a/qemu-char.c
|
||||
+++ b/qemu-char.c
|
||||
@@ -189,19 +189,26 @@ void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...)
|
||||
@@ -192,19 +192,26 @@ void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...)
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
@ -792,7 +852,7 @@ index a5ca611..d2a99a6 100644
|
||||
s->handler_opaque = opaque;
|
||||
if (s->chr_update_read_handler)
|
||||
s->chr_update_read_handler(s);
|
||||
@@ -441,6 +448,12 @@ static void mux_chr_event(void *opaque, int event)
|
||||
@@ -442,6 +449,12 @@ static void mux_chr_event(void *opaque, int event)
|
||||
mux_chr_send_event(d, i, event);
|
||||
}
|
||||
|
||||
@ -805,7 +865,7 @@ index a5ca611..d2a99a6 100644
|
||||
static void mux_chr_update_read_handler(CharDriverState *chr)
|
||||
{
|
||||
MuxDriver *d = chr->opaque;
|
||||
@@ -455,8 +468,7 @@ static void mux_chr_update_read_handler(CharDriverState *chr)
|
||||
@@ -456,8 +469,7 @@ static void mux_chr_update_read_handler(CharDriverState *chr)
|
||||
d->chr_event[d->mux_cnt] = chr->chr_event;
|
||||
/* Fix up the real driver with mux routines */
|
||||
if (d->mux_cnt == 0) {
|
||||
@ -816,7 +876,7 @@ index a5ca611..d2a99a6 100644
|
||||
if (d->focus != -1) {
|
||||
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
|
||||
diff --git a/qemu-char.h b/qemu-char.h
|
||||
index 8ca1e2d..564e688 100644
|
||||
index 486644b..dfa8c2d 100644
|
||||
--- a/qemu-char.h
|
||||
+++ b/qemu-char.h
|
||||
@@ -222,10 +222,15 @@ void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len);
|
||||
@ -839,33 +899,33 @@ index 8ca1e2d..564e688 100644
|
||||
void *opaque);
|
||||
|
||||
void qemu_chr_generic_open(CharDriverState *s);
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index 86bccf8..e421cff 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -865,6 +865,12 @@ static void usbredir_chardev_event(void *opaque, int event)
|
||||
diff --git a/qtest.c b/qtest.c
|
||||
index fbfab4e..4ab5b69 100644
|
||||
--- a/qtest.c
|
||||
+++ b/qtest.c
|
||||
@@ -416,6 +416,13 @@ static void qtest_event(void *opaque, int event)
|
||||
}
|
||||
}
|
||||
|
||||
+static const QemuChrHandlers usbredir_chr_handlers = {
|
||||
+ .fd_can_read = usbredir_chardev_can_read,
|
||||
+ .fd_read = usbredir_chardev_read,
|
||||
+ .fd_event = usbredir_chardev_event,
|
||||
+static const QemuChrHandlers test_handlers = {
|
||||
+ .fd_can_read = qtest_can_read,
|
||||
+ .fd_read = qtest_read,
|
||||
+ .fd_event = qtest_event,
|
||||
+};
|
||||
+
|
||||
/*
|
||||
* init + destroy
|
||||
*/
|
||||
@@ -892,8 +898,7 @@ static int usbredir_initfn(USBDevice *udev)
|
||||
+
|
||||
int qtest_init(void)
|
||||
{
|
||||
CharDriverState *chr;
|
||||
@@ -425,7 +432,7 @@ int qtest_init(void)
|
||||
configure_icount("0");
|
||||
chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
|
||||
|
||||
/* Let the backend know we are ready */
|
||||
qemu_chr_fe_open(dev->cs);
|
||||
- qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
|
||||
- usbredir_chardev_read, usbredir_chardev_event, dev);
|
||||
+ qemu_chr_add_handlers(dev->cs, &usbredir_chr_handlers, dev);
|
||||
- qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
|
||||
+ qemu_chr_add_handlers(chr, &test_handlers, chr);
|
||||
qemu_chr_fe_set_echo(chr, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
inbuf = g_string_new("");
|
||||
--
|
||||
1.7.7.5
|
||||
1.7.10.4
|
||||
|
@ -1,102 +0,0 @@
|
||||
From cc5740ae8aa68dbbdc690f694b0e55d70f9c49ee Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Mon, 19 Dec 2011 13:42:40 +0100
|
||||
Subject: [PATCH 102/118] usb-redir: Dynamically adjust iso buffering size
|
||||
based on ep interval
|
||||
|
||||
Note the bufpq_target_size id stored in the endpoint info struct,
|
||||
even though it only used once. This is done because it will be
|
||||
referenced from other code in a follow up patch.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
usb-redir.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++-----
|
||||
1 files changed, 47 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index 7678f1a..ab2c8fa 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -61,6 +61,7 @@ struct endp_data {
|
||||
uint8_t interrupt_started;
|
||||
uint8_t interrupt_error;
|
||||
QTAILQ_HEAD(, buf_packet) bufpq;
|
||||
+ int bufpq_target_size;
|
||||
};
|
||||
|
||||
struct USBRedirDevice {
|
||||
@@ -332,15 +333,41 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
|
||||
uint8_t ep)
|
||||
{
|
||||
int status, len;
|
||||
-
|
||||
if (!dev->endpoint[EP2I(ep)].iso_started &&
|
||||
!dev->endpoint[EP2I(ep)].iso_error) {
|
||||
struct usb_redir_start_iso_stream_header start_iso = {
|
||||
.endpoint = ep,
|
||||
- /* TODO maybe do something with these depending on ep interval? */
|
||||
- .pkts_per_urb = 32,
|
||||
- .no_urbs = 3,
|
||||
};
|
||||
+ int pkts_per_sec;
|
||||
+
|
||||
+ if (dev->dev.speed == USB_SPEED_HIGH)
|
||||
+ pkts_per_sec = 8000 / dev->endpoint[EP2I(ep)].interval;
|
||||
+ else
|
||||
+ pkts_per_sec = 1000 / dev->endpoint[EP2I(ep)].interval;
|
||||
+ /* Testing has shown that we need circa 60 ms buffer */
|
||||
+ dev->endpoint[EP2I(ep)].bufpq_target_size = (pkts_per_sec * 60) / 1000;
|
||||
+
|
||||
+ /* Aim for approx 100 interrupts / second on the client to
|
||||
+ balance latency and interrupt load */
|
||||
+ start_iso.pkts_per_urb = pkts_per_sec / 100;
|
||||
+ if (start_iso.pkts_per_urb < 1) {
|
||||
+ start_iso.pkts_per_urb = 1;
|
||||
+ } else if (start_iso.pkts_per_urb > 32) {
|
||||
+ start_iso.pkts_per_urb = 32;
|
||||
+ }
|
||||
+
|
||||
+ start_iso.no_urbs = (dev->endpoint[EP2I(ep)].bufpq_target_size +
|
||||
+ start_iso.pkts_per_urb - 1) /
|
||||
+ start_iso.pkts_per_urb;
|
||||
+ /* Output endpoints pre-fill only 1/2 of the packets, keeping the rest
|
||||
+ as overflow buffer. Also see the usbredir protocol documentation */
|
||||
+ if (!(ep & USB_DIR_IN)) {
|
||||
+ start_iso.no_urbs *= 2;
|
||||
+ }
|
||||
+ if (start_iso.no_urbs > 16) {
|
||||
+ start_iso.no_urbs = 16;
|
||||
+ }
|
||||
+
|
||||
/* No id, we look at the ep when receiving a status back */
|
||||
usbredirparser_send_start_iso_stream(dev->parser, 0, &start_iso);
|
||||
usbredirparser_do_write(dev->parser);
|
||||
@@ -961,9 +988,24 @@ static void usbredir_ep_info(void *priv,
|
||||
dev->endpoint[i].type = ep_info->type[i];
|
||||
dev->endpoint[i].interval = ep_info->interval[i];
|
||||
dev->endpoint[i].interface = ep_info->interface[i];
|
||||
- if (dev->endpoint[i].type != usb_redir_type_invalid) {
|
||||
+ switch (dev->endpoint[i].type) {
|
||||
+ case usb_redir_type_invalid:
|
||||
+ break;
|
||||
+ case usb_redir_type_iso:
|
||||
+ case usb_redir_type_interrupt:
|
||||
+ if (dev->endpoint[i].interval == 0) {
|
||||
+ ERROR("Received 0 interval for isoc or irq endpoint\n");
|
||||
+ usbredir_device_disconnect(dev);
|
||||
+ }
|
||||
+ /* Fall through */
|
||||
+ case usb_redir_type_control:
|
||||
+ case usb_redir_type_bulk:
|
||||
DPRINTF("ep: %02X type: %d interface: %d\n", I2EP(i),
|
||||
dev->endpoint[i].type, dev->endpoint[i].interface);
|
||||
+ break;
|
||||
+ default:
|
||||
+ ERROR("Received invalid endpoint type\n");
|
||||
+ usbredir_device_disconnect(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,7 +1,7 @@
|
||||
From f896c023201863927853c5d97e62916e0753fede Mon Sep 17 00:00:00 2001
|
||||
From 32876859aeee3722398d98abfb6b6307e701091f Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Mon, 21 Mar 2011 20:32:58 +0100
|
||||
Subject: [PATCH 108/118] iohandlers: Add enable/disable_write_fd_handler()
|
||||
Subject: [PATCH 103/114] iohandlers: Add enable/disable_write_fd_handler()
|
||||
functions
|
||||
|
||||
These will be used to provide a cleaner API for the nonblocking case.
|
||||
@ -10,10 +10,10 @@ Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
---
|
||||
iohandler.c | 35 +++++++++++++++++++++++++++++++++++
|
||||
main-loop.h | 3 +++
|
||||
2 files changed, 38 insertions(+), 0 deletions(-)
|
||||
2 files changed, 38 insertions(+)
|
||||
|
||||
diff --git a/iohandler.c b/iohandler.c
|
||||
index 5640d49..a9a62cb 100644
|
||||
index 3c74de6..250fd0e 100644
|
||||
--- a/iohandler.c
|
||||
+++ b/iohandler.c
|
||||
@@ -45,6 +45,41 @@ typedef struct IOHandlerRecord {
|
||||
@ -59,10 +59,10 @@ index 5640d49..a9a62cb 100644
|
||||
/* XXX: fd_read_poll should be suppressed, but an API change is
|
||||
necessary in the character devices to suppress fd_can_read(). */
|
||||
diff --git a/main-loop.h b/main-loop.h
|
||||
index 8a716b1..c5a96cd 100644
|
||||
index dce1cd9..eb31273 100644
|
||||
--- a/main-loop.h
|
||||
+++ b/main-loop.h
|
||||
@@ -167,6 +167,9 @@ typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
|
||||
@@ -175,6 +175,9 @@ typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
|
||||
typedef int IOCanReadHandler(void *opaque);
|
||||
typedef void IOHandler(void *opaque);
|
||||
|
||||
@ -73,5 +73,5 @@ index 8a716b1..c5a96cd 100644
|
||||
* qemu_set_fd_handler2: Register a file descriptor with the main loop
|
||||
*
|
||||
--
|
||||
1.7.7.5
|
||||
1.7.10.4
|
||||
|
@ -1,74 +0,0 @@
|
||||
From 577aff1f1df0a41fd5e21f5ff2b470c36565211b Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Mon, 19 Dec 2011 14:55:15 +0100
|
||||
Subject: [PATCH 103/118] usb-redir: Pre-fill our isoc input buffer before
|
||||
sending pkts to the host
|
||||
|
||||
This is something which should have been done from the first version of
|
||||
usb-redir, but wasn't.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
usb-redir.c | 16 ++++++++++++++++
|
||||
1 files changed, 16 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index ab2c8fa..17ea7a7 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -60,7 +60,9 @@ struct endp_data {
|
||||
uint8_t iso_error; /* For reporting iso errors to the HC */
|
||||
uint8_t interrupt_started;
|
||||
uint8_t interrupt_error;
|
||||
+ uint8_t bufpq_prefilled;
|
||||
QTAILQ_HEAD(, buf_packet) bufpq;
|
||||
+ int bufpq_size;
|
||||
int bufpq_target_size;
|
||||
};
|
||||
|
||||
@@ -296,6 +298,7 @@ static struct buf_packet *bufp_alloc(USBRedirDevice *dev,
|
||||
bufp->len = len;
|
||||
bufp->status = status;
|
||||
QTAILQ_INSERT_TAIL(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
|
||||
+ dev->endpoint[EP2I(ep)].bufpq_size++;
|
||||
return bufp;
|
||||
}
|
||||
|
||||
@@ -303,6 +306,7 @@ static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp,
|
||||
uint8_t ep)
|
||||
{
|
||||
QTAILQ_REMOVE(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
|
||||
+ dev->endpoint[EP2I(ep)].bufpq_size--;
|
||||
free(bufp->data);
|
||||
g_free(bufp);
|
||||
}
|
||||
@@ -373,14 +377,26 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
|
||||
usbredirparser_do_write(dev->parser);
|
||||
DPRINTF("iso stream started ep %02X\n", ep);
|
||||
dev->endpoint[EP2I(ep)].iso_started = 1;
|
||||
+ dev->endpoint[EP2I(ep)].bufpq_prefilled = 0;
|
||||
}
|
||||
|
||||
if (ep & USB_DIR_IN) {
|
||||
struct buf_packet *isop;
|
||||
|
||||
+ if (dev->endpoint[EP2I(ep)].iso_started &&
|
||||
+ !dev->endpoint[EP2I(ep)].bufpq_prefilled) {
|
||||
+ if (dev->endpoint[EP2I(ep)].bufpq_size <
|
||||
+ dev->endpoint[EP2I(ep)].bufpq_target_size) {
|
||||
+ return usbredir_handle_status(dev, 0, 0);
|
||||
+ }
|
||||
+ dev->endpoint[EP2I(ep)].bufpq_prefilled = 1;
|
||||
+ }
|
||||
+
|
||||
isop = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
|
||||
if (isop == NULL) {
|
||||
DPRINTF2("iso-token-in ep %02X, no isop\n", ep);
|
||||
+ /* Re-fill the buffer */
|
||||
+ dev->endpoint[EP2I(ep)].bufpq_prefilled = 0;
|
||||
/* Check iso_error for stream errors, otherwise its an underrun */
|
||||
status = dev->endpoint[EP2I(ep)].iso_error;
|
||||
dev->endpoint[EP2I(ep)].iso_error = 0;
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 6d5337e1dc8d926f9183e2f5eb5e97c438203527 Mon Sep 17 00:00:00 2001
|
||||
From 3def2c629b31cfc6dfe54a1a5464bb35359c3b10 Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Mon, 21 Mar 2011 21:41:42 +0100
|
||||
Subject: [PATCH 109/118] char: Add framework for a 'write unblocked' callback
|
||||
Subject: [PATCH 104/114] char: Add framework for a 'write unblocked' callback
|
||||
|
||||
The char layer can let users know that the driver will block on further
|
||||
input. For users interested in not blocking, they can assign a function
|
||||
@ -13,13 +13,13 @@ Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
---
|
||||
qemu-char.c | 3 +++
|
||||
qemu-char.h | 4 ++++
|
||||
2 files changed, 7 insertions(+), 0 deletions(-)
|
||||
2 files changed, 7 insertions(+)
|
||||
|
||||
diff --git a/qemu-char.c b/qemu-char.c
|
||||
index d2a99a6..66b5887 100644
|
||||
index 86bdabf..88cbbd0 100644
|
||||
--- a/qemu-char.c
|
||||
+++ b/qemu-char.c
|
||||
@@ -208,11 +208,14 @@ void qemu_chr_add_handlers(CharDriverState *s,
|
||||
@@ -211,11 +211,14 @@ void qemu_chr_add_handlers(CharDriverState *s,
|
||||
}
|
||||
s->chr_can_read = handlers->fd_can_read;
|
||||
s->chr_read = handlers->fd_read;
|
||||
@ -35,7 +35,7 @@ index d2a99a6..66b5887 100644
|
||||
also get the open event */
|
||||
if (s->opened) {
|
||||
diff --git a/qemu-char.h b/qemu-char.h
|
||||
index 564e688..2628bee 100644
|
||||
index dfa8c2d..b5e23a4 100644
|
||||
--- a/qemu-char.h
|
||||
+++ b/qemu-char.h
|
||||
@@ -62,6 +62,9 @@ struct CharDriverState {
|
||||
@ -57,5 +57,5 @@ index 564e688..2628bee 100644
|
||||
};
|
||||
|
||||
--
|
||||
1.7.7.5
|
||||
1.7.10.4
|
||||
|
@ -1,87 +0,0 @@
|
||||
From b8e632d175063770655e75507de85ae873fa6c2d Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Tue, 20 Dec 2011 16:54:25 +0100
|
||||
Subject: [PATCH 104/118] usb-redir: Try to keep our buffer size near the
|
||||
target size
|
||||
|
||||
Before this patch we would allow the (iso) buffer to grow unlimited
|
||||
(and it would under certain circumstances) leading to way too high
|
||||
latencies for iso data streams.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
usb-redir.c | 30 +++++++++++++++++++++++++++---
|
||||
1 files changed, 27 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index 17ea7a7..88d941a 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -61,6 +61,7 @@ struct endp_data {
|
||||
uint8_t interrupt_started;
|
||||
uint8_t interrupt_error;
|
||||
uint8_t bufpq_prefilled;
|
||||
+ uint8_t bufpq_dropping_packets;
|
||||
QTAILQ_HEAD(, buf_packet) bufpq;
|
||||
int bufpq_size;
|
||||
int bufpq_target_size;
|
||||
@@ -290,16 +291,34 @@ static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
|
||||
}
|
||||
}
|
||||
|
||||
-static struct buf_packet *bufp_alloc(USBRedirDevice *dev,
|
||||
+static void bufp_alloc(USBRedirDevice *dev,
|
||||
uint8_t *data, int len, int status, uint8_t ep)
|
||||
{
|
||||
- struct buf_packet *bufp = g_malloc(sizeof(struct buf_packet));
|
||||
+ struct buf_packet *bufp;
|
||||
+
|
||||
+ if (!dev->endpoint[EP2I(ep)].bufpq_dropping_packets &&
|
||||
+ dev->endpoint[EP2I(ep)].bufpq_size >
|
||||
+ 2 * dev->endpoint[EP2I(ep)].bufpq_target_size) {
|
||||
+ DPRINTF("bufpq overflow, dropping packets ep %02X\n", ep);
|
||||
+ dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 1;
|
||||
+ }
|
||||
+ /* Since we're interupting the stream anyways, drop enough packets to get
|
||||
+ back to our target buffer size */
|
||||
+ if (dev->endpoint[EP2I(ep)].bufpq_dropping_packets) {
|
||||
+ if (dev->endpoint[EP2I(ep)].bufpq_size >
|
||||
+ dev->endpoint[EP2I(ep)].bufpq_target_size) {
|
||||
+ free(data);
|
||||
+ return;
|
||||
+ }
|
||||
+ dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
|
||||
+ }
|
||||
+
|
||||
+ bufp = g_malloc(sizeof(struct buf_packet));
|
||||
bufp->data = data;
|
||||
bufp->len = len;
|
||||
bufp->status = status;
|
||||
QTAILQ_INSERT_TAIL(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
|
||||
dev->endpoint[EP2I(ep)].bufpq_size++;
|
||||
- return bufp;
|
||||
}
|
||||
|
||||
static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp,
|
||||
@@ -378,6 +397,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
|
||||
DPRINTF("iso stream started ep %02X\n", ep);
|
||||
dev->endpoint[EP2I(ep)].iso_started = 1;
|
||||
dev->endpoint[EP2I(ep)].bufpq_prefilled = 0;
|
||||
+ dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
|
||||
}
|
||||
|
||||
if (ep & USB_DIR_IN) {
|
||||
@@ -504,6 +524,10 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
|
||||
usbredirparser_do_write(dev->parser);
|
||||
DPRINTF("interrupt recv started ep %02X\n", ep);
|
||||
dev->endpoint[EP2I(ep)].interrupt_started = 1;
|
||||
+ /* We don't really want to drop interrupt packets ever, but
|
||||
+ having some upper limit to how much we buffer is good. */
|
||||
+ dev->endpoint[EP2I(ep)].bufpq_target_size = 1000;
|
||||
+ dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
|
||||
}
|
||||
|
||||
intp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 9ca6b87b877fa46c81ce8e5b5a97dca4f522a727 Mon Sep 17 00:00:00 2001
|
||||
From 6a36990b303dc64709931e16783e2f2e0a54b9d6 Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Mon, 21 Mar 2011 22:00:27 +0100
|
||||
Subject: [PATCH 110/118] char: Update send_all() to handle nonblocking
|
||||
Subject: [PATCH 105/114] char: Update send_all() to handle nonblocking
|
||||
chardev write requests
|
||||
|
||||
The send_all function is modified to return to the caller in case the
|
||||
@ -16,13 +16,13 @@ commits will add such capability.
|
||||
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
---
|
||||
net/socket.c | 4 +-
|
||||
net/socket.c | 4 ++--
|
||||
qemu-char.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
|
||||
qemu_socket.h | 2 +-
|
||||
3 files changed, 66 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/net/socket.c b/net/socket.c
|
||||
index e9ef128..0d53dce 100644
|
||||
index 0bcf229..c21bb60 100644
|
||||
--- a/net/socket.c
|
||||
+++ b/net/socket.c
|
||||
@@ -56,8 +56,8 @@ static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_
|
||||
@ -37,10 +37,10 @@ index e9ef128..0d53dce 100644
|
||||
|
||||
static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size)
|
||||
diff --git a/qemu-char.c b/qemu-char.c
|
||||
index 66b5887..5e7f68e 100644
|
||||
index 88cbbd0..d8059ff 100644
|
||||
--- a/qemu-char.c
|
||||
+++ b/qemu-char.c
|
||||
@@ -507,7 +507,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
|
||||
@@ -508,7 +508,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -49,7 +49,7 @@ index 66b5887..5e7f68e 100644
|
||||
{
|
||||
int ret, len;
|
||||
|
||||
@@ -515,9 +515,14 @@ int send_all(int fd, const void *buf, int len1)
|
||||
@@ -516,9 +516,14 @@ int send_all(int fd, const void *buf, int len1)
|
||||
while (len > 0) {
|
||||
ret = send(fd, buf, len, 0);
|
||||
if (ret < 0) {
|
||||
@ -64,7 +64,7 @@ index 66b5887..5e7f68e 100644
|
||||
}
|
||||
} else if (ret == 0) {
|
||||
break;
|
||||
@@ -531,7 +536,7 @@ int send_all(int fd, const void *buf, int len1)
|
||||
@@ -532,7 +537,7 @@ int send_all(int fd, const void *buf, int len1)
|
||||
|
||||
#else
|
||||
|
||||
@ -73,7 +73,7 @@ index 66b5887..5e7f68e 100644
|
||||
{
|
||||
int ret, len;
|
||||
const uint8_t *buf = _buf;
|
||||
@@ -540,8 +545,15 @@ int send_all(int fd, const void *_buf, int len1)
|
||||
@@ -541,8 +546,15 @@ int send_all(int fd, const void *_buf, int len1)
|
||||
while (len > 0) {
|
||||
ret = write(fd, buf, len);
|
||||
if (ret < 0) {
|
||||
@ -90,7 +90,7 @@ index 66b5887..5e7f68e 100644
|
||||
} else if (ret == 0) {
|
||||
break;
|
||||
} else {
|
||||
@@ -556,6 +568,44 @@ int send_all(int fd, const void *_buf, int len1)
|
||||
@@ -557,6 +569,44 @@ int send_all(int fd, const void *_buf, int len1)
|
||||
#define STDIO_MAX_CLIENTS 1
|
||||
static int stdio_nb_clients;
|
||||
|
||||
@ -135,7 +135,7 @@ index 66b5887..5e7f68e 100644
|
||||
#ifndef _WIN32
|
||||
|
||||
typedef struct {
|
||||
@@ -567,7 +617,7 @@ typedef struct {
|
||||
@@ -568,7 +618,7 @@ typedef struct {
|
||||
static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
{
|
||||
FDCharDriver *s = chr->opaque;
|
||||
@ -144,7 +144,7 @@ index 66b5887..5e7f68e 100644
|
||||
}
|
||||
|
||||
static int fd_chr_read_poll(void *opaque)
|
||||
@@ -892,7 +942,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
@@ -887,7 +937,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
pty_chr_update_read_handler(chr);
|
||||
return 0;
|
||||
}
|
||||
@ -153,7 +153,7 @@ index 66b5887..5e7f68e 100644
|
||||
}
|
||||
|
||||
static int pty_chr_read_poll(void *opaque)
|
||||
@@ -2196,8 +2246,15 @@ static void tcp_closed(void *opaque)
|
||||
@@ -2174,8 +2224,15 @@ static void tcp_closed(void *opaque)
|
||||
static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
{
|
||||
TCPCharDriver *s = chr->opaque;
|
||||
@ -171,18 +171,18 @@ index 66b5887..5e7f68e 100644
|
||||
/* XXX: indicate an error ? */
|
||||
return len;
|
||||
diff --git a/qemu_socket.h b/qemu_socket.h
|
||||
index 9e32fac..9ea33fe 100644
|
||||
index 4689ff3..3d780ce 100644
|
||||
--- a/qemu_socket.h
|
||||
+++ b/qemu_socket.h
|
||||
@@ -37,7 +37,7 @@ int qemu_socket(int domain, int type, int protocol);
|
||||
int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
|
||||
@@ -36,7 +36,7 @@ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
|
||||
int socket_set_cork(int fd, int v);
|
||||
void socket_set_block(int fd);
|
||||
void socket_set_nonblock(int fd);
|
||||
-int send_all(int fd, const void *buf, int len1);
|
||||
+int send_all(CharDriverState *chr, int fd, const void *buf, int len1);
|
||||
|
||||
/* New, ipv6-ready socket helper functions, see qemu-sockets.c */
|
||||
int inet_listen_opts(QemuOpts *opts, int port_offset);
|
||||
int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp);
|
||||
--
|
||||
1.7.7.5
|
||||
1.7.10.4
|
||||
|
@ -1,58 +0,0 @@
|
||||
From ba411ef969f3dcd8e82929e5577c0e06a60a5707 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Tue, 20 Dec 2011 16:21:34 +0100
|
||||
Subject: [PATCH 105/118] usb-redir: Improve some debugging messages
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
usb-redir.c | 13 ++++++++-----
|
||||
1 files changed, 8 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index 88d941a..86bccf8 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -394,7 +394,8 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
|
||||
/* No id, we look at the ep when receiving a status back */
|
||||
usbredirparser_send_start_iso_stream(dev->parser, 0, &start_iso);
|
||||
usbredirparser_do_write(dev->parser);
|
||||
- DPRINTF("iso stream started ep %02X\n", ep);
|
||||
+ DPRINTF("iso stream started pkts/sec %d pkts/urb %d urbs %d ep %02X\n",
|
||||
+ pkts_per_sec, start_iso.pkts_per_urb, start_iso.no_urbs, ep);
|
||||
dev->endpoint[EP2I(ep)].iso_started = 1;
|
||||
dev->endpoint[EP2I(ep)].bufpq_prefilled = 0;
|
||||
dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
|
||||
@@ -414,7 +415,8 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
|
||||
|
||||
isop = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
|
||||
if (isop == NULL) {
|
||||
- DPRINTF2("iso-token-in ep %02X, no isop\n", ep);
|
||||
+ DPRINTF("iso-token-in ep %02X, no isop, iso_error: %d\n",
|
||||
+ ep, dev->endpoint[EP2I(ep)].iso_error);
|
||||
/* Re-fill the buffer */
|
||||
dev->endpoint[EP2I(ep)].bufpq_prefilled = 0;
|
||||
/* Check iso_error for stream errors, otherwise its an underrun */
|
||||
@@ -422,8 +424,8 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
|
||||
dev->endpoint[EP2I(ep)].iso_error = 0;
|
||||
return usbredir_handle_status(dev, status, 0);
|
||||
}
|
||||
- DPRINTF2("iso-token-in ep %02X status %d len %d\n", ep, isop->status,
|
||||
- isop->len);
|
||||
+ DPRINTF2("iso-token-in ep %02X status %d len %d queue-size: %d\n", ep,
|
||||
+ isop->status, isop->len, dev->endpoint[EP2I(ep)].bufpq_size);
|
||||
|
||||
status = isop->status;
|
||||
if (status != usb_redir_success) {
|
||||
@@ -433,7 +435,8 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
|
||||
|
||||
len = isop->len;
|
||||
if (len > p->iov.size) {
|
||||
- ERROR("received iso data is larger then packet ep %02X\n", ep);
|
||||
+ ERROR("received iso data is larger then packet ep %02X (%d > %d)\n",
|
||||
+ ep, len, (int)p->iov.size);
|
||||
bufp_free(dev, isop, ep);
|
||||
return USB_RET_NAK;
|
||||
}
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -1,7 +1,7 @@
|
||||
From b235c039fbab104ab582922f0083625564e177b1 Mon Sep 17 00:00:00 2001
|
||||
From bccdec085744256038f35b243853d7142b85cddb Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Mon, 21 Mar 2011 22:02:47 +0100
|
||||
Subject: [PATCH 111/118] char: Equip the unix/tcp backend to handle
|
||||
Subject: [PATCH 106/114] char: Equip the unix/tcp backend to handle
|
||||
nonblocking writes#
|
||||
|
||||
Now that the infrastructure is in place to return -EAGAIN to callers,
|
||||
@ -15,10 +15,10 @@ users of chardevs know that a driver became writable again.
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
---
|
||||
qemu-char.c | 34 ++++++++++++++++++++++++++++++++++
|
||||
1 files changed, 34 insertions(+), 0 deletions(-)
|
||||
1 file changed, 34 insertions(+)
|
||||
|
||||
diff --git a/qemu-char.c b/qemu-char.c
|
||||
index 5e7f68e..f98b240 100644
|
||||
index d8059ff..ed306e5 100644
|
||||
--- a/qemu-char.c
|
||||
+++ b/qemu-char.c
|
||||
@@ -106,6 +106,19 @@
|
||||
@ -41,7 +41,7 @@ index 5e7f68e..f98b240 100644
|
||||
void qemu_chr_be_event(CharDriverState *s, int event)
|
||||
{
|
||||
/* Keep track if the char device is open */
|
||||
@@ -2515,6 +2528,25 @@ static void tcp_chr_close(CharDriverState *chr)
|
||||
@@ -2493,6 +2506,25 @@ static void tcp_chr_close(CharDriverState *chr)
|
||||
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
|
||||
}
|
||||
|
||||
@ -64,10 +64,10 @@ index 5e7f68e..f98b240 100644
|
||||
+ disable_write_fd_handler(s->fd);
|
||||
+}
|
||||
+
|
||||
static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
|
||||
static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
|
||||
{
|
||||
CharDriverState *chr = NULL;
|
||||
@@ -2571,6 +2603,8 @@ static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
|
||||
@@ -2547,6 +2579,8 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
|
||||
chr->chr_close = tcp_chr_close;
|
||||
chr->get_msgfd = tcp_get_msgfd;
|
||||
chr->chr_add_client = tcp_chr_add_client;
|
||||
@ -77,5 +77,5 @@ index 5e7f68e..f98b240 100644
|
||||
if (is_listen) {
|
||||
s->listen_fd = fd;
|
||||
--
|
||||
1.7.7.5
|
||||
1.7.10.4
|
||||
|
@ -1,7 +1,7 @@
|
||||
From e5eb5b185d39942a2011b21114bb7f0b8e11427a Mon Sep 17 00:00:00 2001
|
||||
From 52aef47122bcbdd556f9fd3510a2047b8f920064 Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Mon, 21 Mar 2011 22:05:10 +0100
|
||||
Subject: [PATCH 112/118] char: Throttle when host connection is down#
|
||||
Subject: [PATCH 107/114] char: Throttle when host connection is down#
|
||||
|
||||
When the host-side connection goes down, throttle the virtio-serial bus
|
||||
and later unthrottle when a connection gets established. This helps
|
||||
@ -17,10 +17,10 @@ worst case (host d/c, guest write, host connect).
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
---
|
||||
qemu-char.c | 14 ++++++++++++++
|
||||
1 files changed, 14 insertions(+), 0 deletions(-)
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/qemu-char.c b/qemu-char.c
|
||||
index f98b240..5f67652 100644
|
||||
index ed306e5..c263328 100644
|
||||
--- a/qemu-char.c
|
||||
+++ b/qemu-char.c
|
||||
@@ -140,6 +140,9 @@ static void qemu_chr_generic_open_bh(void *opaque)
|
||||
@ -33,7 +33,7 @@ index f98b240..5f67652 100644
|
||||
qemu_bh_delete(s->bh);
|
||||
s->bh = NULL;
|
||||
}
|
||||
@@ -2266,6 +2269,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
@@ -2244,6 +2247,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
ret = send_all(chr, s->fd, buf, len);
|
||||
if (ret == -1 && errno == EPIPE) {
|
||||
tcp_closed(chr);
|
||||
@ -52,5 +52,5 @@ index f98b240..5f67652 100644
|
||||
return ret;
|
||||
} else {
|
||||
--
|
||||
1.7.7.5
|
||||
1.7.10.4
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 71108acb189f5fda923013ed72270642199ab50d Mon Sep 17 00:00:00 2001
|
||||
From 738da364d19bd99b70c79cb1174eef0e19f8e368 Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Mon, 21 Mar 2011 22:06:41 +0100
|
||||
Subject: [PATCH 113/118] virtio-console: Enable port throttling when chardev
|
||||
Subject: [PATCH 108/114] virtio-console: Enable port throttling when chardev
|
||||
is slow to consume data
|
||||
|
||||
When a chardev indicates it can't accept more data, we tell the
|
||||
@ -13,10 +13,10 @@ As soon as the chardev indicates it can accept more data, start pushing!
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
---
|
||||
hw/virtio-console.c | 11 +++++++++++
|
||||
1 files changed, 11 insertions(+), 0 deletions(-)
|
||||
1 file changed, 11 insertions(+)
|
||||
|
||||
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
|
||||
index 6d6f3ef..da68211 100644
|
||||
index 066590c..2b5e515 100644
|
||||
--- a/hw/virtio-console.c
|
||||
+++ b/hw/virtio-console.c
|
||||
@@ -20,6 +20,16 @@ typedef struct VirtConsole {
|
||||
@ -36,7 +36,7 @@ index 6d6f3ef..da68211 100644
|
||||
|
||||
/* Callback function that's called when the guest sends us data */
|
||||
static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
|
||||
@@ -99,6 +109,7 @@ static const QemuChrHandlers chr_handlers = {
|
||||
@@ -110,6 +120,7 @@ static const QemuChrHandlers chr_handlers = {
|
||||
.fd_can_read = chr_can_read,
|
||||
.fd_read = chr_read,
|
||||
.fd_event = chr_event,
|
||||
@ -45,5 +45,5 @@ index 6d6f3ef..da68211 100644
|
||||
|
||||
static int virtconsole_initfn(VirtIOSerialPort *port)
|
||||
--
|
||||
1.7.7.5
|
||||
1.7.10.4
|
||||
|
@ -1,7 +1,7 @@
|
||||
From d4066655fc866ac0e57420b32dec3b37277b374c Mon Sep 17 00:00:00 2001
|
||||
From 484eac58fb0cf9b0ba6d31db868a549ee8799437 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Tue, 22 Mar 2011 12:27:59 +0200
|
||||
Subject: [PATCH 114/118] spice-qemu-char.c: add throttling
|
||||
Subject: [PATCH 109/114] spice-qemu-char.c: add throttling
|
||||
|
||||
BZ: 672191
|
||||
|
||||
@ -36,10 +36,10 @@ was not accepted upstream, and will not be accepted upstream until the mainloop
|
||||
is reworked to use glib.
|
||||
---
|
||||
spice-qemu-char.c | 39 +++++++++++++++++++++++++++++++++++----
|
||||
1 files changed, 35 insertions(+), 4 deletions(-)
|
||||
1 file changed, 35 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
|
||||
index 7e8eaa9..eeeb32e 100644
|
||||
index 09aa22d..fba2bfb 100644
|
||||
--- a/spice-qemu-char.c
|
||||
+++ b/spice-qemu-char.c
|
||||
@@ -1,4 +1,6 @@
|
||||
@ -120,7 +120,7 @@ index 7e8eaa9..eeeb32e 100644
|
||||
}
|
||||
|
||||
static void spice_chr_close(struct CharDriverState *chr)
|
||||
@@ -225,6 +255,7 @@ int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr)
|
||||
@@ -225,6 +255,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
|
||||
chr->chr_close = spice_chr_close;
|
||||
chr->chr_guest_open = spice_chr_guest_open;
|
||||
chr->chr_guest_close = spice_chr_guest_close;
|
||||
@ -129,5 +129,5 @@ index 7e8eaa9..eeeb32e 100644
|
||||
#if SPICE_SERVER_VERSION < 0x000901
|
||||
/* See comment in vmc_state() */
|
||||
--
|
||||
1.7.7.5
|
||||
1.7.10.4
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 9d965c99311c6f3d5c7ba9b66a72398814175865 Mon Sep 17 00:00:00 2001
|
||||
From 606c5ed5369c862c70fa527892b808f189a2b482 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Tue, 22 Mar 2011 12:28:00 +0200
|
||||
Subject: [PATCH 115/118] spice-qemu-char.c: remove intermediate buffer
|
||||
Subject: [PATCH 110/114] spice-qemu-char.c: remove intermediate buffer
|
||||
|
||||
BZ: 672191
|
||||
upstream: not submitted (explained below)
|
||||
@ -17,10 +17,10 @@ This relied on the previous patch that introduces throttling, which
|
||||
can't go upstream right now as explained in that patch.
|
||||
---
|
||||
spice-qemu-char.c | 18 ++++++------------
|
||||
1 files changed, 6 insertions(+), 12 deletions(-)
|
||||
1 file changed, 6 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
|
||||
index eeeb32e..70a83bf 100644
|
||||
index fba2bfb..ef44bc0 100644
|
||||
--- a/spice-qemu-char.c
|
||||
+++ b/spice-qemu-char.c
|
||||
@@ -23,9 +23,8 @@ typedef struct SpiceCharDriver {
|
||||
@ -67,5 +67,5 @@ index eeeb32e..70a83bf 100644
|
||||
/* We'll get passed in the unconsumed data with the next call */
|
||||
s->datalen = 0;
|
||||
--
|
||||
1.7.7.5
|
||||
1.7.10.4
|
||||
|
@ -1,18 +1,18 @@
|
||||
From 80aafc63c842ee902cc9e32d692efed8952a1e14 Mon Sep 17 00:00:00 2001
|
||||
From 2f61a7bed440164c35c739fcef10d19edef3f8ea Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Tue, 19 Jul 2011 10:56:19 +0200
|
||||
Subject: [PATCH 116/118] usb-redir: Add flow control support
|
||||
Subject: [PATCH 111/114] usb-redir: Add flow control support
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
usb-redir.c | 26 ++++++++++++++++++++++++--
|
||||
1 files changed, 24 insertions(+), 2 deletions(-)
|
||||
hw/usb/redirect.c | 26 ++++++++++++++++++++++++--
|
||||
1 file changed, 24 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index e421cff..1289506 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -228,12 +228,22 @@ static int usbredir_read(void *priv, uint8_t *data, int count)
|
||||
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
|
||||
index 6e8180e..5f55d78 100644
|
||||
--- a/hw/usb/redirect.c
|
||||
+++ b/hw/usb/redirect.c
|
||||
@@ -238,12 +238,22 @@ static int usbredir_read(void *priv, uint8_t *data, int count)
|
||||
static int usbredir_write(void *priv, uint8_t *data, int count)
|
||||
{
|
||||
USBRedirDevice *dev = priv;
|
||||
@ -37,7 +37,7 @@ index e421cff..1289506 100644
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -865,10 +875,22 @@ static void usbredir_chardev_event(void *opaque, int event)
|
||||
@@ -890,10 +900,22 @@ static void usbredir_chardev_event(void *opaque, int event)
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,5 +61,5 @@ index e421cff..1289506 100644
|
||||
|
||||
/*
|
||||
--
|
||||
1.7.7.5
|
||||
1.7.10.4
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 8e92fe9feebc319c019feb8c28941e322524932f Mon Sep 17 00:00:00 2001
|
||||
From be9fad02180478f6c9435257e6a7c29b9e4c9841 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Thu, 28 Jul 2011 15:08:48 +0300
|
||||
Subject: [PATCH 117/118] virtio-serial-bus: replay guest_open on migration
|
||||
Subject: [PATCH 112/114] virtio-serial-bus: replay guest_open on migration
|
||||
|
||||
When migrating a host with with a spice agent running the mouse becomes
|
||||
non operational after the migration. This is rhbz #725965.
|
||||
@ -19,32 +19,32 @@ chardev.
|
||||
Signed-off-by: Alon Levy <alevy@redhat.com>
|
||||
---
|
||||
hw/virtio-serial-bus.c | 6 ++++++
|
||||
1 files changed, 6 insertions(+), 0 deletions(-)
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
|
||||
index a4825b9..e5f343f 100644
|
||||
index 72287d1..7ea5bbf 100644
|
||||
--- a/hw/virtio-serial-bus.c
|
||||
+++ b/hw/virtio-serial-bus.c
|
||||
@@ -618,6 +618,7 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
|
||||
@@ -682,6 +682,7 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
|
||||
for (i = 0; i < nr_active_ports; i++) {
|
||||
uint32_t id;
|
||||
bool host_connected;
|
||||
+ VirtIOSerialPortInfo *info;
|
||||
+ VirtIOSerialPortClass *vsc;
|
||||
|
||||
id = qemu_get_be32(f);
|
||||
port = find_port_by_id(s, id);
|
||||
@@ -626,6 +627,11 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
|
||||
@@ -690,6 +691,11 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
|
||||
}
|
||||
|
||||
port->guest_connected = qemu_get_byte(f);
|
||||
+ info = DO_UPCAST(VirtIOSerialPortInfo, qdev, port->dev.info);
|
||||
+ if (port->guest_connected && info->guest_open) {
|
||||
+ vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
|
||||
+ if (port->guest_connected && vsc->guest_open) {
|
||||
+ /* replay guest open */
|
||||
+ info->guest_open(port);
|
||||
+ vsc->guest_open(port);
|
||||
+ }
|
||||
host_connected = qemu_get_byte(f);
|
||||
if (host_connected != port->host_connected) {
|
||||
/*
|
||||
--
|
||||
1.7.7.5
|
||||
1.7.10.4
|
||||
|
@ -1,7 +1,7 @@
|
||||
From fad276489cbc04f228d52b7019bee9e7a88c8a86 Mon Sep 17 00:00:00 2001
|
||||
From 303a46e3877f6d9600151fdf9719fdb2009db7ff Mon Sep 17 00:00:00 2001
|
||||
From: Amit Shah <amit.shah@redhat.com>
|
||||
Date: Fri, 2 Dec 2011 15:42:55 +0530
|
||||
Subject: [PATCH 118/118] char: Disable write callback if throttled chardev is
|
||||
Subject: [PATCH 113/114] char: Disable write callback if throttled chardev is
|
||||
detached
|
||||
|
||||
If a throttled chardev is detached from the frontend device, all future
|
||||
@ -13,13 +13,13 @@ Upstream: Not applicable, since throttling is a RHEL6-only feature.
|
||||
Signed-off-by: Amit Shah <amit.shah@redhat.com>
|
||||
---
|
||||
qemu-char.c | 5 +++++
|
||||
1 files changed, 5 insertions(+), 0 deletions(-)
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/qemu-char.c b/qemu-char.c
|
||||
index 5f67652..5a94919 100644
|
||||
index c263328..622c388 100644
|
||||
--- a/qemu-char.c
|
||||
+++ b/qemu-char.c
|
||||
@@ -220,6 +220,11 @@ void qemu_chr_add_handlers(CharDriverState *s,
|
||||
@@ -223,6 +223,11 @@ void qemu_chr_add_handlers(CharDriverState *s,
|
||||
++s->avail_connections;
|
||||
}
|
||||
if (!handlers) {
|
||||
@ -32,5 +32,5 @@ index 5f67652..5a94919 100644
|
||||
}
|
||||
s->chr_can_read = handlers->fd_can_read;
|
||||
--
|
||||
1.7.7.5
|
||||
1.7.10.4
|
||||
|
@ -1,35 +0,0 @@
|
||||
From 959f57d34f11daf0da6f73541243934f39dfb2b2 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Fri, 13 Jan 2012 14:26:26 +0100
|
||||
Subject: [PATCH 119/140] usb-ehci: Clear the portstatus powner bit on device
|
||||
disconnect
|
||||
|
||||
According to the EHCI spec port ownerhsip should revert to the EHCI controller
|
||||
on device disconnect. This fixes the problem of a port getting stuck on USB 1
|
||||
when using redirection and plugging in a USB 2 device after a USB 1 device
|
||||
has been redirected.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index a946e1d..69bcc4b 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -764,6 +764,11 @@ static void ehci_detach(USBPort *port)
|
||||
USBPort *companion = s->companion_ports[port->index];
|
||||
companion->ops->detach(companion);
|
||||
companion->dev = NULL;
|
||||
+ /*
|
||||
+ * EHCI spec 4.2.2: "When a disconnect occurs... On the event,
|
||||
+ * the port ownership is returned immediately to the EHCI controller."
|
||||
+ */
|
||||
+ *portsc &= ~PORTSC_POWNER;
|
||||
return;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,263 +0,0 @@
|
||||
From bcc4748db3e991fbaa032fe9c0726288a8f1008d Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Thu, 12 Jan 2012 16:54:04 +0100
|
||||
Subject: [PATCH 120/140] usb-redir: Add the posibility to filter out certain
|
||||
devices from redirecion
|
||||
|
||||
This patch adds the posibility to filter out certain devices from redirecion.
|
||||
To use this pass the filter property to -device usb-redir. The filter
|
||||
property takes a string consisting of filter rules, the format for a rule is:
|
||||
<class>:<vendor>:<product>:<version>:<allow>
|
||||
|
||||
-1 can be used to allow any value for a field.
|
||||
|
||||
Muliple rules can be concatonated using | as a separator. Note that if
|
||||
a device matches none of the passed in rules, redirecting it will not be
|
||||
allowed!
|
||||
|
||||
Example:
|
||||
-device usb-redir,filter='-1:0x0781:0x5567:-1:0|0x08:-1:-1:-1:1'
|
||||
|
||||
This example will deny the Sandisk Cruzer Blade being redirected, as it
|
||||
has a usb id of 0781:5567, it will allow any other usb mass storage devices,
|
||||
and it will deny any other devices (the default for devices not matching any
|
||||
of the rules.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
configure | 2 +-
|
||||
usb-redir.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++------
|
||||
2 files changed, 106 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/configure b/configure
|
||||
index 7ecf44e..c7e37df 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -2541,7 +2541,7 @@ fi
|
||||
|
||||
# check for usbredirparser for usb network redirection support
|
||||
if test "$usb_redir" != "no" ; then
|
||||
- if $pkg_config libusbredirparser >/dev/null 2>&1 ; then
|
||||
+ if $pkg_config --atleast-version=0.3.3 libusbredirparser >/dev/null 2>&1 ; then
|
||||
usb_redir="yes"
|
||||
usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null)
|
||||
usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null)
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index 6e92f14..85f40d6 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <signal.h>
|
||||
#include <usbredirparser.h>
|
||||
+#include <usbredirfilter.h>
|
||||
|
||||
#include "hw/usb.h"
|
||||
|
||||
@@ -72,6 +73,7 @@ struct USBRedirDevice {
|
||||
/* Properties */
|
||||
CharDriverState *cs;
|
||||
uint8_t debug;
|
||||
+ char *filter_str;
|
||||
/* Data passed from chardev the fd_read cb to the usbredirparser read cb */
|
||||
const uint8_t *read_buf;
|
||||
int read_buf_size;
|
||||
@@ -84,6 +86,11 @@ struct USBRedirDevice {
|
||||
struct endp_data endpoint[MAX_ENDPOINTS];
|
||||
uint32_t packet_id;
|
||||
QTAILQ_HEAD(, AsyncURB) asyncq;
|
||||
+ /* Data for device filtering */
|
||||
+ struct usb_redir_device_connect_header device_info;
|
||||
+ struct usb_redir_interface_info_header interface_info;
|
||||
+ struct usbredirfilter_rule *filter_rules;
|
||||
+ int filter_rules_count;
|
||||
};
|
||||
|
||||
struct AsyncURB {
|
||||
@@ -790,6 +797,7 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
|
||||
static void usbredir_open_close_bh(void *opaque)
|
||||
{
|
||||
USBRedirDevice *dev = opaque;
|
||||
+ uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, };
|
||||
|
||||
usbredir_device_disconnect(dev);
|
||||
|
||||
@@ -820,7 +828,9 @@ static void usbredir_open_close_bh(void *opaque)
|
||||
dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
|
||||
dev->read_buf = NULL;
|
||||
dev->read_buf_size = 0;
|
||||
- usbredirparser_init(dev->parser, VERSION, NULL, 0, 0);
|
||||
+
|
||||
+ usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version);
|
||||
+ usbredirparser_init(dev->parser, VERSION, caps, USB_REDIR_CAPS_SIZE, 0);
|
||||
usbredirparser_do_write(dev->parser);
|
||||
}
|
||||
}
|
||||
@@ -908,6 +918,17 @@ static int usbredir_initfn(USBDevice *udev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ if (dev->filter_str) {
|
||||
+ i = usbredirfilter_string_to_rules(dev->filter_str, ":", "|",
|
||||
+ &dev->filter_rules,
|
||||
+ &dev->filter_rules_count);
|
||||
+ if (i) {
|
||||
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, "filter",
|
||||
+ "a usb device filter string");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
dev->open_close_bh = qemu_bh_new(usbredir_open_close_bh, dev);
|
||||
dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
|
||||
|
||||
@@ -956,6 +977,44 @@ static void usbredir_handle_destroy(USBDevice *udev)
|
||||
if (dev->parser) {
|
||||
usbredirparser_destroy(dev->parser);
|
||||
}
|
||||
+
|
||||
+ free(dev->filter_rules);
|
||||
+}
|
||||
+
|
||||
+static int usbredir_check_filter(USBRedirDevice *dev)
|
||||
+{
|
||||
+ if (dev->interface_info.interface_count == 0) {
|
||||
+ ERROR("No interface info for device\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (dev->filter_rules) {
|
||||
+ if (!usbredirparser_peer_has_cap(dev->parser,
|
||||
+ usb_redir_cap_connect_device_version)) {
|
||||
+ ERROR("Device filter specified and peer does not have the "
|
||||
+ "connect_device_version capability\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (usbredirfilter_check(
|
||||
+ dev->filter_rules,
|
||||
+ dev->filter_rules_count,
|
||||
+ dev->device_info.device_class,
|
||||
+ dev->device_info.device_subclass,
|
||||
+ dev->device_info.device_protocol,
|
||||
+ dev->interface_info.interface_class,
|
||||
+ dev->interface_info.interface_subclass,
|
||||
+ dev->interface_info.interface_protocol,
|
||||
+ dev->interface_info.interface_count,
|
||||
+ dev->device_info.vendor_id,
|
||||
+ dev->device_info.product_id,
|
||||
+ dev->device_info.device_version_bcd,
|
||||
+ 0) != 0) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -984,6 +1043,7 @@ static void usbredir_device_connect(void *priv,
|
||||
struct usb_redir_device_connect_header *device_connect)
|
||||
{
|
||||
USBRedirDevice *dev = priv;
|
||||
+ const char *speed;
|
||||
|
||||
if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
|
||||
ERROR("Received device connect while already connected\n");
|
||||
@@ -992,26 +1052,48 @@ static void usbredir_device_connect(void *priv,
|
||||
|
||||
switch (device_connect->speed) {
|
||||
case usb_redir_speed_low:
|
||||
- DPRINTF("attaching low speed device\n");
|
||||
+ speed = "low speed";
|
||||
dev->dev.speed = USB_SPEED_LOW;
|
||||
break;
|
||||
case usb_redir_speed_full:
|
||||
- DPRINTF("attaching full speed device\n");
|
||||
+ speed = "full speed";
|
||||
dev->dev.speed = USB_SPEED_FULL;
|
||||
break;
|
||||
case usb_redir_speed_high:
|
||||
- DPRINTF("attaching high speed device\n");
|
||||
+ speed = "high speed";
|
||||
dev->dev.speed = USB_SPEED_HIGH;
|
||||
break;
|
||||
case usb_redir_speed_super:
|
||||
- DPRINTF("attaching super speed device\n");
|
||||
+ speed = "super speed";
|
||||
dev->dev.speed = USB_SPEED_SUPER;
|
||||
break;
|
||||
default:
|
||||
- DPRINTF("attaching unknown speed device, assuming full speed\n");
|
||||
+ speed = "unknown speed";
|
||||
dev->dev.speed = USB_SPEED_FULL;
|
||||
}
|
||||
+
|
||||
+ if (usbredirparser_peer_has_cap(dev->parser,
|
||||
+ usb_redir_cap_connect_device_version)) {
|
||||
+ INFO("attaching %s device %04x:%04x version %d.%d class %02x\n",
|
||||
+ speed, device_connect->vendor_id, device_connect->product_id,
|
||||
+ device_connect->device_version_bcd >> 8,
|
||||
+ device_connect->device_version_bcd & 0xff,
|
||||
+ device_connect->device_class);
|
||||
+ } else {
|
||||
+ INFO("attaching %s device %04x:%04x class %02x\n", speed,
|
||||
+ device_connect->vendor_id, device_connect->product_id,
|
||||
+ device_connect->device_class);
|
||||
+ }
|
||||
+
|
||||
dev->dev.speedmask = (1 << dev->dev.speed);
|
||||
+ dev->device_info = *device_connect;
|
||||
+
|
||||
+ if (usbredir_check_filter(dev)) {
|
||||
+ WARNING("Device %04x:%04x rejected by device filter, not attaching\n",
|
||||
+ device_connect->vendor_id, device_connect->product_id);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
qemu_mod_timer(dev->attach_timer, dev->next_attach_time);
|
||||
}
|
||||
|
||||
@@ -1038,15 +1120,27 @@ static void usbredir_device_disconnect(void *priv)
|
||||
for (i = 0; i < MAX_ENDPOINTS; i++) {
|
||||
QTAILQ_INIT(&dev->endpoint[i].bufpq);
|
||||
}
|
||||
+ dev->interface_info.interface_count = 0;
|
||||
}
|
||||
|
||||
static void usbredir_interface_info(void *priv,
|
||||
struct usb_redir_interface_info_header *interface_info)
|
||||
{
|
||||
- /* The intention is to allow specifying acceptable interface classes
|
||||
- for redirection on the cmdline and in the future verify this here,
|
||||
- and disconnect (or never connect) the device if a not accepted
|
||||
- interface class is detected */
|
||||
+ USBRedirDevice *dev = priv;
|
||||
+
|
||||
+ dev->interface_info = *interface_info;
|
||||
+
|
||||
+ /*
|
||||
+ * If we receive interface info after the device has already been
|
||||
+ * connected (ie on a set_config), re-check the filter.
|
||||
+ */
|
||||
+ if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
|
||||
+ if (usbredir_check_filter(dev)) {
|
||||
+ ERROR("Device no longer matches filter after interface info "
|
||||
+ "change, disconnecting!\n");
|
||||
+ usbredir_device_disconnect(dev);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
static void usbredir_ep_info(void *priv,
|
||||
@@ -1356,6 +1450,7 @@ static struct USBDeviceInfo usbredir_dev_info = {
|
||||
.qdev.props = (Property[]) {
|
||||
DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
|
||||
DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
|
||||
+ DEFINE_PROP_STRING("filter", USBRedirDevice, filter_str),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
},
|
||||
};
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,33 +0,0 @@
|
||||
From 6c13e7b9448b10d966bb99c00c5120678ccd2a3f Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Sat, 18 Feb 2012 09:12:14 +0100
|
||||
Subject: [PATCH 121/140] usb-redir: Fix printing of device version
|
||||
|
||||
The device version is in bcd format, which requires some special handling to
|
||||
print.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
usb-redir.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index 85f40d6..9b804e9 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -1076,8 +1076,10 @@ static void usbredir_device_connect(void *priv,
|
||||
usb_redir_cap_connect_device_version)) {
|
||||
INFO("attaching %s device %04x:%04x version %d.%d class %02x\n",
|
||||
speed, device_connect->vendor_id, device_connect->product_id,
|
||||
- device_connect->device_version_bcd >> 8,
|
||||
- device_connect->device_version_bcd & 0xff,
|
||||
+ ((device_connect->device_version_bcd & 0xf000) >> 12) * 10 +
|
||||
+ ((device_connect->device_version_bcd & 0x0f00) >> 8),
|
||||
+ ((device_connect->device_version_bcd & 0x00f0) >> 4) * 10 +
|
||||
+ ((device_connect->device_version_bcd & 0x000f) >> 0),
|
||||
device_connect->device_class);
|
||||
} else {
|
||||
INFO("attaching %s device %04x:%04x class %02x\n", speed,
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,64 +0,0 @@
|
||||
From 49a01afb24b925de97074d093fb072bb7de470f9 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Sat, 18 Feb 2012 09:18:57 +0100
|
||||
Subject: [PATCH 122/140] usb-redir: Always clear device state on filter
|
||||
reject
|
||||
|
||||
Always call usbredir_device_disconnect() when usbredir_check_filter() fails
|
||||
to clean up all the device state (ie received endpoint info).
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
usb-redir.c | 11 +++++++----
|
||||
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index 9b804e9..fe3b0a3 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -985,7 +985,7 @@ static int usbredir_check_filter(USBRedirDevice *dev)
|
||||
{
|
||||
if (dev->interface_info.interface_count == 0) {
|
||||
ERROR("No interface info for device\n");
|
||||
- return -1;
|
||||
+ goto error;
|
||||
}
|
||||
|
||||
if (dev->filter_rules) {
|
||||
@@ -993,7 +993,7 @@ static int usbredir_check_filter(USBRedirDevice *dev)
|
||||
usb_redir_cap_connect_device_version)) {
|
||||
ERROR("Device filter specified and peer does not have the "
|
||||
"connect_device_version capability\n");
|
||||
- return -1;
|
||||
+ goto error;
|
||||
}
|
||||
|
||||
if (usbredirfilter_check(
|
||||
@@ -1010,11 +1010,15 @@ static int usbredir_check_filter(USBRedirDevice *dev)
|
||||
dev->device_info.product_id,
|
||||
dev->device_info.device_version_bcd,
|
||||
0) != 0) {
|
||||
- return -1;
|
||||
+ goto error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
+
|
||||
+error:
|
||||
+ usbredir_device_disconnect(dev);
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1140,7 +1144,6 @@ static void usbredir_interface_info(void *priv,
|
||||
if (usbredir_check_filter(dev)) {
|
||||
ERROR("Device no longer matches filter after interface info "
|
||||
"change, disconnecting!\n");
|
||||
- usbredir_device_disconnect(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,93 +0,0 @@
|
||||
From f04315d9210f22e5d7317f1cfb3c076fb93b3c08 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Sun, 19 Feb 2012 09:58:03 +0100
|
||||
Subject: [PATCH 123/140] usb-redir: Let the usb-host know about our device
|
||||
filtering
|
||||
|
||||
libusbredirparser-0.3.4 adds 2 new packets which allows us to notify
|
||||
the usb-host:
|
||||
-about the usb device filter we have (if any), so that it knows not the even
|
||||
try to redirect certain devices
|
||||
-when we reject a device based on filtering (in case it tries anyways)
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
configure | 2 +-
|
||||
usb-redir.c | 20 ++++++++++++++++++++
|
||||
2 files changed, 21 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/configure b/configure
|
||||
index c7e37df..a4848a4 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -2541,7 +2541,7 @@ fi
|
||||
|
||||
# check for usbredirparser for usb network redirection support
|
||||
if test "$usb_redir" != "no" ; then
|
||||
- if $pkg_config --atleast-version=0.3.3 libusbredirparser >/dev/null 2>&1 ; then
|
||||
+ if $pkg_config --atleast-version=0.3.4 libusbredirparser >/dev/null 2>&1 ; then
|
||||
usb_redir="yes"
|
||||
usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null)
|
||||
usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null)
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index fe3b0a3..d10d8de 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -106,6 +106,7 @@ struct AsyncURB {
|
||||
QTAILQ_ENTRY(AsyncURB)next;
|
||||
};
|
||||
|
||||
+static void usbredir_hello(void *priv, struct usb_redir_hello_header *h);
|
||||
static void usbredir_device_connect(void *priv,
|
||||
struct usb_redir_device_connect_header *device_connect);
|
||||
static void usbredir_device_disconnect(void *priv);
|
||||
@@ -812,6 +813,7 @@ static void usbredir_open_close_bh(void *opaque)
|
||||
dev->parser->log_func = usbredir_log;
|
||||
dev->parser->read_func = usbredir_read;
|
||||
dev->parser->write_func = usbredir_write;
|
||||
+ dev->parser->hello_func = usbredir_hello;
|
||||
dev->parser->device_connect_func = usbredir_device_connect;
|
||||
dev->parser->device_disconnect_func = usbredir_device_disconnect;
|
||||
dev->parser->interface_info_func = usbredir_interface_info;
|
||||
@@ -830,6 +832,7 @@ static void usbredir_open_close_bh(void *opaque)
|
||||
dev->read_buf_size = 0;
|
||||
|
||||
usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version);
|
||||
+ usbredirparser_caps_set_cap(caps, usb_redir_cap_filter);
|
||||
usbredirparser_init(dev->parser, VERSION, caps, USB_REDIR_CAPS_SIZE, 0);
|
||||
usbredirparser_do_write(dev->parser);
|
||||
}
|
||||
@@ -1018,6 +1021,10 @@ static int usbredir_check_filter(USBRedirDevice *dev)
|
||||
|
||||
error:
|
||||
usbredir_device_disconnect(dev);
|
||||
+ if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter)) {
|
||||
+ usbredirparser_send_filter_reject(dev->parser);
|
||||
+ usbredirparser_do_write(dev->parser);
|
||||
+ }
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1043,6 +1050,19 @@ static int usbredir_handle_status(USBRedirDevice *dev,
|
||||
}
|
||||
}
|
||||
|
||||
+static void usbredir_hello(void *priv, struct usb_redir_hello_header *h)
|
||||
+{
|
||||
+ USBRedirDevice *dev = priv;
|
||||
+
|
||||
+ /* Try to send the filter info now that we've the usb-host's caps */
|
||||
+ if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter) &&
|
||||
+ dev->filter_rules) {
|
||||
+ usbredirparser_send_filter_filter(dev->parser, dev->filter_rules,
|
||||
+ dev->filter_rules_count);
|
||||
+ usbredirparser_do_write(dev->parser);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void usbredir_device_connect(void *priv,
|
||||
struct usb_redir_device_connect_header *device_connect)
|
||||
{
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,42 +0,0 @@
|
||||
From 91338d1b4df14f7454d1b52200d2ae4eb957fa72 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Sun, 26 Feb 2012 15:28:51 +0100
|
||||
Subject: [PATCH 124/140] usb-redir: Limit return values returned by iso
|
||||
packets
|
||||
|
||||
The usbredir protocol uses a status of usb_redir_stall to indicate that
|
||||
an iso data stream has stopped (ie because the urbs failed on resubmit),
|
||||
but iso packets should never return a result of USB_RET_STALL, since iso
|
||||
endpoints cannot stall. So instead simply always return USB_RET_NAK on
|
||||
iso stream errors.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
usb-redir.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index d10d8de..c76e55d 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -441,7 +441,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
|
||||
/* Check iso_error for stream errors, otherwise its an underrun */
|
||||
status = dev->endpoint[EP2I(ep)].iso_error;
|
||||
dev->endpoint[EP2I(ep)].iso_error = 0;
|
||||
- return usbredir_handle_status(dev, status, 0);
|
||||
+ return status ? USB_RET_NAK : 0;
|
||||
}
|
||||
DPRINTF2("iso-token-in ep %02X status %d len %d queue-size: %d\n", ep,
|
||||
isop->status, isop->len, dev->endpoint[EP2I(ep)].bufpq_size);
|
||||
@@ -449,7 +449,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
|
||||
status = isop->status;
|
||||
if (status != usb_redir_success) {
|
||||
bufp_free(dev, isop, ep);
|
||||
- return usbredir_handle_status(dev, status, 0);
|
||||
+ return USB_RET_NAK;
|
||||
}
|
||||
|
||||
len = isop->len;
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,33 +0,0 @@
|
||||
From ddb24b5063e3b4c90295bd4ddaab3bfc428ae79b Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Sun, 26 Feb 2012 15:51:50 +0100
|
||||
Subject: [PATCH 125/140] usb-redir: Return USB_RET_NAK when we've no data for
|
||||
an interrupt endpoint
|
||||
|
||||
We should return USB_RET_NAK, rather then a 0 sized packet, when we've no data
|
||||
for an interrupt IN endpoint.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
usb-redir.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index c76e55d..629c87d 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -558,7 +558,10 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
|
||||
/* Check interrupt_error for stream errors */
|
||||
status = dev->endpoint[EP2I(ep)].interrupt_error;
|
||||
dev->endpoint[EP2I(ep)].interrupt_error = 0;
|
||||
- return usbredir_handle_status(dev, status, 0);
|
||||
+ if (status) {
|
||||
+ return usbredir_handle_status(dev, status, 0);
|
||||
+ }
|
||||
+ return USB_RET_NAK;
|
||||
}
|
||||
DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
|
||||
intp->status, intp->len);
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,64 +0,0 @@
|
||||
From 7a3acb928b617b33605c779e7df05c2c896844b1 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Mon, 20 Feb 2012 16:27:47 +0100
|
||||
Subject: [PATCH 126/140] usb-ehci: Handle ISO packets failing with an error
|
||||
other then NAK
|
||||
|
||||
Before this patch the ehci code was not checking for any other errors other
|
||||
then USB_RET_NAK. This causes 2 problems:
|
||||
1) Other errors are not reported to the guest.
|
||||
2) When transactions with the ITD_XACT_IOC bit set completing with another
|
||||
error would not result in USBSTS_INT getting set.
|
||||
|
||||
I hit this problem when unplugging devices while iso data was streaming from
|
||||
the device to the guest. When this happens it takes a while for the guest to
|
||||
process the unplugging and remove ISO transactions from the ehci schedule, in
|
||||
the mean time these transactions would complete with a result of USB_RET_NODEV,
|
||||
which was not handled. This lead to the Linux guest's usb subsystem "hanging",
|
||||
that is it would no longer see new usb devices getting plugged in and running
|
||||
for example lsusb would lead to a stuck (D state) lsusb process. This patch
|
||||
fixes this.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 22 +++++++++++++++++++---
|
||||
1 file changed, 19 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index 69bcc4b..a6b6ae5 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -1512,11 +1512,27 @@ static int ehci_process_itd(EHCIState *ehci,
|
||||
/* IN */
|
||||
set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
|
||||
}
|
||||
-
|
||||
- if (itd->transact[i] & ITD_XACT_IOC) {
|
||||
- ehci_record_interrupt(ehci, USBSTS_INT);
|
||||
+ } else {
|
||||
+ switch (ret) {
|
||||
+ default:
|
||||
+ fprintf(stderr, "Unexpected iso usb result: %d\n", ret);
|
||||
+ /* Fall through */
|
||||
+ case USB_RET_NODEV:
|
||||
+ /* 3.3.2: XACTERR is only allowed on IN transactions */
|
||||
+ if (dir) {
|
||||
+ itd->transact[i] |= ITD_XACT_XACTERR;
|
||||
+ ehci_record_interrupt(ehci, USBSTS_ERRINT);
|
||||
+ }
|
||||
+ break;
|
||||
+ case USB_RET_BABBLE:
|
||||
+ itd->transact[i] |= ITD_XACT_BABBLE;
|
||||
+ ehci_record_interrupt(ehci, USBSTS_ERRINT);
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
+ if (itd->transact[i] & ITD_XACT_IOC) {
|
||||
+ ehci_record_interrupt(ehci, USBSTS_INT);
|
||||
+ }
|
||||
itd->transact[i] &= ~ITD_XACT_ACTIVE;
|
||||
}
|
||||
}
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,61 +0,0 @@
|
||||
From 82e500c24a026323e0b8b869e227cc68b179fb11 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Mon, 27 Feb 2012 11:44:52 +0100
|
||||
Subject: [PATCH 127/140] usb-ehci: Never follow table entries with the T-bit
|
||||
set
|
||||
|
||||
Before this patch the T-bit was not checked in 2 places, while it should be.
|
||||
|
||||
Once we properly check the T-bit everywhere we no longer need the weird
|
||||
entry < 0x1000 and entry > 0x1000 checks, so this patch removes them.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 10 ++++------
|
||||
1 file changed, 4 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index a6b6ae5..37076a9 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -1596,8 +1596,7 @@ static int ehci_state_fetchentry(EHCIState *ehci, int async)
|
||||
int again = 0;
|
||||
uint32_t entry = ehci_get_fetch_addr(ehci, async);
|
||||
|
||||
- if (entry < 0x1000) {
|
||||
- DPRINTF("fetchentry: entry invalid (0x%08x)\n", entry);
|
||||
+ if (NLPTR_TBIT(entry)) {
|
||||
ehci_set_state(ehci, async, EST_ACTIVE);
|
||||
goto out;
|
||||
}
|
||||
@@ -1705,7 +1704,8 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
|
||||
if (q->qh.token & QTD_TOKEN_HALT) {
|
||||
ehci_set_state(ehci, async, EST_HORIZONTALQH);
|
||||
|
||||
- } else if ((q->qh.token & QTD_TOKEN_ACTIVE) && (q->qh.current_qtd > 0x1000)) {
|
||||
+ } else if ((q->qh.token & QTD_TOKEN_ACTIVE) &&
|
||||
+ (NLPTR_TBIT(q->qh.current_qtd) == 0)) {
|
||||
q->qtdaddr = q->qh.current_qtd;
|
||||
ehci_set_state(ehci, async, EST_FETCHQTD);
|
||||
|
||||
@@ -1784,7 +1784,6 @@ static int ehci_state_advqueue(EHCIQueue *q, int async)
|
||||
* want data and alt-next qTD is valid
|
||||
*/
|
||||
if (((q->qh.token & QTD_TOKEN_TBYTES_MASK) != 0) &&
|
||||
- (q->qh.altnext_qtd > 0x1000) &&
|
||||
(NLPTR_TBIT(q->qh.altnext_qtd) == 0)) {
|
||||
q->qtdaddr = q->qh.altnext_qtd;
|
||||
ehci_set_state(q->ehci, async, EST_FETCHQTD);
|
||||
@@ -1792,8 +1791,7 @@ static int ehci_state_advqueue(EHCIQueue *q, int async)
|
||||
/*
|
||||
* next qTD is valid
|
||||
*/
|
||||
- } else if ((q->qh.next_qtd > 0x1000) &&
|
||||
- (NLPTR_TBIT(q->qh.next_qtd) == 0)) {
|
||||
+ } else if (NLPTR_TBIT(q->qh.next_qtd) == 0) {
|
||||
q->qtdaddr = q->qh.next_qtd;
|
||||
ehci_set_state(q->ehci, async, EST_FETCHQTD);
|
||||
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,219 +0,0 @@
|
||||
From 0f1e5b8d4f36de8b6b1301740226c9858b5a0318 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Tue, 28 Feb 2012 16:34:38 +0100
|
||||
Subject: [PATCH 128/140] usb-ehci: split our qh queue into async and periodic
|
||||
queues
|
||||
|
||||
qhs can be part of both the async and the periodic schedule, as is shown
|
||||
in later patches in this series it is useful to keep track of the qhs on
|
||||
a per schedule basis.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 62 ++++++++++++++++++++++++++++++++++-----------------------
|
||||
1 file changed, 37 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index 37076a9..980cce3 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -347,7 +347,6 @@ enum async_state {
|
||||
struct EHCIQueue {
|
||||
EHCIState *ehci;
|
||||
QTAILQ_ENTRY(EHCIQueue) next;
|
||||
- bool async_schedule;
|
||||
uint32_t seen;
|
||||
uint64_t ts;
|
||||
|
||||
@@ -367,6 +366,8 @@ struct EHCIQueue {
|
||||
int usb_status;
|
||||
};
|
||||
|
||||
+typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead;
|
||||
+
|
||||
struct EHCIState {
|
||||
PCIDevice dev;
|
||||
USBBus bus;
|
||||
@@ -410,7 +411,8 @@ struct EHCIState {
|
||||
USBPort ports[NB_PORTS];
|
||||
USBPort *companion_ports[NB_PORTS];
|
||||
uint32_t usbsts_pending;
|
||||
- QTAILQ_HEAD(, EHCIQueue) queues;
|
||||
+ EHCIQueueHead aqueues;
|
||||
+ EHCIQueueHead pqueues;
|
||||
|
||||
uint32_t a_fetch_addr; // which address to look at next
|
||||
uint32_t p_fetch_addr; // which address to look at next
|
||||
@@ -660,31 +662,34 @@ static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
|
||||
|
||||
static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
|
||||
{
|
||||
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
|
||||
EHCIQueue *q;
|
||||
|
||||
q = g_malloc0(sizeof(*q));
|
||||
q->ehci = ehci;
|
||||
- q->async_schedule = async;
|
||||
- QTAILQ_INSERT_HEAD(&ehci->queues, q, next);
|
||||
+ QTAILQ_INSERT_HEAD(head, q, next);
|
||||
trace_usb_ehci_queue_action(q, "alloc");
|
||||
return q;
|
||||
}
|
||||
|
||||
-static void ehci_free_queue(EHCIQueue *q)
|
||||
+static void ehci_free_queue(EHCIQueue *q, int async)
|
||||
{
|
||||
+ EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues;
|
||||
trace_usb_ehci_queue_action(q, "free");
|
||||
if (q->async == EHCI_ASYNC_INFLIGHT) {
|
||||
usb_cancel_packet(&q->packet);
|
||||
}
|
||||
- QTAILQ_REMOVE(&q->ehci->queues, q, next);
|
||||
+ QTAILQ_REMOVE(head, q, next);
|
||||
g_free(q);
|
||||
}
|
||||
|
||||
-static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr)
|
||||
+static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
|
||||
+ int async)
|
||||
{
|
||||
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
|
||||
EHCIQueue *q;
|
||||
|
||||
- QTAILQ_FOREACH(q, &ehci->queues, next) {
|
||||
+ QTAILQ_FOREACH(q, head, next) {
|
||||
if (addr == q->qhaddr) {
|
||||
return q;
|
||||
}
|
||||
@@ -692,11 +697,12 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static void ehci_queues_rip_unused(EHCIState *ehci)
|
||||
+static void ehci_queues_rip_unused(EHCIState *ehci, int async)
|
||||
{
|
||||
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
|
||||
EHCIQueue *q, *tmp;
|
||||
|
||||
- QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
|
||||
+ QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
|
||||
if (q->seen) {
|
||||
q->seen = 0;
|
||||
q->ts = ehci->last_run_ns;
|
||||
@@ -706,28 +712,30 @@ static void ehci_queues_rip_unused(EHCIState *ehci)
|
||||
/* allow 0.25 sec idle */
|
||||
continue;
|
||||
}
|
||||
- ehci_free_queue(q);
|
||||
+ ehci_free_queue(q, async);
|
||||
}
|
||||
}
|
||||
|
||||
-static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev)
|
||||
+static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
|
||||
{
|
||||
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
|
||||
EHCIQueue *q, *tmp;
|
||||
|
||||
- QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
|
||||
+ QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
|
||||
if (q->packet.owner != dev) {
|
||||
continue;
|
||||
}
|
||||
- ehci_free_queue(q);
|
||||
+ ehci_free_queue(q, async);
|
||||
}
|
||||
}
|
||||
|
||||
-static void ehci_queues_rip_all(EHCIState *ehci)
|
||||
+static void ehci_queues_rip_all(EHCIState *ehci, int async)
|
||||
{
|
||||
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
|
||||
EHCIQueue *q, *tmp;
|
||||
|
||||
- QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
|
||||
- ehci_free_queue(q);
|
||||
+ QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
|
||||
+ ehci_free_queue(q, async);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -772,7 +780,8 @@ static void ehci_detach(USBPort *port)
|
||||
return;
|
||||
}
|
||||
|
||||
- ehci_queues_rip_device(s, port->dev);
|
||||
+ ehci_queues_rip_device(s, port->dev, 0);
|
||||
+ ehci_queues_rip_device(s, port->dev, 1);
|
||||
|
||||
*portsc &= ~(PORTSC_CONNECT|PORTSC_PED);
|
||||
*portsc |= PORTSC_CSC;
|
||||
@@ -792,7 +801,8 @@ static void ehci_child_detach(USBPort *port, USBDevice *child)
|
||||
return;
|
||||
}
|
||||
|
||||
- ehci_queues_rip_device(s, child);
|
||||
+ ehci_queues_rip_device(s, child, 0);
|
||||
+ ehci_queues_rip_device(s, child, 1);
|
||||
}
|
||||
|
||||
static void ehci_wakeup(USBPort *port)
|
||||
@@ -890,7 +900,8 @@ static void ehci_reset(void *opaque)
|
||||
usb_send_msg(devs[i], USB_MSG_RESET);
|
||||
}
|
||||
}
|
||||
- ehci_queues_rip_all(s);
|
||||
+ ehci_queues_rip_all(s, 0);
|
||||
+ ehci_queues_rip_all(s, 1);
|
||||
}
|
||||
|
||||
static uint32_t ehci_mem_readb(void *ptr, target_phys_addr_t addr)
|
||||
@@ -1554,7 +1565,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci, int async)
|
||||
ehci_set_usbsts(ehci, USBSTS_REC);
|
||||
}
|
||||
|
||||
- ehci_queues_rip_unused(ehci);
|
||||
+ ehci_queues_rip_unused(ehci, async);
|
||||
|
||||
/* Find the head of the list (4.9.1.1) */
|
||||
for(i = 0; i < MAX_QH; i++) {
|
||||
@@ -1641,7 +1652,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
|
||||
int reload;
|
||||
|
||||
entry = ehci_get_fetch_addr(ehci, async);
|
||||
- q = ehci_find_queue_by_qh(ehci, entry);
|
||||
+ q = ehci_find_queue_by_qh(ehci, entry, async);
|
||||
if (NULL == q) {
|
||||
q = ehci_alloc_queue(ehci, async);
|
||||
}
|
||||
@@ -2092,7 +2103,7 @@ static void ehci_advance_state(EHCIState *ehci,
|
||||
|
||||
static void ehci_advance_async_state(EHCIState *ehci)
|
||||
{
|
||||
- int async = 1;
|
||||
+ const int async = 1;
|
||||
|
||||
switch(ehci_get_state(ehci, async)) {
|
||||
case EST_INACTIVE:
|
||||
@@ -2149,7 +2160,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
|
||||
{
|
||||
uint32_t entry;
|
||||
uint32_t list;
|
||||
- int async = 0;
|
||||
+ const int async = 0;
|
||||
|
||||
// 4.6
|
||||
|
||||
@@ -2366,7 +2377,8 @@ static int usb_ehci_initfn(PCIDevice *dev)
|
||||
}
|
||||
|
||||
s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s);
|
||||
- QTAILQ_INIT(&s->queues);
|
||||
+ QTAILQ_INIT(&s->aqueues);
|
||||
+ QTAILQ_INIT(&s->pqueues);
|
||||
|
||||
qemu_register_reset(ehci_reset, s);
|
||||
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,42 +0,0 @@
|
||||
From 320063f7165c5a5f9ddd5a09a4663bc1a81f5bd6 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Fri, 2 Mar 2012 13:52:44 +0100
|
||||
Subject: [PATCH 129/140] usb-ehci: always call ehci_queues_rip_unused for
|
||||
period queues
|
||||
|
||||
Before this patch USB 2 devices with interrupt endpoints were not working
|
||||
properly. The problem is that to avoid loops we stop processing as soon
|
||||
as we encounter a queue-head (qh) we've already seen since qhs can be linked
|
||||
in a circular fashion, this is tracked by the seen flag in our qh struct.
|
||||
|
||||
The resetting of the seen flag is done from ehci_queues_rip_unused which
|
||||
before this patch was only called when executing the statemachine for the
|
||||
async schedule.
|
||||
|
||||
But packets for interrupt endpoints are part of the periodic schedule! So what
|
||||
would happen is that when there were no ctrl or bulk packets for a USB 2
|
||||
device with an interrupt endpoint, the async schedule would become non
|
||||
active, then ehci_queues_rip_unused would no longer get called and when
|
||||
processing the qhs for the interrupt endpoints from the periodic schedule
|
||||
their seen bit would still be 1 and they would be skipped.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index 980cce3..422afc8 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -2195,6 +2195,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
|
||||
ehci_set_fetch_addr(ehci, async,entry);
|
||||
ehci_set_state(ehci, async, EST_FETCHENTRY);
|
||||
ehci_advance_state(ehci, async);
|
||||
+ ehci_queues_rip_unused(ehci, async, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,115 +0,0 @@
|
||||
From 35562fb521547e081e732453a6395fc00d9ee9e4 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Thu, 1 Mar 2012 15:20:17 +0100
|
||||
Subject: [PATCH 130/140] usb-ehci: Drop cached qhs when the doorbell gets
|
||||
rung
|
||||
|
||||
The purpose of the IAAD bit / the doorbell is to make the ehci controller
|
||||
forget about cached qhs, this is mainly used when cancelling transactions,
|
||||
the qh is unlinked from the async schedule and then the doorbell gets rung,
|
||||
once the doorbell is acked by the controller the hcd knows that the qh is
|
||||
no longer in use and that it can do something else with the memory, such
|
||||
as re-use it for a new qh! But we keep our struct representing this qh around
|
||||
for circa 250 ms. This allows for a (mightily large) race window where the
|
||||
following could happen:
|
||||
-hcd submits a qh at address 0xdeadbeef
|
||||
-our ehci code sees the qh, sends a request to a usb-device, gets a result
|
||||
of USB_RET_ASYNC, sets the async_state of the qh to EHCI_ASYNC_INFLIGHT
|
||||
-hcd unlinks the qh at address 0xdeadbeef
|
||||
-hcd rings the doorbell, wait for us to ack it
|
||||
-hcd re-uses the qh at address 0xdeadbeef
|
||||
-our ehci code sees the qh, looks in the async_queue, sees there already is
|
||||
a qh at address 0xdeadbeef there with async_state of EHCI_ASYNC_INFLIGHT,
|
||||
does nothing
|
||||
-the *original* (which the hcd thinks it has cancelled) transaction finishes
|
||||
-our ehci code sees the qh on yet another pass through the async list,
|
||||
looks in the async_queue, sees there already is a qh at address 0xdeadbeef
|
||||
there with async_state of EHCI_ASYNC_COMPLETED, and finished the transaction
|
||||
with the results of the *original* transaction.
|
||||
|
||||
Not good (tm), this patch fixes this race by removing all qhs which have not
|
||||
been seen during the last cycle through the async list immidiately when the
|
||||
doorbell is rung.
|
||||
|
||||
Note this patch does not fix any actually observed problem, but upon
|
||||
reading of the EHCI spec it became apparent to me that the above race could
|
||||
happen and the usb-ehci behavior from before this patch is not good.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 31 ++++++++++++++++---------------
|
||||
1 file changed, 16 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index 422afc8..b8ba483 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -697,7 +697,7 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static void ehci_queues_rip_unused(EHCIState *ehci, int async)
|
||||
+static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
|
||||
{
|
||||
EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
|
||||
EHCIQueue *q, *tmp;
|
||||
@@ -708,7 +708,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async)
|
||||
q->ts = ehci->last_run_ns;
|
||||
continue;
|
||||
}
|
||||
- if (ehci->last_run_ns < q->ts + 250000000) {
|
||||
+ if (!flush && ehci->last_run_ns < q->ts + 250000000) {
|
||||
/* allow 0.25 sec idle */
|
||||
continue;
|
||||
}
|
||||
@@ -1565,7 +1565,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci, int async)
|
||||
ehci_set_usbsts(ehci, USBSTS_REC);
|
||||
}
|
||||
|
||||
- ehci_queues_rip_unused(ehci, async);
|
||||
+ ehci_queues_rip_unused(ehci, async, 0);
|
||||
|
||||
/* Find the head of the list (4.9.1.1) */
|
||||
for(i = 0; i < MAX_QH; i++) {
|
||||
@@ -2121,18 +2121,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
|
||||
break;
|
||||
}
|
||||
|
||||
- /* If the doorbell is set, the guest wants to make a change to the
|
||||
- * schedule. The host controller needs to release cached data.
|
||||
- * (section 4.8.2)
|
||||
- */
|
||||
- if (ehci->usbcmd & USBCMD_IAAD) {
|
||||
- DPRINTF("ASYNC: doorbell request acknowledged\n");
|
||||
- ehci->usbcmd &= ~USBCMD_IAAD;
|
||||
- ehci_set_interrupt(ehci, USBSTS_IAA);
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- /* make sure guest has acknowledged */
|
||||
+ /* make sure guest has acknowledged the doorbell interrupt */
|
||||
/* TO-DO: is this really needed? */
|
||||
if (ehci->usbsts & USBSTS_IAA) {
|
||||
DPRINTF("IAA status bit still set.\n");
|
||||
@@ -2146,6 +2135,18 @@ static void ehci_advance_async_state(EHCIState *ehci)
|
||||
|
||||
ehci_set_state(ehci, async, EST_WAITLISTHEAD);
|
||||
ehci_advance_state(ehci, async);
|
||||
+
|
||||
+ /* If the doorbell is set, the guest wants to make a change to the
|
||||
+ * schedule. The host controller needs to release cached data.
|
||||
+ * (section 4.8.2)
|
||||
+ */
|
||||
+ if (ehci->usbcmd & USBCMD_IAAD) {
|
||||
+ /* Remove all unseen qhs from the async qhs queue */
|
||||
+ ehci_queues_rip_unused(ehci, async, 1);
|
||||
+ DPRINTF("ASYNC: doorbell request acknowledged\n");
|
||||
+ ehci->usbcmd &= ~USBCMD_IAAD;
|
||||
+ ehci_set_interrupt(ehci, USBSTS_IAA);
|
||||
+ }
|
||||
break;
|
||||
|
||||
default:
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,44 +0,0 @@
|
||||
From cbb6384d32c4926822ba9216992253deef9ef3b5 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Fri, 2 Mar 2012 11:02:04 +0100
|
||||
Subject: [PATCH 131/140] usb-ehci: Rip the queues when the async or period
|
||||
schedule is halted
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index b8ba483..11eded7 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -1054,7 +1054,8 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
|
||||
|
||||
if (!(val & USBCMD_RUNSTOP) && (s->usbcmd & USBCMD_RUNSTOP)) {
|
||||
qemu_del_timer(s->frame_timer);
|
||||
- // TODO - should finish out some stuff before setting halt
|
||||
+ ehci_queues_rip_all(s, 0);
|
||||
+ ehci_queues_rip_all(s, 1);
|
||||
ehci_set_usbsts(s, USBSTS_HALT);
|
||||
}
|
||||
|
||||
@@ -2116,6 +2117,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
|
||||
|
||||
case EST_ACTIVE:
|
||||
if ( !(ehci->usbcmd & USBCMD_ASE)) {
|
||||
+ ehci_queues_rip_all(ehci, async);
|
||||
ehci_clear_usbsts(ehci, USBSTS_ASS);
|
||||
ehci_set_state(ehci, async, EST_INACTIVE);
|
||||
break;
|
||||
@@ -2176,6 +2178,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
|
||||
|
||||
case EST_ACTIVE:
|
||||
if ( !(ehci->frindex & 7) && !(ehci->usbcmd & USBCMD_PSE)) {
|
||||
+ ehci_queues_rip_all(ehci, async);
|
||||
ehci_clear_usbsts(ehci, USBSTS_PSS);
|
||||
ehci_set_state(ehci, async, EST_INACTIVE);
|
||||
break;
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,33 +0,0 @@
|
||||
From 73a9969c47459ee208d6247999823f2a36ee51fe Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Thu, 1 Mar 2012 16:34:56 +0100
|
||||
Subject: [PATCH 132/140] usb-ehci: Any packet completion except for NAK
|
||||
should set the interrupt
|
||||
|
||||
As clearly stated in the 2.3.2 of the EHCI spec, any time USBERRINT get
|
||||
sets then if the td has its IOC bit set USBINT should be set as well.
|
||||
|
||||
This means that for any status except for USB_RET_NAK we should set
|
||||
USBINT if the IOC bit is set.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index 11eded7..bc5f591 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -1338,7 +1338,7 @@ err:
|
||||
q->qh.token ^= QTD_TOKEN_DTOGGLE;
|
||||
q->qh.token &= ~QTD_TOKEN_ACTIVE;
|
||||
|
||||
- if ((q->usb_status >= 0) && (q->qh.token & QTD_TOKEN_IOC)) {
|
||||
+ if ((q->usb_status != USB_RET_NAK) && (q->qh.token & QTD_TOKEN_IOC)) {
|
||||
ehci_record_interrupt(q->ehci, USBSTS_INT);
|
||||
}
|
||||
}
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,72 +0,0 @@
|
||||
From 6e6bfa88ae3867afd8258b43e3c05cba2585ee37 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Thu, 1 Mar 2012 21:43:56 +0100
|
||||
Subject: [PATCH 133/140] usb-ehci: Fix cerr tracking
|
||||
|
||||
cerr should only be decremented on errors which cause XactErr to be set, and
|
||||
when that happens the failing transaction should be retried until cerr reaches
|
||||
0 and only then should USBSTS_ERRINT be set (and inactive cleared and
|
||||
USBSTS_INT set if requested).
|
||||
|
||||
Since we don't have any hardware level errors (and in case of redirection
|
||||
the real hardware has already retried), re-trying makes no sense, so
|
||||
immediately set cerr to 0 on errors which set XactErr.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 19 ++++++-------------
|
||||
1 file changed, 6 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index bc5f591..a3d5c11 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -1269,7 +1269,7 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
|
||||
|
||||
static void ehci_execute_complete(EHCIQueue *q)
|
||||
{
|
||||
- int c_err, reload;
|
||||
+ int reload;
|
||||
|
||||
assert(q->async != EHCI_ASYNC_INFLIGHT);
|
||||
q->async = EHCI_ASYNC_NONE;
|
||||
@@ -1278,15 +1278,10 @@ static void ehci_execute_complete(EHCIQueue *q)
|
||||
q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status);
|
||||
|
||||
if (q->usb_status < 0) {
|
||||
-err:
|
||||
- /* TO-DO: put this is in a function that can be invoked below as well */
|
||||
- c_err = get_field(q->qh.token, QTD_TOKEN_CERR);
|
||||
- c_err--;
|
||||
- set_field(&q->qh.token, c_err, QTD_TOKEN_CERR);
|
||||
-
|
||||
switch(q->usb_status) {
|
||||
case USB_RET_NODEV:
|
||||
q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
|
||||
+ set_field(&q->qh.token, 0, QTD_TOKEN_CERR);
|
||||
ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
|
||||
break;
|
||||
case USB_RET_STALL:
|
||||
@@ -1314,15 +1309,13 @@ err:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
+ } else if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
|
||||
+ q->usb_status = USB_RET_BABBLE;
|
||||
+ q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
|
||||
+ ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
|
||||
} else {
|
||||
- // DPRINTF("Short packet condition\n");
|
||||
// TODO check 4.12 for splits
|
||||
|
||||
- if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
|
||||
- q->usb_status = USB_RET_BABBLE;
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
if (q->tbytes && q->pid == USB_TOKEN_IN) {
|
||||
q->tbytes -= q->usb_status;
|
||||
} else {
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,78 +0,0 @@
|
||||
From 6177c3610b6416a7200ae6c6985f01fccdbdc7e5 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Thu, 1 Mar 2012 23:11:13 +0100
|
||||
Subject: [PATCH 134/140] usb-ehci: Remove dead nakcnt code
|
||||
|
||||
This patch removes 2 bits of dead nakcnt code:
|
||||
|
||||
1) usb_ehci_execute calls ehci_qh_do_overlay which does:
|
||||
nakcnt = reload;
|
||||
and then has a block of code which is conditional on:
|
||||
if (reload && !nakcnt) {
|
||||
which ofcourse is never true now as nakcnt == reload.
|
||||
|
||||
2) ehci_state_fetchqh does:
|
||||
nakcnt = reload;
|
||||
but before nakcnt is ever used ehci_state_fetchqh is always followed
|
||||
by a ehci_qh_do_overlay call which also does:
|
||||
nakcnt = reload;
|
||||
So doing this from ehci_state_fetchqh is redundant.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 20 --------------------
|
||||
1 file changed, 20 deletions(-)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index a3d5c11..92cdf2a 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -1643,7 +1643,6 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
|
||||
{
|
||||
uint32_t entry;
|
||||
EHCIQueue *q;
|
||||
- int reload;
|
||||
|
||||
entry = ehci_get_fetch_addr(ehci, async);
|
||||
q = ehci_find_queue_by_qh(ehci, entry, async);
|
||||
@@ -1701,11 +1700,6 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
|
||||
}
|
||||
#endif
|
||||
|
||||
- reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
|
||||
- if (reload) {
|
||||
- set_field(&q->qh.altnext_qtd, reload, QH_ALTNEXT_NAKCNT);
|
||||
- }
|
||||
-
|
||||
if (q->qh.token & QTD_TOKEN_HALT) {
|
||||
ehci_set_state(ehci, async, EST_HORIZONTALQH);
|
||||
|
||||
@@ -1865,25 +1859,11 @@ static void ehci_flush_qh(EHCIQueue *q)
|
||||
static int ehci_state_execute(EHCIQueue *q, int async)
|
||||
{
|
||||
int again = 0;
|
||||
- int reload, nakcnt;
|
||||
- int smask;
|
||||
|
||||
if (ehci_qh_do_overlay(q) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
- smask = get_field(q->qh.epcap, QH_EPCAP_SMASK);
|
||||
-
|
||||
- if (!smask) {
|
||||
- reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
|
||||
- nakcnt = get_field(q->qh.altnext_qtd, QH_ALTNEXT_NAKCNT);
|
||||
- if (reload && !nakcnt) {
|
||||
- ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
|
||||
- again = 1;
|
||||
- goto out;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
// TODO verify enough time remains in the uframe as in 4.4.1.1
|
||||
// TODO write back ptr to async list when done or out of time
|
||||
// TODO Windows does not seem to ever set the MULT field
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,120 +0,0 @@
|
||||
From 2d9b6cb9bd00ede47635dc4db413f647143d5a1d Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Thu, 1 Mar 2012 23:55:11 +0100
|
||||
Subject: [PATCH 135/140] usb-ehci: Fix and simplify nakcnt handling
|
||||
|
||||
The nakcnt code in ehci_execute_complete() marked transactions as finished
|
||||
when a packet completed with a result of USB_RET_NAK, but USB_RET_NAK
|
||||
means that the device cannot receive / send data at that time and that
|
||||
the transaction should be retried later, which is also what the usb-uhci
|
||||
and usb-ohci code does.
|
||||
|
||||
Note that there already was some special code in place to handle this
|
||||
for interrupt endpoints in the form of doing a return from
|
||||
ehci_execute_complete() when reload == 0, but that for bulk transactions
|
||||
this was not handled correctly (where as for example the usb-ccid device does
|
||||
return USB_RET_NAK for bulk packets).
|
||||
|
||||
Besides that the code in ehci_execute_complete() decrement nakcnt by 1
|
||||
on a packet result of USB_RET_NAK, but
|
||||
-since the transaction got marked as finished,
|
||||
nakcnt would never be decremented again
|
||||
-there is no code checking for nakcnt becoming 0
|
||||
-there is no use in re-trying the transaction within the same usb frame /
|
||||
usb-ehci frame-timer call, since the status of emulated devices won't change
|
||||
as long as the usb-ehci frame-timer is running
|
||||
So we should simply set the nakcnt to 0 when we get a USB_RET_NAK, thus
|
||||
claiming that we've tried reload times (or as many times as possible if
|
||||
reload is 0).
|
||||
|
||||
Besides the code in ehci_execute_complete() handling USB_RET_NAK there
|
||||
was also code handling it in ehci_state_executing(), which calls
|
||||
ehci_execute_complete(), and then does its own handling on top of the handling
|
||||
in ehci_execute_complete(), this code would decrement nakcnt *again* (if not
|
||||
already 0), or restore the reload value (which was never changed) on success.
|
||||
|
||||
Since the double decrement was wrong to begin with, and is no longer needed
|
||||
now that we set nakcnt directly to 0 on USB_RET_NAK, and the restore of reload
|
||||
is not needed either, this patch simply removes all nakcnt handling from
|
||||
ehci_state_executing().
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 32 ++++----------------------------
|
||||
1 file changed, 4 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index 92cdf2a..aa6fae5 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -1269,8 +1269,6 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
|
||||
|
||||
static void ehci_execute_complete(EHCIQueue *q)
|
||||
{
|
||||
- int reload;
|
||||
-
|
||||
assert(q->async != EHCI_ASYNC_INFLIGHT);
|
||||
q->async = EHCI_ASYNC_NONE;
|
||||
|
||||
@@ -1289,16 +1287,8 @@ static void ehci_execute_complete(EHCIQueue *q)
|
||||
ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
|
||||
break;
|
||||
case USB_RET_NAK:
|
||||
- /* 4.10.3 */
|
||||
- reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
|
||||
- if ((q->pid == USB_TOKEN_IN) && reload) {
|
||||
- int nakcnt = get_field(q->qh.altnext_qtd, QH_ALTNEXT_NAKCNT);
|
||||
- nakcnt--;
|
||||
- set_field(&q->qh.altnext_qtd, nakcnt, QH_ALTNEXT_NAKCNT);
|
||||
- } else if (!reload) {
|
||||
- return;
|
||||
- }
|
||||
- break;
|
||||
+ set_field(&q->qh.altnext_qtd, 0, QH_ALTNEXT_NAKCNT);
|
||||
+ return; /* We're not done yet with this transaction */
|
||||
case USB_RET_BABBLE:
|
||||
q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
|
||||
ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
|
||||
@@ -1331,7 +1321,7 @@ static void ehci_execute_complete(EHCIQueue *q)
|
||||
q->qh.token ^= QTD_TOKEN_DTOGGLE;
|
||||
q->qh.token &= ~QTD_TOKEN_ACTIVE;
|
||||
|
||||
- if ((q->usb_status != USB_RET_NAK) && (q->qh.token & QTD_TOKEN_IOC)) {
|
||||
+ if (q->qh.token & QTD_TOKEN_IOC) {
|
||||
ehci_record_interrupt(q->ehci, USBSTS_INT);
|
||||
}
|
||||
}
|
||||
@@ -1905,7 +1895,6 @@ out:
|
||||
static int ehci_state_executing(EHCIQueue *q, int async)
|
||||
{
|
||||
int again = 0;
|
||||
- int reload, nakcnt;
|
||||
|
||||
ehci_execute_complete(q);
|
||||
if (q->usb_status == USB_RET_ASYNC) {
|
||||
@@ -1925,21 +1914,8 @@ static int ehci_state_executing(EHCIQueue *q, int async)
|
||||
// counter decrements to 0
|
||||
}
|
||||
|
||||
- reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
|
||||
- if (reload) {
|
||||
- nakcnt = get_field(q->qh.altnext_qtd, QH_ALTNEXT_NAKCNT);
|
||||
- if (q->usb_status == USB_RET_NAK) {
|
||||
- if (nakcnt) {
|
||||
- nakcnt--;
|
||||
- }
|
||||
- } else {
|
||||
- nakcnt = reload;
|
||||
- }
|
||||
- set_field(&q->qh.altnext_qtd, nakcnt, QH_ALTNEXT_NAKCNT);
|
||||
- }
|
||||
-
|
||||
/* 4.10.5 */
|
||||
- if ((q->usb_status == USB_RET_NAK) || (q->qh.token & QTD_TOKEN_ACTIVE)) {
|
||||
+ if (q->usb_status == USB_RET_NAK) {
|
||||
ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
|
||||
} else {
|
||||
ehci_set_state(q->ehci, async, EST_WRITEBACK);
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,114 +0,0 @@
|
||||
From 0e6cd6e6da3d0648204526e8ebd79047f48d009a Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Fri, 2 Mar 2012 00:36:50 +0100
|
||||
Subject: [PATCH 136/140] usb-ehci: Remove dead isoch_pause code
|
||||
|
||||
I see no value in keeping this around, so lets delete it.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 60 +++++++++++++++------------------------------------------
|
||||
1 file changed, 15 insertions(+), 45 deletions(-)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index aa6fae5..72c3f2a 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -419,7 +419,6 @@ struct EHCIState {
|
||||
|
||||
USBPacket ipacket;
|
||||
QEMUSGList isgl;
|
||||
- int isoch_pause;
|
||||
|
||||
uint64_t last_run_ns;
|
||||
};
|
||||
@@ -886,7 +885,6 @@ static void ehci_reset(void *opaque)
|
||||
|
||||
s->astate = EST_INACTIVE;
|
||||
s->pstate = EST_INACTIVE;
|
||||
- s->isoch_pause = -1;
|
||||
s->attach_poll_counter = 0;
|
||||
|
||||
for(i = 0; i < NB_PORTS; i++) {
|
||||
@@ -1468,46 +1466,7 @@ static int ehci_process_itd(EHCIState *ehci,
|
||||
usb_packet_unmap(&ehci->ipacket);
|
||||
qemu_sglist_destroy(&ehci->isgl);
|
||||
|
||||
-#if 0
|
||||
- /* In isoch, there is no facility to indicate a NAK so let's
|
||||
- * instead just complete a zero-byte transaction. Setting
|
||||
- * DBERR seems too draconian.
|
||||
- */
|
||||
-
|
||||
- if (ret == USB_RET_NAK) {
|
||||
- if (ehci->isoch_pause > 0) {
|
||||
- DPRINTF("ISOCH: received a NAK but paused so returning\n");
|
||||
- ehci->isoch_pause--;
|
||||
- return 0;
|
||||
- } else if (ehci->isoch_pause == -1) {
|
||||
- DPRINTF("ISOCH: recv NAK & isoch pause inactive, setting\n");
|
||||
- // Pause frindex for up to 50 msec waiting for data from
|
||||
- // remote
|
||||
- ehci->isoch_pause = 50;
|
||||
- return 0;
|
||||
- } else {
|
||||
- DPRINTF("ISOCH: isoch pause timeout! return 0\n");
|
||||
- ret = 0;
|
||||
- }
|
||||
- } else {
|
||||
- DPRINTF("ISOCH: received ACK, clearing pause\n");
|
||||
- ehci->isoch_pause = -1;
|
||||
- }
|
||||
-#else
|
||||
- if (ret == USB_RET_NAK) {
|
||||
- ret = 0;
|
||||
- }
|
||||
-#endif
|
||||
-
|
||||
- if (ret >= 0) {
|
||||
- if (!dir) {
|
||||
- /* OUT */
|
||||
- set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH);
|
||||
- } else {
|
||||
- /* IN */
|
||||
- set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
|
||||
- }
|
||||
- } else {
|
||||
+ if (ret < 0) {
|
||||
switch (ret) {
|
||||
default:
|
||||
fprintf(stderr, "Unexpected iso usb result: %d\n", ret);
|
||||
@@ -1523,6 +1482,19 @@ static int ehci_process_itd(EHCIState *ehci,
|
||||
itd->transact[i] |= ITD_XACT_BABBLE;
|
||||
ehci_record_interrupt(ehci, USBSTS_ERRINT);
|
||||
break;
|
||||
+ case USB_RET_NAK:
|
||||
+ /* no data for us, so do a zero-length transfer */
|
||||
+ ret = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (ret >= 0) {
|
||||
+ if (!dir) {
|
||||
+ /* OUT */
|
||||
+ set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH);
|
||||
+ } else {
|
||||
+ /* IN */
|
||||
+ set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
|
||||
}
|
||||
}
|
||||
if (itd->transact[i] & ITD_XACT_IOC) {
|
||||
@@ -2176,9 +2148,7 @@ static void ehci_frame_timer(void *opaque)
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
if ( !(ehci->usbsts & USBSTS_HALT)) {
|
||||
- if (ehci->isoch_pause <= 0) {
|
||||
- ehci->frindex += 8;
|
||||
- }
|
||||
+ ehci->frindex += 8;
|
||||
|
||||
if (ehci->frindex > 0x00001fff) {
|
||||
ehci->frindex = 0;
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,70 +0,0 @@
|
||||
From 9726556968aef62213b80bd4e351a4f7f721f941 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Thu, 1 Mar 2012 17:22:14 +0100
|
||||
Subject: [PATCH 137/140] usb: return BABBLE rather then NAK when we receive
|
||||
too much data
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
usb-linux.c | 8 +++++++-
|
||||
usb-redir.c | 4 ++--
|
||||
2 files changed, 9 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/usb-linux.c b/usb-linux.c
|
||||
index ab4c693..b2d70f9 100644
|
||||
--- a/usb-linux.c
|
||||
+++ b/usb-linux.c
|
||||
@@ -390,6 +390,10 @@ static void async_complete(void *opaque)
|
||||
p->result = USB_RET_STALL;
|
||||
break;
|
||||
|
||||
+ case -EOVERFLOW:
|
||||
+ p->result = USB_RET_BABBLE;
|
||||
+ break;
|
||||
+
|
||||
default:
|
||||
p->result = USB_RET_NAK;
|
||||
break;
|
||||
@@ -718,6 +722,8 @@ static int urb_status_to_usb_ret(int status)
|
||||
switch (status) {
|
||||
case -EPIPE:
|
||||
return USB_RET_STALL;
|
||||
+ case -EOVERFLOW:
|
||||
+ return USB_RET_BABBLE;
|
||||
default:
|
||||
return USB_RET_NAK;
|
||||
}
|
||||
@@ -755,7 +761,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
|
||||
} else if (aurb[i].urb.iso_frame_desc[j].actual_length
|
||||
> p->iov.size) {
|
||||
printf("husb: received iso data is larger then packet\n");
|
||||
- len = USB_RET_NAK;
|
||||
+ len = USB_RET_BABBLE;
|
||||
/* All good copy data over */
|
||||
} else {
|
||||
len = aurb[i].urb.iso_frame_desc[j].actual_length;
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index 629c87d..61860ef 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -457,7 +457,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
|
||||
ERROR("received iso data is larger then packet ep %02X (%d > %d)\n",
|
||||
ep, len, (int)p->iov.size);
|
||||
bufp_free(dev, isop, ep);
|
||||
- return USB_RET_NAK;
|
||||
+ return USB_RET_BABBLE;
|
||||
}
|
||||
usb_packet_copy(p, isop->data, len);
|
||||
bufp_free(dev, isop, ep);
|
||||
@@ -576,7 +576,7 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
|
||||
if (len > p->iov.size) {
|
||||
ERROR("received int data is larger then packet ep %02X\n", ep);
|
||||
bufp_free(dev, intp, ep);
|
||||
- return USB_RET_NAK;
|
||||
+ return USB_RET_BABBLE;
|
||||
}
|
||||
usb_packet_copy(p, intp->data, len);
|
||||
bufp_free(dev, intp, ep);
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,167 +0,0 @@
|
||||
From 2a6bbdddc2aca6af038c42054c3d3a7b09e5ac3a Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Fri, 2 Mar 2012 00:26:23 +0100
|
||||
Subject: [PATCH 138/140] usb: add USB_RET_IOERROR
|
||||
|
||||
We already have USB_RET_NAK, but that means that a device does not want
|
||||
to send/receive right now. But with host / network redirection we can
|
||||
actually have a transaction fail due to some io error, rather then ie
|
||||
the device just not having any data atm.
|
||||
|
||||
This patch adds a new error code named USB_RET_IOERROR for this, and uses
|
||||
it were appropriate.
|
||||
|
||||
Notes:
|
||||
-Currently all usb-controllers handle this the same as NODEV, but that
|
||||
may change in the future, OHCI could indicate a CRC error instead for example.
|
||||
-This patch does not touch hw/usb-musb.c, that is because the code in there
|
||||
handles STALL and NAK specially and has a if status < 0 generic catch all
|
||||
for all other errors
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 2 ++
|
||||
hw/usb-ohci.c | 2 ++
|
||||
hw/usb-uhci.c | 1 +
|
||||
hw/usb.h | 11 ++++++-----
|
||||
usb-linux.c | 4 ++--
|
||||
usb-redir.c | 9 ++++++---
|
||||
6 files changed, 19 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index 72c3f2a..ba1b9da 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -1275,6 +1275,7 @@ static void ehci_execute_complete(EHCIQueue *q)
|
||||
|
||||
if (q->usb_status < 0) {
|
||||
switch(q->usb_status) {
|
||||
+ case USB_RET_IOERROR:
|
||||
case USB_RET_NODEV:
|
||||
q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
|
||||
set_field(&q->qh.token, 0, QTD_TOKEN_CERR);
|
||||
@@ -1471,6 +1472,7 @@ static int ehci_process_itd(EHCIState *ehci,
|
||||
default:
|
||||
fprintf(stderr, "Unexpected iso usb result: %d\n", ret);
|
||||
/* Fall through */
|
||||
+ case USB_RET_IOERROR:
|
||||
case USB_RET_NODEV:
|
||||
/* 3.3.2: XACTERR is only allowed on IN transactions */
|
||||
if (dir) {
|
||||
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
|
||||
index c2981c5..d805497 100644
|
||||
--- a/hw/usb-ohci.c
|
||||
+++ b/hw/usb-ohci.c
|
||||
@@ -828,6 +828,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
|
||||
OHCI_CC_DATAUNDERRUN);
|
||||
} else {
|
||||
switch (ret) {
|
||||
+ case USB_RET_IOERROR:
|
||||
case USB_RET_NODEV:
|
||||
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
|
||||
OHCI_CC_DEVICENOTRESPONDING);
|
||||
@@ -1051,6 +1052,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
|
||||
OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN);
|
||||
} else {
|
||||
switch (ret) {
|
||||
+ case USB_RET_IOERROR:
|
||||
case USB_RET_NODEV:
|
||||
OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING);
|
||||
case USB_RET_NAK:
|
||||
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
|
||||
index f9e3ea5..a994943 100644
|
||||
--- a/hw/usb-uhci.c
|
||||
+++ b/hw/usb-uhci.c
|
||||
@@ -751,6 +751,7 @@ out:
|
||||
break;
|
||||
return 1;
|
||||
|
||||
+ case USB_RET_IOERROR:
|
||||
case USB_RET_NODEV:
|
||||
default:
|
||||
break;
|
||||
diff --git a/hw/usb.h b/hw/usb.h
|
||||
index c6e1870..4010e12 100644
|
||||
--- a/hw/usb.h
|
||||
+++ b/hw/usb.h
|
||||
@@ -41,11 +41,12 @@
|
||||
#define USB_MSG_DETACH 0x101
|
||||
#define USB_MSG_RESET 0x102
|
||||
|
||||
-#define USB_RET_NODEV (-1)
|
||||
-#define USB_RET_NAK (-2)
|
||||
-#define USB_RET_STALL (-3)
|
||||
-#define USB_RET_BABBLE (-4)
|
||||
-#define USB_RET_ASYNC (-5)
|
||||
+#define USB_RET_NODEV (-1)
|
||||
+#define USB_RET_NAK (-2)
|
||||
+#define USB_RET_STALL (-3)
|
||||
+#define USB_RET_BABBLE (-4)
|
||||
+#define USB_RET_IOERROR (-5)
|
||||
+#define USB_RET_ASYNC (-6)
|
||||
|
||||
#define USB_SPEED_LOW 0
|
||||
#define USB_SPEED_FULL 1
|
||||
diff --git a/usb-linux.c b/usb-linux.c
|
||||
index b2d70f9..9f13d1e 100644
|
||||
--- a/usb-linux.c
|
||||
+++ b/usb-linux.c
|
||||
@@ -395,7 +395,7 @@ static void async_complete(void *opaque)
|
||||
break;
|
||||
|
||||
default:
|
||||
- p->result = USB_RET_NAK;
|
||||
+ p->result = USB_RET_IOERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -725,7 +725,7 @@ static int urb_status_to_usb_ret(int status)
|
||||
case -EOVERFLOW:
|
||||
return USB_RET_BABBLE;
|
||||
default:
|
||||
- return USB_RET_NAK;
|
||||
+ return USB_RET_IOERROR;
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index 61860ef..f64443e 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -441,7 +441,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
|
||||
/* Check iso_error for stream errors, otherwise its an underrun */
|
||||
status = dev->endpoint[EP2I(ep)].iso_error;
|
||||
dev->endpoint[EP2I(ep)].iso_error = 0;
|
||||
- return status ? USB_RET_NAK : 0;
|
||||
+ return status ? USB_RET_IOERROR : 0;
|
||||
}
|
||||
DPRINTF2("iso-token-in ep %02X status %d len %d queue-size: %d\n", ep,
|
||||
isop->status, isop->len, dev->endpoint[EP2I(ep)].bufpq_size);
|
||||
@@ -449,7 +449,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
|
||||
status = isop->status;
|
||||
if (status != usb_redir_success) {
|
||||
bufp_free(dev, isop, ep);
|
||||
- return USB_RET_NAK;
|
||||
+ return USB_RET_IOERROR;
|
||||
}
|
||||
|
||||
len = isop->len;
|
||||
@@ -1045,11 +1045,14 @@ static int usbredir_handle_status(USBRedirDevice *dev,
|
||||
return USB_RET_STALL;
|
||||
case usb_redir_cancelled:
|
||||
WARNING("returning cancelled packet to HC?\n");
|
||||
+ return USB_RET_NAK;
|
||||
case usb_redir_inval:
|
||||
+ WARNING("got invalid param error from usb-host?\n");
|
||||
+ return USB_RET_NAK;
|
||||
case usb_redir_ioerror:
|
||||
case usb_redir_timeout:
|
||||
default:
|
||||
- return USB_RET_NAK;
|
||||
+ return USB_RET_IOERROR;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,40 +0,0 @@
|
||||
From 21946e621f14553b72cde7fae221ae390a427eac Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Thu, 23 Feb 2012 13:24:00 +0000
|
||||
Subject: [PATCH 139/140] usb-ehci: fix reset
|
||||
|
||||
Two reset fixes:
|
||||
* pick up s->usbcmd value after ehci_reset call to make sure it
|
||||
keeps the reset value and doesn't get rubbish filled in when
|
||||
val is written back to the mmio register array later on.
|
||||
* make sure the frame timer is zapped on reset.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index ba1b9da..ad0f6e1 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -900,6 +900,7 @@ static void ehci_reset(void *opaque)
|
||||
}
|
||||
ehci_queues_rip_all(s, 0);
|
||||
ehci_queues_rip_all(s, 1);
|
||||
+ qemu_del_timer(s->frame_timer);
|
||||
}
|
||||
|
||||
static uint32_t ehci_mem_readb(void *ptr, target_phys_addr_t addr)
|
||||
@@ -1059,7 +1060,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
|
||||
|
||||
if (val & USBCMD_HCRESET) {
|
||||
ehci_reset(s);
|
||||
- val &= ~USBCMD_HCRESET;
|
||||
+ val = s->usbcmd;
|
||||
}
|
||||
|
||||
/* not supporting dynamic frame list size at the moment */
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,42 +0,0 @@
|
||||
From 985b7cfbd45960bb74a13ad8044765a8e35f2251 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Sun, 4 Mar 2012 12:41:11 +0100
|
||||
Subject: [PATCH 140/140] usb-ehci: sanity-check iso xfers
|
||||
|
||||
This patch adds a sanity check to itd processing to make sure the
|
||||
endpoint addressed by the guest is actually an iso endpoint. Also
|
||||
verify that usb drivers don't return USB_RET_ASYNC which is illegal for
|
||||
iso xfers.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
(Cherry picked from: aa0568ff2559d7717f4684af6a83d0bd1a125f56)
|
||||
|
||||
[qemu-kvm-1.0: we don't track ep types on RHEL-6 like we do upstream, so we
|
||||
cannot check if an itd is pointing to a non iso ep in advance, but we do still
|
||||
need to make sure that we never handle an iso xfer async. So check if the
|
||||
device does want to handle it async, and if so cancel the xfer and treat it as
|
||||
a NAK, like upstream does when the ep type check fails.]
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index ad0f6e1..b5d7037 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -1485,6 +1485,10 @@ static int ehci_process_itd(EHCIState *ehci,
|
||||
itd->transact[i] |= ITD_XACT_BABBLE;
|
||||
ehci_record_interrupt(ehci, USBSTS_ERRINT);
|
||||
break;
|
||||
+ case USB_RET_ASYNC:
|
||||
+ /* ISO endpoints are never ASYNC, not an iso endpoint? */
|
||||
+ usb_cancel_packet(&ehci->ipacket);
|
||||
+ /* Treat this as a NAK (fall through) */
|
||||
case USB_RET_NAK:
|
||||
/* no data for us, so do a zero-length transfer */
|
||||
ret = 0;
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,74 +0,0 @@
|
||||
From 9d604ddc4770f8f25de148e9b35687817a5d4110 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Wed, 28 Mar 2012 20:31:32 +0200
|
||||
Subject: [PATCH 141/146] usb-ehci: frindex always is a 14 bits counter
|
||||
|
||||
frindex always is a 14 bits counter, and not a 13 bits one as we were
|
||||
emulating. There are some subtle hints to this in the spec, first of all
|
||||
"Table 2-12. FRINDEX - Frame Index Register" says:
|
||||
"Bit 13:0 Frame Index. The value in this register increments at the end of
|
||||
each time frame (e.g. micro-frame). Bits [N:3] are used for the Frame List
|
||||
current index. This means that each location of the frame list is accessed
|
||||
8 times (frames or micro-frames) before moving to the next index. The
|
||||
following illustrates values of N based on the value of the Frame List
|
||||
Size field in the USBCMD register.
|
||||
|
||||
USBCMD[Frame List Size] Number Elements N
|
||||
00b 1024 12
|
||||
01b 512 11
|
||||
10b 256 10
|
||||
11b Reserved"
|
||||
|
||||
Notice how the text talks about "Bits [N:3]" are used ..., it does
|
||||
NOT say that when N == 12 (our case) the counter will wrap from 8191 to 0,
|
||||
or in otherwords that it is a 13 bits counter (bits 0 - 12).
|
||||
|
||||
The other hint is in "Table 2-10. USBSTS USB Status Register Bit Definitions":
|
||||
|
||||
"Bit 3 Frame List Rollover - R/WC. The Host Controller sets this bit to a one
|
||||
when the Frame List Index (see Section 2.3.4) rolls over from its maximum value
|
||||
to zero. The exact value at which the rollover occurs depends on the frame
|
||||
list size. For example, if the frame list size (as programmed in the Frame
|
||||
List Size field of the USBCMD register) is 1024, the Frame Index Register
|
||||
rolls over every time FRINDEX[13] toggles. Similarly, if the size is 512,
|
||||
the Host Controller sets this bit to a one every time FRINDEX[12] toggles."
|
||||
|
||||
Notice how this text talks about setting bit 3 when bit 13 of frindex toggles
|
||||
(when there are 1024 entries, so our case), so this indicates that frindex
|
||||
has a bit 13 making it a 14 bit counter.
|
||||
|
||||
Besides these clear hints the real proof is in the pudding. Before this
|
||||
patch I could not stream data from a USB2 webcam under Windows XP, after
|
||||
this cam using a USB2 webcam under Windows XP works fine, and no regressions
|
||||
with other operating systems were seen.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 8 ++++++--
|
||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index b5d7037..3934bf0 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -2157,11 +2157,15 @@ static void ehci_frame_timer(void *opaque)
|
||||
if ( !(ehci->usbsts & USBSTS_HALT)) {
|
||||
ehci->frindex += 8;
|
||||
|
||||
- if (ehci->frindex > 0x00001fff) {
|
||||
- ehci->frindex = 0;
|
||||
+ if (ehci->frindex == 0x00002000) {
|
||||
ehci_set_interrupt(ehci, USBSTS_FLR);
|
||||
}
|
||||
|
||||
+ if (ehci->frindex == 0x00004000) {
|
||||
+ ehci_set_interrupt(ehci, USBSTS_FLR);
|
||||
+ ehci->frindex = 0;
|
||||
+ }
|
||||
+
|
||||
ehci->sofv = (ehci->frindex - 1) >> 3;
|
||||
ehci->sofv &= 0x000003ff;
|
||||
}
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,49 +0,0 @@
|
||||
From ef3477db39f2eb38610b7e99a4a4f4d8ddb903df Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Thu, 29 Mar 2012 16:37:34 +0200
|
||||
Subject: [PATCH 142/146] usb-ehci: Drop unused sofv value
|
||||
|
||||
The sofv value only ever gets a value assigned and is never used (read)
|
||||
anywhere, so we can just drop it.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 8 --------
|
||||
1 file changed, 8 deletions(-)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index 3934bf0..ff69587 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -403,7 +403,6 @@ struct EHCIState {
|
||||
/*
|
||||
* Internal states, shadow registers, etc
|
||||
*/
|
||||
- uint32_t sofv;
|
||||
QEMUTimer *frame_timer;
|
||||
int attach_poll_counter;
|
||||
int astate; // Current state in asynchronous schedule
|
||||
@@ -1082,10 +1081,6 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
|
||||
val &= USBINTR_MASK;
|
||||
break;
|
||||
|
||||
- case FRINDEX:
|
||||
- s->sofv = val >> 3;
|
||||
- break;
|
||||
-
|
||||
case CONFIGFLAG:
|
||||
val &= 0x1;
|
||||
if (val) {
|
||||
@@ -2165,9 +2160,6 @@ static void ehci_frame_timer(void *opaque)
|
||||
ehci_set_interrupt(ehci, USBSTS_FLR);
|
||||
ehci->frindex = 0;
|
||||
}
|
||||
-
|
||||
- ehci->sofv = (ehci->frindex - 1) >> 3;
|
||||
- ehci->sofv &= 0x000003ff;
|
||||
}
|
||||
|
||||
if (frames - i > ehci->maxframes) {
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,36 +0,0 @@
|
||||
From 89c9752afa77c6936ab9839d8fb1ce42147086b2 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Thu, 29 Mar 2012 16:41:23 +0200
|
||||
Subject: [PATCH 143/146] usb-redir: Notify our peer when we reject a device
|
||||
due to a speed mismatch
|
||||
|
||||
Also cleanup (reset) our device state when we reject a device due to a
|
||||
speed mismatch.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
usb-redir.c | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index f64443e..8ee3f07 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -845,7 +845,13 @@ static void usbredir_do_attach(void *opaque)
|
||||
{
|
||||
USBRedirDevice *dev = opaque;
|
||||
|
||||
- usb_device_attach(&dev->dev);
|
||||
+ if (usb_device_attach(&dev->dev) != 0) {
|
||||
+ usbredir_device_disconnect(dev);
|
||||
+ if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter)) {
|
||||
+ usbredirparser_send_filter_reject(dev->parser);
|
||||
+ usbredirparser_do_write(dev->parser);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
/*
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,47 +0,0 @@
|
||||
From c6b10d4d87d8158c1b0bd8648491db8501dff784 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Sat, 31 Mar 2012 13:07:24 +0200
|
||||
Subject: [PATCH 144/146] usb-redir: An interface count of 0 is a valid value
|
||||
|
||||
An interface-count of 0 happens when a device is in unconfigured state when
|
||||
it gets redirected. So we should not use 0 to detect not having received
|
||||
interface info from our peer.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
usb-redir.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index 8ee3f07..3187b68 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "hw/usb.h"
|
||||
|
||||
#define MAX_ENDPOINTS 32
|
||||
+#define NO_INTERFACE_INFO 255 /* Valid interface_count always <= 32 */
|
||||
#define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f))
|
||||
#define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f))
|
||||
|
||||
@@ -995,7 +996,7 @@ static void usbredir_handle_destroy(USBDevice *udev)
|
||||
|
||||
static int usbredir_check_filter(USBRedirDevice *dev)
|
||||
{
|
||||
- if (dev->interface_info.interface_count == 0) {
|
||||
+ if (dev->interface_info.interface_count == NO_INTERFACE_INFO) {
|
||||
ERROR("No interface info for device\n");
|
||||
goto error;
|
||||
}
|
||||
@@ -1158,7 +1159,7 @@ static void usbredir_device_disconnect(void *priv)
|
||||
for (i = 0; i < MAX_ENDPOINTS; i++) {
|
||||
QTAILQ_INIT(&dev->endpoint[i].bufpq);
|
||||
}
|
||||
- dev->interface_info.interface_count = 0;
|
||||
+ dev->interface_info.interface_count = NO_INTERFACE_INFO;
|
||||
}
|
||||
|
||||
static void usbredir_interface_info(void *priv,
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,30 +0,0 @@
|
||||
From 442d81d00308b0145307b175a1910c7443184a3f Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Sat, 31 Mar 2012 13:12:09 +0200
|
||||
Subject: [PATCH 145/146] usb-redir: Reset device address and speed on
|
||||
disconnect
|
||||
|
||||
Without this disconnected devices look like the last redirected device
|
||||
in the monitor in "info usb".
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
usb-redir.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index 3187b68..1a9d766 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -1160,6 +1160,8 @@ static void usbredir_device_disconnect(void *priv)
|
||||
QTAILQ_INIT(&dev->endpoint[i].bufpq);
|
||||
}
|
||||
dev->interface_info.interface_count = NO_INTERFACE_INFO;
|
||||
+ dev->dev.addr = 0;
|
||||
+ dev->dev.speed = 0;
|
||||
}
|
||||
|
||||
static void usbredir_interface_info(void *priv,
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,31 +0,0 @@
|
||||
From b467871a6a08b8ff12382e33e49f991fe02f3cc7 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Sat, 31 Mar 2012 13:17:13 +0200
|
||||
Subject: [PATCH 146/146] usb-redir: Not finding an async urb id is not an
|
||||
error
|
||||
|
||||
We clear our pending async urb list on device disconnect and we may still
|
||||
receive "packet complete" packets from our peer after this, which will then
|
||||
refer to packet ids no longer in our list.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
usb-redir.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/usb-redir.c b/usb-redir.c
|
||||
index 1a9d766..a41c231 100644
|
||||
--- a/usb-redir.c
|
||||
+++ b/usb-redir.c
|
||||
@@ -286,7 +286,7 @@ static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id)
|
||||
return aurb;
|
||||
}
|
||||
}
|
||||
- ERROR("could not find async urb for packet_id %u\n", packet_id);
|
||||
+ DPRINTF("could not find async urb for packet_id %u\n", packet_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.9.3
|
||||
|
@ -1,36 +0,0 @@
|
||||
From 4c245e5ecbc7d5c30c8e8bb4bfcd18c79fafddfe Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Tue, 3 Apr 2012 14:04:31 +0200
|
||||
Subject: [PATCH 147/181] usb-ehci: Ensure frindex writes leave a valid
|
||||
frindex value
|
||||
|
||||
frindex is a 14 bits counter, so bits 31-14 should always be 0, and
|
||||
after the commit titled "usb-ehci: frindex always is a 14 bits counter"
|
||||
we rely on frindex always being a multiple of 8. I've not seen this in
|
||||
practice, but theoretically a guest can write a value >= 0x4000 or a value
|
||||
which is not a multiple of 8 value to frindex, this patch ensures that
|
||||
things will still work when that happens.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb-ehci.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
|
||||
index ff69587..16e6053 100644
|
||||
--- a/hw/usb-ehci.c
|
||||
+++ b/hw/usb-ehci.c
|
||||
@@ -1081,6 +1081,10 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
|
||||
val &= USBINTR_MASK;
|
||||
break;
|
||||
|
||||
+ case FRINDEX:
|
||||
+ val &= 0x00003ff8; /* frindex is 14bits and always a multiple of 8 */
|
||||
+ break;
|
||||
+
|
||||
case CONFIGFLAG:
|
||||
val &= 0x1;
|
||||
if (val) {
|
||||
--
|
||||
1.7.10
|
||||
|
@ -0,0 +1,27 @@
|
||||
From 1271c4b3437a8bcf9b35ae8ed03be3dc758fe756 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Fri, 22 Jun 2012 09:43:08 +0200
|
||||
Subject: [PATCH] usb-redir: Correctly handle the usb_redir_babble usbredir
|
||||
status
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
hw/usb/redirect.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
|
||||
index 5f55d78..c6358c0 100644
|
||||
--- a/hw/usb/redirect.c
|
||||
+++ b/hw/usb/redirect.c
|
||||
@@ -1058,6 +1058,8 @@ static int usbredir_handle_status(USBRedirDevice *dev,
|
||||
case usb_redir_inval:
|
||||
WARNING("got invalid param error from usb-host?\n");
|
||||
return USB_RET_NAK;
|
||||
+ case usb_redir_babble:
|
||||
+ return USB_RET_BABBLE;
|
||||
case usb_redir_ioerror:
|
||||
case usb_redir_timeout:
|
||||
default:
|
||||
--
|
||||
1.7.10.4
|
||||
|
@ -1,30 +0,0 @@
|
||||
From 8858b6d0dac346d9f841cfa84f57cb03bffdf050 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Armbruster <armbru@redhat.com>
|
||||
Date: Fri, 4 Nov 2011 10:34:24 +0100
|
||||
Subject: [PATCH 401/434] qxl: Slot sanity check in qxl_phys2virt() is off by
|
||||
one, fix
|
||||
|
||||
Spotted by Coverity.
|
||||
|
||||
Signed-off-by: Markus Armbruster <armbru@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/qxl.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 41500e9..e0f9d4a 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -1020,7 +1020,7 @@ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
|
||||
case MEMSLOT_GROUP_HOST:
|
||||
return (void*)offset;
|
||||
case MEMSLOT_GROUP_GUEST:
|
||||
- PANIC_ON(slot > NUM_MEMSLOTS);
|
||||
+ PANIC_ON(slot >= NUM_MEMSLOTS);
|
||||
PANIC_ON(!qxl->guest_slots[slot].active);
|
||||
PANIC_ON(offset < qxl->guest_slots[slot].delta);
|
||||
offset -= qxl->guest_slots[slot].delta;
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,45 +0,0 @@
|
||||
From f87b93c3944652f90e2c0010da6ee8c182382369 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 15 Feb 2012 09:15:37 +0100
|
||||
Subject: [PATCH 402/434] input: send kbd+mouse events only to running guests.
|
||||
|
||||
Trying to interact with a stopped guest will queue up the events,
|
||||
then send them all at once when the guest continues running, with
|
||||
a high chance to have them cause unwanted actions.
|
||||
|
||||
Avoid that by only injecting the input events only when the guest
|
||||
is in running state.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
||||
---
|
||||
input.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/input.c b/input.c
|
||||
index 9ade63f..b48408d 100644
|
||||
--- a/input.c
|
||||
+++ b/input.c
|
||||
@@ -130,6 +130,9 @@ void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
|
||||
|
||||
void kbd_put_keycode(int keycode)
|
||||
{
|
||||
+ if (!runstate_is_running()) {
|
||||
+ return;
|
||||
+ }
|
||||
if (qemu_put_kbd_event) {
|
||||
qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
|
||||
}
|
||||
@@ -151,6 +154,9 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
|
||||
void *mouse_event_opaque;
|
||||
int width, height;
|
||||
|
||||
+ if (!runstate_is_running()) {
|
||||
+ return;
|
||||
+ }
|
||||
if (QTAILQ_EMPTY(&mouse_handlers)) {
|
||||
return;
|
||||
}
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,45 +0,0 @@
|
||||
From 3b36dd31d54b24e02493fdd86269ba5286086c98 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 8 Feb 2012 15:58:35 +0100
|
||||
Subject: [PATCH 403/434] qxl: fix warnings on 32bit
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/qxl.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index e0f9d4a..4fd5e4e 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -628,7 +628,7 @@ static void interface_release_resource(QXLInstance *sin,
|
||||
|
||||
if (ext.group_id == MEMSLOT_GROUP_HOST) {
|
||||
/* host group -> vga mode update request */
|
||||
- qemu_spice_destroy_update(&qxl->ssd, (void*)ext.info->id);
|
||||
+ qemu_spice_destroy_update(&qxl->ssd, (void *)(intptr_t)ext.info->id);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -751,7 +751,8 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
|
||||
qxl->current_async = QXL_UNDEFINED_IO;
|
||||
qemu_mutex_unlock(&qxl->async_lock);
|
||||
|
||||
- dprint(qxl, 2, "async_complete: %d (%ld) done\n", current_async, cookie);
|
||||
+ dprint(qxl, 2, "async_complete: %d (%" PRId64 ") done\n",
|
||||
+ current_async, cookie);
|
||||
switch (current_async) {
|
||||
case QXL_IO_CREATE_PRIMARY_ASYNC:
|
||||
qxl_create_guest_primary_complete(qxl);
|
||||
@@ -1018,7 +1019,7 @@ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
|
||||
|
||||
switch (group_id) {
|
||||
case MEMSLOT_GROUP_HOST:
|
||||
- return (void*)offset;
|
||||
+ return (void *)(intptr_t)offset;
|
||||
case MEMSLOT_GROUP_GUEST:
|
||||
PANIC_ON(slot >= NUM_MEMSLOTS);
|
||||
PANIC_ON(!qxl->guest_slots[slot].active);
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,56 +0,0 @@
|
||||
From 29fdb0f3a401e5590e465a0cc37d82383f3d5f07 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Wed, 15 Feb 2012 14:04:44 +0100
|
||||
Subject: [PATCH 404/434] qxl: don't render stuff when the vm is stopped.
|
||||
|
||||
This patch fixes the local qxl renderer to not kick spice-server
|
||||
in case the vm is stopped. First it is largely pointless because
|
||||
we ask spice-server to process all not-yet processed commands when
|
||||
the vm is stopped, so there isn't much do do anyway. Second we
|
||||
avoid triggering an assert in spice-server.
|
||||
|
||||
The patch makes sure we still honor redraw requests, even if we don't
|
||||
ask spice-server for updates. This is needed to handle displaysurface
|
||||
changes with a stopped vm correctly.
|
||||
|
||||
With this patch applied it is possible to take screen shots (via
|
||||
screendump monitor command) from a qxl gpu even in case the guest
|
||||
is stopped.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/qxl-render.c | 12 +++++-------
|
||||
1 file changed, 5 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
|
||||
index 2c51ba9..a7891b2 100644
|
||||
--- a/hw/qxl-render.c
|
||||
+++ b/hw/qxl-render.c
|
||||
@@ -121,19 +121,17 @@ void qxl_render_update(PCIQXLDevice *qxl)
|
||||
dpy_resize(vga->ds);
|
||||
}
|
||||
|
||||
- if (!qxl->guest_primary.commands) {
|
||||
- return;
|
||||
- }
|
||||
- qxl->guest_primary.commands = 0;
|
||||
-
|
||||
update.left = 0;
|
||||
update.right = qxl->guest_primary.surface.width;
|
||||
update.top = 0;
|
||||
update.bottom = qxl->guest_primary.surface.height;
|
||||
|
||||
memset(dirty, 0, sizeof(dirty));
|
||||
- qxl_spice_update_area(qxl, 0, &update,
|
||||
- dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC);
|
||||
+ if (runstate_is_running() && qxl->guest_primary.commands) {
|
||||
+ qxl->guest_primary.commands = 0;
|
||||
+ qxl_spice_update_area(qxl, 0, &update,
|
||||
+ dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC);
|
||||
+ }
|
||||
if (redraw) {
|
||||
memset(dirty, 0, sizeof(dirty));
|
||||
dirty[0] = update;
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,97 +0,0 @@
|
||||
From 0386bf2be16745ce87f35ce65153ef4e11f93b22 Mon Sep 17 00:00:00 2001
|
||||
From: Yonit Halperin <yhalperi@redhat.com>
|
||||
Date: Wed, 15 Feb 2012 11:22:15 +0200
|
||||
Subject: [PATCH 405/434] qxl: set only off-screen surfaces dirty instead of
|
||||
the whole vram
|
||||
|
||||
We used to assure the guest surfaces were saved before migration by
|
||||
setting the whole vram dirty. This patch sets dirty only the areas
|
||||
that are actually used in the vram.
|
||||
|
||||
Signed-off-by: Yonit Halperin <yhalperi@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/qxl.c | 53 ++++++++++++++++++++++++++++++++++++++++++++---------
|
||||
1 file changed, 44 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 4fd5e4e..3d9b1b3 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -1010,7 +1010,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d)
|
||||
qxl_spice_destroy_surfaces(d, QXL_SYNC);
|
||||
}
|
||||
|
||||
-/* called from spice server thread context only */
|
||||
+/* can be also called from spice server thread context */
|
||||
void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
|
||||
{
|
||||
uint64_t phys = le64_to_cpu(pqxl);
|
||||
@@ -1469,6 +1469,46 @@ static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
|
||||
}
|
||||
}
|
||||
|
||||
+static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
|
||||
+{
|
||||
+ intptr_t vram_start;
|
||||
+ int i;
|
||||
+
|
||||
+ if (qxl->mode != QXL_MODE_NATIVE) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* dirty the primary surface */
|
||||
+ qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset,
|
||||
+ qxl->shadow_rom.surface0_area_size);
|
||||
+
|
||||
+ vram_start = (intptr_t)memory_region_get_ram_ptr(&qxl->vram_bar);
|
||||
+
|
||||
+ /* dirty the off-screen surfaces */
|
||||
+ for (i = 0; i < NUM_SURFACES; i++) {
|
||||
+ QXLSurfaceCmd *cmd;
|
||||
+ intptr_t surface_offset;
|
||||
+ int surface_size;
|
||||
+
|
||||
+ if (qxl->guest_surfaces.cmds[i] == 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ cmd = qxl_phys2virt(qxl, qxl->guest_surfaces.cmds[i],
|
||||
+ MEMSLOT_GROUP_GUEST);
|
||||
+ assert(cmd->type == QXL_SURFACE_CMD_CREATE);
|
||||
+ surface_offset = (intptr_t)qxl_phys2virt(qxl,
|
||||
+ cmd->u.surface_create.data,
|
||||
+ MEMSLOT_GROUP_GUEST);
|
||||
+ surface_offset -= vram_start;
|
||||
+ surface_size = cmd->u.surface_create.height *
|
||||
+ abs(cmd->u.surface_create.stride);
|
||||
+ dprint(qxl, 3, "%s: dirty surface %d, offset %d, size %d\n", __func__,
|
||||
+ i, (int)surface_offset, surface_size);
|
||||
+ qxl_set_dirty(&qxl->vram_bar, surface_offset, surface_size);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void qxl_vm_change_state_handler(void *opaque, int running,
|
||||
RunState state)
|
||||
{
|
||||
@@ -1482,14 +1522,9 @@ static void qxl_vm_change_state_handler(void *opaque, int running,
|
||||
* called
|
||||
*/
|
||||
qxl_update_irq(qxl);
|
||||
- } else if (qxl->mode == QXL_MODE_NATIVE) {
|
||||
- /* dirty all vram (which holds surfaces) and devram (primary surface)
|
||||
- * to make sure they are saved */
|
||||
- /* FIXME #1: should go out during "live" stage */
|
||||
- /* FIXME #2: we only need to save the areas which are actually used */
|
||||
- qxl_set_dirty(&qxl->vram_bar, 0, qxl->vram_size);
|
||||
- qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset,
|
||||
- qxl->shadow_rom.surface0_area_size);
|
||||
+ } else {
|
||||
+ /* make sure surfaces are saved before migration */
|
||||
+ qxl_dirty_surfaces(qxl);
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,30 +0,0 @@
|
||||
From ba922e5e6a5687f13def623e36bfb834ece2defc Mon Sep 17 00:00:00 2001
|
||||
From: Yonit Halperin <yhalperi@redhat.com>
|
||||
Date: Wed, 15 Feb 2012 11:22:16 +0200
|
||||
Subject: [PATCH 406/434] qxl: make sure primary surface is saved on migration
|
||||
also in compat mode
|
||||
|
||||
RHBZ #790083
|
||||
|
||||
Signed-off-by: Yonit Halperin <yhalperi@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/qxl.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 3d9b1b3..b910337 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -1474,7 +1474,7 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
|
||||
intptr_t vram_start;
|
||||
int i;
|
||||
|
||||
- if (qxl->mode != QXL_MODE_NATIVE) {
|
||||
+ if (qxl->mode != QXL_MODE_NATIVE && qxl->mode != QXL_MODE_COMPAT) {
|
||||
return;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,139 +0,0 @@
|
||||
From 9ada192cfea65a92a765c6a2f6b56a08f1b865df Mon Sep 17 00:00:00 2001
|
||||
From: "Daniel P. Berrange" <berrange@redhat.com>
|
||||
Date: Mon, 13 Feb 2012 13:43:08 +0000
|
||||
Subject: [PATCH 407/434] Add SPICE support to add_client monitor command
|
||||
|
||||
With the acceptance of some new APIs to libspice-server.so it
|
||||
is possible to add support for SPICE to the 'add_client'
|
||||
monitor command, bringing parity with VNC. Since SPICE can
|
||||
use TLS or plain connections, the command also gains a new
|
||||
'tls' parameter to specify whether TLS should be attempted
|
||||
on the injected client sockets.
|
||||
|
||||
This new feature is only enabled if building against a
|
||||
libspice-server >= 0.10.1
|
||||
|
||||
* qmp-commands.hx: Add 'tls' parameter & missing doc for
|
||||
'skipauth' parameter
|
||||
* monitor.c: Wire up SPICE for 'add_client' command
|
||||
* ui/qemu-spice.h, ui/spice-core.c: Add qemu_spice_display_add_client
|
||||
API to wire up from monitor
|
||||
|
||||
[1] http://cgit.freedesktop.org/spice/spice/commit/server/spice.h?id=d55b68b6b44f2499278fa860fb47ff22f5011faa
|
||||
http://cgit.freedesktop.org/spice/spice/commit/server/spice.h?id=bd07dde530d9504e1cfe7ed5837fc00c26f36716
|
||||
|
||||
Changes in v3:
|
||||
- Added 'optional' flag to new parameters documented
|
||||
- Added no-op impl of qemu_spice_display_add_client when
|
||||
SPICE is disabled during build
|
||||
|
||||
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
monitor.c | 9 +++++++--
|
||||
qmp-commands.hx | 6 ++++--
|
||||
ui/qemu-spice.h | 7 +++++++
|
||||
ui/spice-core.c | 13 +++++++++++++
|
||||
4 files changed, 31 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/monitor.c b/monitor.c
|
||||
index a82fda3..3c23aa4 100644
|
||||
--- a/monitor.c
|
||||
+++ b/monitor.c
|
||||
@@ -998,13 +998,18 @@ static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_d
|
||||
CharDriverState *s;
|
||||
|
||||
if (strcmp(protocol, "spice") == 0) {
|
||||
+ int fd = monitor_get_fd(mon, fdname);
|
||||
+ int skipauth = qdict_get_try_bool(qdict, "skipauth", 0);
|
||||
+ int tls = qdict_get_try_bool(qdict, "tls", 0);
|
||||
if (!using_spice) {
|
||||
/* correct one? spice isn't a device ,,, */
|
||||
qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
|
||||
return -1;
|
||||
}
|
||||
- qerror_report(QERR_ADD_CLIENT_FAILED);
|
||||
- return -1;
|
||||
+ if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) {
|
||||
+ close(fd);
|
||||
+ }
|
||||
+ return 0;
|
||||
#ifdef CONFIG_VNC
|
||||
} else if (strcmp(protocol, "vnc") == 0) {
|
||||
int fd = monitor_get_fd(mon, fdname);
|
||||
diff --git a/qmp-commands.hx b/qmp-commands.hx
|
||||
index 97975a5..122b10d 100644
|
||||
--- a/qmp-commands.hx
|
||||
+++ b/qmp-commands.hx
|
||||
@@ -909,8 +909,8 @@ EQMP
|
||||
|
||||
{
|
||||
.name = "add_client",
|
||||
- .args_type = "protocol:s,fdname:s,skipauth:b?",
|
||||
- .params = "protocol fdname skipauth",
|
||||
+ .args_type = "protocol:s,fdname:s,skipauth:b?,tls:b?",
|
||||
+ .params = "protocol fdname skipauth tls",
|
||||
.help = "add a graphics client",
|
||||
.user_print = monitor_user_noop,
|
||||
.mhandler.cmd_new = add_graphics_client,
|
||||
@@ -926,6 +926,8 @@ Arguments:
|
||||
|
||||
- "protocol": protocol name (json-string)
|
||||
- "fdname": file descriptor name (json-string)
|
||||
+- "skipauth": whether to skip authentication (json-bool, optional)
|
||||
+- "tls": whether to perform TLS (json-bool, optional)
|
||||
|
||||
Example:
|
||||
|
||||
diff --git a/ui/qemu-spice.h b/ui/qemu-spice.h
|
||||
index c35b29c..680206a 100644
|
||||
--- a/ui/qemu-spice.h
|
||||
+++ b/ui/qemu-spice.h
|
||||
@@ -33,6 +33,7 @@ void qemu_spice_init(void);
|
||||
void qemu_spice_input_init(void);
|
||||
void qemu_spice_audio_init(void);
|
||||
void qemu_spice_display_init(DisplayState *ds);
|
||||
+int qemu_spice_display_add_client(int csock, int skipauth, int tls);
|
||||
int qemu_spice_add_interface(SpiceBaseInstance *sin);
|
||||
int qemu_spice_set_passwd(const char *passwd,
|
||||
bool fail_if_connected, bool disconnect_if_connected);
|
||||
@@ -68,6 +69,12 @@ static inline int qemu_spice_migrate_info(const char *h, int p, int t,
|
||||
return -1;
|
||||
}
|
||||
|
||||
+static inline int qemu_spice_display_add_client(int csock, int skipauth,
|
||||
+ int tls)
|
||||
+{
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
#endif /* CONFIG_SPICE */
|
||||
|
||||
#endif /* QEMU_SPICE_H */
|
||||
diff --git a/ui/spice-core.c b/ui/spice-core.c
|
||||
index 5639c6f..d98863e 100644
|
||||
--- a/ui/spice-core.c
|
||||
+++ b/ui/spice-core.c
|
||||
@@ -747,6 +747,19 @@ int qemu_spice_set_pw_expire(time_t expires)
|
||||
return qemu_spice_set_ticket(false, false);
|
||||
}
|
||||
|
||||
+int qemu_spice_display_add_client(int csock, int skipauth, int tls)
|
||||
+{
|
||||
+#if SPICE_SERVER_VERSION >= 0x000a01
|
||||
+ if (tls) {
|
||||
+ return spice_server_add_ssl_client(spice_server, csock, skipauth);
|
||||
+ } else {
|
||||
+ return spice_server_add_client(spice_server, csock, skipauth);
|
||||
+ }
|
||||
+#else
|
||||
+ return -1;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
static void spice_register_config(void)
|
||||
{
|
||||
qemu_add_opts(&qemu_spice_opts);
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,83 +0,0 @@
|
||||
From 6594551ebe427cae4298b038be02ddc9c335219f Mon Sep 17 00:00:00 2001
|
||||
From: Yonit Halperin <yhalperi@redhat.com>
|
||||
Date: Wed, 8 Feb 2012 15:40:15 +0200
|
||||
Subject: [PATCH 408/434] spice: support ipv6 channel address in monitor
|
||||
events and in spice info
|
||||
|
||||
RHBZ #788444
|
||||
|
||||
CC: Gerd Hoffmann <kraxel@redhat.com>
|
||||
|
||||
Signed-off-by: Yonit Halperin <yhalperi@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
ui/spice-core.c | 37 ++++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 32 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/ui/spice-core.c b/ui/spice-core.c
|
||||
index d98863e..27216e9 100644
|
||||
--- a/ui/spice-core.c
|
||||
+++ b/ui/spice-core.c
|
||||
@@ -220,10 +220,23 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
|
||||
}
|
||||
|
||||
client = qdict_new();
|
||||
- add_addr_info(client, &info->paddr, info->plen);
|
||||
-
|
||||
server = qdict_new();
|
||||
- add_addr_info(server, &info->laddr, info->llen);
|
||||
+
|
||||
+#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
|
||||
+ if (info->flags & SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT) {
|
||||
+ add_addr_info(client, (struct sockaddr *)&info->paddr_ext,
|
||||
+ info->plen_ext);
|
||||
+ add_addr_info(server, (struct sockaddr *)&info->laddr_ext,
|
||||
+ info->llen_ext);
|
||||
+ } else {
|
||||
+ fprintf(stderr, "spice: %s, extended address is expected\n",
|
||||
+ __func__);
|
||||
+#endif
|
||||
+ add_addr_info(client, &info->paddr, info->plen);
|
||||
+ add_addr_info(server, &info->laddr, info->llen);
|
||||
+#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
if (event == SPICE_CHANNEL_EVENT_INITIALIZED) {
|
||||
qdict_put(server, "auth", qstring_from_str(auth));
|
||||
@@ -376,16 +389,30 @@ static SpiceChannelList *qmp_query_spice_channels(void)
|
||||
QTAILQ_FOREACH(item, &channel_list, link) {
|
||||
SpiceChannelList *chan;
|
||||
char host[NI_MAXHOST], port[NI_MAXSERV];
|
||||
+ struct sockaddr *paddr;
|
||||
+ socklen_t plen;
|
||||
|
||||
chan = g_malloc0(sizeof(*chan));
|
||||
chan->value = g_malloc0(sizeof(*chan->value));
|
||||
|
||||
- getnameinfo(&item->info->paddr, item->info->plen,
|
||||
+#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
|
||||
+ if (item->info->flags & SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT) {
|
||||
+ paddr = (struct sockaddr *)&item->info->paddr_ext;
|
||||
+ plen = item->info->plen_ext;
|
||||
+ } else {
|
||||
+#endif
|
||||
+ paddr = &item->info->paddr;
|
||||
+ plen = item->info->plen;
|
||||
+#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ getnameinfo(paddr, plen,
|
||||
host, sizeof(host), port, sizeof(port),
|
||||
NI_NUMERICHOST | NI_NUMERICSERV);
|
||||
chan->value->host = g_strdup(host);
|
||||
chan->value->port = g_strdup(port);
|
||||
- chan->value->family = g_strdup(inet_strfamily(item->info->paddr.sa_family));
|
||||
+ chan->value->family = g_strdup(inet_strfamily(paddr->sa_family));
|
||||
|
||||
chan->value->connection_id = item->info->connection_id;
|
||||
chan->value->channel_type = item->info->type;
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,30 +0,0 @@
|
||||
From f7656005900f3c07450303afa66151b6a1bb9599 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Fri, 17 Feb 2012 14:40:01 +0100
|
||||
Subject: [PATCH 409/434] qxl: drop vram bar minimum size
|
||||
|
||||
There is no reason to require a minimum size of 16 MB for the vram.
|
||||
Lower the limit to 4096 (one page). Make it disapper completely would
|
||||
break guests.
|
||||
---
|
||||
hw/qxl.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index b910337..d71c94d 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -1595,8 +1595,8 @@ static int qxl_init_common(PCIQXLDevice *qxl)
|
||||
init_qxl_rom(qxl);
|
||||
init_qxl_ram(qxl);
|
||||
|
||||
- if (qxl->vram_size < 16 * 1024 * 1024) {
|
||||
- qxl->vram_size = 16 * 1024 * 1024;
|
||||
+ if (qxl->vram_size < 4096) {
|
||||
+ qxl->vram_size = 4096;
|
||||
}
|
||||
if (qxl->revision == 1) {
|
||||
qxl->vram_size = 4096;
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,97 +0,0 @@
|
||||
From 619c68418809149d56025e5b4e7a9828eef90ea8 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Fri, 17 Feb 2012 15:02:40 +0100
|
||||
Subject: [PATCH 410/434] qxl: move ram size init to new function
|
||||
|
||||
Factor memory bar sizing bits out to a separate function.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
|
||||
hw/qxl.c
|
||||
---
|
||||
hw/qxl.c | 41 ++++++++++++++++++++++-------------------
|
||||
1 file changed, 22 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index d71c94d..df8efbc 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -1557,6 +1557,25 @@ static DisplayChangeListener display_listener = {
|
||||
.dpy_refresh = display_refresh,
|
||||
};
|
||||
|
||||
+static void qxl_init_ramsize(PCIQXLDevice *qxl, uint32_t ram_min_mb)
|
||||
+{
|
||||
+ /* vga ram (bar 0) */
|
||||
+ if (qxl->vga.vram_size < ram_min_mb * 1024 * 1024) {
|
||||
+ qxl->vga.vram_size = ram_min_mb * 1024 * 1024;
|
||||
+ }
|
||||
+
|
||||
+ /* vram (surfaces, bar 1) */
|
||||
+ if (qxl->vram_size < 4096) {
|
||||
+ qxl->vram_size = 4096;
|
||||
+ }
|
||||
+ if (qxl->revision == 1) {
|
||||
+ qxl->vram_size = 4096;
|
||||
+ }
|
||||
+
|
||||
+ qxl->vga.vram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
|
||||
+ qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
|
||||
+}
|
||||
+
|
||||
static int qxl_init_common(PCIQXLDevice *qxl)
|
||||
{
|
||||
uint8_t* config = qxl->pci.config;
|
||||
@@ -1595,13 +1614,6 @@ static int qxl_init_common(PCIQXLDevice *qxl)
|
||||
init_qxl_rom(qxl);
|
||||
init_qxl_ram(qxl);
|
||||
|
||||
- if (qxl->vram_size < 4096) {
|
||||
- qxl->vram_size = 4096;
|
||||
- }
|
||||
- if (qxl->revision == 1) {
|
||||
- qxl->vram_size = 4096;
|
||||
- }
|
||||
- qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
|
||||
memory_region_init_ram(&qxl->vram_bar, &qxl->pci.qdev, "qxl.vram",
|
||||
qxl->vram_size);
|
||||
|
||||
@@ -1644,15 +1656,11 @@ static int qxl_init_primary(PCIDevice *dev)
|
||||
{
|
||||
PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
|
||||
VGACommonState *vga = &qxl->vga;
|
||||
- ram_addr_t ram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
|
||||
PortioList *qxl_vga_port_list = g_new(PortioList, 1);
|
||||
|
||||
qxl->id = 0;
|
||||
-
|
||||
- if (ram_size < 32 * 1024 * 1024) {
|
||||
- ram_size = 32 * 1024 * 1024;
|
||||
- }
|
||||
- vga_common_init(vga, ram_size);
|
||||
+ qxl_init_ramsize(qxl, 32);
|
||||
+ vga_common_init(vga, qxl->vga.vram_size);
|
||||
vga_init(vga, pci_address_space(dev), pci_address_space_io(dev), false);
|
||||
portio_list_init(qxl_vga_port_list, qxl_vga_portio_list, vga, "vga");
|
||||
portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);
|
||||
@@ -1671,14 +1679,9 @@ static int qxl_init_secondary(PCIDevice *dev)
|
||||
{
|
||||
static int device_id = 1;
|
||||
PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
|
||||
- ram_addr_t ram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
|
||||
|
||||
qxl->id = device_id++;
|
||||
-
|
||||
- if (ram_size < 16 * 1024 * 1024) {
|
||||
- ram_size = 16 * 1024 * 1024;
|
||||
- }
|
||||
- qxl->vga.vram_size = ram_size;
|
||||
+ qxl_init_ramsize(qxl, 16);
|
||||
memory_region_init_ram(&qxl->vga.vram, &qxl->pci.qdev, "qxl.vgavram",
|
||||
qxl->vga.vram_size);
|
||||
qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram);
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,63 +0,0 @@
|
||||
From eff66c7db18e9a3ef0b6ce5deb9a49b61090d809 Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Fri, 17 Feb 2012 15:03:24 +0100
|
||||
Subject: [PATCH 411/434] qxl: add user-friendly bar size properties
|
||||
|
||||
Add two properties to specify bar sizes in megabytes instead of bytes,
|
||||
which is alot more user-friendly.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/qxl.c | 8 ++++++++
|
||||
hw/qxl.h | 4 ++++
|
||||
2 files changed, 12 insertions(+)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index df8efbc..c8839c3 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -1560,11 +1560,17 @@ static DisplayChangeListener display_listener = {
|
||||
static void qxl_init_ramsize(PCIQXLDevice *qxl, uint32_t ram_min_mb)
|
||||
{
|
||||
/* vga ram (bar 0) */
|
||||
+ if (qxl->ram_size_mb != -1) {
|
||||
+ qxl->vga.vram_size = qxl->ram_size_mb * 1024 * 1024;
|
||||
+ }
|
||||
if (qxl->vga.vram_size < ram_min_mb * 1024 * 1024) {
|
||||
qxl->vga.vram_size = ram_min_mb * 1024 * 1024;
|
||||
}
|
||||
|
||||
/* vram (surfaces, bar 1) */
|
||||
+ if (qxl->vram_size_mb != -1) {
|
||||
+ qxl->vram_size = qxl->vram_size_mb * 1024 * 1024;
|
||||
+ }
|
||||
if (qxl->vram_size < 4096) {
|
||||
qxl->vram_size = 4096;
|
||||
}
|
||||
@@ -1863,6 +1869,8 @@ static Property qxl_properties[] = {
|
||||
DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0),
|
||||
DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
|
||||
DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
|
||||
+ DEFINE_PROP_UINT32("ram_size_mb", PCIQXLDevice, ram_size_mb, -1),
|
||||
+ DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram_size_mb, -1),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
diff --git a/hw/qxl.h b/hw/qxl.h
|
||||
index 766aa6d..d062991 100644
|
||||
--- a/hw/qxl.h
|
||||
+++ b/hw/qxl.h
|
||||
@@ -89,6 +89,10 @@ typedef struct PCIQXLDevice {
|
||||
|
||||
/* io bar */
|
||||
MemoryRegion io_bar;
|
||||
+
|
||||
+ /* user-friendly properties (in megabytes) */
|
||||
+ uint32_t ram_size_mb;
|
||||
+ uint32_t vram_size_mb;
|
||||
} PCIQXLDevice;
|
||||
|
||||
#define PANIC_ON(x) if ((x)) { \
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,93 +0,0 @@
|
||||
From 1cae61c4d4fe994e5158d63d5f4fe9b52a7b8211 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Fri, 24 Feb 2012 23:19:25 +0200
|
||||
Subject: [PATCH 412/434] qxl: fix spice+sdl no cursor regression
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
regression introduced by 075360945860ad9bdd491921954b383bf762b0e5,
|
||||
|
||||
v2: lock around qemu_spice_cursor_refresh_unlocked
|
||||
|
||||
Reported-by: Fabiano Fidêncio <fabiano@fidencio.org>
|
||||
Signed-off-by: Alon Levy <alevy@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/qxl.c | 4 ++++
|
||||
ui/spice-display.c | 23 ++++++++++++++---------
|
||||
ui/spice-display.h | 1 +
|
||||
3 files changed, 19 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index c8839c3..17f2576 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -1548,6 +1548,10 @@ static void display_refresh(struct DisplayState *ds)
|
||||
{
|
||||
if (qxl0->mode == QXL_MODE_VGA) {
|
||||
qemu_spice_display_refresh(&qxl0->ssd);
|
||||
+ } else {
|
||||
+ qemu_mutex_lock(&qxl0->ssd.lock);
|
||||
+ qemu_spice_cursor_refresh_unlocked(&qxl0->ssd);
|
||||
+ qemu_mutex_unlock(&qxl0->ssd.lock);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/ui/spice-display.c b/ui/spice-display.c
|
||||
index 6c302a3..c6e61d8 100644
|
||||
--- a/ui/spice-display.c
|
||||
+++ b/ui/spice-display.c
|
||||
@@ -317,16 +317,8 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
|
||||
ssd->notify++;
|
||||
}
|
||||
|
||||
-void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
|
||||
+void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd)
|
||||
{
|
||||
- dprint(3, "%s:\n", __FUNCTION__);
|
||||
- vga_hw_update();
|
||||
-
|
||||
- qemu_mutex_lock(&ssd->lock);
|
||||
- if (ssd->update == NULL) {
|
||||
- ssd->update = qemu_spice_create_update(ssd);
|
||||
- ssd->notify++;
|
||||
- }
|
||||
if (ssd->cursor) {
|
||||
ssd->ds->cursor_define(ssd->cursor);
|
||||
cursor_put(ssd->cursor);
|
||||
@@ -337,6 +329,19 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
|
||||
ssd->mouse_x = -1;
|
||||
ssd->mouse_y = -1;
|
||||
}
|
||||
+}
|
||||
+
|
||||
+void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
|
||||
+{
|
||||
+ dprint(3, "%s:\n", __func__);
|
||||
+ vga_hw_update();
|
||||
+
|
||||
+ qemu_mutex_lock(&ssd->lock);
|
||||
+ if (ssd->update == NULL) {
|
||||
+ ssd->update = qemu_spice_create_update(ssd);
|
||||
+ ssd->notify++;
|
||||
+ }
|
||||
+ qemu_spice_cursor_refresh_unlocked(ssd);
|
||||
qemu_mutex_unlock(&ssd->lock);
|
||||
|
||||
if (ssd->notify) {
|
||||
diff --git a/ui/spice-display.h b/ui/spice-display.h
|
||||
index 5e52df9..a23bfc8 100644
|
||||
--- a/ui/spice-display.h
|
||||
+++ b/ui/spice-display.h
|
||||
@@ -97,6 +97,7 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
|
||||
int x, int y, int w, int h);
|
||||
void qemu_spice_display_resize(SimpleSpiceDisplay *ssd);
|
||||
void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd);
|
||||
+void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd);
|
||||
|
||||
void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
|
||||
qxl_async_io async);
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,29 +0,0 @@
|
||||
From 4888e60d646b0f8cdfe4180bacc90857d3d2a5dd Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Fri, 24 Feb 2012 23:19:26 +0200
|
||||
Subject: [PATCH 413/434] sdl: remove NULL check, g_malloc0 can't fail
|
||||
|
||||
Signed-off-by: Alon Levy <alevy@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
ui/sdl.c | 4 ----
|
||||
1 file changed, 4 deletions(-)
|
||||
|
||||
diff --git a/ui/sdl.c b/ui/sdl.c
|
||||
index 8cafc44..6844c83 100644
|
||||
--- a/ui/sdl.c
|
||||
+++ b/ui/sdl.c
|
||||
@@ -167,10 +167,6 @@ static PixelFormat sdl_to_qemu_pixelformat(SDL_PixelFormat *sdl_pf)
|
||||
static DisplaySurface* sdl_create_displaysurface(int width, int height)
|
||||
{
|
||||
DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface));
|
||||
- if (surface == NULL) {
|
||||
- fprintf(stderr, "sdl_create_displaysurface: malloc failed\n");
|
||||
- exit(1);
|
||||
- }
|
||||
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,34 +0,0 @@
|
||||
From 813c46edf4f3f69347353749755e040bc5fbd597 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Fri, 24 Feb 2012 23:19:27 +0200
|
||||
Subject: [PATCH 414/434] qxl: drop qxl_spice_update_area_async definition
|
||||
|
||||
It was never used. Introduced in
|
||||
5ff4e36c804157bd84af43c139f8cd3a59722db9
|
||||
qxl: async io support using new spice api
|
||||
|
||||
But not used even then.
|
||||
|
||||
Signed-off-by: Alon Levy <alevy@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/qxl.h | 6 ------
|
||||
1 file changed, 6 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.h b/hw/qxl.h
|
||||
index d062991..a615eca 100644
|
||||
--- a/hw/qxl.h
|
||||
+++ b/hw/qxl.h
|
||||
@@ -138,9 +138,3 @@ void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext);
|
||||
void qxl_render_resize(PCIQXLDevice *qxl);
|
||||
void qxl_render_update(PCIQXLDevice *qxl);
|
||||
void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext);
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
-void qxl_spice_update_area_async(PCIQXLDevice *qxl, uint32_t surface_id,
|
||||
- struct QXLRect *area,
|
||||
- uint32_t clear_dirty_region,
|
||||
- int is_vga);
|
||||
-#endif
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,358 +0,0 @@
|
||||
From e07eeb01819b40b839cc12b2eb658f48f13a5ff0 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Fri, 24 Feb 2012 23:19:28 +0200
|
||||
Subject: [PATCH 415/434] qxl: require spice >= 0.8.2
|
||||
|
||||
drop all ifdefs on SPICE_INTERFACE_QXL_MINOR >= 1 as a result,
|
||||
any check for SPICE_SERVER_VERSION that is now always satisfied,
|
||||
and SPICE_INTERFACE_CORE_MINOR >= 3 tests, because
|
||||
0.8.2 has SPICE_INTERFACE_QXL_MINOR == 1 and
|
||||
SPICE_INTERFACE_CORE_MINOR == 3.
|
||||
|
||||
Signed-off-by: Alon Levy <alevy@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
configure | 2 +-
|
||||
hw/qxl.c | 40 ----------------------------------------
|
||||
hw/qxl.h | 4 ----
|
||||
ui/spice-core.c | 17 -----------------
|
||||
ui/spice-display.c | 12 ------------
|
||||
5 files changed, 1 insertion(+), 74 deletions(-)
|
||||
|
||||
diff --git a/configure b/configure
|
||||
index a4848a4..b03172c 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -2501,7 +2501,7 @@ int main(void) { spice_server_new(); return 0; }
|
||||
EOF
|
||||
spice_cflags=$($pkg_config --cflags spice-protocol spice-server 2>/dev/null)
|
||||
spice_libs=$($pkg_config --libs spice-protocol spice-server 2>/dev/null)
|
||||
- if $pkg_config --atleast-version=0.6.0 spice-server >/dev/null 2>&1 && \
|
||||
+ if $pkg_config --atleast-version=0.8.2 spice-server >/dev/null 2>&1 && \
|
||||
compile_prog "$spice_cflags" "$spice_libs" ; then
|
||||
spice="yes"
|
||||
libs_softmmu="$libs_softmmu $spice_libs"
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 17f2576..0be9859 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -125,9 +125,7 @@ static void qxl_ring_set_dirty(PCIQXLDevice *qxl);
|
||||
|
||||
void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...)
|
||||
{
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
qxl_send_events(qxl, QXL_INTERRUPT_ERROR);
|
||||
-#endif
|
||||
if (qxl->guestdebug) {
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
@@ -149,12 +147,8 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
|
||||
qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area,
|
||||
dirty_rects, num_dirty_rects, clear_dirty_region);
|
||||
} else {
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
spice_qxl_update_area_async(&qxl->ssd.qxl, surface_id, area,
|
||||
clear_dirty_region, 0);
|
||||
-#else
|
||||
- abort();
|
||||
-#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,24 +165,18 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
|
||||
qxl_async_io async)
|
||||
{
|
||||
if (async) {
|
||||
-#if SPICE_INTERFACE_QXL_MINOR < 1
|
||||
- abort();
|
||||
-#else
|
||||
spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id,
|
||||
(uint64_t)id);
|
||||
-#endif
|
||||
} else {
|
||||
qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
|
||||
qxl_spice_destroy_surface_wait_complete(qxl, id);
|
||||
}
|
||||
}
|
||||
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl)
|
||||
{
|
||||
spice_qxl_flush_surfaces_async(&qxl->ssd.qxl, 0);
|
||||
}
|
||||
-#endif
|
||||
|
||||
void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
|
||||
uint32_t count)
|
||||
@@ -217,11 +205,7 @@ static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
|
||||
static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
|
||||
{
|
||||
if (async) {
|
||||
-#if SPICE_INTERFACE_QXL_MINOR < 1
|
||||
- abort();
|
||||
-#else
|
||||
spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl, 0);
|
||||
-#endif
|
||||
} else {
|
||||
qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker);
|
||||
qxl_spice_destroy_surfaces_complete(qxl);
|
||||
@@ -493,7 +477,6 @@ static const char *io_port_to_string(uint32_t io_port)
|
||||
[QXL_IO_DESTROY_PRIMARY] = "QXL_IO_DESTROY_PRIMARY",
|
||||
[QXL_IO_DESTROY_SURFACE_WAIT] = "QXL_IO_DESTROY_SURFACE_WAIT",
|
||||
[QXL_IO_DESTROY_ALL_SURFACES] = "QXL_IO_DESTROY_ALL_SURFACES",
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
[QXL_IO_UPDATE_AREA_ASYNC] = "QXL_IO_UPDATE_AREA_ASYNC",
|
||||
[QXL_IO_MEMSLOT_ADD_ASYNC] = "QXL_IO_MEMSLOT_ADD_ASYNC",
|
||||
[QXL_IO_CREATE_PRIMARY_ASYNC] = "QXL_IO_CREATE_PRIMARY_ASYNC",
|
||||
@@ -503,7 +486,6 @@ static const char *io_port_to_string(uint32_t io_port)
|
||||
= "QXL_IO_DESTROY_ALL_SURFACES_ASYNC",
|
||||
[QXL_IO_FLUSH_SURFACES_ASYNC] = "QXL_IO_FLUSH_SURFACES_ASYNC",
|
||||
[QXL_IO_FLUSH_RELEASE] = "QXL_IO_FLUSH_RELEASE",
|
||||
-#endif
|
||||
};
|
||||
return io_port_to_string[io_port];
|
||||
}
|
||||
@@ -738,8 +720,6 @@ static int interface_flush_resources(QXLInstance *sin)
|
||||
|
||||
static void qxl_create_guest_primary_complete(PCIQXLDevice *d);
|
||||
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
-
|
||||
/* called from spice server thread context only */
|
||||
static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
|
||||
{
|
||||
@@ -767,8 +747,6 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
|
||||
qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD);
|
||||
}
|
||||
|
||||
-#endif
|
||||
-
|
||||
static const QXLInterface qxl_interface = {
|
||||
.base.type = SPICE_INTERFACE_QXL,
|
||||
.base.description = "qxl gpu",
|
||||
@@ -788,9 +766,7 @@ static const QXLInterface qxl_interface = {
|
||||
.req_cursor_notification = interface_req_cursor_notification,
|
||||
.notify_update = interface_notify_update,
|
||||
.flush_resources = interface_flush_resources,
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
.async_complete = interface_async_complete,
|
||||
-#endif
|
||||
};
|
||||
|
||||
static void qxl_enter_vga_mode(PCIQXLDevice *d)
|
||||
@@ -1140,9 +1116,7 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
|
||||
PCIQXLDevice *d = opaque;
|
||||
uint32_t io_port = addr;
|
||||
qxl_async_io async = QXL_SYNC;
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
uint32_t orig_io_port = io_port;
|
||||
-#endif
|
||||
|
||||
switch (io_port) {
|
||||
case QXL_IO_RESET:
|
||||
@@ -1152,10 +1126,8 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
|
||||
case QXL_IO_CREATE_PRIMARY:
|
||||
case QXL_IO_UPDATE_IRQ:
|
||||
case QXL_IO_LOG:
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
case QXL_IO_MEMSLOT_ADD_ASYNC:
|
||||
case QXL_IO_CREATE_PRIMARY_ASYNC:
|
||||
-#endif
|
||||
break;
|
||||
default:
|
||||
if (d->mode != QXL_MODE_VGA) {
|
||||
@@ -1163,17 +1135,14 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
|
||||
}
|
||||
dprint(d, 1, "%s: unexpected port 0x%x (%s) in vga mode\n",
|
||||
__func__, io_port, io_port_to_string(io_port));
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
/* be nice to buggy guest drivers */
|
||||
if (io_port >= QXL_IO_UPDATE_AREA_ASYNC &&
|
||||
io_port <= QXL_IO_DESTROY_ALL_SURFACES_ASYNC) {
|
||||
qxl_send_events(d, QXL_INTERRUPT_IO_CMD);
|
||||
}
|
||||
-#endif
|
||||
return;
|
||||
}
|
||||
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
/* we change the io_port to avoid ifdeffery in the main switch */
|
||||
orig_io_port = io_port;
|
||||
switch (io_port) {
|
||||
@@ -1212,7 +1181,6 @@ async_common:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
-#endif
|
||||
|
||||
switch (io_port) {
|
||||
case QXL_IO_UPDATE_AREA:
|
||||
@@ -1304,7 +1272,6 @@ async_common:
|
||||
}
|
||||
qxl_spice_destroy_surface_wait(d, val, async);
|
||||
break;
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
case QXL_IO_FLUSH_RELEASE: {
|
||||
QXLReleaseRing *ring = &d->ram->release_ring;
|
||||
if (ring->prod - ring->cons + 1 == ring->num_items) {
|
||||
@@ -1325,7 +1292,6 @@ async_common:
|
||||
d->num_free_res);
|
||||
qxl_spice_flush_surfaces_async(d);
|
||||
break;
|
||||
-#endif
|
||||
case QXL_IO_DESTROY_ALL_SURFACES:
|
||||
d->mode = QXL_MODE_UNDEFINED;
|
||||
qxl_spice_destroy_surfaces(d, async);
|
||||
@@ -1336,16 +1302,12 @@ async_common:
|
||||
}
|
||||
return;
|
||||
cancel_async:
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
if (async) {
|
||||
qxl_send_events(d, QXL_INTERRUPT_IO_CMD);
|
||||
qemu_mutex_lock(&d->async_lock);
|
||||
d->current_async = QXL_UNDEFINED_IO;
|
||||
qemu_mutex_unlock(&d->async_lock);
|
||||
}
|
||||
-#else
|
||||
- return;
|
||||
-#endif
|
||||
}
|
||||
|
||||
static uint64_t ioport_read(void *opaque, target_phys_addr_t addr,
|
||||
@@ -1607,9 +1569,7 @@ static int qxl_init_common(PCIQXLDevice *qxl)
|
||||
case 2: /* spice 0.6 -- qxl-2 */
|
||||
pci_device_rev = QXL_REVISION_STABLE_V06;
|
||||
break;
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
case 3: /* qxl-3 */
|
||||
-#endif
|
||||
default:
|
||||
pci_device_rev = QXL_DEFAULT_REVISION;
|
||||
break;
|
||||
diff --git a/hw/qxl.h b/hw/qxl.h
|
||||
index a615eca..9288e46 100644
|
||||
--- a/hw/qxl.h
|
||||
+++ b/hw/qxl.h
|
||||
@@ -108,11 +108,7 @@ typedef struct PCIQXLDevice {
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V10
|
||||
-#else
|
||||
-#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V06
|
||||
-#endif
|
||||
|
||||
/* qxl.c */
|
||||
void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
|
||||
diff --git a/ui/spice-core.c b/ui/spice-core.c
|
||||
index 27216e9..2c815f1 100644
|
||||
--- a/ui/spice-core.c
|
||||
+++ b/ui/spice-core.c
|
||||
@@ -139,8 +139,6 @@ static void watch_remove(SpiceWatch *watch)
|
||||
g_free(watch);
|
||||
}
|
||||
|
||||
-#if SPICE_INTERFACE_CORE_MINOR >= 3
|
||||
-
|
||||
typedef struct ChannelList ChannelList;
|
||||
struct ChannelList {
|
||||
SpiceChannelEventInfo *info;
|
||||
@@ -257,15 +255,6 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
|
||||
}
|
||||
}
|
||||
|
||||
-#else /* SPICE_INTERFACE_CORE_MINOR >= 3 */
|
||||
-
|
||||
-static QList *channel_list_get(void)
|
||||
-{
|
||||
- return NULL;
|
||||
-}
|
||||
-
|
||||
-#endif /* SPICE_INTERFACE_CORE_MINOR >= 3 */
|
||||
-
|
||||
static SpiceCoreInterface core_interface = {
|
||||
.base.type = SPICE_INTERFACE_CORE,
|
||||
.base.description = "qemu core services",
|
||||
@@ -281,9 +270,7 @@ static SpiceCoreInterface core_interface = {
|
||||
.watch_update_mask = watch_update_mask,
|
||||
.watch_remove = watch_remove,
|
||||
|
||||
-#if SPICE_INTERFACE_CORE_MINOR >= 3
|
||||
.channel_event = channel_event,
|
||||
-#endif
|
||||
};
|
||||
|
||||
#ifdef SPICE_INTERFACE_MIGRATION
|
||||
@@ -490,7 +477,6 @@ static void migration_state_notifier(Notifier *notifier, void *data)
|
||||
spice_server_migrate_start(spice_server);
|
||||
#endif
|
||||
} else if (migration_has_finished(s)) {
|
||||
-#if SPICE_SERVER_VERSION >= 0x000701 /* 0.7.1 */
|
||||
#ifndef SPICE_INTERFACE_MIGRATION
|
||||
spice_server_migrate_switch(spice_server);
|
||||
#else
|
||||
@@ -498,7 +484,6 @@ static void migration_state_notifier(Notifier *notifier, void *data)
|
||||
} else if (migration_has_failed(s)) {
|
||||
spice_server_migrate_end(spice_server, false);
|
||||
#endif
|
||||
-#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,11 +644,9 @@ void qemu_spice_init(void)
|
||||
spice_server_set_noauth(spice_server);
|
||||
}
|
||||
|
||||
-#if SPICE_SERVER_VERSION >= 0x000801
|
||||
if (qemu_opt_get_bool(opts, "disable-copy-paste", 0)) {
|
||||
spice_server_set_agent_copypaste(spice_server, false);
|
||||
}
|
||||
-#endif
|
||||
|
||||
compression = SPICE_IMAGE_COMPRESS_AUTO_GLZ;
|
||||
str = qemu_opt_get(opts, "image-compression");
|
||||
diff --git a/ui/spice-display.c b/ui/spice-display.c
|
||||
index c6e61d8..ad76bae 100644
|
||||
--- a/ui/spice-display.c
|
||||
+++ b/ui/spice-display.c
|
||||
@@ -64,11 +64,7 @@ void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
|
||||
qxl_async_io async)
|
||||
{
|
||||
if (async != QXL_SYNC) {
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
spice_qxl_add_memslot_async(&ssd->qxl, memslot, 0);
|
||||
-#else
|
||||
- abort();
|
||||
-#endif
|
||||
} else {
|
||||
ssd->worker->add_memslot(ssd->worker, memslot);
|
||||
}
|
||||
@@ -84,11 +80,7 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
|
||||
qxl_async_io async)
|
||||
{
|
||||
if (async != QXL_SYNC) {
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface, 0);
|
||||
-#else
|
||||
- abort();
|
||||
-#endif
|
||||
} else {
|
||||
ssd->worker->create_primary_surface(ssd->worker, id, surface);
|
||||
}
|
||||
@@ -99,11 +91,7 @@ void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
|
||||
uint32_t id, qxl_async_io async)
|
||||
{
|
||||
if (async != QXL_SYNC) {
|
||||
-#if SPICE_INTERFACE_QXL_MINOR >= 1
|
||||
spice_qxl_destroy_primary_surface_async(&ssd->qxl, id, 0);
|
||||
-#else
|
||||
- abort();
|
||||
-#endif
|
||||
} else {
|
||||
ssd->worker->destroy_primary_surface(ssd->worker, id);
|
||||
}
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,145 +0,0 @@
|
||||
From f9344933bcc1425cf1e8142dc2f8321522dc00af Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Fri, 24 Feb 2012 23:19:29 +0200
|
||||
Subject: [PATCH 416/434] qxl: remove flipped
|
||||
|
||||
Tested on linux and windows guests. For negative stride, qxl_flip copies
|
||||
directly to vga->ds->surface->data, for positive it's reallocated to
|
||||
share qxl->guest_primary.data
|
||||
|
||||
Signed-off-by: Alon Levy <alevy@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/qxl-render.c | 66 +++++++++++++++++++++++++------------------------------
|
||||
hw/qxl.h | 2 +-
|
||||
2 files changed, 31 insertions(+), 37 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
|
||||
index a7891b2..5811d74 100644
|
||||
--- a/hw/qxl-render.c
|
||||
+++ b/hw/qxl-render.c
|
||||
@@ -23,10 +23,21 @@
|
||||
|
||||
static void qxl_flip(PCIQXLDevice *qxl, QXLRect *rect)
|
||||
{
|
||||
- uint8_t *src = qxl->guest_primary.data;
|
||||
- uint8_t *dst = qxl->guest_primary.flipped;
|
||||
+ uint8_t *src;
|
||||
+ uint8_t *dst = qxl->vga.ds->surface->data;
|
||||
int len, i;
|
||||
|
||||
+ if (qxl->guest_primary.qxl_stride > 0) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (!qxl->guest_primary.data) {
|
||||
+ dprint(qxl, 1, "%s: initializing guest_primary.data\n", __func__);
|
||||
+ qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
|
||||
+ }
|
||||
+ dprint(qxl, 1, "%s: stride %d, [%d, %d, %d, %d]\n", __func__,
|
||||
+ qxl->guest_primary.qxl_stride,
|
||||
+ rect->left, rect->right, rect->top, rect->bottom);
|
||||
+ src = qxl->guest_primary.data;
|
||||
src += (qxl->guest_primary.surface.height - rect->top - 1) *
|
||||
qxl->guest_primary.abs_stride;
|
||||
dst += rect->top * qxl->guest_primary.abs_stride;
|
||||
@@ -75,52 +86,38 @@ void qxl_render_update(PCIQXLDevice *qxl)
|
||||
{
|
||||
VGACommonState *vga = &qxl->vga;
|
||||
QXLRect dirty[32], update;
|
||||
- void *ptr;
|
||||
int i, redraw = 0;
|
||||
-
|
||||
- if (!is_buffer_shared(vga->ds->surface)) {
|
||||
- dprint(qxl, 1, "%s: restoring shared displaysurface\n", __func__);
|
||||
- qxl->guest_primary.resized++;
|
||||
- qxl->guest_primary.commands++;
|
||||
- redraw = 1;
|
||||
- }
|
||||
+ DisplaySurface *surface = vga->ds->surface;
|
||||
|
||||
if (qxl->guest_primary.resized) {
|
||||
qxl->guest_primary.resized = 0;
|
||||
|
||||
- if (qxl->guest_primary.flipped) {
|
||||
- g_free(qxl->guest_primary.flipped);
|
||||
- qxl->guest_primary.flipped = NULL;
|
||||
- }
|
||||
- qemu_free_displaysurface(vga->ds);
|
||||
-
|
||||
qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
|
||||
- if (qxl->guest_primary.qxl_stride < 0) {
|
||||
- /* spice surface is upside down -> need extra buffer to flip */
|
||||
- qxl->guest_primary.flipped =
|
||||
- g_malloc(qxl->guest_primary.surface.width *
|
||||
- qxl->guest_primary.abs_stride);
|
||||
- ptr = qxl->guest_primary.flipped;
|
||||
- } else {
|
||||
- ptr = qxl->guest_primary.data;
|
||||
- }
|
||||
- dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d, flip %s\n",
|
||||
+ dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d\n",
|
||||
__FUNCTION__,
|
||||
qxl->guest_primary.surface.width,
|
||||
qxl->guest_primary.surface.height,
|
||||
qxl->guest_primary.qxl_stride,
|
||||
qxl->guest_primary.bytes_pp,
|
||||
- qxl->guest_primary.bits_pp,
|
||||
- qxl->guest_primary.flipped ? "yes" : "no");
|
||||
- vga->ds->surface =
|
||||
+ qxl->guest_primary.bits_pp);
|
||||
+ }
|
||||
+ if (surface->width != qxl->guest_primary.surface.width ||
|
||||
+ surface->height != qxl->guest_primary.surface.height) {
|
||||
+ dprint(qxl, 1, "%s: resizing displaysurface to guest_primary\n",
|
||||
+ __func__);
|
||||
+ if (qxl->guest_primary.qxl_stride > 0) {
|
||||
+ qemu_free_displaysurface(vga->ds);
|
||||
qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
|
||||
qxl->guest_primary.surface.height,
|
||||
qxl->guest_primary.bits_pp,
|
||||
qxl->guest_primary.abs_stride,
|
||||
- ptr);
|
||||
- dpy_resize(vga->ds);
|
||||
+ qxl->guest_primary.data);
|
||||
+ } else {
|
||||
+ qemu_resize_displaysurface(vga->ds,
|
||||
+ qxl->guest_primary.surface.width,
|
||||
+ qxl->guest_primary.surface.height);
|
||||
+ }
|
||||
}
|
||||
-
|
||||
update.left = 0;
|
||||
update.right = qxl->guest_primary.surface.width;
|
||||
update.top = 0;
|
||||
@@ -136,14 +133,11 @@ void qxl_render_update(PCIQXLDevice *qxl)
|
||||
memset(dirty, 0, sizeof(dirty));
|
||||
dirty[0] = update;
|
||||
}
|
||||
-
|
||||
for (i = 0; i < ARRAY_SIZE(dirty); i++) {
|
||||
if (qemu_spice_rect_is_empty(dirty+i)) {
|
||||
break;
|
||||
}
|
||||
- if (qxl->guest_primary.flipped) {
|
||||
- qxl_flip(qxl, dirty+i);
|
||||
- }
|
||||
+ qxl_flip(qxl, dirty+i);
|
||||
dpy_update(vga->ds,
|
||||
dirty[i].left, dirty[i].top,
|
||||
dirty[i].right - dirty[i].left,
|
||||
diff --git a/hw/qxl.h b/hw/qxl.h
|
||||
index 9288e46..53a3ace 100644
|
||||
--- a/hw/qxl.h
|
||||
+++ b/hw/qxl.h
|
||||
@@ -52,7 +52,7 @@ typedef struct PCIQXLDevice {
|
||||
uint32_t abs_stride;
|
||||
uint32_t bits_pp;
|
||||
uint32_t bytes_pp;
|
||||
- uint8_t *data, *flipped;
|
||||
+ uint8_t *data;
|
||||
} guest_primary;
|
||||
|
||||
struct surfaces {
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,264 +0,0 @@
|
||||
From bbe362cd6a386d98a94ac791f1263671bd79b754 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Fri, 24 Feb 2012 23:19:30 +0200
|
||||
Subject: [PATCH 417/434] qxl: introduce QXLCookie
|
||||
|
||||
Will be used in the next patch.
|
||||
|
||||
Signed-off-by: Alon Levy <alevy@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/qxl-render.c | 2 +-
|
||||
hw/qxl.c | 61 ++++++++++++++++++++++++++++++++++++++++------------
|
||||
hw/qxl.h | 2 +-
|
||||
ui/spice-display.c | 22 ++++++++++++++++---
|
||||
ui/spice-display.h | 14 ++++++++++++
|
||||
5 files changed, 82 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
|
||||
index 5811d74..4c22166 100644
|
||||
--- a/hw/qxl-render.c
|
||||
+++ b/hw/qxl-render.c
|
||||
@@ -127,7 +127,7 @@ void qxl_render_update(PCIQXLDevice *qxl)
|
||||
if (runstate_is_running() && qxl->guest_primary.commands) {
|
||||
qxl->guest_primary.commands = 0;
|
||||
qxl_spice_update_area(qxl, 0, &update,
|
||||
- dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC);
|
||||
+ dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC, NULL);
|
||||
}
|
||||
if (redraw) {
|
||||
memset(dirty, 0, sizeof(dirty));
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 0be9859..e6e65d9 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -141,14 +141,15 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
|
||||
struct QXLRect *area, struct QXLRect *dirty_rects,
|
||||
uint32_t num_dirty_rects,
|
||||
uint32_t clear_dirty_region,
|
||||
- qxl_async_io async)
|
||||
+ qxl_async_io async, struct QXLCookie *cookie)
|
||||
{
|
||||
if (async == QXL_SYNC) {
|
||||
qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area,
|
||||
dirty_rects, num_dirty_rects, clear_dirty_region);
|
||||
} else {
|
||||
+ assert(cookie != NULL);
|
||||
spice_qxl_update_area_async(&qxl->ssd.qxl, surface_id, area,
|
||||
- clear_dirty_region, 0);
|
||||
+ clear_dirty_region, (uint64_t)cookie);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,9 +165,13 @@ static void qxl_spice_destroy_surface_wait_complete(PCIQXLDevice *qxl,
|
||||
static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
|
||||
qxl_async_io async)
|
||||
{
|
||||
+ QXLCookie *cookie;
|
||||
+
|
||||
if (async) {
|
||||
- spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id,
|
||||
- (uint64_t)id);
|
||||
+ cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
|
||||
+ QXL_IO_DESTROY_SURFACE_ASYNC);
|
||||
+ cookie->u.surface_id = id;
|
||||
+ spice_qxl_destroy_surface_async(&qxl->ssd.qxl, id, (uint64_t)cookie);
|
||||
} else {
|
||||
qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id);
|
||||
qxl_spice_destroy_surface_wait_complete(qxl, id);
|
||||
@@ -175,7 +180,9 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id,
|
||||
|
||||
static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl)
|
||||
{
|
||||
- spice_qxl_flush_surfaces_async(&qxl->ssd.qxl, 0);
|
||||
+ spice_qxl_flush_surfaces_async(&qxl->ssd.qxl,
|
||||
+ (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
|
||||
+ QXL_IO_FLUSH_SURFACES_ASYNC));
|
||||
}
|
||||
|
||||
void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
|
||||
@@ -205,7 +212,9 @@ static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
|
||||
static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
|
||||
{
|
||||
if (async) {
|
||||
- spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl, 0);
|
||||
+ spice_qxl_destroy_surfaces_async(&qxl->ssd.qxl,
|
||||
+ (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
|
||||
+ QXL_IO_DESTROY_ALL_SURFACES_ASYNC));
|
||||
} else {
|
||||
qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker);
|
||||
qxl_spice_destroy_surfaces_complete(qxl);
|
||||
@@ -721,9 +730,8 @@ static int interface_flush_resources(QXLInstance *sin)
|
||||
static void qxl_create_guest_primary_complete(PCIQXLDevice *d);
|
||||
|
||||
/* called from spice server thread context only */
|
||||
-static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
|
||||
+static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
|
||||
{
|
||||
- PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
|
||||
uint32_t current_async;
|
||||
|
||||
qemu_mutex_lock(&qxl->async_lock);
|
||||
@@ -731,8 +739,16 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
|
||||
qxl->current_async = QXL_UNDEFINED_IO;
|
||||
qemu_mutex_unlock(&qxl->async_lock);
|
||||
|
||||
- dprint(qxl, 2, "async_complete: %d (%" PRId64 ") done\n",
|
||||
- current_async, cookie);
|
||||
+ dprint(qxl, 2, "async_complete: %d (%p) done\n", current_async, cookie);
|
||||
+ if (!cookie) {
|
||||
+ fprintf(stderr, "qxl: %s: error, cookie is NULL\n", __func__);
|
||||
+ return;
|
||||
+ }
|
||||
+ if (cookie && current_async != cookie->io) {
|
||||
+ fprintf(stderr,
|
||||
+ "qxl: %s: error: current_async = %d != %ld = cookie->io\n",
|
||||
+ __func__, current_async, cookie->io);
|
||||
+ }
|
||||
switch (current_async) {
|
||||
case QXL_IO_CREATE_PRIMARY_ASYNC:
|
||||
qxl_create_guest_primary_complete(qxl);
|
||||
@@ -741,12 +757,29 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
|
||||
qxl_spice_destroy_surfaces_complete(qxl);
|
||||
break;
|
||||
case QXL_IO_DESTROY_SURFACE_ASYNC:
|
||||
- qxl_spice_destroy_surface_wait_complete(qxl, (uint32_t)cookie);
|
||||
+ qxl_spice_destroy_surface_wait_complete(qxl, cookie->u.surface_id);
|
||||
break;
|
||||
}
|
||||
qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD);
|
||||
}
|
||||
|
||||
+/* called from spice server thread context only */
|
||||
+static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
|
||||
+{
|
||||
+ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
|
||||
+ QXLCookie *cookie = (QXLCookie *)cookie_token;
|
||||
+
|
||||
+ switch (cookie->type) {
|
||||
+ case QXL_COOKIE_TYPE_IO:
|
||||
+ interface_async_complete_io(qxl, cookie);
|
||||
+ break;
|
||||
+ default:
|
||||
+ fprintf(stderr, "qxl: %s: unexpected cookie type %d\n",
|
||||
+ __func__, cookie->type);
|
||||
+ }
|
||||
+ g_free(cookie);
|
||||
+}
|
||||
+
|
||||
static const QXLInterface qxl_interface = {
|
||||
.base.type = SPICE_INTERFACE_QXL,
|
||||
.base.description = "qxl gpu",
|
||||
@@ -1057,9 +1090,7 @@ static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async)
|
||||
if (d->mode == QXL_MODE_UNDEFINED) {
|
||||
return 0;
|
||||
}
|
||||
-
|
||||
dprint(d, 1, "%s\n", __FUNCTION__);
|
||||
-
|
||||
d->mode = QXL_MODE_UNDEFINED;
|
||||
qemu_spice_destroy_primary_surface(&d->ssd, 0, async);
|
||||
qxl_spice_reset_cursor(d);
|
||||
@@ -1187,7 +1218,9 @@ async_common:
|
||||
{
|
||||
QXLRect update = d->ram->update_area;
|
||||
qxl_spice_update_area(d, d->ram->update_surface,
|
||||
- &update, NULL, 0, 0, async);
|
||||
+ &update, NULL, 0, 0, async,
|
||||
+ qxl_cookie_new(QXL_COOKIE_TYPE_IO,
|
||||
+ QXL_IO_UPDATE_AREA_ASYNC));
|
||||
break;
|
||||
}
|
||||
case QXL_IO_NOTIFY_CMD:
|
||||
diff --git a/hw/qxl.h b/hw/qxl.h
|
||||
index 53a3ace..1443925 100644
|
||||
--- a/hw/qxl.h
|
||||
+++ b/hw/qxl.h
|
||||
@@ -118,7 +118,7 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id,
|
||||
struct QXLRect *area, struct QXLRect *dirty_rects,
|
||||
uint32_t num_dirty_rects,
|
||||
uint32_t clear_dirty_region,
|
||||
- qxl_async_io async);
|
||||
+ qxl_async_io async, QXLCookie *cookie);
|
||||
void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext,
|
||||
uint32_t count);
|
||||
void qxl_spice_oom(PCIQXLDevice *qxl);
|
||||
diff --git a/ui/spice-display.c b/ui/spice-display.c
|
||||
index ad76bae..ab266ae 100644
|
||||
--- a/ui/spice-display.c
|
||||
+++ b/ui/spice-display.c
|
||||
@@ -60,11 +60,23 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r)
|
||||
dest->right = MAX(dest->right, r->right);
|
||||
}
|
||||
|
||||
+QXLCookie *qxl_cookie_new(int type, uint64_t io)
|
||||
+{
|
||||
+ QXLCookie *cookie;
|
||||
+
|
||||
+ cookie = g_malloc0(sizeof(*cookie));
|
||||
+ cookie->type = type;
|
||||
+ cookie->io = io;
|
||||
+ return cookie;
|
||||
+}
|
||||
+
|
||||
void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot,
|
||||
qxl_async_io async)
|
||||
{
|
||||
if (async != QXL_SYNC) {
|
||||
- spice_qxl_add_memslot_async(&ssd->qxl, memslot, 0);
|
||||
+ spice_qxl_add_memslot_async(&ssd->qxl, memslot,
|
||||
+ (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
|
||||
+ QXL_IO_MEMSLOT_ADD_ASYNC));
|
||||
} else {
|
||||
ssd->worker->add_memslot(ssd->worker, memslot);
|
||||
}
|
||||
@@ -80,7 +92,9 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
|
||||
qxl_async_io async)
|
||||
{
|
||||
if (async != QXL_SYNC) {
|
||||
- spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface, 0);
|
||||
+ spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface,
|
||||
+ (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
|
||||
+ QXL_IO_CREATE_PRIMARY_ASYNC));
|
||||
} else {
|
||||
ssd->worker->create_primary_surface(ssd->worker, id, surface);
|
||||
}
|
||||
@@ -91,7 +105,9 @@ void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
|
||||
uint32_t id, qxl_async_io async)
|
||||
{
|
||||
if (async != QXL_SYNC) {
|
||||
- spice_qxl_destroy_primary_surface_async(&ssd->qxl, id, 0);
|
||||
+ spice_qxl_destroy_primary_surface_async(&ssd->qxl, id,
|
||||
+ (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
|
||||
+ QXL_IO_DESTROY_PRIMARY_ASYNC));
|
||||
} else {
|
||||
ssd->worker->destroy_primary_surface(ssd->worker, id);
|
||||
}
|
||||
diff --git a/ui/spice-display.h b/ui/spice-display.h
|
||||
index a23bfc8..8a010cb 100644
|
||||
--- a/ui/spice-display.h
|
||||
+++ b/ui/spice-display.h
|
||||
@@ -48,6 +48,20 @@ typedef enum qxl_async_io {
|
||||
QXL_ASYNC,
|
||||
} qxl_async_io;
|
||||
|
||||
+enum {
|
||||
+ QXL_COOKIE_TYPE_IO,
|
||||
+};
|
||||
+
|
||||
+typedef struct QXLCookie {
|
||||
+ int type;
|
||||
+ uint64_t io;
|
||||
+ union {
|
||||
+ uint32_t surface_id;
|
||||
+ } u;
|
||||
+} QXLCookie;
|
||||
+
|
||||
+QXLCookie *qxl_cookie_new(int type, uint64_t io);
|
||||
+
|
||||
typedef struct SimpleSpiceDisplay SimpleSpiceDisplay;
|
||||
typedef struct SimpleSpiceUpdate SimpleSpiceUpdate;
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,360 +0,0 @@
|
||||
From c26805e29312fee136008a57c70a2f5f140ba706 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Fri, 24 Feb 2012 23:19:31 +0200
|
||||
Subject: [PATCH 418/434] qxl: make qxl_render_update async
|
||||
|
||||
RHBZ# 747011
|
||||
|
||||
Removes the last user of QXL_SYNC when using update drivers that use the
|
||||
_ASYNC io ports.
|
||||
|
||||
The last user is qxl_render_update, it is called both by qxl_hw_update
|
||||
which is the vga_hw_update_ptr passed to graphic_console_init, and by
|
||||
qxl_hw_screen_dump.
|
||||
|
||||
At the same time the QXLRect area being passed to the red_worker thread
|
||||
is passed as a copy, as part of the QXLCookie.
|
||||
|
||||
The implementation uses interface_update_area_complete with a bh to make
|
||||
sure dpy_update and qxl_flip are called from the io thread, otherwise
|
||||
the vga->ds->surface.data can change under our feet.
|
||||
|
||||
With this patch sdl+spice works fine. But spice by itself doesn't
|
||||
produce the expected screendumps unless repeated a few times, due to
|
||||
ppm_save being called before update_area (rendering done in spice server
|
||||
thread) having a chance to complete. Fixed by next patch, but see commit
|
||||
message for problem introduced by it.
|
||||
|
||||
Signed-off-by: Alon Levy <alevy@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/qxl-render.c | 96 +++++++++++++++++++++++++++++++++++++---------------
|
||||
hw/qxl.c | 69 ++++++++++++++++++++++++++++++++++---
|
||||
hw/qxl.h | 10 ++++++
|
||||
ui/spice-display.h | 6 ++++
|
||||
4 files changed, 150 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
|
||||
index 4c22166..4857838 100644
|
||||
--- a/hw/qxl-render.c
|
||||
+++ b/hw/qxl-render.c
|
||||
@@ -82,17 +82,25 @@ void qxl_render_resize(PCIQXLDevice *qxl)
|
||||
}
|
||||
}
|
||||
|
||||
-void qxl_render_update(PCIQXLDevice *qxl)
|
||||
+static void qxl_set_rect_to_surface(PCIQXLDevice *qxl, QXLRect *area)
|
||||
+{
|
||||
+ area->left = 0;
|
||||
+ area->right = qxl->guest_primary.surface.width;
|
||||
+ area->top = 0;
|
||||
+ area->bottom = qxl->guest_primary.surface.height;
|
||||
+}
|
||||
+
|
||||
+static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
|
||||
{
|
||||
VGACommonState *vga = &qxl->vga;
|
||||
- QXLRect dirty[32], update;
|
||||
- int i, redraw = 0;
|
||||
+ int i;
|
||||
DisplaySurface *surface = vga->ds->surface;
|
||||
|
||||
if (qxl->guest_primary.resized) {
|
||||
qxl->guest_primary.resized = 0;
|
||||
-
|
||||
qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
|
||||
+ qxl_set_rect_to_surface(qxl, &qxl->dirty[0]);
|
||||
+ qxl->num_dirty_rects = 1;
|
||||
dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d\n",
|
||||
__FUNCTION__,
|
||||
qxl->guest_primary.surface.width,
|
||||
@@ -103,9 +111,9 @@ void qxl_render_update(PCIQXLDevice *qxl)
|
||||
}
|
||||
if (surface->width != qxl->guest_primary.surface.width ||
|
||||
surface->height != qxl->guest_primary.surface.height) {
|
||||
- dprint(qxl, 1, "%s: resizing displaysurface to guest_primary\n",
|
||||
- __func__);
|
||||
if (qxl->guest_primary.qxl_stride > 0) {
|
||||
+ dprint(qxl, 1, "%s: using guest_primary for displaysurface\n",
|
||||
+ __func__);
|
||||
qemu_free_displaysurface(vga->ds);
|
||||
qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
|
||||
qxl->guest_primary.surface.height,
|
||||
@@ -113,36 +121,70 @@ void qxl_render_update(PCIQXLDevice *qxl)
|
||||
qxl->guest_primary.abs_stride,
|
||||
qxl->guest_primary.data);
|
||||
} else {
|
||||
+ dprint(qxl, 1, "%s: resizing displaysurface to guest_primary\n",
|
||||
+ __func__);
|
||||
qemu_resize_displaysurface(vga->ds,
|
||||
qxl->guest_primary.surface.width,
|
||||
qxl->guest_primary.surface.height);
|
||||
}
|
||||
}
|
||||
- update.left = 0;
|
||||
- update.right = qxl->guest_primary.surface.width;
|
||||
- update.top = 0;
|
||||
- update.bottom = qxl->guest_primary.surface.height;
|
||||
-
|
||||
- memset(dirty, 0, sizeof(dirty));
|
||||
- if (runstate_is_running() && qxl->guest_primary.commands) {
|
||||
- qxl->guest_primary.commands = 0;
|
||||
- qxl_spice_update_area(qxl, 0, &update,
|
||||
- dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC, NULL);
|
||||
- }
|
||||
- if (redraw) {
|
||||
- memset(dirty, 0, sizeof(dirty));
|
||||
- dirty[0] = update;
|
||||
- }
|
||||
- for (i = 0; i < ARRAY_SIZE(dirty); i++) {
|
||||
- if (qemu_spice_rect_is_empty(dirty+i)) {
|
||||
+ for (i = 0; i < qxl->num_dirty_rects; i++) {
|
||||
+ if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
|
||||
break;
|
||||
}
|
||||
- qxl_flip(qxl, dirty+i);
|
||||
+ qxl_flip(qxl, qxl->dirty+i);
|
||||
dpy_update(vga->ds,
|
||||
- dirty[i].left, dirty[i].top,
|
||||
- dirty[i].right - dirty[i].left,
|
||||
- dirty[i].bottom - dirty[i].top);
|
||||
+ qxl->dirty[i].left, qxl->dirty[i].top,
|
||||
+ qxl->dirty[i].right - qxl->dirty[i].left,
|
||||
+ qxl->dirty[i].bottom - qxl->dirty[i].top);
|
||||
+ }
|
||||
+ qxl->num_dirty_rects = 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * use ssd.lock to protect render_update_cookie_num.
|
||||
+ * qxl_render_update is called by io thread or vcpu thread, and the completion
|
||||
+ * callbacks are called by spice_server thread, defering to bh called from the
|
||||
+ * io thread.
|
||||
+ */
|
||||
+void qxl_render_update(PCIQXLDevice *qxl)
|
||||
+{
|
||||
+ QXLCookie *cookie;
|
||||
+
|
||||
+ qemu_mutex_lock(&qxl->ssd.lock);
|
||||
+
|
||||
+ if (!runstate_is_running() || !qxl->guest_primary.commands) {
|
||||
+ qxl_render_update_area_unlocked(qxl);
|
||||
+ qemu_mutex_unlock(&qxl->ssd.lock);
|
||||
+ return;
|
||||
}
|
||||
+
|
||||
+ qxl->guest_primary.commands = 0;
|
||||
+ qxl->render_update_cookie_num++;
|
||||
+ qemu_mutex_unlock(&qxl->ssd.lock);
|
||||
+ cookie = qxl_cookie_new(QXL_COOKIE_TYPE_RENDER_UPDATE_AREA,
|
||||
+ 0);
|
||||
+ qxl_set_rect_to_surface(qxl, &cookie->u.render.area);
|
||||
+ qxl_spice_update_area(qxl, 0, &cookie->u.render.area, NULL,
|
||||
+ 0, 1 /* clear_dirty_region */, QXL_ASYNC, cookie);
|
||||
+}
|
||||
+
|
||||
+void qxl_render_update_area_bh(void *opaque)
|
||||
+{
|
||||
+ PCIQXLDevice *qxl = opaque;
|
||||
+
|
||||
+ qemu_mutex_lock(&qxl->ssd.lock);
|
||||
+ qxl_render_update_area_unlocked(qxl);
|
||||
+ qemu_mutex_unlock(&qxl->ssd.lock);
|
||||
+}
|
||||
+
|
||||
+void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie)
|
||||
+{
|
||||
+ qemu_mutex_lock(&qxl->ssd.lock);
|
||||
+ qemu_bh_schedule(qxl->update_area_bh);
|
||||
+ qxl->render_update_cookie_num--;
|
||||
+ qemu_mutex_unlock(&qxl->ssd.lock);
|
||||
+ g_free(cookie);
|
||||
}
|
||||
|
||||
static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor)
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index e6e65d9..73be115 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -750,6 +750,11 @@ static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
|
||||
__func__, current_async, cookie->io);
|
||||
}
|
||||
switch (current_async) {
|
||||
+ case QXL_IO_MEMSLOT_ADD_ASYNC:
|
||||
+ case QXL_IO_DESTROY_PRIMARY_ASYNC:
|
||||
+ case QXL_IO_UPDATE_AREA_ASYNC:
|
||||
+ case QXL_IO_FLUSH_SURFACES_ASYNC:
|
||||
+ break;
|
||||
case QXL_IO_CREATE_PRIMARY_ASYNC:
|
||||
qxl_create_guest_primary_complete(qxl);
|
||||
break;
|
||||
@@ -759,11 +764,54 @@ static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
|
||||
case QXL_IO_DESTROY_SURFACE_ASYNC:
|
||||
qxl_spice_destroy_surface_wait_complete(qxl, cookie->u.surface_id);
|
||||
break;
|
||||
+ default:
|
||||
+ fprintf(stderr, "qxl: %s: unexpected current_async %d\n", __func__,
|
||||
+ current_async);
|
||||
}
|
||||
qxl_send_events(qxl, QXL_INTERRUPT_IO_CMD);
|
||||
}
|
||||
|
||||
/* called from spice server thread context only */
|
||||
+static void interface_update_area_complete(QXLInstance *sin,
|
||||
+ uint32_t surface_id,
|
||||
+ QXLRect *dirty, uint32_t num_updated_rects)
|
||||
+{
|
||||
+ PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
|
||||
+ int i;
|
||||
+ int qxl_i;
|
||||
+
|
||||
+ qemu_mutex_lock(&qxl->ssd.lock);
|
||||
+ if (surface_id != 0 || !qxl->render_update_cookie_num) {
|
||||
+ qemu_mutex_unlock(&qxl->ssd.lock);
|
||||
+ return;
|
||||
+ }
|
||||
+ if (qxl->num_dirty_rects + num_updated_rects > QXL_NUM_DIRTY_RECTS) {
|
||||
+ /*
|
||||
+ * overflow - treat this as a full update. Not expected to be common.
|
||||
+ */
|
||||
+ dprint(qxl, 1, "%s: overflow of dirty rects\n", __func__);
|
||||
+ qxl->guest_primary.resized = 1;
|
||||
+ }
|
||||
+ if (qxl->guest_primary.resized) {
|
||||
+ /*
|
||||
+ * Don't bother copying or scheduling the bh since we will flip
|
||||
+ * the whole area anyway on completion of the update_area async call
|
||||
+ */
|
||||
+ qemu_mutex_unlock(&qxl->ssd.lock);
|
||||
+ return;
|
||||
+ }
|
||||
+ qxl_i = qxl->num_dirty_rects;
|
||||
+ for (i = 0; i < num_updated_rects; i++) {
|
||||
+ qxl->dirty[qxl_i++] = dirty[i];
|
||||
+ }
|
||||
+ qxl->num_dirty_rects += num_updated_rects;
|
||||
+ dprint(qxl, 1, "%s: scheduling update_area_bh, #dirty %d\n",
|
||||
+ __func__, qxl->num_dirty_rects);
|
||||
+ qemu_bh_schedule(qxl->update_area_bh);
|
||||
+ qemu_mutex_unlock(&qxl->ssd.lock);
|
||||
+}
|
||||
+
|
||||
+/* called from spice server thread context only */
|
||||
static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
|
||||
{
|
||||
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
|
||||
@@ -772,12 +820,16 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
|
||||
switch (cookie->type) {
|
||||
case QXL_COOKIE_TYPE_IO:
|
||||
interface_async_complete_io(qxl, cookie);
|
||||
+ g_free(cookie);
|
||||
+ break;
|
||||
+ case QXL_COOKIE_TYPE_RENDER_UPDATE_AREA:
|
||||
+ qxl_render_update_area_done(qxl, cookie);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "qxl: %s: unexpected cookie type %d\n",
|
||||
__func__, cookie->type);
|
||||
+ g_free(cookie);
|
||||
}
|
||||
- g_free(cookie);
|
||||
}
|
||||
|
||||
static const QXLInterface qxl_interface = {
|
||||
@@ -800,6 +852,7 @@ static const QXLInterface qxl_interface = {
|
||||
.notify_update = interface_notify_update,
|
||||
.flush_resources = interface_flush_resources,
|
||||
.async_complete = interface_async_complete,
|
||||
+ .update_area_complete = interface_update_area_complete,
|
||||
};
|
||||
|
||||
static void qxl_enter_vga_mode(PCIQXLDevice *d)
|
||||
@@ -1216,11 +1269,17 @@ async_common:
|
||||
switch (io_port) {
|
||||
case QXL_IO_UPDATE_AREA:
|
||||
{
|
||||
+ QXLCookie *cookie = NULL;
|
||||
QXLRect update = d->ram->update_area;
|
||||
+
|
||||
+ if (async == QXL_ASYNC) {
|
||||
+ cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
|
||||
+ QXL_IO_UPDATE_AREA_ASYNC);
|
||||
+ cookie->u.area = update;
|
||||
+ }
|
||||
qxl_spice_update_area(d, d->ram->update_surface,
|
||||
- &update, NULL, 0, 0, async,
|
||||
- qxl_cookie_new(QXL_COOKIE_TYPE_IO,
|
||||
- QXL_IO_UPDATE_AREA_ASYNC));
|
||||
+ cookie ? &cookie->u.area : &update,
|
||||
+ NULL, 0, 0, async, cookie);
|
||||
break;
|
||||
}
|
||||
case QXL_IO_NOTIFY_CMD:
|
||||
@@ -1652,6 +1711,8 @@ static int qxl_init_common(PCIQXLDevice *qxl)
|
||||
init_pipe_signaling(qxl);
|
||||
qxl_reset_state(qxl);
|
||||
|
||||
+ qxl->update_area_bh = qemu_bh_new(qxl_render_update_area_bh, qxl);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/hw/qxl.h b/hw/qxl.h
|
||||
index 1443925..86e415b 100644
|
||||
--- a/hw/qxl.h
|
||||
+++ b/hw/qxl.h
|
||||
@@ -18,6 +18,8 @@ enum qxl_mode {
|
||||
|
||||
#define QXL_UNDEFINED_IO UINT32_MAX
|
||||
|
||||
+#define QXL_NUM_DIRTY_RECTS 64
|
||||
+
|
||||
typedef struct PCIQXLDevice {
|
||||
PCIDevice pci;
|
||||
SimpleSpiceDisplay ssd;
|
||||
@@ -93,6 +95,12 @@ typedef struct PCIQXLDevice {
|
||||
/* user-friendly properties (in megabytes) */
|
||||
uint32_t ram_size_mb;
|
||||
uint32_t vram_size_mb;
|
||||
+
|
||||
+ /* qxl_render_update state */
|
||||
+ int render_update_cookie_num;
|
||||
+ int num_dirty_rects;
|
||||
+ QXLRect dirty[QXL_NUM_DIRTY_RECTS];
|
||||
+ QEMUBH *update_area_bh;
|
||||
} PCIQXLDevice;
|
||||
|
||||
#define PANIC_ON(x) if ((x)) { \
|
||||
@@ -134,3 +142,5 @@ void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext);
|
||||
void qxl_render_resize(PCIQXLDevice *qxl);
|
||||
void qxl_render_update(PCIQXLDevice *qxl);
|
||||
void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext);
|
||||
+void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie);
|
||||
+void qxl_render_update_area_bh(void *opaque);
|
||||
diff --git a/ui/spice-display.h b/ui/spice-display.h
|
||||
index 8a010cb..12e50b6 100644
|
||||
--- a/ui/spice-display.h
|
||||
+++ b/ui/spice-display.h
|
||||
@@ -50,6 +50,7 @@ typedef enum qxl_async_io {
|
||||
|
||||
enum {
|
||||
QXL_COOKIE_TYPE_IO,
|
||||
+ QXL_COOKIE_TYPE_RENDER_UPDATE_AREA,
|
||||
};
|
||||
|
||||
typedef struct QXLCookie {
|
||||
@@ -57,6 +58,11 @@ typedef struct QXLCookie {
|
||||
uint64_t io;
|
||||
union {
|
||||
uint32_t surface_id;
|
||||
+ QXLRect area;
|
||||
+ struct {
|
||||
+ QXLRect area;
|
||||
+ int redraw;
|
||||
+ } render;
|
||||
} u;
|
||||
} QXLCookie;
|
||||
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,102 +0,0 @@
|
||||
From 2b973a5ea22635211cbde2e559cc6e6355ca8205 Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Fergeau <cfergeau@redhat.com>
|
||||
Date: Fri, 24 Feb 2012 18:13:12 +0100
|
||||
Subject: [PATCH 419/434] spice: use error_report to report errors
|
||||
|
||||
Error message reporting during spice startup wasn't consistent, it was done
|
||||
with fprintf(stderr, "") but sometimes the message didn't have a trailing
|
||||
\n. Using error_report make the intent of the message clearer and deal
|
||||
with the final \n for us.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
ui/spice-core.c | 22 +++++++++++-----------
|
||||
1 file changed, 11 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/ui/spice-core.c b/ui/spice-core.c
|
||||
index 2c815f1..8503f03 100644
|
||||
--- a/ui/spice-core.c
|
||||
+++ b/ui/spice-core.c
|
||||
@@ -227,8 +227,8 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
|
||||
add_addr_info(server, (struct sockaddr *)&info->laddr_ext,
|
||||
info->llen_ext);
|
||||
} else {
|
||||
- fprintf(stderr, "spice: %s, extended address is expected\n",
|
||||
- __func__);
|
||||
+ error_report("spice: %s, extended address is expected",
|
||||
+ __func__);
|
||||
#endif
|
||||
add_addr_info(client, &info->paddr, info->plen);
|
||||
add_addr_info(server, &info->laddr, info->llen);
|
||||
@@ -333,7 +333,7 @@ static int parse_name(const char *string, const char *optname,
|
||||
if (value != -1) {
|
||||
return value;
|
||||
}
|
||||
- fprintf(stderr, "spice: invalid %s: %s\n", optname, string);
|
||||
+ error_report("spice: invalid %s: %s", optname, string);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -525,7 +525,7 @@ static int add_channel(const char *name, const char *value, void *opaque)
|
||||
rc = spice_server_set_channel_security(spice_server, value, security);
|
||||
}
|
||||
if (rc != 0) {
|
||||
- fprintf(stderr, "spice: failed to set channel security for %s\n", value);
|
||||
+ error_report("spice: failed to set channel security for %s", value);
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
@@ -553,15 +553,15 @@ void qemu_spice_init(void)
|
||||
port = qemu_opt_get_number(opts, "port", 0);
|
||||
tls_port = qemu_opt_get_number(opts, "tls-port", 0);
|
||||
if (!port && !tls_port) {
|
||||
- fprintf(stderr, "neither port nor tls-port specified for spice.");
|
||||
+ error_report("neither port nor tls-port specified for spice");
|
||||
exit(1);
|
||||
}
|
||||
if (port < 0 || port > 65535) {
|
||||
- fprintf(stderr, "spice port is out of range");
|
||||
+ error_report("spice port is out of range");
|
||||
exit(1);
|
||||
}
|
||||
if (tls_port < 0 || tls_port > 65535) {
|
||||
- fprintf(stderr, "spice tls-port is out of range");
|
||||
+ error_report("spice tls-port is out of range");
|
||||
exit(1);
|
||||
}
|
||||
password = qemu_opt_get(opts, "password");
|
||||
@@ -631,11 +631,11 @@ void qemu_spice_init(void)
|
||||
#if SPICE_SERVER_VERSION >= 0x000900 /* 0.9.0 */
|
||||
if (spice_server_set_sasl_appname(spice_server, "qemu") == -1 ||
|
||||
spice_server_set_sasl(spice_server, 1) == -1) {
|
||||
- fprintf(stderr, "spice: failed to enable sasl\n");
|
||||
+ error_report("spice: failed to enable sasl");
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
- fprintf(stderr, "spice: sasl is not available (spice >= 0.9 required)\n");
|
||||
+ error_report("spice: sasl is not available (spice >= 0.9 required)");
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
@@ -683,7 +683,7 @@ void qemu_spice_init(void)
|
||||
qemu_opt_foreach(opts, add_channel, NULL, 0);
|
||||
|
||||
if (0 != spice_server_init(spice_server, &core_interface)) {
|
||||
- fprintf(stderr, "failed to initialize spice server");
|
||||
+ error_report("failed to initialize spice server");
|
||||
exit(1);
|
||||
};
|
||||
using_spice = 1;
|
||||
@@ -708,7 +708,7 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin)
|
||||
{
|
||||
if (!spice_server) {
|
||||
if (QTAILQ_FIRST(&qemu_spice_opts.head) != NULL) {
|
||||
- fprintf(stderr, "Oops: spice configured but not active\n");
|
||||
+ error_report("Oops: spice configured but not active");
|
||||
exit(1);
|
||||
}
|
||||
/*
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,44 +0,0 @@
|
||||
From d01f59d652b8ac906ecd129afa338f56b2aaef90 Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Fergeau <cfergeau@redhat.com>
|
||||
Date: Fri, 24 Feb 2012 18:28:32 +0100
|
||||
Subject: [PATCH 420/434] Error out when tls-channel option is used without
|
||||
TLS
|
||||
|
||||
It's currently possible to setup spice channels using TLS when
|
||||
no TLS port has been specified (ie TLS is disabled). This cannot
|
||||
work, so better to error out in such a situation.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
ui/spice-core.c | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/ui/spice-core.c b/ui/spice-core.c
|
||||
index 8503f03..98356b0 100644
|
||||
--- a/ui/spice-core.c
|
||||
+++ b/ui/spice-core.c
|
||||
@@ -511,6 +511,12 @@ static int add_channel(const char *name, const char *value, void *opaque)
|
||||
int rc;
|
||||
|
||||
if (strcmp(name, "tls-channel") == 0) {
|
||||
+ int *tls_port = opaque;
|
||||
+ if (!*tls_port) {
|
||||
+ error_report("spice: tried to setup tls-channel"
|
||||
+ " without specifying a TLS port");
|
||||
+ exit(1);
|
||||
+ }
|
||||
security = SPICE_CHANNEL_SECURITY_SSL;
|
||||
}
|
||||
if (strcmp(name, "plaintext-channel") == 0) {
|
||||
@@ -680,7 +686,7 @@ void qemu_spice_init(void)
|
||||
spice_server_set_playback_compression
|
||||
(spice_server, qemu_opt_get_bool(opts, "playback-compression", 1));
|
||||
|
||||
- qemu_opt_foreach(opts, add_channel, NULL, 0);
|
||||
+ qemu_opt_foreach(opts, add_channel, &tls_port, 0);
|
||||
|
||||
if (0 != spice_server_init(spice_server, &core_interface)) {
|
||||
error_report("failed to initialize spice server");
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,77 +0,0 @@
|
||||
From 7027fa0d3be22f48a51420a45aff13bec54fef1e Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Mon, 27 Feb 2012 11:05:09 +0100
|
||||
Subject: [PATCH 421/434] qxl: properly handle upright and non-shared surfaces
|
||||
|
||||
Although qxl creates a shared displaysurface when the qxl surface is
|
||||
upright and doesn't need to be flipped there is no guarantee that the
|
||||
surface doesn't become unshared for some reason. Rename qxl_flip to
|
||||
qxl_blit and fix it to handle both flip and non-flip cases.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/qxl-render.c | 20 +++++++++++++-------
|
||||
1 file changed, 13 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
|
||||
index 4857838..2e10e93 100644
|
||||
--- a/hw/qxl-render.c
|
||||
+++ b/hw/qxl-render.c
|
||||
@@ -21,25 +21,31 @@
|
||||
|
||||
#include "qxl.h"
|
||||
|
||||
-static void qxl_flip(PCIQXLDevice *qxl, QXLRect *rect)
|
||||
+static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
|
||||
{
|
||||
uint8_t *src;
|
||||
uint8_t *dst = qxl->vga.ds->surface->data;
|
||||
int len, i;
|
||||
|
||||
- if (qxl->guest_primary.qxl_stride > 0) {
|
||||
+ if (is_buffer_shared(qxl->vga.ds->surface)) {
|
||||
return;
|
||||
}
|
||||
if (!qxl->guest_primary.data) {
|
||||
dprint(qxl, 1, "%s: initializing guest_primary.data\n", __func__);
|
||||
qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram);
|
||||
}
|
||||
- dprint(qxl, 1, "%s: stride %d, [%d, %d, %d, %d]\n", __func__,
|
||||
+ dprint(qxl, 2, "%s: stride %d, [%d, %d, %d, %d]\n", __func__,
|
||||
qxl->guest_primary.qxl_stride,
|
||||
rect->left, rect->right, rect->top, rect->bottom);
|
||||
src = qxl->guest_primary.data;
|
||||
- src += (qxl->guest_primary.surface.height - rect->top - 1) *
|
||||
- qxl->guest_primary.abs_stride;
|
||||
+ if (qxl->guest_primary.qxl_stride < 0) {
|
||||
+ /* qxl surface is upside down, walk src scanlines
|
||||
+ * in reverse order to flip it */
|
||||
+ src += (qxl->guest_primary.surface.height - rect->top - 1) *
|
||||
+ qxl->guest_primary.abs_stride;
|
||||
+ } else {
|
||||
+ src += rect->top * qxl->guest_primary.abs_stride;
|
||||
+ }
|
||||
dst += rect->top * qxl->guest_primary.abs_stride;
|
||||
src += rect->left * qxl->guest_primary.bytes_pp;
|
||||
dst += rect->left * qxl->guest_primary.bytes_pp;
|
||||
@@ -48,7 +54,7 @@ static void qxl_flip(PCIQXLDevice *qxl, QXLRect *rect)
|
||||
for (i = rect->top; i < rect->bottom; i++) {
|
||||
memcpy(dst, src, len);
|
||||
dst += qxl->guest_primary.abs_stride;
|
||||
- src -= qxl->guest_primary.abs_stride;
|
||||
+ src += qxl->guest_primary.qxl_stride;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +138,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
|
||||
if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
|
||||
break;
|
||||
}
|
||||
- qxl_flip(qxl, qxl->dirty+i);
|
||||
+ qxl_blit(qxl, qxl->dirty+i);
|
||||
dpy_update(vga->ds,
|
||||
qxl->dirty[i].left, qxl->dirty[i].top,
|
||||
qxl->dirty[i].right - qxl->dirty[i].left,
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,39 +0,0 @@
|
||||
From 544cfc4a2c730aca346df7215a0dd83280f864d5 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@gmail.com>
|
||||
Date: Mon, 5 Mar 2012 18:22:26 +0100
|
||||
Subject: [PATCH 422/434] spice: set spice uuid and name
|
||||
|
||||
This allows a Spice client to identify a VM
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
ui/spice-core.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/ui/spice-core.c b/ui/spice-core.c
|
||||
index 98356b0..4ad0a67 100644
|
||||
--- a/ui/spice-core.c
|
||||
+++ b/ui/spice-core.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <spice-experimental.h>
|
||||
|
||||
#include <netdb.h>
|
||||
+#include "sysemu.h"
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qemu-spice.h"
|
||||
@@ -688,6 +689,11 @@ void qemu_spice_init(void)
|
||||
|
||||
qemu_opt_foreach(opts, add_channel, &tls_port, 0);
|
||||
|
||||
+#if SPICE_SERVER_VERSION >= 0x000a02 /* 0.10.2 */
|
||||
+ spice_server_set_name(spice_server, qemu_name);
|
||||
+ spice_server_set_uuid(spice_server, qemu_uuid);
|
||||
+#endif
|
||||
+
|
||||
if (0 != spice_server_init(spice_server, &core_interface)) {
|
||||
error_report("failed to initialize spice server");
|
||||
exit(1);
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,35 +0,0 @@
|
||||
From 63f3e6ee49e0a88bbd7915d81962c9046205c411 Mon Sep 17 00:00:00 2001
|
||||
From: Yonit Halperin <yhalperi@redhat.com>
|
||||
Date: Sun, 18 Mar 2012 09:42:39 +0200
|
||||
Subject: [PATCH 423/434] monitor: fix client_migrate_info error handling
|
||||
|
||||
Report QERR_MISSING_PARAMETER when port is missing. Otherwise
|
||||
QERR_UNDEFINED_ERROR will occur.
|
||||
|
||||
rhbz #795652
|
||||
|
||||
Signed-off-by: Yonit Halperin <yhalperi@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
monitor.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/monitor.c b/monitor.c
|
||||
index 3c23aa4..76739d7 100644
|
||||
--- a/monitor.c
|
||||
+++ b/monitor.c
|
||||
@@ -1046,6 +1046,11 @@ static int client_migrate_info(Monitor *mon, const QDict *qdict,
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ if (port == -1 && tls_port == -1) {
|
||||
+ qerror_report(QERR_MISSING_PARAMETER, "port/tls-port");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
ret = qemu_spice_migrate_info(hostname, port, tls_port, subject,
|
||||
cb, opaque);
|
||||
if (ret != 0) {
|
||||
--
|
||||
1.7.10
|
||||
|
@ -1,49 +0,0 @@
|
||||
From d3e6c37f68e7e4573a47b0540f626a2add0d05e4 Mon Sep 17 00:00:00 2001
|
||||
From: Alon Levy <alevy@redhat.com>
|
||||
Date: Sun, 18 Mar 2012 13:46:13 +0100
|
||||
Subject: [PATCH 424/434] qxl: init_pipe_signaling: exit on failure
|
||||
|
||||
If pipe creation fails, exit, don't log and continue. Fix indentation at
|
||||
the same time.
|
||||
|
||||
Signed-off-by: Alon Levy <alevy@redhat.com>
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
---
|
||||
hw/qxl.c | 21 +++++++++++----------
|
||||
1 file changed, 11 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/hw/qxl.c b/hw/qxl.c
|
||||
index 73be115..9ad5807 100644
|
||||
--- a/hw/qxl.c
|
||||
+++ b/hw/qxl.c
|
||||
@@ -1453,16 +1453,17 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
|
||||
|
||||
static void init_pipe_signaling(PCIQXLDevice *d)
|
||||
{
|
||||
- if (pipe(d->pipe) < 0) {
|
||||
- dprint(d, 1, "%s: pipe creation failed\n", __FUNCTION__);
|
||||
- return;
|
||||
- }
|
||||
- fcntl(d->pipe[0], F_SETFL, O_NONBLOCK);
|
||||
- fcntl(d->pipe[1], F_SETFL, O_NONBLOCK);
|
||||
- fcntl(d->pipe[0], F_SETOWN, getpid());
|
||||
-
|
||||
- qemu_thread_get_self(&d->main);
|
||||
- qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d);
|
||||
+ if (pipe(d->pipe) < 0) {
|
||||
+ fprintf(stderr, "%s:%s: qxl pipe creation failed\n",
|
||||
+ __FILE__, __func__);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ fcntl(d->pipe[0], F_SETFL, O_NONBLOCK);
|
||||
+ fcntl(d->pipe[1], F_SETFL, O_NONBLOCK);
|
||||
+ fcntl(d->pipe[0], F_SETOWN, getpid());
|
||||
+
|
||||
+ qemu_thread_get_self(&d->main);
|
||||
+ qemu_set_fd_handler(d->pipe[0], pipe_read, NULL, d);
|
||||
}
|
||||
|
||||
/* graphics console */
|
||||
--
|
||||
1.7.10
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user