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:
Hans de Goede 2012-07-05 11:22:23 +02:00
parent 188256aae3
commit 329b588089
128 changed files with 557 additions and 12684 deletions

View File

@ -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

View 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,22 +1,22 @@
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);
+static void tcp_closed(void *opaque)
+{
+ CharDriverState *chr = 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

View File

@ -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

View File

@ -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,30 +24,31 @@ 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
+static const QemuChrHandlers gdb_handlers = {
+ .fd_can_read = gdb_chr_can_receive,
+ .fd_read = gdb_chr_receive,
@ -55,24 +58,51 @@ 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;
- qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
- gdb_chr_event, NULL);
+ qemu_chr_add_handlers(chr, &gdb_handlers, NULL);
}
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)
return card->atr;
}
+static const QemuChrHandlers passthru_handlers = {
+ .fd_can_read = ccid_card_vscard_can_read,
+ .fd_read = ccid_card_vscard_read,
@ -95,26 +125,26 @@ 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)
exit(1);
}
- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
+ qemu_chr_add_handlers(s->chr, NULL, s);
}
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,
sysbus_mmio_map(s, 0, base);
}
+static const QemuChrHandlers serial_handlers = {
+ .fd_can_read = serial_can_receive,
+ .fd_read = serial_receive1,
@ -135,13 +165,13 @@ 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)
}
+static const QemuChrHandlers serial_handlers = {
+ .fd_can_read = serial_can_receive,
+ .fd_read = serial_receive,
@ -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);
s->chr = qdev_init_chardev(&dev->qdev);
sysbus_init_mmio(dev, &s->mmio);
s->chr = qemu_char_get_next_serial();
- if (s->chr)
- qemu_chr_add_handlers(s->chr,
- serial_can_receive, serial_receive,
@ -164,15 +194,42 @@ 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 = {
+ .fd_can_read = grlib_apbuart_can_receive,
+ .fd_read = grlib_apbuart_receive,
@ -181,26 +238,25 @@ index c90b810..ac6c33b 100644
+
static int grlib_apbuart_init(SysBusDevice *dev)
{
UART *uart = FROM_SYSBUS(typeof(*uart), dev);
int uart_regs = 0;
UART *uart = FROM_SYSBUS(typeof(*uart), dev);
- qemu_chr_add_handlers(uart->chr,
- grlib_apbuart_can_receive,
- grlib_apbuart_receive,
- grlib_apbuart_event,
- uart);
+ qemu_chr_add_handlers(uart->chr, &grlib_handlers, uart);
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);
}
+static const QemuChrHandlers ivshmem_handlers = {
+ .fd_can_read = ivshmem_can_receive,
+ .fd_read = ivshmem_receive,
@ -216,10 +272,10 @@ 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;
- qemu_chr_add_handlers(chr, ivshmem_can_receive, fake_irqfd,
- ivshmem_event, &s->eventfd_table[vector]);
+ qemu_chr_add_handlers(chr, &ivshmem_msi_handlers,
@ -229,12 +285,12 @@ index 7b4dbf6..ee78576 100644
- ivshmem_event, s);
+ qemu_chr_add_handlers(chr, &ivshmem_handlers, s);
}
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 = {
+ .fd_can_read = ivshmem_can_receive,
+ .fd_read = ivshmem_read,
@ -244,10 +300,10 @@ 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 *));
- qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read,
- ivshmem_event, s);
+ qemu_chr_add_handlers(s->server_chr, &ivshmem_server_handlers, s);
@ -255,13 +311,13 @@ 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)
s->jrx = 0;
}
+static const QemuChrHandlers juart_handlers = {
+ .fd_can_read = juart_can_rx,
+ .fd_read = juart_rx,
@ -271,22 +327,22 @@ index 5454aa4..1b9fa07 100644
static int lm32_juart_init(SysBusDevice *dev)
{
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;
}
+static const QemuChrHandlers uart_handlers = {
+ .fd_can_read = uart_can_rx,
+ .fd_read = uart_rx,
@ -296,23 +352,23 @@ 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)
s->chr = qdev_init_chardev(&dev->qdev);
@@ -254,7 +260,7 @@ static int lm32_uart_init(SysBusDevice *dev)
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]);
}
+static const QemuChrHandlers mcf_uart_handlers = {
+ .fd_can_read = mcf_uart_can_receive,
+ .fd_read = mcf_uart_receive,
@ -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,13 +389,13 @@ 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)
s->regs[R_STAT] = STAT_THRE;
}
+static const QemuChrHandlers uart_handlers = {
+ .fd_can_read = uart_can_rx,
+ .fd_read = uart_rx,
@ -350,22 +406,22 @@ 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 = {
}
};
+static const QemuChrHandlers pl011_handlers = {
+ .fd_can_read = pl011_can_receive,
+ .fd_read = pl011_receive,
@ -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,13 +442,13 @@ 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;
}
+static const QemuChrHandlers pxa2xx_handlers = {
+ .fd_can_read = pxa2xx_fir_is_empty,
+ .fd_read = pxa2xx_fir_rx,
@ -402,10 +458,10 @@ 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);
- if (chr)
- qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
- pxa2xx_fir_rx, pxa2xx_fir_event, s);
@ -415,15 +471,28 @@ 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);
}
+static const QemuChrHandlers serial_handlers = {
+ .fd_can_read = serial_can_receive1,
+ .fd_read = serial_receive1,
@ -433,54 +502,54 @@ 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);
- qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
- serial_event, s);
+ qemu_chr_add_handlers(s->chr, &serial_handlers, s);
}
/* 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 = {
+ .fd_can_read = sh_serial_can_receive1,
+ .fd_read = sh_serial_receive1,
+ .fd_event = sh_serial_event,
+};
+
void sh_serial_init (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,
void sh_serial_init(MemoryRegion *sysmem,
target_phys_addr_t base, int feat,
uint32_t freq, CharDriverState *chr,
@@ -394,9 +400,9 @@ void sh_serial_init(MemoryRegion *sysmem,
s->chr = chr;
- if (chr)
- qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
- sh_serial_event, s);
+ if (chr) {
+ qemu_chr_add_handlers(chr, &sh_serial_handlers, s);
+ }
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)
qemu_chr_fe_write(dev->chardev, buf, len);
}
+static const QemuChrHandlers vty_handlers = {
+ .fd_can_read = vty_can_receive,
+ .fd_read = vty_receive,
@ -492,21 +561,21 @@ index f23cc36..0d9cd59 100644
@@ -63,8 +68,7 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev)
exit(1);
}
- 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,
};
+static const QemuChrHandlers strongarm_uart_handlers = {
+ .fd_can_read = strongarm_uart_can_receive,
+ .fd_read = strongarm_uart_receive,
@ -516,9 +585,9 @@ 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) {
- qemu_chr_add_handlers(s->chr,
- strongarm_uart_can_receive,
@ -527,43 +596,16 @@ index a3d9080..8a8a219 100644
- s);
+ qemu_chr_add_handlers(s->chr, &strongarm_uart_handlers, s);
}
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)
}
}
+static const QemuChrHandlers usb_serial_handlers = {
+ .fd_can_read = usb_serial_can_read,
+ .fd_read = usb_serial_read,
@ -573,24 +615,51 @@ 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;
}
- qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
- usb_serial_event, s);
+ qemu_chr_add_handlers(s->cs, &usb_serial_handlers, s);
usb_serial_handle_reset(dev);
return 0;
}
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index d3351c8..6d6f3ef 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -95,6 +95,12 @@ static void chr_event(void *opaque, int event)
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 cffee3d..066590c 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -106,6 +106,12 @@ static void chr_event(void *opaque, int event)
}
}
+static const QemuChrHandlers chr_handlers = {
+ .fd_can_read = chr_can_read,
+ .fd_read = chr_read,
@ -600,33 +669,24 @@ 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:
return ret;
}
+static const QemuChrHandlers xencons_handlers = {
+ .fd_can_read = xencons_can_receive,
+ .fd_read = xencons_receive,
@ -637,7 +697,7 @@ index edcb31c..2ba74f0 100644
struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
@@ -232,9 +237,9 @@ static int con_initialise(struct XenDevice *xendev)
return -1;
xen_be_bind_evtchn(&con->xendev);
- if (con->chr)
- qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive,
@ -645,29 +705,29 @@ index edcb31c..2ba74f0 100644
+ if (con->chr) {
+ qemu_chr_add_handlers(con->chr, &xencons_handlers, con);
+ }
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) {
+ qemu_chr_add_handlers(con->chr, NULL, NULL);
+ }
xen_be_unbind_evtchn(&con->xendev);
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)
}
+static const QemuChrHandlers uart_handlers = {
+ .fd_can_read = uart_can_rx,
+ .fd_read = uart_rx,
@ -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);
s->chr = qdev_init_chardev(&dev->qdev);
sysbus_init_mmio(dev, &s->mmio);
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) {
@ -688,15 +748,15 @@ index ceb7b4d..69f7191 100644
+ }
return 0;
}
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:
*/
+static const QemuChrHandlers monitor_handlers = {
+ .fd_can_read = monitor_can_read,
+ .fd_read = monitor_read,
@ -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 */
@ -725,16 +785,16 @@ index f956eb7..a82fda3 100644
- monitor_event, mon);
+ qemu_chr_add_handlers(chr, &monitor_handlers, mon);
}
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);
}
+static const QemuChrHandlers guestfwd_handlers = {
+ .fd_can_read = guestfwd_can_read,
+ .fd_read = guestfwd_read,
@ -743,24 +803,24 @@ 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;
- qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
- NULL, fwd);
+ qemu_chr_add_handlers(fwd->hd, &guestfwd_handlers, fwd);
return 0;
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);
}
+static const QemuChrHandlers null_handlers = {
+ /* All handlers are initialised to NULL */
+};
@ -792,10 +852,10 @@ 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);
}
+static const QemuChrHandlers mux_chr_handlers = {
+ .fd_can_read = mux_chr_can_read,
+ .fd_read = mux_chr_read,
@ -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,13 +876,13 @@ 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);
*/
void qemu_chr_be_event(CharDriverState *s, int event);
-void qemu_chr_add_handlers(CharDriverState *s,
- IOCanReadHandler *fd_can_read,
- IOReadHandler *fd_read,
@ -837,35 +897,35 @@ index 8ca1e2d..564e688 100644
+
+void qemu_chr_add_handlers(CharDriverState *s, const QemuChrHandlers *handlers,
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)
/* 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);
return 0;
}
+
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);
- 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);
inbuf = g_string_new("");
--
1.7.7.5
1.7.10.4

View File

@ -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

View File

@ -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,16 +10,16 @@ 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 {
static QLIST_HEAD(, IOHandlerRecord) io_handlers =
QLIST_HEAD_INITIALIZER(io_handlers);
+static IOHandlerRecord *find_iohandler(int fd)
+{
+ IOHandlerRecord *ioh;
@ -55,17 +55,17 @@ index 5640d49..a9a62cb 100644
+
+ ioh->fd_write = NULL;
+}
/* 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);
+void enable_write_fd_handler(int fd, IOHandler *fd_write);
+void disable_write_fd_handler(int fd);
+
@ -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

View File

@ -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

View File

@ -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;
@ -28,14 +28,14 @@ index d2a99a6..66b5887 100644
s->handler_opaque = opaque;
if (s->chr_update_read_handler)
s->chr_update_read_handler(s);
+ s->write_blocked = false;
+
/* We're connecting to an already opened device, so let's make sure we
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 {
@ -55,7 +55,7 @@ index 564e688..2628bee 100644
+ bool write_blocked; /* Are we in a blocked state? */
QTAILQ_ENTRY(CharDriverState) next;
};
--
1.7.7.5
1.7.10.4

