From 3a395142ba99197429a2378930d3c1551fc053cc Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 18 Nov 2011 16:31:59 +0100 Subject: virtio-blk: fix cross-endian config space Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- hw/virtio-blk.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 19e89e71e..d6d1f87cd 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -485,6 +485,7 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config) struct virtio_blk_config blkcfg; uint64_t capacity; int cylinders, heads, secs; + int blk_size = s->conf->logical_block_size; bdrv_get_geometry(s->bs, &capacity); bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs); @@ -492,14 +493,14 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config) stq_raw(&blkcfg.capacity, capacity); stl_raw(&blkcfg.seg_max, 128 - 2); stw_raw(&blkcfg.cylinders, cylinders); + stl_raw(&blkcfg.blk_size, blk_size); + stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size); + stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size); blkcfg.heads = heads; blkcfg.sectors = secs & ~s->sector_mask; - blkcfg.blk_size = s->conf->logical_block_size; blkcfg.size_max = 0; blkcfg.physical_block_exp = get_physical_block_exp(s->conf); blkcfg.alignment_offset = 0; - blkcfg.min_io_size = s->conf->min_io_size / blkcfg.blk_size; - blkcfg.opt_io_size = s->conf->opt_io_size / blkcfg.blk_size; memcpy(config, &blkcfg, sizeof(struct virtio_blk_config)); } -- cgit v1.2.3 From ce4e7e4661af433674f349ccdd5709b4b7a8b2fd Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 18 Nov 2011 16:32:00 +0100 Subject: usb-msd: do not register twice in the boot order USB mass storage devices are registered twice in the boot order. To avoid having to keep the two paths in sync, pass the bootindex property down to the scsi-disk device and let it register itself. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- hw/pci-hotplug.c | 3 ++- hw/scsi-bus.c | 7 +++++-- hw/scsi.h | 2 +- hw/usb-msd.c | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c index b59be2a59..12f61fea6 100644 --- a/hw/pci-hotplug.c +++ b/hw/pci-hotplug.c @@ -91,7 +91,8 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter, */ dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1); dinfo->bus = scsibus->busnr; - scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, false); + scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, + false, -1); if (!scsidev) { return -1; } diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 3a2a7bb72..2feeaa299 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -162,7 +162,7 @@ void scsi_qdev_register(SCSIDeviceInfo *info) /* handle legacy '-drive if=scsi,...' cmd line args */ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, - int unit, bool removable) + int unit, bool removable, int bootindex) { const char *driver; DeviceState *dev; @@ -170,6 +170,9 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, driver = bdrv_is_sg(bdrv) ? "scsi-generic" : "scsi-disk"; dev = qdev_create(&bus->qbus, driver); qdev_prop_set_uint32(dev, "scsi-id", unit); + if (bootindex >= 0) { + qdev_prop_set_int32(dev, "bootindex", bootindex); + } if (qdev_prop_exists(dev, "removable")) { qdev_prop_set_bit(dev, "removable", removable); } @@ -195,7 +198,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus) continue; } qemu_opts_loc_restore(dinfo->opts); - if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false)) { + if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1)) { res = -1; break; } diff --git a/hw/scsi.h b/hw/scsi.h index 61c64d5c7..ab6e95232 100644 --- a/hw/scsi.h +++ b/hw/scsi.h @@ -128,7 +128,7 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d) } SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, - int unit, bool removable); + int unit, bool removable, int bootindex); int scsi_bus_legacy_handle_cmdline(SCSIBus *bus); /* diff --git a/hw/usb-msd.c b/hw/usb-msd.c index 68e375678..4c0695012 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -546,7 +546,8 @@ static int usb_msd_initfn(USBDevice *dev) usb_desc_init(dev); scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info); - s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable); + s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable, + s->conf.bootindex); if (!s->scsi_dev) { return -1; } @@ -562,7 +563,6 @@ static int usb_msd_initfn(USBDevice *dev) } } - add_boot_device_path(s->conf.bootindex, &dev->qdev, "/disk@0,0"); return 0; } -- cgit v1.2.3 From 795928f61daff10b06bb21e837bc5bf0227cf076 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 18 Nov 2011 17:03:45 +0100 Subject: scsi: fix fw path The pre-1.0 firmware path for SCSI devices already included the LUN using the suffix argument to add_boot_device_path. Avoid that it is included twice, and convert the colons to commas for consistency with other kinds of devices Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- hw/scsi-bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 2feeaa299..64e709ee9 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -1370,8 +1370,8 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev) SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev); char path[100]; - snprintf(path, sizeof(path), "%s@%d,%d,%d", qdev_fw_name(dev), - d->channel, d->id, d->lun); + snprintf(path, sizeof(path), "channel@%x/%s@%x,%x", d->channel, + qdev_fw_name(dev), d->id, d->lun); return strdup(path); } -- cgit v1.2.3 From 28b77657cfb44cdcc379997340701d73432b9007 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 18 Nov 2011 16:32:02 +0100 Subject: scsi-generic: add as boot device There is no reason why a scsi-generic device cannot boot if it has the right type, and indeed it provides already a bootindex property. So register those devices too. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- hw/scsi-generic.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index 9594cc127..e62044f39 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -413,6 +413,10 @@ static int scsi_generic_initfn(SCSIDevice *s) /* define device state */ s->type = scsiid.scsi_type; DPRINTF("device type %d\n", s->type); + if (s->type == TYPE_DISK || s->type == TYPE_ROM) { + add_boot_device_path(s->conf.bootindex, &s->qdev, NULL); + } + switch (s->type) { case TYPE_TAPE: s->blocksize = get_stream_blocksize(s->conf.bs); @@ -459,6 +463,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun, static SCSIDeviceInfo scsi_generic_info = { .qdev.name = "scsi-generic", + .qdev.fw_name = "disk", .qdev.desc = "pass through generic scsi device (/dev/sg*)", .qdev.size = sizeof(SCSIDevice), .qdev.reset = scsi_generic_reset, -- cgit v1.2.3 From c3fecea50dc0f27198b8658a0c9c4fbfdd0f95db Mon Sep 17 00:00:00 2001 From: Dong Xu Wang Date: Tue, 22 Nov 2011 10:56:58 +0800 Subject: sheepdog: Avoid deadlock in error path s->lock should be unlocked before leaving add_aio_request. Signed-off-by: Dong Xu Wang Signed-off-by: Kevin Wolf --- block/sheepdog.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/block/sheepdog.c b/block/sheepdog.c index 9f8060960..62f1f3a0c 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1116,6 +1116,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, /* send a header */ ret = do_write(s->fd, &hdr, sizeof(hdr)); if (ret) { + qemu_co_mutex_unlock(&s->lock); error_report("failed to send a req, %s", strerror(errno)); return -EIO; } @@ -1123,6 +1124,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, if (wlen) { ret = do_writev(s->fd, iov, wlen, aio_req->iov_offset); if (ret) { + qemu_co_mutex_unlock(&s->lock); error_report("failed to send a data, %s", strerror(errno)); return -EIO; } -- cgit v1.2.3 From e30e5eb6136aa3311dad4ca90f6546e05ae98f92 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 16 Nov 2011 15:45:59 +0100 Subject: slirp: Clean up net_slirp_hostfwd_remove()'s use of get_str_sep() get_str_sep() can fail, but net_slirp_hostfwd_remove() doesn't check. Works, because it initializes buf[] to "", which get_str_sep() doesn't touch when it fails. Coverity doesn't like it, and neither do I. Change it to work exactly like slirp_hostfwd(). Acked-by: Jan Kiszka Signed-off-by: Markus Armbruster Signed-off-by: Stefan Hajnoczi --- net/slirp.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/net/slirp.c b/net/slirp.c index c6cda5dcb..6646ecb1c 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -305,7 +305,7 @@ void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict) { struct in_addr host_addr = { .s_addr = INADDR_ANY }; int host_port; - char buf[256] = ""; + char buf[256]; const char *src_str, *p; SlirpState *s; int is_udp = 0; @@ -325,11 +325,10 @@ void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict) return; } - if (!src_str || !src_str[0]) - goto fail_syntax; - p = src_str; - get_str_sep(buf, sizeof(buf), &p, ':'); + if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) { + goto fail_syntax; + } if (!strcmp(buf, "tcp") || buf[0] == '\0') { is_udp = 0; -- cgit v1.2.3 From 2af2a1b8d05a1a64c5005ed930137632b9d5aa22 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 22 Nov 2011 12:39:58 +0100 Subject: usb: make usb_create_simple catch and pass up errors. Use qdev_init() instead of qdev_init_nofail(), usb device initialization can fail, most common case being port and device speed mismatch. Handle failures correctly and pass up NULL pointers then. Also fixup usb_create_simple() callers (only one was buggy) to properly check for NULL pointers before referncing the usb_create_simple() return value. Signed-off-by: Gerd Hoffmann --- hw/usb-bt.c | 3 +++ hw/usb-bus.c | 11 +++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/hw/usb-bt.c b/hw/usb-bt.c index 529fa3355..f30eec1ea 100644 --- a/hw/usb-bt.c +++ b/hw/usb-bt.c @@ -528,6 +528,9 @@ USBDevice *usb_bt_init(HCIInfo *hci) if (!hci) return NULL; dev = usb_create_simple(NULL /* FIXME */, "usb-bt-dongle"); + if (!dev) { + return NULL; + } s = DO_UPCAST(struct USBBtState, dev, dev); s->dev.opaque = s; diff --git a/hw/usb-bus.c b/hw/usb-bus.c index 93f640d37..f8b980723 100644 --- a/hw/usb-bus.c +++ b/hw/usb-bus.c @@ -139,10 +139,17 @@ USBDevice *usb_create(USBBus *bus, const char *name) USBDevice *usb_create_simple(USBBus *bus, const char *name) { USBDevice *dev = usb_create(bus, name); + int rc; + if (!dev) { - hw_error("Failed to create USB device '%s'\n", name); + error_report("Failed to create USB device '%s'\n", name); + return NULL; + } + rc = qdev_init(&dev->qdev); + if (rc < 0) { + error_report("Failed to initialize USB device '%s'\n", name); + return NULL; } - qdev_init_nofail(&dev->qdev); return dev; } -- cgit v1.2.3 From f462141f18ffdd75847f6459ef83d90b831d12c0 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 22 Nov 2011 12:48:14 +0100 Subject: usb: fix usb_qdev_init error handling. qdev doesn't call the ->exit callback on ->init failures, so we have to take care ourself that we cleanup property on errors. Signed-off-by: Gerd Hoffmann --- hw/usb-bus.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/hw/usb-bus.c b/hw/usb-bus.c index f8b980723..8cafb76ff 100644 --- a/hw/usb-bus.c +++ b/hw/usb-bus.c @@ -9,6 +9,7 @@ static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent); static char *usb_get_dev_path(DeviceState *dev); static char *usb_get_fw_dev_path(DeviceState *qdev); +static int usb_qdev_exit(DeviceState *qdev); static struct BusInfo usb_bus_info = { .name = "USB", @@ -75,12 +76,23 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base) dev->auto_attach = 1; QLIST_INIT(&dev->strings); rc = usb_claim_port(dev); - if (rc == 0) { - rc = dev->info->init(dev); + if (rc != 0) { + goto err; } - if (rc == 0 && dev->auto_attach) { + rc = dev->info->init(dev); + if (rc != 0) { + goto err; + } + if (dev->auto_attach) { rc = usb_device_attach(dev); + if (rc != 0) { + goto err; + } } + return 0; + +err: + usb_qdev_exit(qdev); return rc; } -- cgit v1.2.3 From be35cbbc8802eeba750c300c35339d69929989a6 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 22 Nov 2011 13:20:14 +0100 Subject: usb-hub: wakeup on detach too. When detaching devices from the usb hub we must wakeup too, otherwise the host misses the detach event. Commit 4a33a9ea06f6fbb08d8311a7cfed72975344f9ab does the same for device attach. Found by hkran@linux.vnet.ibm.com Signed-off-by: Gerd Hoffmann --- hw/usb-hub.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/usb-hub.c b/hw/usb-hub.c index 3eb0f1aa0..5b4876331 100644 --- a/hw/usb-hub.c +++ b/hw/usb-hub.c @@ -171,6 +171,8 @@ static void usb_hub_detach(USBPort *port1) USBHubState *s = port1->opaque; USBHubPort *port = &s->ports[port1->index]; + usb_wakeup(&s->dev); + /* Let upstream know the device on this port is gone */ s->dev.port->ops->child_detach(s->dev.port, port1->dev); -- cgit v1.2.3 From 4abf12f4ea866779b493ecf4606bd0b6d35f8348 Mon Sep 17 00:00:00 2001 From: Julian Pidancet Date: Wed, 23 Nov 2011 01:03:15 +0000 Subject: rtl8139: Fix invalid IO access alignment This patch makes iPXE work with the rtl8139 emulation. The rtl8139 driver in iPXE issues a 16bit access on the ChipCmd register (offset 0x37) to check the status of the rx buffer. The offset of the ioport access was getting fixed up to 0x36 in qemu, causing the value read in iPXE to be invalid. This fixes an issue with iPXE reporting timeouts during TFTP transfers. Reposting this here because it is trivial enough and the original post on qemu-devel didn't attract much attention. Also, the inw() which was causing the issue has been replaced with an inb() in upstream iPXE: https://git.ipxe.org/ipxe.git/commit/91dd64ad25baa27954a7518e73df4fca8a2d0c93 Signed-off-by: Julian Pidancet Signed-off-by: Stefan Hajnoczi --- hw/rtl8139.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/hw/rtl8139.c b/hw/rtl8139.c index 4c379932e..aa8ed0a91 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -1971,7 +1971,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) cplus_tx_ring_desc += 16 * descriptor; DPRINTF("+++ C+ mode reading TX descriptor %d from host memory at " - "%08x0x%08x = 0x"DMA_ADDR_FMT"\n", descriptor, s->TxAddr[1], + "%08x %08x = 0x"DMA_ADDR_FMT"\n", descriptor, s->TxAddr[1], s->TxAddr[0], cplus_tx_ring_desc); uint32_t val, txdw0,txdw1,txbufLO,txbufHI; @@ -2713,8 +2713,6 @@ static void rtl8139_io_writeb(void *opaque, uint8_t addr, uint32_t val) { RTL8139State *s = opaque; - addr &= 0xff; - switch (addr) { case MAC0 ... MAC0+5: @@ -2800,8 +2798,6 @@ static void rtl8139_io_writew(void *opaque, uint8_t addr, uint32_t val) { RTL8139State *s = opaque; - addr &= 0xfe; - switch (addr) { case IntrMask: @@ -2900,8 +2896,6 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val) { RTL8139State *s = opaque; - addr &= 0xfc; - switch (addr) { case RxMissed: @@ -2969,8 +2963,6 @@ static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr) RTL8139State *s = opaque; int ret; - addr &= 0xff; - switch (addr) { case MAC0 ... MAC0+5: @@ -3043,8 +3035,6 @@ static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr) RTL8139State *s = opaque; uint32_t ret; - addr &= 0xfe; /* mask lower bit */ - switch (addr) { case IntrMask: @@ -3120,8 +3110,6 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr) RTL8139State *s = opaque; uint32_t ret; - addr &= 0xfc; /* also mask low 2 bits */ - switch (addr) { case RxMissed: -- cgit v1.2.3 From be85c90b74f56dca51782fa3080fcdf88593e045 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Tue, 22 Nov 2011 17:27:15 +0000 Subject: fix out of tree build Signed-off-by: Stefano Stabellini Signed-off-by: Stefan Hajnoczi --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7c9373960..b06599c16 100644 --- a/Makefile +++ b/Makefile @@ -168,7 +168,7 @@ check-qjson: check-qjson.o $(qobject-obj-y) $(tools-obj-y) test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(tools-obj-y) $(qapi-obj-y): $(GENERATED_HEADERS) -qapi-dir := qapi-generated +qapi-dir := $(SRC_PATH)/qapi-generated test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir) qemu-ga$(EXESUF): LIBS = $(LIBS_QGA) -- cgit v1.2.3 From 20d183b6f0e14424d245493e7bc6fd6d14a08436 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 23 Nov 2011 13:31:08 +0100 Subject: usb-hub: implement reset based on a patch from hkran@linux.vnet.ibm.com Signed-off-by: Gerd Hoffmann --- hw/usb-hub.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/hw/usb-hub.c b/hw/usb-hub.c index 5b4876331..e1959372e 100644 --- a/hw/usb-hub.c +++ b/hw/usb-hub.c @@ -222,7 +222,22 @@ static void usb_hub_complete(USBPort *port, USBPacket *packet) static void usb_hub_handle_reset(USBDevice *dev) { - /* XXX: do it */ + USBHubState *s = DO_UPCAST(USBHubState, dev, dev); + USBHubPort *port; + int i; + + for (i = 0; i < NUM_PORTS; i++) { + port = s->ports + i; + port->wPortStatus = PORT_STAT_POWER; + port->wPortChange = 0; + if (port->port.dev && port->port.dev->attached) { + port->wPortStatus |= PORT_STAT_CONNECTION; + port->wPortChange |= PORT_STAT_C_CONNECTION; + if (port->port.dev->speed == USB_SPEED_LOW) { + port->wPortStatus |= PORT_STAT_LOW_SPEED; + } + } + } } static int usb_hub_handle_control(USBDevice *dev, USBPacket *p, @@ -497,9 +512,8 @@ static int usb_hub_initfn(USBDevice *dev) &port->port, s, i, &usb_hub_port_ops, USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL); usb_port_location(&port->port, dev->port, i+1); - port->wPortStatus = PORT_STAT_POWER; - port->wPortChange = 0; } + usb_hub_handle_reset(dev); return 0; } -- cgit v1.2.3 From aac882e7ce52f12f1b0712534c2456acea4f03d7 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 18 Nov 2011 10:48:47 +0100 Subject: usb-ehci: codestyle fixups Signed-off-by: Gerd Hoffmann --- hw/usb-ehci.c | 56 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c index 3eea94d09..2609aba34 100644 --- a/hw/usb-ehci.c +++ b/hw/usb-ehci.c @@ -437,37 +437,37 @@ struct EHCIState { } while(0) static const char *ehci_state_names[] = { - [ EST_INACTIVE ] = "INACTIVE", - [ EST_ACTIVE ] = "ACTIVE", - [ EST_EXECUTING ] = "EXECUTING", - [ EST_SLEEPING ] = "SLEEPING", - [ EST_WAITLISTHEAD ] = "WAITLISTHEAD", - [ EST_FETCHENTRY ] = "FETCH ENTRY", - [ EST_FETCHQH ] = "FETCH QH", - [ EST_FETCHITD ] = "FETCH ITD", - [ EST_ADVANCEQUEUE ] = "ADVANCEQUEUE", - [ EST_FETCHQTD ] = "FETCH QTD", - [ EST_EXECUTE ] = "EXECUTE", - [ EST_WRITEBACK ] = "WRITEBACK", - [ EST_HORIZONTALQH ] = "HORIZONTALQH", + [EST_INACTIVE] = "INACTIVE", + [EST_ACTIVE] = "ACTIVE", + [EST_EXECUTING] = "EXECUTING", + [EST_SLEEPING] = "SLEEPING", + [EST_WAITLISTHEAD] = "WAITLISTHEAD", + [EST_FETCHENTRY] = "FETCH ENTRY", + [EST_FETCHQH] = "FETCH QH", + [EST_FETCHITD] = "FETCH ITD", + [EST_ADVANCEQUEUE] = "ADVANCEQUEUE", + [EST_FETCHQTD] = "FETCH QTD", + [EST_EXECUTE] = "EXECUTE", + [EST_WRITEBACK] = "WRITEBACK", + [EST_HORIZONTALQH] = "HORIZONTALQH", }; static const char *ehci_mmio_names[] = { - [ CAPLENGTH ] = "CAPLENGTH", - [ HCIVERSION ] = "HCIVERSION", - [ HCSPARAMS ] = "HCSPARAMS", - [ HCCPARAMS ] = "HCCPARAMS", - [ USBCMD ] = "USBCMD", - [ USBSTS ] = "USBSTS", - [ USBINTR ] = "USBINTR", - [ FRINDEX ] = "FRINDEX", - [ PERIODICLISTBASE ] = "P-LIST BASE", - [ ASYNCLISTADDR ] = "A-LIST ADDR", - [ PORTSC_BEGIN ] = "PORTSC #0", - [ PORTSC_BEGIN + 4] = "PORTSC #1", - [ PORTSC_BEGIN + 8] = "PORTSC #2", - [ PORTSC_BEGIN + 12] = "PORTSC #3", - [ CONFIGFLAG ] = "CONFIGFLAG", + [CAPLENGTH] = "CAPLENGTH", + [HCIVERSION] = "HCIVERSION", + [HCSPARAMS] = "HCSPARAMS", + [HCCPARAMS] = "HCCPARAMS", + [USBCMD] = "USBCMD", + [USBSTS] = "USBSTS", + [USBINTR] = "USBINTR", + [FRINDEX] = "FRINDEX", + [PERIODICLISTBASE] = "P-LIST BASE", + [ASYNCLISTADDR] = "A-LIST ADDR", + [PORTSC_BEGIN] = "PORTSC #0", + [PORTSC_BEGIN + 4] = "PORTSC #1", + [PORTSC_BEGIN + 8] = "PORTSC #2", + [PORTSC_BEGIN + 12] = "PORTSC #3", + [CONFIGFLAG] = "CONFIGFLAG", }; static const char *nr2str(const char **n, size_t len, uint32_t nr) -- cgit v1.2.3 From 335b8d2068cbc56ce86b3c89b0fcd1c1eb4b61e2 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 18 Nov 2011 10:49:25 +0100 Subject: usb-ehci: add register names The mmio register name list only had the names for four port status registers. We emulate a EHCI adapter with six ports though, the last two ones are listed as "unknown" in traces. Fix it. Signed-off-by: Gerd Hoffmann --- hw/usb-ehci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c index 2609aba34..a946e1d1f 100644 --- a/hw/usb-ehci.c +++ b/hw/usb-ehci.c @@ -467,6 +467,8 @@ static const char *ehci_mmio_names[] = { [PORTSC_BEGIN + 4] = "PORTSC #1", [PORTSC_BEGIN + 8] = "PORTSC #2", [PORTSC_BEGIN + 12] = "PORTSC #3", + [PORTSC_BEGIN + 16] = "PORTSC #4", + [PORTSC_BEGIN + 20] = "PORTSC #5", [CONFIGFLAG] = "CONFIGFLAG", }; -- cgit v1.2.3 From fd9f102c3e38ac606ef8ee2a5ba0130f7c87422f Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 22 Nov 2011 16:44:45 +0100 Subject: qcow: Add migration blocker qcow caches L2 tables. For migration to work, they would have to be invalidated. Block migration for now. Signed-off-by: Kevin Wolf --- block/qcow.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/block/qcow.c b/block/qcow.c index adecee06c..4814ed0ce 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -26,6 +26,7 @@ #include "module.h" #include #include "aes.h" +#include "migration.h" /**************************************************************/ /* QEMU COW block driver with compression and encryption support */ @@ -74,6 +75,7 @@ typedef struct BDRVQcowState { AES_KEY aes_encrypt_key; AES_KEY aes_decrypt_key; CoMutex lock; + Error *migration_blocker; } BDRVQcowState; static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset); @@ -160,6 +162,12 @@ static int qcow_open(BlockDriverState *bs, int flags) bs->backing_file[len] = '\0'; } + /* Disable migration when qcow images are used */ + error_set(&s->migration_blocker, + QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, + "qcow", bs->device_name, "live migration"); + migrate_add_blocker(s->migration_blocker); + qemu_co_mutex_init(&s->lock); return 0; @@ -604,10 +612,14 @@ static int qcow_co_writev(BlockDriverState *bs, int64_t sector_num, static void qcow_close(BlockDriverState *bs) { BDRVQcowState *s = bs->opaque; + g_free(s->l1_table); g_free(s->l2_cache); g_free(s->cluster_cache); g_free(s->cluster_data); + + migrate_del_blocker(s->migration_blocker); + error_free(s->migration_blocker); } static int qcow_create(const char *filename, QEMUOptionParameter *options) -- cgit v1.2.3 From fc9d106c8dfe1c4afe0e127dfcd2764e63f0efb0 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 22 Nov 2011 16:46:26 +0100 Subject: vdi: Add migration blocker vdi caches the block map. For migration to work, it would have to be invalidated. Block migration for now. Signed-off-by: Kevin Wolf --- block/vdi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/block/vdi.c b/block/vdi.c index 684a4a87b..7dda5222e 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -52,6 +52,7 @@ #include "qemu-common.h" #include "block_int.h" #include "module.h" +#include "migration.h" #if defined(CONFIG_UUID) #include @@ -203,6 +204,8 @@ typedef struct { uint32_t bmap_sector; /* VDI header (converted to host endianness). */ VdiHeader header; + + Error *migration_blocker; } BDRVVdiState; /* Change UUID from little endian (IPRT = VirtualBox format) to big endian @@ -454,6 +457,12 @@ static int vdi_open(BlockDriverState *bs, int flags) goto fail_free_bmap; } + /* Disable migration when vdi images are used */ + error_set(&s->migration_blocker, + QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, + "vdi", bs->device_name, "live migration"); + migrate_add_blocker(s->migration_blocker); + return 0; fail_free_bmap: @@ -939,6 +948,9 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options) static void vdi_close(BlockDriverState *bs) { + BDRVVdiState *s = bs->opaque; + migrate_del_blocker(s->migration_blocker); + error_free(s->migration_blocker); } static coroutine_fn int vdi_co_flush(BlockDriverState *bs) -- cgit v1.2.3 From 2bc3166c22aeeb5cd7b8f21104f4744f08c7a288 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 22 Nov 2011 16:50:27 +0100 Subject: vmdk: Add migration blocker VMDK caches L2 tables. For migration to work, they would have to be invalidated. Block migration for now. Signed-off-by: Kevin Wolf --- block/vmdk.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/block/vmdk.c b/block/vmdk.c index 96f7d5d90..f5441591d 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -26,6 +26,7 @@ #include "qemu-common.h" #include "block_int.h" #include "module.h" +#include "migration.h" #include #define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D') @@ -97,6 +98,7 @@ typedef struct BDRVVmdkState { int num_extents; /* Extent array with num_extents entries, ascend ordered by address */ VmdkExtent *extents; + Error *migration_blocker; } BDRVVmdkState; typedef struct VmdkMetaData { @@ -659,7 +661,14 @@ static int vmdk_open(BlockDriverState *bs, int flags) } s->parent_cid = vmdk_read_cid(bs, 1); qemu_co_mutex_init(&s->lock); - return ret; + + /* Disable migration when VMDK images are used */ + error_set(&s->migration_blocker, + QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, + "vmdk", bs->device_name, "live migration"); + migrate_add_blocker(s->migration_blocker); + + return 0; fail: vmdk_free_extents(bs); @@ -1504,7 +1513,12 @@ exit: static void vmdk_close(BlockDriverState *bs) { + BDRVVmdkState *s = bs->opaque; + vmdk_free_extents(bs); + + migrate_del_blocker(s->migration_blocker); + error_free(s->migration_blocker); } static coroutine_fn int vmdk_co_flush(BlockDriverState *bs) -- cgit v1.2.3 From 612ff3d8876a6df0484aa6ebb5cae4575f7514c5 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 22 Nov 2011 16:51:12 +0100 Subject: vpc: Add migration blocker vpc caches the BAT. For migration to work, it would have to be invalidated. Block migration for now. Signed-off-by: Kevin Wolf --- block/vpc.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/block/vpc.c b/block/vpc.c index 39a324705..75d7d4ac7 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -25,6 +25,7 @@ #include "qemu-common.h" #include "block_int.h" #include "module.h" +#include "migration.h" /**************************************************************/ @@ -128,6 +129,8 @@ typedef struct BDRVVPCState { uint64_t last_bitmap; #endif + + Error *migration_blocker; } BDRVVPCState; static uint32_t vpc_checksum(uint8_t* buf, size_t size) @@ -228,6 +231,13 @@ static int vpc_open(BlockDriverState *bs, int flags) #endif qemu_co_mutex_init(&s->lock); + + /* Disable migration when VHD images are used */ + error_set(&s->migration_blocker, + QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, + "vpc", bs->device_name, "live migration"); + migrate_add_blocker(s->migration_blocker); + return 0; fail: return err; @@ -651,6 +661,9 @@ static void vpc_close(BlockDriverState *bs) #ifdef CACHE g_free(s->pageentry_u8); #endif + + migrate_del_blocker(s->migration_blocker); + error_free(s->migration_blocker); } static QEMUOptionParameter vpc_create_options[] = { -- cgit v1.2.3 From 3397f0cb483b40785678d2328da584c8a35c358c Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 22 Nov 2011 16:52:13 +0100 Subject: vvfat: Add migration blocker vvfat caches more or less everything when in writable mode. For migration to work, it would have to be invalidated. Block migration for now when in writable mode (default is readonly). Signed-off-by: Kevin Wolf --- block/vvfat.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/block/vvfat.c b/block/vvfat.c index 131680f6f..a310ce8c3 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -27,6 +27,7 @@ #include "qemu-common.h" #include "block_int.h" #include "module.h" +#include "migration.h" #ifndef S_IWGRP #define S_IWGRP 0 @@ -350,6 +351,8 @@ typedef struct BDRVVVFATState { array_t commits; const char* path; int downcase_short_names; + + Error *migration_blocker; } BDRVVVFATState; /* take the sector position spos and convert it to Cylinder/Head/Sector position @@ -1073,6 +1076,15 @@ DLOG(if (stderr == NULL) { // assert(is_consistent(s)); qemu_co_mutex_init(&s->lock); + + /* Disable migration when vvfat is used rw */ + if (s->qcow) { + error_set(&s->migration_blocker, + QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, + "vvfat (rw)", bs->device_name, "live migration"); + migrate_add_blocker(s->migration_blocker); + } + return 0; } @@ -2829,6 +2841,11 @@ static void vvfat_close(BlockDriverState *bs) array_free(&(s->directory)); array_free(&(s->mapping)); g_free(s->cluster_buffer); + + if (s->qcow) { + migrate_del_blocker(s->migration_blocker); + error_free(s->migration_blocker); + } } static BlockDriver bdrv_vvfat = { -- cgit v1.2.3 From 6ac5f3881fd9880f55e30c5f5bd9984d9d47fd62 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 22 Nov 2011 16:57:34 +0100 Subject: vdi: Fix memory leak The block map is allocated in vdi_open, but was never freed. Signed-off-by: Kevin Wolf --- block/vdi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/block/vdi.c b/block/vdi.c index 7dda5222e..02da6b44d 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -949,6 +949,9 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options) static void vdi_close(BlockDriverState *bs) { BDRVVdiState *s = bs->opaque; + + g_free(s->bmap); + migrate_del_blocker(s->migration_blocker); error_free(s->migration_blocker); } -- cgit v1.2.3 From 5bb1cbac4fdb1ca28f33c8d68538d03e3db7c160 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 23 Nov 2011 11:38:01 +0100 Subject: vpc: Add missing error handling in alloc_block Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- block/vpc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/block/vpc.c b/block/vpc.c index 75d7d4ac7..89a5ee266 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -362,8 +362,11 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num) // Initialize the block's bitmap memset(bitmap, 0xff, s->bitmap_size); - bdrv_pwrite_sync(bs->file, s->free_data_block_offset, bitmap, + ret = bdrv_pwrite_sync(bs->file, s->free_data_block_offset, bitmap, s->bitmap_size); + if (ret < 0) { + return ret; + } // Write new footer (the old one will be overwritten) s->free_data_block_offset += s->block_size + s->bitmap_size; -- cgit v1.2.3 From c7662daaa2898fa5a9a39bc51985cd1dd08af988 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 16 Nov 2011 12:37:17 +0100 Subject: usb-host: add usb_host_do_reset function. Add a special function to reset the host usb device. It tracks the time needed by the USBDEVFS_RESET ioctl and prints a warning in case it needs too long. Usually it should be finished in 200 - 300 miliseconds. Warning threshold is one second. Intention is to help troubleshooting by indicating that the usb device stopped responding even to a reset request and is possibly broken. Signed-off-by: Gerd Hoffmann --- usb-linux.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/usb-linux.c b/usb-linux.c index d4426ea73..ab4c6930c 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -148,6 +148,25 @@ static int usb_host_read_file(char *line, size_t line_size, const char *device_file, const char *device_name); static int usb_linux_update_endp_table(USBHostDevice *s); +static int usb_host_do_reset(USBHostDevice *dev) +{ + struct timeval s, e; + uint32_t usecs; + int ret; + + gettimeofday(&s, NULL); + ret = ioctl(dev->fd, USBDEVFS_RESET); + gettimeofday(&e, NULL); + usecs = (e.tv_sec - s.tv_sec) * 1000000; + usecs += e.tv_usec - s.tv_usec; + if (usecs > 1000000) { + /* more than a second, something is fishy, broken usb device? */ + fprintf(stderr, "husb: device %d:%d reset took %d.%06d seconds\n", + dev->bus_num, dev->addr, usecs / 1000000, usecs % 1000000); + } + return ret; +} + static struct endp_data *get_endp(USBHostDevice *s, int pid, int ep) { struct endp_data *eps = pid == USB_TOKEN_IN ? s->ep_in : s->ep_out; @@ -606,7 +625,7 @@ static void usb_host_handle_reset(USBDevice *dev) trace_usb_host_reset(s->bus_num, s->addr); - ioctl(s->fd, USBDEVFS_RESET); + usb_host_do_reset(s);; usb_host_claim_interfaces(s, 0); usb_linux_update_endp_table(s); @@ -1370,7 +1389,7 @@ static int usb_host_close(USBHostDevice *dev) if (dev->dev.attached) { usb_device_detach(&dev->dev); } - ioctl(dev->fd, USBDEVFS_RESET); + usb_host_do_reset(dev); close(dev->fd); dev->fd = -1; return 0; @@ -1381,7 +1400,7 @@ static void usb_host_exit_notifier(struct Notifier *n, void *data) USBHostDevice *s = container_of(n, USBHostDevice, exit); if (s->fd != -1) { - ioctl(s->fd, USBDEVFS_RESET); + usb_host_do_reset(s);; } } -- cgit v1.2.3 From a1fd24af4d4d5f96283ba48e7b1e83ffe3b72273 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Sun, 27 Nov 2011 11:13:01 -0600 Subject: Revert "i386: derive '-cpu host' from KVM_GET_SUPPORTED_CPUID" This reverts commit 66e3dd9282141b5ae75637c9676002cf3ceeb988. From Avi, "Anthony, I think we should revert that commit and refactor cpuid for 1.1. The logic is spread over too many places which makes it hard to reason about." Signed-off-by: Anthony Liguori --- target-i386/cpuid.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c index 21e589675..9fc9769ed 100644 --- a/target-i386/cpuid.c +++ b/target-i386/cpuid.c @@ -107,14 +107,33 @@ void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { #if defined(CONFIG_KVM) + uint32_t vec[4]; + +#ifdef __x86_64__ + asm volatile("cpuid" + : "=a"(vec[0]), "=b"(vec[1]), + "=c"(vec[2]), "=d"(vec[3]) + : "0"(function), "c"(count) : "cc"); +#else + asm volatile("pusha \n\t" + "cpuid \n\t" + "mov %%eax, 0(%2) \n\t" + "mov %%ebx, 4(%2) \n\t" + "mov %%ecx, 8(%2) \n\t" + "mov %%edx, 12(%2) \n\t" + "popa" + : : "a"(function), "c"(count), "S"(vec) + : "memory", "cc"); +#endif + if (eax) - *eax = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_EAX); + *eax = vec[0]; if (ebx) - *ebx = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_EBX); + *ebx = vec[1]; if (ecx) - *ecx = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_ECX); + *ecx = vec[2]; if (edx) - *edx = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_EDX); + *edx = vec[3]; #endif } -- cgit v1.2.3 From ae0f940e6b4f5177892dd6a12762282fa9089972 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 21 Nov 2011 09:29:11 +0100 Subject: 9pfs: improve portability to older systems Small requirements on "new" features have percolated to virtio-9p-local.c. In particular, the utimensat wrapper actually only supports dirfd = AT_FDCWD and flags = AT_SYMLINK_NOFOLLOW in the fallback code. Remove the arguments so that virtio-9p-local.c will not use AT_* constants. At the same time, fail local_ioc_getversion if the ioctl is not supported by the host. Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- hw/9pfs/virtio-9p-local.c | 7 +++++-- oslib-posix.c | 5 ++--- qemu-os-posix.h | 3 +-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index 7f1c0894d..cbd07e865 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -583,8 +583,7 @@ static int local_utimensat(FsContext *s, V9fsPath *fs_path, char buffer[PATH_MAX]; char *path = fs_path->data; - return qemu_utimensat(AT_FDCWD, rpath(s, path, buffer), buf, - AT_SYMLINK_NOFOLLOW); + return qemu_utimens(rpath(s, path, buffer), buf); } static int local_remove(FsContext *ctx, const char *path) @@ -694,6 +693,7 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, mode_t st_mode, uint64_t *st_gen) { int err; +#ifdef FS_IOC_GETVERSION V9fsFidOpenState fid_open; /* @@ -709,6 +709,9 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, } err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen); local_close(ctx, &fid_open); +#else + err = -ENOTTY; +#endif return err; } diff --git a/oslib-posix.c b/oslib-posix.c index 6f297626c..ce755496b 100644 --- a/oslib-posix.c +++ b/oslib-posix.c @@ -162,8 +162,7 @@ int qemu_pipe(int pipefd[2]) return ret; } -int qemu_utimensat(int dirfd, const char *path, const struct timespec *times, - int flags) +int qemu_utimens(const char *path, const struct timespec *times) { struct timeval tv[2], tv_now; struct stat st; @@ -171,7 +170,7 @@ int qemu_utimensat(int dirfd, const char *path, const struct timespec *times, #ifdef CONFIG_UTIMENSAT int ret; - ret = utimensat(dirfd, path, times, flags); + ret = utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW); if (ret != -1 || errno != ENOSYS) { return ret; } diff --git a/qemu-os-posix.h b/qemu-os-posix.h index 920499d83..8e1149d96 100644 --- a/qemu-os-posix.h +++ b/qemu-os-posix.h @@ -44,7 +44,6 @@ typedef struct timeval qemu_timeval; #endif #endif typedef struct timespec qemu_timespec; -int qemu_utimensat(int dirfd, const char *path, const qemu_timespec *times, - int flags); +int qemu_utimens(const char *path, const qemu_timespec *times); #endif -- cgit v1.2.3 From ad0c93328dcb7a0ad68a68d0f66ea1949ebaaa2d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 24 Nov 2011 13:28:52 +0100 Subject: virtio: add and use virtio_set_features vdev->guest_features is not masking features that are not supported by the guest. Fix this by introducing a common wrapper to be used by all virtio bus implementations. Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- hw/s390-virtio-bus.c | 5 +---- hw/syborg_virtio.c | 4 +--- hw/virtio-pci.c | 9 ++------- hw/virtio.c | 24 ++++++++++++++++++------ hw/virtio.h | 1 + 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index 0ce6406b6..c4b9a99e6 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -254,10 +254,7 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev) /* Update guest supported feature bitmap */ features = bswap32(ldl_be_phys(dev->feat_offs)); - if (vdev->set_features) { - vdev->set_features(vdev, features); - } - vdev->guest_features = features; + virtio_set_features(vdev, features); } VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus) diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c index 00c7be8c8..6de952c93 100644 --- a/hw/syborg_virtio.c +++ b/hw/syborg_virtio.c @@ -131,9 +131,7 @@ static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset, } switch (offset >> 2) { case SYBORG_VIRTIO_GUEST_FEATURES: - if (vdev->set_features) - vdev->set_features(vdev, value); - vdev->guest_features = value; + virtio_set_features(vdev, value); break; case SYBORG_VIRTIO_QUEUE_BASE: if (value == 0) diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index ca5923c49..64c6a9414 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -285,14 +285,9 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) case VIRTIO_PCI_GUEST_FEATURES: /* Guest does not negotiate properly? We have to assume nothing. */ if (val & (1 << VIRTIO_F_BAD_FEATURE)) { - if (vdev->bad_features) - val = proxy->host_features & vdev->bad_features(vdev); - else - val = 0; + val = vdev->bad_features ? vdev->bad_features(vdev) : 0; } - if (vdev->set_features) - vdev->set_features(vdev, val); - vdev->guest_features = val; + virtio_set_features(vdev, val); break; case VIRTIO_PCI_QUEUE_PFN: pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT; diff --git a/hw/virtio.c b/hw/virtio.c index 7011b5b39..81ecc40b3 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -763,12 +763,25 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) } } +int virtio_set_features(VirtIODevice *vdev, uint32_t val) +{ + uint32_t supported_features = + vdev->binding->get_features(vdev->binding_opaque); + bool bad = (val & ~supported_features) != 0; + + val &= supported_features; + if (vdev->set_features) { + vdev->set_features(vdev, val); + } + vdev->guest_features = val; + return bad ? -1 : 0; +} + int virtio_load(VirtIODevice *vdev, QEMUFile *f) { int num, i, ret; uint32_t features; - uint32_t supported_features = - vdev->binding->get_features(vdev->binding_opaque); + uint32_t supported_features; if (vdev->binding->load_config) { ret = vdev->binding->load_config(vdev->binding_opaque, f); @@ -780,14 +793,13 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f) qemu_get_8s(f, &vdev->isr); qemu_get_be16s(f, &vdev->queue_sel); qemu_get_be32s(f, &features); - if (features & ~supported_features) { + + if (virtio_set_features(vdev, features) < 0) { + supported_features = vdev->binding->get_features(vdev->binding_opaque); error_report("Features 0x%x unsupported. Allowed features: 0x%x", features, supported_features); return -1; } - if (vdev->set_features) - vdev->set_features(vdev, features); - vdev->guest_features = features; vdev->config_len = qemu_get_be32(f); qemu_get_buffer(f, vdev->config, vdev->config_len); diff --git a/hw/virtio.h b/hw/virtio.h index 2d18209fb..25f55647b 100644 --- a/hw/virtio.h +++ b/hw/virtio.h @@ -185,6 +185,7 @@ void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector); void virtio_set_status(VirtIODevice *vdev, uint8_t val); void virtio_reset(void *opaque); void virtio_update_irq(VirtIODevice *vdev); +int virtio_set_features(VirtIODevice *vdev, uint32_t val); void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding, void *opaque); -- cgit v1.2.3 From c16ada980f439c414eac83d184ac9fb66ed60cc0 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 23 Nov 2011 22:20:30 +0100 Subject: eepro100: Fix alignment requirement for statistical counters According to Intel's Open Source Software Developer Manual, the dump counters address must be Dword aligned. The new code enforces this alignment, so s->statsaddr may now be used with stw_le_pci_dma() and stl_le_pci_dma(). Signed-off-by: Stefan Weil Signed-off-by: Anthony Liguori --- hw/eepro100.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/hw/eepro100.c b/hw/eepro100.c index 7d59e7136..29ec5b44f 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -976,7 +976,15 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val) case CU_STATSADDR: /* Load dump counters address. */ s->statsaddr = e100_read_reg4(s, SCBPointer); - TRACE(OTHER, logout("val=0x%02x (status address)\n", val)); + TRACE(OTHER, logout("val=0x%02x (dump counters address)\n", val)); + if (s->statsaddr & 3) { + /* Memory must be Dword aligned. */ + logout("unaligned dump counters address\n"); + /* Handling of misaligned addresses is undefined. + * Here we align the address by ignoring the lower bits. */ + /* TODO: Test unaligned dump counter address on real hardware. */ + s->statsaddr &= ~3; + } break; case CU_SHOWSTATS: /* Dump statistical counters. */ -- cgit v1.2.3 From 51711aee8cb0b17d53872cc06fe73af50c7d9ebd Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 24 Nov 2011 23:16:10 +0100 Subject: tci: Make flush_icache_range() inline This is standard for other tcg targets and improves tci, too. Signed-off-by: Stefan Weil Signed-off-by: Anthony Liguori --- tcg/tci/tcg-target.c | 4 ---- tcg/tci/tcg-target.h | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c index 942910e14..fc0880cec 100644 --- a/tcg/tci/tcg-target.c +++ b/tcg/tci/tcg-target.c @@ -373,10 +373,6 @@ static const char *const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { }; #endif -static void flush_icache_range(unsigned long start, unsigned long stop) -{ -} - static void patch_reloc(uint8_t *code_ptr, int type, tcg_target_long value, tcg_target_long addend) { diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h index cb5858c9c..03e0fd1a7 100644 --- a/tcg/tci/tcg-target.h +++ b/tcg/tci/tcg-target.h @@ -157,4 +157,8 @@ void tci_disas(uint8_t opc); unsigned long tcg_qemu_tb_exec(CPUState *env, uint8_t *tb_ptr); #define tcg_qemu_tb_exec tcg_qemu_tb_exec +static inline void flush_icache_range(unsigned long start, unsigned long stop) +{ +} + #endif /* TCG_TARGET_H */ -- cgit v1.2.3 From 2507718baf311ea78156c6777d38410a9f89ce89 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 23 Nov 2011 11:46:27 +0530 Subject: 9pfs: improve portability to older systems I guess we can also make sure we don't call local_ioc_getversion at all. Reported-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- hw/9pfs/virtio-9p-local.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index cbd07e865..99ef0cd33 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -717,10 +717,14 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, static int local_init(FsContext *ctx) { - int err; + int err = 0; struct statfs stbuf; ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT; +#ifdef FS_IOC_GETVERSION + /* + * use ioc_getversion only if the iocl is definied + */ err = statfs(ctx->fs_root, &stbuf); if (!err) { switch (stbuf.f_type) { @@ -732,6 +736,7 @@ static int local_init(FsContext *ctx) break; } } +#endif return err; } -- cgit v1.2.3 From a425d23f8fad482f7792745036896eb2f72330de Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 19 Nov 2011 10:22:43 +0100 Subject: qemu-char: rename qemu_chr_event to qemu_chr_be_event and make it public Rename qemu_chr_event to qemu_chr_be_event, since it is only to be called by backends and make it public so that it can be used by chardev code which lives outside of qemu-char.c Signed-off-by: Hans de Goede Signed-off-by: Anthony Liguori --- qemu-char.c | 26 +++++++++++++------------- qemu-char.h | 10 ++++++++++ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index b562bf88a..27abcb918 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -106,7 +106,7 @@ static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs = QTAILQ_HEAD_INITIALIZER(chardevs); -static void qemu_chr_event(CharDriverState *s, int event) +void qemu_chr_be_event(CharDriverState *s, int event) { /* Keep track if the char device is open */ switch (event) { @@ -126,7 +126,7 @@ static void qemu_chr_event(CharDriverState *s, int event) static void qemu_chr_generic_open_bh(void *opaque) { CharDriverState *s = opaque; - qemu_chr_event(s, CHR_EVENT_OPENED); + qemu_chr_be_event(s, CHR_EVENT_OPENED); qemu_bh_delete(s->bh); s->bh = NULL; } @@ -359,7 +359,7 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch) bdrv_commit_all(); break; case 'b': - qemu_chr_event(chr, CHR_EVENT_BREAK); + qemu_chr_be_event(chr, CHR_EVENT_BREAK); break; case 'c': /* Switch to the next registered device */ @@ -580,7 +580,7 @@ static void fd_chr_read(void *opaque) if (size == 0) { /* FD has been closed. Remove it from the active list. */ qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL); - qemu_chr_event(chr, CHR_EVENT_CLOSED); + qemu_chr_be_event(chr, CHR_EVENT_CLOSED); return; } if (size > 0) { @@ -613,7 +613,7 @@ static void fd_chr_close(struct CharDriverState *chr) } g_free(s); - qemu_chr_event(chr, CHR_EVENT_CLOSED); + qemu_chr_be_event(chr, CHR_EVENT_CLOSED); } /* open a character device to a unix fd */ @@ -715,7 +715,7 @@ static void stdio_read(void *opaque) if (size == 0) { /* stdin has been closed. Remove it from the active list. */ qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL); - qemu_chr_event(chr, CHR_EVENT_CLOSED); + qemu_chr_be_event(chr, CHR_EVENT_CLOSED); return; } if (size > 0) { @@ -977,7 +977,7 @@ static void pty_chr_close(struct CharDriverState *chr) qemu_del_timer(s->timer); qemu_free_timer(s->timer); g_free(s); - qemu_chr_event(chr, CHR_EVENT_CLOSED); + qemu_chr_be_event(chr, CHR_EVENT_CLOSED); } static int qemu_chr_open_pty(QemuOpts *opts, CharDriverState **_chr) @@ -1355,7 +1355,7 @@ static void pp_close(CharDriverState *chr) ioctl(fd, PPRELEASE); close(fd); g_free(drv); - qemu_chr_event(chr, CHR_EVENT_CLOSED); + qemu_chr_be_event(chr, CHR_EVENT_CLOSED); } static int qemu_chr_open_pp(QemuOpts *opts, CharDriverState **_chr) @@ -1500,7 +1500,7 @@ static void win_chr_close(CharDriverState *chr) else qemu_del_polling_cb(win_chr_poll, chr); - qemu_chr_event(chr, CHR_EVENT_CLOSED); + qemu_chr_be_event(chr, CHR_EVENT_CLOSED); } static int win_chr_init(CharDriverState *chr, const char *filename) @@ -2108,7 +2108,7 @@ static void udp_chr_close(CharDriverState *chr) closesocket(s->fd); } g_free(s); - qemu_chr_event(chr, CHR_EVENT_CLOSED); + qemu_chr_be_event(chr, CHR_EVENT_CLOSED); } static int qemu_chr_open_udp(QemuOpts *opts, CharDriverState **_chr) @@ -2213,7 +2213,7 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr, } else { if ((unsigned char)buf[i] == IAC_BREAK && s->do_telnetopt == 2) { /* Handle IAC break commands by sending a serial break */ - qemu_chr_event(chr, CHR_EVENT_BREAK); + qemu_chr_be_event(chr, CHR_EVENT_BREAK); s->do_telnetopt++; } s->do_telnetopt++; @@ -2321,7 +2321,7 @@ static void tcp_chr_read(void *opaque) qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); closesocket(s->fd); s->fd = -1; - qemu_chr_event(chr, CHR_EVENT_CLOSED); + qemu_chr_be_event(chr, CHR_EVENT_CLOSED); } else if (size > 0) { if (s->do_telnetopt) tcp_chr_process_IAC_bytes(chr, s, buf, &size); @@ -2433,7 +2433,7 @@ static void tcp_chr_close(CharDriverState *chr) closesocket(s->listen_fd); } g_free(s); - qemu_chr_event(chr, CHR_EVENT_CLOSED); + qemu_chr_be_event(chr, CHR_EVENT_CLOSED); } static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr) diff --git a/qemu-char.h b/qemu-char.h index 7efcf99f5..8ca1e2d54 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -212,6 +212,16 @@ int qemu_chr_be_can_write(CharDriverState *s); */ void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len); + +/** + * @qemu_chr_be_event: + * + * Send an event from the back end to the front end. + * + * @event the event to send + */ +void qemu_chr_be_event(CharDriverState *s, int event); + void qemu_chr_add_handlers(CharDriverState *s, IOCanReadHandler *fd_can_read, IOReadHandler *fd_read, -- cgit v1.2.3 From f76e4c7f16c7ab966a792310b6630d3e240688b3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 19 Nov 2011 10:22:44 +0100 Subject: spice-qemu-char: Generate chardev open/close events Define a state callback and make that generate chardev open/close events when called by the spice-server. Notes: 1) For all but the newest spice-server versions (which have a fix for this) the code ignores these events for a spicevmc with a subtype of vdagent, this subtype specific knowledge is undesirable, but unavoidable for now, see: http://lists.freedesktop.org/archives/spice-devel/2011-July/004837.html 2) This code deliberately sends the events immediately rather then from a bh. This is done this way because: a) There is no need to do it from a bh; and b) Doing it from a bh actually causes issues because the spice-server may send data immediately after the open and when the open runs from a bh, then qemu_chr_be_can_write will return 0 for the first write which the spice-server does not expect, when this happens the spice-server will never retry the write causing communication to stall. Signed-off-by: Hans de Goede Signed-off-by: Anthony Liguori --- spice-qemu-char.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/spice-qemu-char.c b/spice-qemu-char.c index ac522022c..7e8eaa9fd 100644 --- a/spice-qemu-char.c +++ b/spice-qemu-char.c @@ -69,11 +69,40 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) return bytes; } +static void vmc_state(SpiceCharDeviceInstance *sin, int connected) +{ + SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); + +#if SPICE_SERVER_VERSION < 0x000901 + /* + * spice-server calls the state callback for the agent channel when the + * spice client connects / disconnects. Given that not the client but + * the server is doing the parsing of the messages this is wrong as the + * server is still listening. Worse, this causes the parser in the server + * to go out of sync, so we ignore state calls for subtype vdagent + * spicevmc chardevs. For the full story see: + * http://lists.freedesktop.org/archives/spice-devel/2011-July/004837.html + */ + if (strcmp(sin->subtype, "vdagent") == 0) { + return; + } +#endif + + if ((scd->chr->opened && connected) || + (!scd->chr->opened && !connected)) { + return; + } + + qemu_chr_be_event(scd->chr, + connected ? CHR_EVENT_OPENED : CHR_EVENT_CLOSED); +} + static SpiceCharDeviceInterface vmc_interface = { .base.type = SPICE_INTERFACE_CHAR_DEVICE, .base.description = "spice virtual channel char device", .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR, .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR, + .state = vmc_state, .write = vmc_write, .read = vmc_read, }; @@ -197,7 +226,12 @@ int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr) chr->chr_guest_open = spice_chr_guest_open; chr->chr_guest_close = spice_chr_guest_close; - qemu_chr_generic_open(chr); +#if SPICE_SERVER_VERSION < 0x000901 + /* See comment in vmc_state() */ + if (strcmp(subtype, "vdagent") == 0) { + qemu_chr_generic_open(chr); + } +#endif *_chr = chr; return 0; -- cgit v1.2.3 From 65f9d98673cb04436257628958177516416456fa Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 19 Nov 2011 10:22:45 +0100 Subject: usb-redir: Call qemu_chr_fe_open/close To let the chardev now we're ready start receiving data. This is necessary with the spicevmc chardev to get it registered with the spice-server. Signed-off-by: Hans de Goede Signed-off-by: Anthony Liguori --- usb-redir.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/usb-redir.c b/usb-redir.c index c74b1560b..9e1341082 100644 --- a/usb-redir.c +++ b/usb-redir.c @@ -814,6 +814,8 @@ static int usbredir_initfn(USBDevice *udev) /* We'll do the attach once we receive the speed from the usb-host */ udev->auto_attach = 0; + /* 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); @@ -837,6 +839,7 @@ static void usbredir_handle_destroy(USBDevice *udev) { USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + qemu_chr_fe_close(dev->cs); qemu_chr_delete(dev->cs); /* Note must be done after qemu_chr_close, as that causes a close event */ qemu_bh_delete(dev->open_close_bh); -- cgit v1.2.3 From 99f08100cd2b35a35e1c5b2e6b043911a568906c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 19 Nov 2011 10:22:46 +0100 Subject: usb-redir: Device disconnect + re-connect robustness fixes These fixes mainly target the other side sending some (error status) packets after a disconnect packet. In some cases these would get queued up and then reported to the controller when a new device gets connected. * Fully reset device state on disconnect * Don't allow a connect message when already connected * Ignore iso and interrupt status messages when disconnected Signed-off-by: Hans de Goede Signed-off-by: Anthony Liguori --- usb-redir.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/usb-redir.c b/usb-redir.c index 9e1341082..24fdd31ce 100644 --- a/usb-redir.c +++ b/usb-redir.c @@ -881,6 +881,11 @@ static void usbredir_device_connect(void *priv, { USBRedirDevice *dev = priv; + if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) { + ERROR("Received device connect while already connected\n"); + return; + } + switch (device_connect->speed) { case usb_redir_speed_low: DPRINTF("attaching low speed device\n"); @@ -909,19 +914,26 @@ static void usbredir_device_connect(void *priv, static void usbredir_device_disconnect(void *priv) { USBRedirDevice *dev = priv; + int i; /* Stop any pending attaches */ qemu_del_timer(dev->attach_timer); if (dev->dev.attached) { usb_device_detach(&dev->dev); - usbredir_cleanup_device_queues(dev); /* * Delay next usb device attach to give the guest a chance to see * see the detach / attach in case of quick close / open succession */ dev->next_attach_time = qemu_get_clock_ms(vm_clock) + 200; } + + /* Reset state so that the next dev connected starts with a clean slate */ + usbredir_cleanup_device_queues(dev); + memset(dev->endpoint, 0, sizeof(dev->endpoint)); + for (i = 0; i < MAX_ENDPOINTS; i++) { + QTAILQ_INIT(&dev->endpoint[i].bufpq); + } } static void usbredir_interface_info(void *priv, @@ -1013,6 +1025,10 @@ 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) { + return; + } + dev->endpoint[EP2I(ep)].iso_error = iso_stream_status->status; if (iso_stream_status->status == usb_redir_stall) { DPRINTF("iso stream stopped by peer ep %02X\n", ep); @@ -1030,6 +1046,10 @@ 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) { + return; + } + dev->endpoint[EP2I(ep)].interrupt_error = interrupt_receiving_status->status; if (interrupt_receiving_status->status == usb_redir_stall) { -- cgit v1.2.3 From c1b71a1df682fc49f91218130b1837d6d91dcb57 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 19 Nov 2011 10:22:47 +0100 Subject: usb-redir: Don't try to write to the chardev after a close event Since we handle close async in a bh, do_write and thus write can get called after receiving a close event. This patch adds a check to the usb-redir write callback to not call qemu_chr_fe_write on a closed backend. Signed-off-by: Hans de Goede Signed-off-by: Anthony Liguori --- usb-redir.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/usb-redir.c b/usb-redir.c index 24fdd31ce..fb91c926a 100644 --- a/usb-redir.c +++ b/usb-redir.c @@ -225,6 +225,10 @@ static int usbredir_write(void *priv, uint8_t *data, int count) { USBRedirDevice *dev = priv; + if (!dev->cs->opened) { + return 0; + } + return qemu_chr_fe_write(dev->cs, data, count); } -- cgit v1.2.3 From 21d4a791da47cf35956102d0b96208e3e595b617 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 23 Nov 2011 11:24:25 +0200 Subject: configure: tighten pie toolchain support test for tls variables Some toolchains don't support pie properly when tls variables are in use. Disallow pie when such toolchains are detected. Signed-off-by: Avi Kivity Signed-off-by: Anthony Liguori --- configure | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/configure b/configure index f03343821..a7caf1e19 100755 --- a/configure +++ b/configure @@ -1120,7 +1120,17 @@ fi if test "$pie" != "no" ; then cat > $TMPC << EOF -int main(void) { return 0; } + +#ifdef __linux__ +# define THREAD __thread +#else +# define THREAD +#endif + +static THREAD int tls_var; + +int main(void) { return tls_var; } + EOF if compile_prog "-fPIE -DPIE" "-pie"; then QEMU_CFLAGS="-fPIE -DPIE $QEMU_CFLAGS" -- cgit v1.2.3 From 8dddfb553151724a6a2110e56e8ced3213faf750 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 22 Nov 2011 09:46:01 +0100 Subject: cutils: Drop broken support for zero strtosz default_suffix Commit 9f9b17a4's strtosz() defaults a missing suffix to 'M', except it rejects fractions then (switch case 0). When commit d8427002 introduced strtosz_suffix(), that changed: fractions are no longer rejected, because we go to switch case 'M' on missing suffix now. Not mentioned in commit message, probably unintentional. Not worth changing back now. Because case 0 is still around, you can get the old behavior by passing a zero default_suffix to strtosz_suffix() or strtosz_suffix_unit(). Undocumented and not used. Drop. Commit d8427002 also neglected to update the function comment. Fix it up. Signed-off-by: Markus Armbruster Signed-off-by: Anthony Liguori --- cutils.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/cutils.c b/cutils.c index 5d995bc4e..55b059645 100644 --- a/cutils.c +++ b/cutils.c @@ -317,10 +317,9 @@ int fcntl_setfl(int fd, int flag) /* * Convert string to bytes, allowing either B/b for bytes, K/k for KB, - * M/m for MB, G/g for GB or T/t for TB. Default without any postfix - * is MB. End pointer will be returned in *end, if not NULL. A valid - * value must be terminated by whitespace, ',' or '\0'. Return -1 on - * error. + * M/m for MB, G/g for GB or T/t for TB. End pointer will be returned + * in *end, if not NULL. A valid value must be terminated by + * whitespace, ',' or '\0'. Return -1 on error. */ int64_t strtosz_suffix_unit(const char *nptr, char **end, const char default_suffix, int64_t unit) @@ -349,11 +348,7 @@ int64_t strtosz_suffix_unit(const char *nptr, char **end, d = c; if (qemu_isspace(c) || c == '\0' || c == ',') { c = 0; - if (default_suffix) { - d = default_suffix; - } else { - d = c; - } + d = default_suffix; } switch (qemu_toupper(d)) { case STRTOSZ_DEFSUFFIX_B: @@ -365,10 +360,6 @@ int64_t strtosz_suffix_unit(const char *nptr, char **end, case STRTOSZ_DEFSUFFIX_KB: mul = unit; break; - case 0: - if (mul_required) { - goto fail; - } case STRTOSZ_DEFSUFFIX_MB: mul = unit * unit; break; -- cgit v1.2.3 From c03417b438624988f1a027ce7829696ac98c3165 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 22 Nov 2011 09:46:02 +0100 Subject: vl: Tighten parsing of -numa's parameter mem strtosz_suffix() fails unless the size is followed by 0, whitespace or ','. Useless here, because we need to fail for any junk following the size, even if it starts with whitespace or ','. Check manually. Things like -smp 4 -numa "node,mem=1024,cpus=0-1" -numa "node,mem=1024 cpus=2-3" are now caught. Before, the second -numa's argument was silently interpreted as just "node,mem=1024". Signed-off-by: Markus Armbruster Signed-off-by: Anthony Liguori --- vl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vl.c b/vl.c index f5afed4c4..b9146cfde 100644 --- a/vl.c +++ b/vl.c @@ -953,8 +953,8 @@ static void numa_add(const char *optarg) node_mem[nodenr] = 0; } else { int64_t sval; - sval = strtosz(option, NULL); - if (sval < 0) { + sval = strtosz(option, &endptr); + if (sval < 0 || *endptr) { fprintf(stderr, "qemu: invalid numa mem size: %s\n", optarg); exit(1); } -- cgit v1.2.3 From 961b42b9dc858936f32effc3f47c76b1c4e7de56 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 22 Nov 2011 09:46:03 +0100 Subject: vl: Tighten parsing of -m argument strtosz_suffix() fails unless the size is followed by 0, whitespace or ','. Useless here, because we need to fail for any junk following the size, even if it starts with whitespace or ','. Check manually. Things like "-m 1024," are now caught. Signed-off-by: Markus Armbruster Signed-off-by: Anthony Liguori --- vl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vl.c b/vl.c index b9146cfde..a50842bb7 100644 --- a/vl.c +++ b/vl.c @@ -2535,9 +2535,10 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_m: { int64_t value; + char *end; - value = strtosz(optarg, NULL); - if (value < 0) { + value = strtosz(optarg, &end); + if (value < 0 || *end) { fprintf(stderr, "qemu: invalid ram size: %s\n", optarg); exit(1); } -- cgit v1.2.3 From 45009a3087b4acd8b1c91fcd0b1ee723ac3b0aec Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 22 Nov 2011 09:46:04 +0100 Subject: x86/cpuid: Tighten parsing of tsc_freq=FREQ cpu_x86_find_by_name() uses strtosz_suffix_unit(), but screws up the error checking. It detects some failures, but not all. Undetected failures result in a zero tsc_khz value (error value -1 divided by 1000), which means "no tsc_freq set". To reproduce, try "-cpu qemu64,tsc_freq=9999999T". strtosz_suffix_unit() fails, because the value overflows int64_t, Signed-off-by: Markus Armbruster Signed-off-by: Anthony Liguori --- target-i386/cpuid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c index 9fc9769ed..0b3af9060 100644 --- a/target-i386/cpuid.c +++ b/target-i386/cpuid.c @@ -711,7 +711,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) tsc_freq = strtosz_suffix_unit(val, &err, STRTOSZ_DEFSUFFIX_B, 1000); - if (!*val || *err) { + if (tsc_freq < 0 || *err) { fprintf(stderr, "bad numerical value %s\n", val); goto error; } -- cgit v1.2.3 From e36b369577784ac59a7d74725368eec66f23ad52 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 22 Nov 2011 09:46:05 +0100 Subject: qemu-img: Tighten parsing of size arguments strtosz_suffix() fails unless the size is followed by 0, whitespace or ','. Useless here, because we need to fail for any junk following the size, even if it starts with whitespace or ','. Check manually. Things like "qemu-img create xxx 1024," and "qemu-img convert -S '1024 junk'" are now caught. Signed-off-by: Markus Armbruster Signed-off-by: Anthony Liguori --- qemu-img.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index 86127f0b1..8bdae6649 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -332,8 +332,9 @@ static int img_create(int argc, char **argv) /* Get image size, if specified */ if (optind < argc) { int64_t sval; - sval = strtosz_suffix(argv[optind++], NULL, STRTOSZ_DEFSUFFIX_B); - if (sval < 0) { + char *end; + sval = strtosz_suffix(argv[optind++], &end, STRTOSZ_DEFSUFFIX_B); + if (sval < 0 || *end) { error_report("Invalid image size specified! You may use k, M, G or " "T suffixes for "); error_report("kilobytes, megabytes, gigabytes and terabytes."); @@ -710,8 +711,9 @@ static int img_convert(int argc, char **argv) case 'S': { int64_t sval; - sval = strtosz_suffix(optarg, NULL, STRTOSZ_DEFSUFFIX_B); - if (sval < 0) { + char *end; + sval = strtosz_suffix(optarg, &end, STRTOSZ_DEFSUFFIX_B); + if (sval < 0 || *end) { error_report("Invalid minimum zero buffer size for sparse output specified"); return 1; } -- cgit v1.2.3 From eba90e4efc80bc30c7d952ee6ea442207517a0da Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 22 Nov 2011 09:46:06 +0100 Subject: cutils: Make strtosz & friends leave follow set to callers strtosz() & friends require the size to be at the end of the string, or be followed by whitespace or ','. I find this surprising, because the name suggests it works like strtol(). The check simplifies callers that accept exactly that follow set slightly. No such callers exist. The check is redundant for callers that accept a smaller follow set, and thus need to check themselves anyway. Right now, this is the case for all but one caller. All of them neglected to check, or checked incorrectly, but the previous few commits fixed them up. Finally, the check is problematic for callers that accept a larger follow set. This is the case in monitor_parse_command(). Fortunately, the problems there are relatively harmless. monitor_parse_command() uses strtosz() for argument type 'o'. When the last argument is of type 'o', a trailing ',' is diagnosed differently than other trailing junk: (qemu) migrate_set_speed 1x invalid size (qemu) migrate_set_speed 1, migrate_set_speed: extraneous characters at the end of line A related inconsistency exists with non-last arguments. No such command exists, but let's use memsave to explore the inconsistency. The monitor permits, but does not require whitespace between arguments. For instance, "memsave (1-1)1024foo" is parsed as command memsave with three arguments 0, 1024 and "foo". Yes, this is daft, but at least it's consistently daft. If I change memsave's second argument from 'i' to 'o', then "memsave (1-1)1foo" is rejected, because the size is followed by an 'f'. But "memsave (1-1)1," is still accepted, and duly saves to file ",". We don't have any users of strtosz that profit from the check. In the users we have, it appears to encourage sloppy error checking, or gets in the way. Drop the bothersome check. Signed-off-by: Markus Armbruster Signed-off-by: Anthony Liguori --- cutils.c | 70 ++++++++++++++++++++++++---------------------------------------- 1 file changed, 26 insertions(+), 44 deletions(-) diff --git a/cutils.c b/cutils.c index 55b059645..6db6304bb 100644 --- a/cutils.c +++ b/cutils.c @@ -315,18 +315,34 @@ int fcntl_setfl(int fd, int flag) } #endif +static int64_t suffix_mul(char suffix, int64_t unit) +{ + switch (qemu_toupper(suffix)) { + case STRTOSZ_DEFSUFFIX_B: + return 1; + case STRTOSZ_DEFSUFFIX_KB: + return unit; + case STRTOSZ_DEFSUFFIX_MB: + return unit * unit; + case STRTOSZ_DEFSUFFIX_GB: + return unit * unit * unit; + case STRTOSZ_DEFSUFFIX_TB: + return unit * unit * unit * unit; + } + return -1; +} + /* * Convert string to bytes, allowing either B/b for bytes, K/k for KB, * M/m for MB, G/g for GB or T/t for TB. End pointer will be returned - * in *end, if not NULL. A valid value must be terminated by - * whitespace, ',' or '\0'. Return -1 on error. + * in *end, if not NULL. Return -1 on error. */ int64_t strtosz_suffix_unit(const char *nptr, char **end, const char default_suffix, int64_t unit) { int64_t retval = -1; char *endptr; - unsigned char c, d; + unsigned char c; int mul_required = 0; double val, mul, integral, fraction; @@ -339,51 +355,17 @@ int64_t strtosz_suffix_unit(const char *nptr, char **end, if (fraction != 0) { mul_required = 1; } - /* - * Any whitespace character is fine for terminating the number, - * in addition we accept ',' to handle strings where the size is - * part of a multi token argument. - */ c = *endptr; - d = c; - if (qemu_isspace(c) || c == '\0' || c == ',') { - c = 0; - d = default_suffix; + mul = suffix_mul(c, unit); + if (mul >= 0) { + endptr++; + } else { + mul = suffix_mul(default_suffix, unit); + assert(mul >= 0); } - switch (qemu_toupper(d)) { - case STRTOSZ_DEFSUFFIX_B: - mul = 1; - if (mul_required) { - goto fail; - } - break; - case STRTOSZ_DEFSUFFIX_KB: - mul = unit; - break; - case STRTOSZ_DEFSUFFIX_MB: - mul = unit * unit; - break; - case STRTOSZ_DEFSUFFIX_GB: - mul = unit * unit * unit; - break; - case STRTOSZ_DEFSUFFIX_TB: - mul = unit * unit * unit * unit; - break; - default: + if (mul == 1 && mul_required) { goto fail; } - /* - * If not terminated by whitespace, ',', or \0, increment endptr - * to point to next character, then check that we are terminated - * by an appropriate separating character, ie. whitespace, ',', or - * \0. If not, we are seeing trailing garbage, thus fail. - */ - if (c != 0) { - endptr++; - if (!qemu_isspace(*endptr) && *endptr != ',' && *endptr != 0) { - goto fail; - } - } if ((val * mul >= INT64_MAX) || val < 0) { goto fail; } -- cgit v1.2.3 From 023ddd743136d2b1f7a2e6b3772736f96bfca1ff Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 24 Nov 2011 16:11:31 +0400 Subject: configure: avoid screening of --{en, dis}able-usb-redir options --*dir) option pattern precede --{en,dis}able-usb-redir) patterns in the option analysis switch, making the latter options have no effect. There were some --*dir that are supported by Autoconf and not by QEMU configure. The aim was to let QEMU packagers use the rpm (or similar) macro that overrides directories for their distribution. Replace --*dir with exact option names. Reviewed-by: Paolo Bonzini Signed-off-by: Max Filippov Signed-off-by: Anthony Liguori --- configure | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/configure b/configure index a7caf1e19..ac4840d45 100755 --- a/configure +++ b/configure @@ -569,6 +569,14 @@ for opt do ;; --sysconfdir=*) sysconfdir="$optarg" ;; + --sbindir=*|--libexecdir=*|--sharedstatedir=*|--localstatedir=*|\ + --oldincludedir=*|--datarootdir=*|--infodir=*|--localedir=*|\ + --htmldir=*|--dvidir=*|--pdfdir=*|--psdir=*) + # These switches are silently ignored, for compatibility with + # autoconf-generated configure scripts. This allows QEMU's + # configure to be used by RPM and similar macros that set + # lots of directory switches by default. + ;; --disable-sdl) sdl="no" ;; --enable-sdl) sdl="yes" @@ -759,8 +767,6 @@ for opt do ;; --enable-opengl) opengl="yes" ;; - --*dir) - ;; --disable-rbd) rbd="no" ;; --enable-rbd) rbd="yes" -- cgit v1.2.3 From aea317aaa5d92ee8789f976ccf105be67d956f5e Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Mon, 28 Nov 2011 12:45:28 -0600 Subject: Revert "fix out of tree build" This reverts commit be85c90b74f56dca51782fa3080fcdf88593e045. This patch is incorrect and breaks the build with a freshly cloned git tree. Signed-off-by: Anthony Liguori --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b06599c16..7c9373960 100644 --- a/Makefile +++ b/Makefile @@ -168,7 +168,7 @@ check-qjson: check-qjson.o $(qobject-obj-y) $(tools-obj-y) test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(tools-obj-y) $(qapi-obj-y): $(GENERATED_HEADERS) -qapi-dir := $(SRC_PATH)/qapi-generated +qapi-dir := qapi-generated test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir) qemu-ga$(EXESUF): LIBS = $(LIBS_QGA) -- cgit v1.2.3 From 7e62255a4b3e0e2ab84a3ec7398640e8ed58620a Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 28 Nov 2011 20:27:37 +0100 Subject: ccid: Fix buffer overrun in handling of VSC_ATR message ATR size exceeding the limit is diagnosed, but then we merrily use it anyway, overrunning card->atr[]. The message is read from a character device. Obvious security implications unless the other end of the character device is trusted. Spotted by Coverity. CVE-2011-4111. Signed-off-by: Markus Armbruster Signed-off-by: Anthony Liguori --- hw/ccid-card-passthru.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c index 2cbc81b9f..9f51c6cb0 100644 --- a/hw/ccid-card-passthru.c +++ b/hw/ccid-card-passthru.c @@ -150,6 +150,7 @@ static void ccid_card_vscard_handle_message(PassthruState *card, error_report("ATR size exceeds spec, ignoring"); ccid_card_vscard_send_error(card, scr_msg_header->reader_id, VSC_GENERAL_ERROR); + break; } memcpy(card->atr, data, scr_msg_header->length); card->atr_length = scr_msg_header->length; -- cgit v1.2.3 From 85e83264b2acaaeaf737386d693373c39c30cb0d Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Mon, 28 Nov 2011 11:37:57 -0600 Subject: Update version for 1.0-rc4 Signed-off-by: Anthony Liguori --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 82fd64152..490438d65 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.15.93 +0.15.94 -- cgit v1.2.3 From d8e1f214a0046b85f5297b0396f3678531b8982d Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Tue, 29 Nov 2011 16:47:48 -0600 Subject: qapi: fix guardname generation Fix a bug in handling dotted paths, and exclude directory prefixes from generated guardnames to avoid odd/pseudo-random guardnames in generated headers. Signed-off-by: Anthony Liguori --- scripts/qapi.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/qapi.py b/scripts/qapi.py index 52999763e..6e05469e6 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -200,6 +200,7 @@ def basename(filename): return filename.split("/")[-1] def guardname(filename): - if filename.startswith('./'): - filename = filename[2:] - return filename.replace("/", "_").replace("-", "_").split(".")[0].upper() + '_H' + guard = basename(filename).rsplit(".", 1)[0] + for substr in [".", " ", "-"]: + guard = guard.replace(substr, "_") + return guard.upper() + '_H' -- cgit v1.2.3 From 9b129408589b2ed7bb2cdea03d2aba46a5fd74d4 Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Tue, 29 Nov 2011 16:47:49 -0600 Subject: Makefile: use full path for qapi-generated directory Generally $(BUILD_DIR) == $(CURDIR), but that isn't necessarilly the case, so use $(BUILD_DIR)/qapi-generated for generated files to avoid potentionally sticking generating files in odd places outside the build's include paths. Signed-off-by: Anthony Liguori --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7c9373960..301c75e7e 100644 --- a/Makefile +++ b/Makefile @@ -168,7 +168,7 @@ check-qjson: check-qjson.o $(qobject-obj-y) $(tools-obj-y) test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(tools-obj-y) $(qapi-obj-y): $(GENERATED_HEADERS) -qapi-dir := qapi-generated +qapi-dir := $(BUILD_DIR)/qapi-generated test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir) qemu-ga$(EXESUF): LIBS = $(LIBS_QGA) -- cgit v1.2.3 From 1c8a881daaca6fe0646a425b0970fb3ad25f6732 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Thu, 1 Dec 2011 14:04:21 -0600 Subject: Update version for 1.0 release Signed-off-by: Anthony Liguori --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 490438d65..d3827e75a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.15.94 +1.0 -- cgit v1.2.3