View File

@ -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

View File

@ -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,40 +16,40 @@ 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_
uint32_t len;
len = htonl(size);
- send_all(s->fd, (const uint8_t *)&len, sizeof(len));
- return send_all(s->fd, buf, size);
+ send_all(NULL, s->fd, (const uint8_t *)&len, sizeof(len));
+ return send_all(NULL, s->fd, buf, size);
}
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
-int send_all(int fd, const void *buf, int len1)
+static int do_send(int fd, const void *buf, int len1, bool nonblock)
{
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,16 +64,16 @@ 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
-int send_all(int fd, const void *_buf, int len1)
+static int do_send(int fd, const void *_buf, int len1, bool nonblock)
{
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,10 +90,10 @@ 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;
+int send_all(CharDriverState *chr, int fd, const void *_buf, int len1)
+{
+ int ret, eagain_errno;
@ -133,27 +133,27 @@ 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;
- return send_all(s->fd_out, buf, len);
+ return send_all(chr, s->fd_out, buf, len);
}
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;
}
- return send_all(s->fd, buf, len);
+ return send_all(chr, s->fd, buf, len);
}
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

View File

@ -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

View File

@ -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,16 +15,16 @@ 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 @@
static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
QTAILQ_HEAD_INITIALIZER(chardevs);
+/*
+ * Generic routine that gets called when chardev becomes writable.
+ * Lets chardev user know it's OK to send more data.
@ -41,10 +41,10 @@ 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);
}
+static void tcp_enable_write_fd_handler(CharDriverState *chr)
+{
+ TCPCharDriver *s = chr->opaque;
@ -64,18 +64,18 @@ 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;
+ chr->chr_enable_write_fd_handler = tcp_enable_write_fd_handler;
+ chr->chr_disable_write_fd_handler = tcp_disable_write_fd_handler;
if (is_listen) {
s->listen_fd = fd;
--
1.7.7.5
1.7.10.4

View File

@ -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

View File

@ -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,16 +13,16 @@ 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 {
CharDriverState *chr;
} VirtConsole;
+/*
+ * Callback function that's called from chardevs when backend becomes
+ * writable.
@ -33,17 +33,17 @@ index 6d6f3ef..da68211 100644
+
+ virtio_serial_throttle_port(&vcon->port, false);
+}
/* 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,
+ .fd_write_unblocked = chr_write_unblocked,
};
static int virtconsole_initfn(VirtIOSerialPort *port)
--
1.7.7.5
1.7.10.4

View File

@ -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 @@
@ -55,12 +55,12 @@ index 7e8eaa9..eeeb32e 100644
uint32_t debug;
+ QEMUTimer *unblock_timer;
} SpiceCharDriver;
static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
@@ -50,6 +53,17 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
return out;
}
+static void spice_chr_unblock(void *opaque)
+{
+ SpiceCharDriver *scd = opaque;
@ -100,7 +100,7 @@ index 7e8eaa9..eeeb32e 100644
{
SpiceCharDriver *s = chr->opaque;
+ int read_bytes;
dprintf(s, 2, "%s: %d\n", __func__, len);
vmc_register_interface(s);
@@ -147,7 +169,15 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
@ -118,16 +118,16 @@ index 7e8eaa9..eeeb32e 100644
+ }
+ return read_bytes;
}
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;
+ s->unblock_timer = qemu_new_timer_ms(vm_clock, spice_chr_unblock, s);
#if SPICE_SERVER_VERSION < 0x000901
/* See comment in vmc_state() */
--
1.7.7.5
1.7.10.4

View File

@ -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 {
@ -38,7 +38,7 @@ index eeeb32e..70a83bf 100644
@@ -69,7 +68,7 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
int bytes = MIN(len, scd->datalen);
- dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen);
+ dprintf(scd, 2, "%s: %p %d/%d/%d\n", __func__, scd->datapos, len, bytes, scd->datalen);
if (bytes > 0) {
@ -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

View File

@ -1,28 +1,28 @@
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;
+ int r;
- if (!dev->cs->opened) {
+ if (!dev->cs->opened || dev->cs->write_blocked) {
return 0;
}
- return qemu_chr_fe_write(dev->cs, data, count);
+ r = qemu_chr_fe_write(dev->cs, data, count);
+
@ -35,12 +35,12 @@ index e421cff..1289506 100644
+
+ return r;
}
/*
@@ -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)
}
}
+static void usbredir_chardev_write_unblocked(void *opaque)
+{
+ USBRedirDevice *dev = opaque;
@ -58,8 +58,8 @@ index e421cff..1289506 100644
.fd_event = usbredir_chardev_event,
+ .fd_write_unblocked = usbredir_chardev_write_unblocked,
};
/*
--
1.7.7.5
1.7.10.4

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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