diff options
41 files changed, 727 insertions, 354 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 82ca5fb60a..654e2cb410 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -225,7 +225,7 @@ ARM Machines Exynos M: Evgeny Voevodin <e.voevodin@samsung.com> M: Maksim Kozlov <m.kozlov@samsung.com> -M: Igor Mitsyanko <i.mitsyanko@samsung.com> +M: Igor Mitsyanko <i.mitsyanko@gmail.com> M: Dmitry Solodkiy <d.solodkiy@samsung.com> S: Maintained F: hw/*/exynos* @@ -1 +1 @@ -1.5.90 +1.5.91 diff --git a/block/iscsi.c b/block/iscsi.c index 5f28c6a2ea..e7c1c2b538 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -247,7 +247,9 @@ static bool is_request_lun_aligned(int64_t sector_num, int nb_sectors, { if ((sector_num * BDRV_SECTOR_SIZE) % iscsilun->block_size || (nb_sectors * BDRV_SECTOR_SIZE) % iscsilun->block_size) { - error_report("iSCSI misaligned request: iscsilun->block_size %u, sector_num %ld, nb_sectors %d", + error_report("iSCSI misaligned request: " + "iscsilun->block_size %u, sector_num %" PRIi64 + ", nb_sectors %d", iscsilun->block_size, sector_num, nb_sectors); return 0; } diff --git a/block/vmdk.c b/block/vmdk.c index 3756333c60..e6c50b1e35 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1200,8 +1200,10 @@ static coroutine_fn int vmdk_co_read(BlockDriverState *bs, int64_t sector_num, /** * vmdk_write: * @zeroed: buf is ignored (data is zero), use zeroed_grain GTE feature - * if possible, otherwise return -ENOTSUP. - * @zero_dry_run: used for zeroed == true only, don't update L2 table, just + * if possible, otherwise return -ENOTSUP. + * @zero_dry_run: used for zeroed == true only, don't update L2 table, just try + * with each cluster. By dry run we can find if the zero write + * is possible without modifying image data. * * Returns: error code with 0 for success. */ @@ -1328,6 +1330,8 @@ static int coroutine_fn vmdk_co_write_zeroes(BlockDriverState *bs, int ret; BDRVVmdkState *s = bs->opaque; qemu_co_mutex_lock(&s->lock); + /* write zeroes could fail if sectors not aligned to cluster, test it with + * dry_run == true before really updating image */ ret = vmdk_write(bs, sector_num, NULL, nb_sectors, true, true); if (!ret) { ret = vmdk_write(bs, sector_num, NULL, nb_sectors, true, false); diff --git a/blockdev.c b/blockdev.c index 7879e8593d..41b0a49344 100644 --- a/blockdev.c +++ b/blockdev.c @@ -46,6 +46,7 @@ static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives); extern QemuOptsList qemu_common_drive_opts; +extern QemuOptsList qemu_old_drive_opts; static const char *const if_name[IF_COUNT] = { [IF_NONE] = "none", @@ -745,6 +746,26 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) { const char *value; + /* + * Check that only old options are used by copying into a QemuOpts with + * stricter checks. Going through a QDict seems to be the easiest way to + * achieve this... + */ + QemuOpts* check_opts; + QDict *qdict; + Error *local_err = NULL; + + qdict = qemu_opts_to_qdict(all_opts, NULL); + check_opts = qemu_opts_from_qdict(&qemu_old_drive_opts, qdict, &local_err); + QDECREF(qdict); + + if (error_is_set(&local_err)) { + qerror_report_err(local_err); + error_free(local_err); + return NULL; + } + qemu_opts_del(check_opts); + /* Change legacy command line options into QMP ones */ qemu_opt_rename(all_opts, "iops", "throttling.iops-total"); qemu_opt_rename(all_opts, "iops_rd", "throttling.iops-read"); @@ -1971,6 +1992,128 @@ QemuOptsList qemu_common_drive_opts = { }, }; +QemuOptsList qemu_old_drive_opts = { + .name = "drive", + .head = QTAILQ_HEAD_INITIALIZER(qemu_old_drive_opts.head), + .desc = { + { + .name = "bus", + .type = QEMU_OPT_NUMBER, + .help = "bus number", + },{ + .name = "unit", + .type = QEMU_OPT_NUMBER, + .help = "unit number (i.e. lun for scsi)", + },{ + .name = "if", + .type = QEMU_OPT_STRING, + .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)", + },{ + .name = "index", + .type = QEMU_OPT_NUMBER, + .help = "index number", + },{ + .name = "cyls", + .type = QEMU_OPT_NUMBER, + .help = "number of cylinders (ide disk geometry)", + },{ + .name = "heads", + .type = QEMU_OPT_NUMBER, + .help = "number of heads (ide disk geometry)", + },{ + .name = "secs", + .type = QEMU_OPT_NUMBER, + .help = "number of sectors (ide disk geometry)", + },{ + .name = "trans", + .type = QEMU_OPT_STRING, + .help = "chs translation (auto, lba. none)", + },{ + .name = "media", + .type = QEMU_OPT_STRING, + .help = "media type (disk, cdrom)", + },{ + .name = "snapshot", + .type = QEMU_OPT_BOOL, + .help = "enable/disable snapshot mode", + },{ + .name = "file", + .type = QEMU_OPT_STRING, + .help = "disk image", + },{ + .name = "discard", + .type = QEMU_OPT_STRING, + .help = "discard operation (ignore/off, unmap/on)", + },{ + .name = "cache", + .type = QEMU_OPT_STRING, + .help = "host cache usage (none, writeback, writethrough, " + "directsync, unsafe)", + },{ + .name = "aio", + .type = QEMU_OPT_STRING, + .help = "host AIO implementation (threads, native)", + },{ + .name = "format", + .type = QEMU_OPT_STRING, + .help = "disk format (raw, qcow2, ...)", + },{ + .name = "serial", + .type = QEMU_OPT_STRING, + .help = "disk serial number", + },{ + .name = "rerror", + .type = QEMU_OPT_STRING, + .help = "read error action", + },{ + .name = "werror", + .type = QEMU_OPT_STRING, + .help = "write error action", + },{ + .name = "addr", + .type = QEMU_OPT_STRING, + .help = "pci address (virtio only)", + },{ + .name = "readonly", + .type = QEMU_OPT_BOOL, + .help = "open drive file as read-only", + },{ + .name = "iops", + .type = QEMU_OPT_NUMBER, + .help = "limit total I/O operations per second", + },{ + .name = "iops_rd", + .type = QEMU_OPT_NUMBER, + .help = "limit read operations per second", + },{ + .name = "iops_wr", + .type = QEMU_OPT_NUMBER, + .help = "limit write operations per second", + },{ + .name = "bps", + .type = QEMU_OPT_NUMBER, + .help = "limit total bytes per second", + },{ + .name = "bps_rd", + .type = QEMU_OPT_NUMBER, + .help = "limit read bytes per second", + },{ + .name = "bps_wr", + .type = QEMU_OPT_NUMBER, + .help = "limit write bytes per second", + },{ + .name = "copy-on-read", + .type = QEMU_OPT_BOOL, + .help = "copy read data from backing file into image file", + },{ + .name = "boot", + .type = QEMU_OPT_BOOL, + .help = "(deprecated, ignored)", + }, + { /* end of list */ } + }, +}; + QemuOptsList qemu_drive_opts = { .name = "drive", .head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head), @@ -231,7 +231,7 @@ libusb="" usb_redir="" glx="" zlib="yes" -guest_agent="yes" +guest_agent="" want_tools="yes" libiscsi="" coroutine="" @@ -3444,10 +3444,15 @@ if test "$softmmu" = yes ; then virtfs=no fi fi +fi +if [ "$guest_agent" != "no" ]; then if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then - if [ "$guest_agent" = "yes" ]; then tools="qemu-ga\$(EXESUF) $tools" - fi + guest_agent=yes + elif [ "$guest_agent" != yes ]; then + guest_agent=no + else + error_exit "Guest agent is not supported on this platform" fi fi @@ -402,11 +402,14 @@ void cpu_exec_init(CPUArchState *env) #if defined(CONFIG_USER_ONLY) cpu_list_unlock(); #endif - vmstate_register(NULL, cpu_index, &vmstate_cpu_common, cpu); + if (qdev_get_vmsd(DEVICE(cpu)) == NULL) { + vmstate_register(NULL, cpu_index, &vmstate_cpu_common, cpu); + } #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY) register_savevm(NULL, "cpu", cpu_index, CPU_SAVE_VERSION, cpu_save, cpu_load, env); assert(cc->vmsd == NULL); + assert(qdev_get_vmsd(DEVICE(cpu)) == NULL); #endif if (cc->vmsd != NULL) { vmstate_register(NULL, cpu_index, cc->vmsd, cpu); diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index de6f0fe290..f0ffbe8c0d 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -61,6 +61,8 @@ static int virtio_9p_device_init(VirtIODevice *vdev) s->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output); + v9fs_path_init(&path); + fse = get_fsdev_fsentry(s->fsconf.fsdev_id); if (!fse) { @@ -111,7 +113,6 @@ static int virtio_9p_device_init(VirtIODevice *vdev) * call back to do that. Since we are in the init path, we don't * use co-routines here. */ - v9fs_path_init(&path); if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) { fprintf(stderr, "error in converting name to path %s", strerror(errno)); diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c index bcc7893230..eb3988c2e4 100644 --- a/hw/char/sclpconsole.c +++ b/hw/char/sclpconsole.c @@ -184,8 +184,6 @@ static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr, static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf, size_t len) { - ssize_t ret = 0; - const uint8_t *iov_offset; SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event); if (!scon->chr) { @@ -193,21 +191,7 @@ static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf, return len; } - iov_offset = buf; - while (len > 0) { - ret = qemu_chr_fe_write(scon->chr, buf, len); - if (ret == 0) { - /* a pty doesn't seem to be connected - no error */ - len = 0; - } else if (ret == -EAGAIN || (ret > 0 && ret < len)) { - len -= ret; - iov_offset += ret; - } else { - len = 0; - } - } - - return ret; + return qemu_chr_fe_write_all(scon->chr, buf, len); } static int write_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr) diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c index 6759e514a6..2e00ad2a7c 100644 --- a/hw/char/virtio-console.c +++ b/hw/char/virtio-console.c @@ -185,6 +185,7 @@ static void virtserialport_class_init(ObjectClass *klass, void *data) VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass); k->init = virtconsole_initfn; + k->exit = virtconsole_exitfn; k->have_data = flush_buf; k->set_guest_connected = set_guest_connected; dc->props = virtserialport_properties; diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index 8d43a8d272..dc8ae6958c 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -1172,15 +1172,21 @@ static int parse_size(DeviceState *dev, Property *prop, const char *str) static int print_size(DeviceState *dev, Property *prop, char *dest, size_t len) { - uint64_t *ptr = qdev_get_prop_ptr(dev, prop); - char suffixes[] = {'T', 'G', 'M', 'K', 'B'}; - int i = 0; - uint64_t div; + static const char suffixes[] = { 'B', 'K', 'M', 'G', 'T' }; + uint64_t div, val = *(uint64_t *)qdev_get_prop_ptr(dev, prop); + int i; - for (div = (long int)1 << 40; !(*ptr / div) ; div >>= 10) { - i++; + /* Compute floor(log2(val)). */ + i = 64 - clz64(val); + + /* Find the power of 1024 that we'll display as the units. */ + i /= 10; + if (i >= ARRAY_SIZE(suffixes)) { + i = ARRAY_SIZE(suffixes) - 1; } - return snprintf(dest, len, "%0.03f%c", (double)*ptr/div, suffixes[i]); + div = 1ULL << (i * 10); + + return snprintf(dest, len, "%0.03f%c", (double)val/div, suffixes[i]); } PropertyInfo qdev_prop_size = { diff --git a/hw/isa/i82378.c b/hw/isa/i82378.c index a542134585..a7d9aa6da1 100644 --- a/hw/isa/i82378.c +++ b/hw/isa/i82378.c @@ -22,135 +22,28 @@ #include "hw/timer/i8254.h" #include "hw/audio/pcspk.h" -//#define DEBUG_I82378 - -#ifdef DEBUG_I82378 -#define DPRINTF(fmt, ...) \ -do { fprintf(stderr, "i82378: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) \ -do {} while (0) -#endif - -#define BADF(fmt, ...) \ -do { fprintf(stderr, "i82378 ERROR: " fmt , ## __VA_ARGS__); } while (0) +#define TYPE_I82378 "i82378" +#define I82378(obj) \ + OBJECT_CHECK(I82378State, (obj), TYPE_I82378) typedef struct I82378State { + PCIDevice parent_obj; + qemu_irq out[2]; qemu_irq *i8259; MemoryRegion io; - MemoryRegion mem; } I82378State; -typedef struct PCIi82378State { - PCIDevice pci_dev; - uint32_t isa_io_base; - uint32_t isa_mem_base; - I82378State state; -} PCIi82378State; - -static const VMStateDescription vmstate_pci_i82378 = { +static const VMStateDescription vmstate_i82378 = { .name = "pci-i82378", .version_id = 0, .minimum_version_id = 0, .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(pci_dev, PCIi82378State), + VMSTATE_PCI_DEVICE(parent_obj, I82378State), VMSTATE_END_OF_LIST() }, }; -static void i82378_io_write(void *opaque, hwaddr addr, - uint64_t value, unsigned int size) -{ - switch (size) { - case 1: - DPRINTF("%s: " TARGET_FMT_plx "=%02" PRIx64 "\n", __func__, - addr, value); - cpu_outb(addr, value); - break; - case 2: - DPRINTF("%s: " TARGET_FMT_plx "=%04" PRIx64 "\n", __func__, - addr, value); - cpu_outw(addr, value); - break; - case 4: - DPRINTF("%s: " TARGET_FMT_plx "=%08" PRIx64 "\n", __func__, - addr, value); - cpu_outl(addr, value); - break; - default: - abort(); - } -} - -static uint64_t i82378_io_read(void *opaque, hwaddr addr, - unsigned int size) -{ - DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr); - switch (size) { - case 1: - return cpu_inb(addr); - case 2: - return cpu_inw(addr); - case 4: - return cpu_inl(addr); - default: - abort(); - } -} - -static const MemoryRegionOps i82378_io_ops = { - .read = i82378_io_read, - .write = i82378_io_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static void i82378_mem_write(void *opaque, hwaddr addr, - uint64_t value, unsigned int size) -{ - switch (size) { - case 1: - DPRINTF("%s: " TARGET_FMT_plx "=%02" PRIx64 "\n", __func__, - addr, value); - cpu_outb(addr, value); - break; - case 2: - DPRINTF("%s: " TARGET_FMT_plx "=%04" PRIx64 "\n", __func__, - addr, value); - cpu_outw(addr, value); - break; - case 4: - DPRINTF("%s: " TARGET_FMT_plx "=%08" PRIx64 "\n", __func__, - addr, value); - cpu_outl(addr, value); - break; - default: - abort(); - } -} - -static uint64_t i82378_mem_read(void *opaque, hwaddr addr, - unsigned int size) -{ - DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr); - switch (size) { - case 1: - return cpu_inb(addr); - case 2: - return cpu_inw(addr); - case 4: - return cpu_inl(addr); - default: - abort(); - } -} - -static const MemoryRegionOps i82378_mem_ops = { - .read = i82378_mem_read, - .write = i82378_mem_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - static void i82378_request_out0_irq(void *opaque, int irq, int level) { I82378State *s = opaque; @@ -160,19 +53,30 @@ static void i82378_request_out0_irq(void *opaque, int irq, int level) static void i82378_request_pic_irq(void *opaque, int irq, int level) { DeviceState *dev = opaque; - PCIDevice *pci = DO_UPCAST(PCIDevice, qdev, dev); - PCIi82378State *s = DO_UPCAST(PCIi82378State, pci_dev, pci); + I82378State *s = I82378(dev); - qemu_set_irq(s->state.i8259[irq], level); + qemu_set_irq(s->i8259[irq], level); } -static void i82378_init(DeviceState *dev, I82378State *s) +static int i82378_initfn(PCIDevice *pci) { - ISABus *isabus = ISA_BUS(qdev_get_child_bus(dev, "isa.0")); - ISADevice *pit; + DeviceState *dev = DEVICE(pci); + I82378State *s = I82378(dev); + uint8_t *pci_conf; + ISABus *isabus; ISADevice *isa; qemu_irq *out0_irq; + pci_conf = pci->config; + pci_set_word(pci_conf + PCI_COMMAND, + PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + pci_set_word(pci_conf + PCI_STATUS, + PCI_STATUS_DEVSEL_MEDIUM); + + pci_config_set_interrupt_pin(pci_conf, 1); /* interrupt pin 0 */ + + isabus = isa_bus_new(dev, pci_address_space_io(pci)); + /* This device has: 2 82C59 (irq) 1 82C54 (pit) @@ -183,9 +87,6 @@ static void i82378_init(DeviceState *dev, I82378State *s) All devices accept byte access only, except timer */ - qdev_init_gpio_out(dev, s->out, 2); - qdev_init_gpio_in(dev, i82378_request_pic_irq, 16); - /* Workaround the fact that i8259 is not qdev'ified... */ out0_irq = qemu_allocate_irqs(i82378_request_out0_irq, s, 1); @@ -194,10 +95,10 @@ static void i82378_init(DeviceState *dev, I82378State *s) isa_bus_irqs(isabus, s->i8259); /* 1 82C54 (pit) */ - pit = pit_init(isabus, 0x40, 0, NULL); + isa = pit_init(isabus, 0x40, 0, NULL); /* speaker */ - pcspk_init(isabus, pit); + pcspk_init(isabus, isa); /* 2 82C37 (dma) */ isa = isa_create_simple(isabus, "i82374"); @@ -205,76 +106,44 @@ static void i82378_init(DeviceState *dev, I82378State *s) /* timer */ isa_create_simple(isabus, "mc146818rtc"); + + return 0; } -static int pci_i82378_init(PCIDevice *dev) +static void i82378_init(Object *obj) { - PCIi82378State *pci = DO_UPCAST(PCIi82378State, pci_dev, dev); - I82378State *s = &pci->state; - uint8_t *pci_conf; + DeviceState *dev = DEVICE(obj); + I82378State *s = I82378(obj); - pci_conf = dev->config; - pci_set_word(pci_conf + PCI_COMMAND, - PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - pci_set_word(pci_conf + PCI_STATUS, - PCI_STATUS_DEVSEL_MEDIUM); - - pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin 0 */ - - memory_region_init_io(&s->io, OBJECT(pci), &i82378_io_ops, s, - "i82378-io", 0x00010000); - pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io); - - memory_region_init_io(&s->mem, OBJECT(pci), &i82378_mem_ops, s, - "i82378-mem", 0x01000000); - pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); - - /* Make I/O address read only */ - pci_set_word(dev->wmask + PCI_COMMAND, PCI_COMMAND_SPECIAL); - pci_set_long(dev->wmask + PCI_BASE_ADDRESS_0, 0); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, pci->isa_io_base); - - isa_mem_base = pci->isa_mem_base; - isa_bus_new(&dev->qdev, pci_address_space_io(dev)); - - i82378_init(&dev->qdev, s); - - return 0; + qdev_init_gpio_out(dev, s->out, 2); + qdev_init_gpio_in(dev, i82378_request_pic_irq, 16); } -static Property i82378_properties[] = { - DEFINE_PROP_HEX32("iobase", PCIi82378State, isa_io_base, 0x80000000), - DEFINE_PROP_HEX32("membase", PCIi82378State, isa_mem_base, 0xc0000000), - DEFINE_PROP_END_OF_LIST() -}; - -static void pci_i82378_class_init(ObjectClass *klass, void *data) +static void i82378_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = pci_i82378_init; + k->init = i82378_initfn; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82378; k->revision = 0x03; k->class_id = PCI_CLASS_BRIDGE_ISA; - k->subsystem_vendor_id = 0x0; - k->subsystem_id = 0x0; - dc->vmsd = &vmstate_pci_i82378; + dc->vmsd = &vmstate_i82378; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - dc->props = i82378_properties; } -static const TypeInfo pci_i82378_info = { - .name = "i82378", +static const TypeInfo i82378_type_info = { + .name = TYPE_I82378, .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIi82378State), - .class_init = pci_i82378_class_init, + .instance_size = sizeof(I82378State), + .instance_init = i82378_init, + .class_init = i82378_class_init, }; static void i82378_register_types(void) { - type_register_static(&pci_i82378_info); + type_register_static(&i82378_type_info); } type_init(i82378_register_types) diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c index 99014415ca..b13750d0d9 100644 --- a/hw/mips/mips_fulong2e.c +++ b/hw/mips/mips_fulong2e.c @@ -43,6 +43,7 @@ #include "hw/timer/i8254.h" #include "sysemu/blockdev.h" #include "exec/address-spaces.h" +#include "sysemu/qtest.h" #define DEBUG_FULONG2E_INIT @@ -332,7 +333,8 @@ static void mips_fulong2e_init(QEMUMachineInitArgs *args) bios_size = -1; } - if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) { + if ((bios_size < 0 || bios_size > BIOS_SIZE) && + !kernel_filename && !qtest_enabled()) { fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n", bios_name); } } diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c index d6e0860a83..36677cc652 100644 --- a/hw/mips/mips_jazz.c +++ b/hw/mips/mips_jazz.c @@ -42,6 +42,7 @@ #include "sysemu/blockdev.h" #include "hw/sysbus.h" #include "exec/address-spaces.h" +#include "sysemu/qtest.h" enum jazz_model_e { @@ -176,7 +177,7 @@ static void mips_jazz_init(MemoryRegion *address_space, } else { bios_size = -1; } - if (bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) { + if ((bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) && !qtest_enabled()) { fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n", bios_name); } diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 1589b59194..f56f34f3e6 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -48,6 +48,7 @@ #include "exec/address-spaces.h" #include "hw/sysbus.h" /* SysBusDevice */ #include "qemu/host-utils.h" +#include "sysemu/qtest.h" //#define DEBUG_BOARD_INIT @@ -1005,7 +1006,8 @@ void mips_malta_init(QEMUMachineInitArgs *args) } else { bios_size = -1; } - if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) { + if ((bios_size < 0 || bios_size > BIOS_SIZE) && + !kernel_filename && !qtest_enabled()) { fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s', and no -kernel argument was specified\n", bios_name); diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c index 7af08b8d0f..044f232de0 100644 --- a/hw/mips/mips_r4k.c +++ b/hw/mips/mips_r4k.c @@ -26,6 +26,7 @@ #include "hw/timer/i8254.h" #include "sysemu/blockdev.h" #include "exec/address-spaces.h" +#include "sysemu/qtest.h" #define MAX_IDE_BUS 2 @@ -244,8 +245,7 @@ void mips_r4k_init(QEMUMachineInitArgs *args) 4, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); } - } - else { + } else if (!qtest_enabled()) { /* not fatal */ fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n", bios_name); diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c index b606d2be3b..63aa73a241 100644 --- a/hw/net/pcnet.c +++ b/hw/net/pcnet.c @@ -861,6 +861,8 @@ static void pcnet_init(PCNetState *s) s->csr[0] |= 0x0101; s->csr[0] &= ~0x0004; /* clear STOP bit */ + + qemu_flush_queued_packets(qemu_get_queue(s->nic)); } static void pcnet_start(PCNetState *s) @@ -878,6 +880,8 @@ static void pcnet_start(PCNetState *s) s->csr[0] &= ~0x0004; /* clear STOP bit */ s->csr[0] |= 0x0002; pcnet_poll_timer(s); + + qemu_flush_queued_packets(qemu_get_queue(s->nic)); } static void pcnet_stop(PCNetState *s) diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c index 09d3b32291..e120058511 100644 --- a/hw/pci-host/prep.c +++ b/hw/pci-host/prep.c @@ -119,6 +119,8 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp) MemoryRegion *address_space_mem = get_system_memory(); int i; + isa_mem_base = 0xc0000000; + for (i = 0; i < 4; i++) { sysbus_init_irq(dev, &s->irq[i]); } diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index d438d648b3..d7836d6803 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -22,7 +22,6 @@ * o Allocate bandwidth in frames properly * o Disable timers when nothing needs to be done, or remove timer usage * all together. - * o Handle unrecoverable errors properly * o BIOS work to boot from USB storage */ @@ -308,6 +307,8 @@ struct ohci_iso_td { #define OHCI_HRESET_FSBIR (1 << 0) +static void ohci_die(OHCIState *ohci); + /* Update IRQ levels */ static inline void ohci_intr_update(OHCIState *ohci) { @@ -508,11 +509,13 @@ static inline int get_dwords(OHCIState *ohci, addr += ohci->localmem_base; for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { - dma_memory_read(ohci->as, addr, buf, sizeof(*buf)); + if (dma_memory_read(ohci->as, addr, buf, sizeof(*buf))) { + return -1; + } *buf = le32_to_cpu(*buf); } - return 1; + return 0; } /* Put an array of dwords in to main memory */ @@ -525,10 +528,12 @@ static inline int put_dwords(OHCIState *ohci, for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { uint32_t tmp = cpu_to_le32(*buf); - dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp)); + if (dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp))) { + return -1; + } } - return 1; + return 0; } /* Get an array of words from main memory */ @@ -540,11 +545,13 @@ static inline int get_words(OHCIState *ohci, addr += ohci->localmem_base; for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { - dma_memory_read(ohci->as, addr, buf, sizeof(*buf)); + if (dma_memory_read(ohci->as, addr, buf, sizeof(*buf))) { + return -1; + } *buf = le16_to_cpu(*buf); } - return 1; + return 0; } /* Put an array of words in to main memory */ @@ -557,10 +564,12 @@ static inline int put_words(OHCIState *ohci, for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { uint16_t tmp = cpu_to_le16(*buf); - dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp)); + if (dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp))) { + return -1; + } } - return 1; + return 0; } static inline int ohci_read_ed(OHCIState *ohci, @@ -578,15 +587,15 @@ static inline int ohci_read_td(OHCIState *ohci, static inline int ohci_read_iso_td(OHCIState *ohci, dma_addr_t addr, struct ohci_iso_td *td) { - return (get_dwords(ohci, addr, (uint32_t *)td, 4) && - get_words(ohci, addr + 16, td->offset, 8)); + return get_dwords(ohci, addr, (uint32_t *)td, 4) || + get_words(ohci, addr + 16, td->offset, 8); } static inline int ohci_read_hcca(OHCIState *ohci, dma_addr_t addr, struct ohci_hcca *hcca) { - dma_memory_read(ohci->as, addr + ohci->localmem_base, hcca, sizeof(*hcca)); - return 1; + return dma_memory_read(ohci->as, addr + ohci->localmem_base, + hcca, sizeof(*hcca)); } static inline int ohci_put_ed(OHCIState *ohci, @@ -610,23 +619,22 @@ static inline int ohci_put_td(OHCIState *ohci, static inline int ohci_put_iso_td(OHCIState *ohci, dma_addr_t addr, struct ohci_iso_td *td) { - return (put_dwords(ohci, addr, (uint32_t *)td, 4) && - put_words(ohci, addr + 16, td->offset, 8)); + return put_dwords(ohci, addr, (uint32_t *)td, 4 || + put_words(ohci, addr + 16, td->offset, 8)); } static inline int ohci_put_hcca(OHCIState *ohci, dma_addr_t addr, struct ohci_hcca *hcca) { - dma_memory_write(ohci->as, - addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET, - (char *)hcca + HCCA_WRITEBACK_OFFSET, - HCCA_WRITEBACK_SIZE); - return 1; + return dma_memory_write(ohci->as, + addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET, + (char *)hcca + HCCA_WRITEBACK_OFFSET, + HCCA_WRITEBACK_SIZE); } /* Read/Write the contents of a TD from/to main memory. */ -static void ohci_copy_td(OHCIState *ohci, struct ohci_td *td, - uint8_t *buf, int len, DMADirection dir) +static int ohci_copy_td(OHCIState *ohci, struct ohci_td *td, + uint8_t *buf, int len, DMADirection dir) { dma_addr_t ptr, n; @@ -634,18 +642,26 @@ static void ohci_copy_td(OHCIState *ohci, struct ohci_td *td, n = 0x1000 - (ptr & 0xfff); if (n > len) n = len; - dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir); - if (n == len) - return; + + if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir)) { + return -1; + } + if (n == len) { + return 0; + } ptr = td->be & ~0xfffu; buf += n; - dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, len - n, dir); + if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, + len - n, dir)) { + return -1; + } + return 0; } /* Read/Write the contents of an ISO TD from/to main memory. */ -static void ohci_copy_iso_td(OHCIState *ohci, - uint32_t start_addr, uint32_t end_addr, - uint8_t *buf, int len, DMADirection dir) +static int ohci_copy_iso_td(OHCIState *ohci, + uint32_t start_addr, uint32_t end_addr, + uint8_t *buf, int len, DMADirection dir) { dma_addr_t ptr, n; @@ -653,12 +669,20 @@ static void ohci_copy_iso_td(OHCIState *ohci, n = 0x1000 - (ptr & 0xfff); if (n > len) n = len; - dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir); - if (n == len) - return; + + if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir)) { + return -1; + } + if (n == len) { + return 0; + } ptr = end_addr & ~0xfffu; buf += n; - dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, len - n, dir); + if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, + len - n, dir)) { + return -1; + } + return 0; } static void ohci_process_lists(OHCIState *ohci, int completion); @@ -698,8 +722,9 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, addr = ed->head & OHCI_DPTR_MASK; - if (!ohci_read_iso_td(ohci, addr, &iso_td)) { + if (ohci_read_iso_td(ohci, addr, &iso_td)) { printf("usb-ohci: ISO_TD read error at %x\n", addr); + ohci_die(ohci); return 0; } @@ -740,7 +765,10 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, i = OHCI_BM(iso_td.flags, TD_DI); if (i < ohci->done_count) ohci->done_count = i; - ohci_put_iso_td(ohci, addr, &iso_td); + if (ohci_put_iso_td(ohci, addr, &iso_td)) { + ohci_die(ohci); + return 1; + } return 0; } @@ -821,8 +849,11 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, } if (len && dir != OHCI_TD_DIR_IN) { - ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len, - DMA_DIRECTION_TO_DEVICE); + if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len, + DMA_DIRECTION_TO_DEVICE)) { + ohci_die(ohci); + return 1; + } } if (!completion) { @@ -852,8 +883,11 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, /* Writeback */ if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) { /* IN transfer succeeded */ - ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret, - DMA_DIRECTION_FROM_DEVICE); + if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret, + DMA_DIRECTION_FROM_DEVICE)) { + ohci_die(ohci); + return 1; + } OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, OHCI_CC_NOERROR); OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret); @@ -910,7 +944,9 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, if (i < ohci->done_count) ohci->done_count = i; } - ohci_put_iso_td(ohci, addr, &iso_td); + if (ohci_put_iso_td(ohci, addr, &iso_td)) { + ohci_die(ohci); + } return 1; } @@ -943,8 +979,9 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) #endif return 1; } - if (!ohci_read_td(ohci, addr, &td)) { + if (ohci_read_td(ohci, addr, &td)) { fprintf(stderr, "usb-ohci: TD read error at %x\n", addr); + ohci_die(ohci); return 0; } @@ -997,8 +1034,10 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) pktlen = len; } if (!completion) { - ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen, - DMA_DIRECTION_TO_DEVICE); + if (ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen, + DMA_DIRECTION_TO_DEVICE)) { + ohci_die(ohci); + } } } } @@ -1055,8 +1094,10 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) if (ret >= 0) { if (dir == OHCI_TD_DIR_IN) { - ohci_copy_td(ohci, &td, ohci->usb_buf, ret, - DMA_DIRECTION_FROM_DEVICE); + if (ohci_copy_td(ohci, &td, ohci->usb_buf, ret, + DMA_DIRECTION_FROM_DEVICE)) { + ohci_die(ohci); + } #ifdef DEBUG_PACKET DPRINTF(" data:"); for (i = 0; i < ret; i++) @@ -1133,7 +1174,10 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) if (i < ohci->done_count) ohci->done_count = i; exit_no_retire: - ohci_put_td(ohci, addr, &td); + if (ohci_put_td(ohci, addr, &td)) { + ohci_die(ohci); + return 1; + } return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR; } @@ -1151,8 +1195,9 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion) return 0; for (cur = head; cur; cur = next_ed) { - if (!ohci_read_ed(ohci, cur, &ed)) { + if (ohci_read_ed(ohci, cur, &ed)) { fprintf(stderr, "usb-ohci: ED read error at %x\n", cur); + ohci_die(ohci); return 0; } @@ -1194,7 +1239,10 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion) } } - ohci_put_ed(ohci, cur, &ed); + if (ohci_put_ed(ohci, cur, &ed)) { + ohci_die(ohci); + return 0; + } } return active; @@ -1236,7 +1284,11 @@ static void ohci_frame_boundary(void *opaque) OHCIState *ohci = opaque; struct ohci_hcca hcca; - ohci_read_hcca(ohci, ohci->hcca, &hcca); + if (ohci_read_hcca(ohci, ohci->hcca, &hcca)) { + fprintf(stderr, "usb-ohci: HCCA read error at %x\n", ohci->hcca); + ohci_die(ohci); + return; + } /* Process all the lists at the end of the frame */ if (ohci->ctl & OHCI_CTL_PLE) { @@ -1257,6 +1309,11 @@ static void ohci_frame_boundary(void *opaque) ohci->old_ctl = ohci->ctl; ohci_process_lists(ohci, 0); + /* Stop if UnrecoverableError happened or ohci_sof will crash */ + if (ohci->intr_status & OHCI_INTR_UE) { + return; + } + /* Frame boundary, so do EOF stuf here */ ohci->frt = ohci->fit; @@ -1282,7 +1339,9 @@ static void ohci_frame_boundary(void *opaque) ohci_sof(ohci); /* Writeback HCCA */ - ohci_put_hcca(ohci, ohci->hcca, &hcca); + if (ohci_put_hcca(ohci, ohci->hcca, &hcca)) { + ohci_die(ohci); + } } /* Start sending SOF tokens across the USB bus, lists are processed in @@ -1296,7 +1355,7 @@ static int ohci_bus_start(OHCIState *ohci) if (ohci->eof_timer == NULL) { fprintf(stderr, "usb-ohci: %s: qemu_new_timer_ns failed\n", ohci->name); - /* TODO: Signal unrecoverable error */ + ohci_die(ohci); return 0; } @@ -1857,6 +1916,22 @@ typedef struct { uint32_t firstport; } OHCIPCIState; +/** A typical O/EHCI will stop operating, set itself into error state + * (which can be queried by MMIO) and will set PERR in its config + * space to signal that it got an error + */ +static void ohci_die(OHCIState *ohci) +{ + OHCIPCIState *dev = container_of(ohci, OHCIPCIState, state); + + fprintf(stderr, "%s: DMA error\n", __func__); + + ohci_set_interrupt(ohci, OHCI_INTR_UE); + ohci_bus_stop(ohci); + pci_set_word(dev->parent_obj.config + PCI_STATUS, + PCI_STATUS_DETECTED_PARITY); +} + static int usb_ohci_initfn_pci(PCIDevice *dev) { OHCIPCIState *ohci = PCI_OHCI(dev); diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index cb44abc7bc..ac8283313e 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -189,6 +189,7 @@ typedef struct UHCI_QH { static void uhci_async_cancel(UHCIAsync *async); static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td); +static void uhci_resume(void *opaque); static inline int32_t uhci_queue_token(UHCI_TD *td) { @@ -498,6 +499,12 @@ static void uhci_port_write(void *opaque, hwaddr addr, return; } s->cmd = val; + if (val & UHCI_CMD_EGSM) { + if ((s->ports[0].ctrl & UHCI_PORT_RD) || + (s->ports[1].ctrl & UHCI_PORT_RD)) { + uhci_resume(s); + } + } break; case 0x02: s->status &= ~val; diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 58f311db0f..ff5f68135c 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1429,7 +1429,6 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid, { XHCISlot *slot; XHCIEPContext *epctx; - USBDevice *dev; trace_usb_xhci_ep_reset(slotid, epid); assert(slotid >= 1 && slotid <= xhci->numslots); @@ -1465,8 +1464,8 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid, ep |= 0x80; } - dev = xhci->slots[slotid-1].uport->dev; - if (!dev) { + if (!xhci->slots[slotid-1].uport || + !xhci->slots[slotid-1].uport->dev) { return CC_USB_TRANSACTION_ERROR; } @@ -1741,6 +1740,7 @@ static int xhci_complete_packet(XHCITransfer *xfer) trace_usb_xhci_xfer_error(xfer, xfer->packet.status); switch (xfer->packet.status) { case USB_RET_NODEV: + case USB_RET_IOERROR: xfer->status = CC_USB_TRANSACTION_ERROR; xhci_xfer_report(xfer); xhci_stall_ep(xfer); diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 8b8c010d94..e3b9f324b3 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1334,6 +1334,7 @@ static void usbredir_handle_destroy(USBDevice *udev) USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); qemu_chr_delete(dev->cs); + dev->cs = NULL; /* Note must be done after qemu_chr_close, as that causes a close event */ qemu_bh_delete(dev->chardev_close_bh); diff --git a/include/elf.h b/include/elf.h index cf0d3e2bd6..58bfbf8817 100644 --- a/include/elf.h +++ b/include/elf.h @@ -1348,11 +1348,17 @@ typedef struct elf64_shdr { /* Notes used in ET_CORE */ #define NT_PRSTATUS 1 +#define NT_FPREGSET 2 #define NT_PRFPREG 2 #define NT_PRPSINFO 3 #define NT_TASKSTRUCT 4 #define NT_AUXV 6 #define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ +#define NT_S390_PREFIX 0x305 /* s390 prefix register */ +#define NT_S390_CTRS 0x304 /* s390 control registers */ +#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */ +#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */ +#define NT_S390_TIMER 0x301 /* s390 timer register */ /* Note header in a PT_NOTE section */ diff --git a/include/sysemu/char.h b/include/sysemu/char.h index e65e4a4844..8053130a97 100644 --- a/include/sysemu/char.h +++ b/include/sysemu/char.h @@ -77,6 +77,7 @@ struct CharDriverState { int explicit_fe_open; int explicit_be_open; int avail_connections; + int is_mux; QemuOpts *opts; QTAILQ_ENTRY(CharDriverState) next; }; diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 3caeb66eb2..d7a77b6488 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -103,7 +103,6 @@ typedef enum { extern int vga_interface_type; #define xenfb_enabled (vga_interface_type == VGA_XENFB) -#define qxl_enabled (vga_interface_type == VGA_QXL) extern int graphic_width; extern int graphic_height; diff --git a/include/ui/qemu-spice.h b/include/ui/qemu-spice.h index eba6d77d1d..c6c756b23d 100644 --- a/include/ui/qemu-spice.h +++ b/include/ui/qemu-spice.h @@ -27,6 +27,7 @@ #include "monitor/monitor.h" extern int using_spice; +extern int spice_displays; void qemu_spice_init(void); void qemu_spice_input_init(void); @@ -57,6 +58,7 @@ static inline CharDriverState *qemu_chr_open_spice_port(const char *name) #include "monitor/monitor.h" #define using_spice 0 +#define spice_displays 0 static inline int qemu_spice_set_passwd(const char *passwd, bool fail_if_connected, bool disconnect_if_connected) @@ -18,7 +18,6 @@ #include "exec/ioport.h" #include "qemu/bitops.h" #include "qom/object.h" -#include "sysemu/kvm.h" #include "trace.h" #include <assert.h> diff --git a/migration.c b/migration.c index 9fc72943fb..1402fa7680 100644 --- a/migration.c +++ b/migration.c @@ -231,6 +231,7 @@ MigrationInfo *qmp_query_migrate(Error **errp) info->has_status = true; info->status = g_strdup("completed"); + info->has_total_time = true; info->total_time = s->total_time; info->has_downtime = true; info->downtime = s->downtime; @@ -399,8 +400,8 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, MigrationParams params; const char *p; - params.blk = blk; - params.shared = inc; + params.blk = has_blk && blk; + params.shared = has_inc && inc; if (s->state == MIG_STATE_ACTIVE || s->state == MIG_STATE_SETUP) { error_set(errp, QERR_MIGRATION_ACTIVE); diff --git a/qemu-char.c b/qemu-char.c index 3f606c935b..16f3ad77de 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -476,6 +476,46 @@ static void mux_chr_update_read_handler(CharDriverState *chr) mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN); } +static bool muxes_realized; + +/** + * Called after processing of default and command-line-specified + * chardevs to deliver CHR_EVENT_OPENED events to any FEs attached + * to a mux chardev. This is done here to ensure that + * output/prompts/banners are only displayed for the FE that has + * focus when initial command-line processing/machine init is + * completed. + * + * After this point, any new FE attached to any new or existing + * mux will receive CHR_EVENT_OPENED notifications for the BE + * immediately. + */ +static void muxes_realize_done(Notifier *notifier, void *unused) +{ + CharDriverState *chr; + + QTAILQ_FOREACH(chr, &chardevs, next) { + if (chr->is_mux) { + MuxDriver *d = chr->opaque; + int i; + + /* send OPENED to all already-attached FEs */ + for (i = 0; i < d->mux_cnt; i++) { + mux_chr_send_event(d, i, CHR_EVENT_OPENED); + } + /* mark mux as OPENED so any new FEs will immediately receive + * OPENED event + */ + qemu_chr_be_generic_open(chr); + } + } + muxes_realized = true; +} + +static Notifier muxes_realize_notify = { + .notify = muxes_realize_done, +}; + static CharDriverState *qemu_chr_open_mux(CharDriverState *drv) { CharDriverState *chr; @@ -492,6 +532,11 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv) chr->chr_accept_input = mux_chr_accept_input; /* Frontend guest-open / -close notification is not support with muxes */ chr->chr_set_fe_open = NULL; + /* only default to opened state if we've realized the initial + * set of muxes + */ + chr->explicit_be_open = muxes_realized ? 0 : 1; + chr->is_mux = 1; return chr; } @@ -3798,6 +3843,11 @@ static void register_types(void) /* Bug-compatibility: */ register_char_driver_qapi("memory", CHARDEV_BACKEND_KIND_MEMORY, qemu_chr_parse_ringbuf); + /* this must be done after machine init, since we register FEs with muxes + * as part of realize functions like serial_isa_realizefn when -nographic + * is specified + */ + qemu_add_machine_init_done_notifier(&muxes_realize_notify); } type_init(register_types); diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index 7cf238f34b..c45b1b21b2 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -274,14 +274,13 @@ static const mips_def_t mips_defs[] = (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | (1 << CP0C1_CA), .CP0_Config2 = MIPS_CONFIG2, - .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_VInt) | (1 << CP0C3_MT), + .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_VInt) | (1 << CP0C3_MT) | + (1 << CP0C3_DSPP), .CP0_LLAddr_rw_bitmask = 0, .CP0_LLAddr_shift = 0, .SYNCI_Step = 32, .CCRes = 2, - /* No DSP implemented. */ - .CP0_Status_rw_bitmask = 0x3678FF1F, - /* No DSP implemented. */ + .CP0_Status_rw_bitmask = 0x3778FF1F, .CP0_TCStatus_rw_bitmask = (0 << CP0TCSt_TCU3) | (0 << CP0TCSt_TCU2) | (1 << CP0TCSt_TCU1) | (1 << CP0TCSt_TCU0) | (0 << CP0TCSt_TMX) | (1 << CP0TCSt_DT) | diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 0724226dd6..b14aec8e7b 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -7825,7 +7825,7 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp) error_setg(errp, "Unable to virtualize selected CPU with KVM"); return; } - } else { + } else if (tcg_enabled()) { if (ppc_fixup_cpu(cpu) != 0) { error_setg(errp, "Unable to emulate selected CPU with TCG"); return; diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs index ab938e7ad8..f8731463ff 100644 --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -1,5 +1,5 @@ obj-y += translate.o helper.o cpu.o interrupt.o obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o obj-y += gdbstub.o -obj-$(CONFIG_SOFTMMU) += ioinst.o +obj-$(CONFIG_SOFTMMU) += ioinst.o arch_dump.o obj-$(CONFIG_KVM) += kvm.o diff --git a/target-s390x/arch_dump.c b/target-s390x/arch_dump.c new file mode 100644 index 0000000000..f3e5144cc1 --- /dev/null +++ b/target-s390x/arch_dump.c @@ -0,0 +1,212 @@ +/* + * writing ELF notes for s390x arch + * + * + * Copyright IBM Corp. 2012, 2013 + * + * Ekaterina Tumanova <tumanova@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "cpu.h" +#include "elf.h" +#include "exec/cpu-all.h" +#include "sysemu/dump.h" +#include "sysemu/kvm.h" + + +struct S390xUserRegsStruct { + uint64_t psw[2]; + uint64_t gprs[16]; + uint32_t acrs[16]; +} QEMU_PACKED; + +typedef struct S390xUserRegsStruct S390xUserRegs; + +struct S390xElfPrstatusStruct { + uint8_t pad1[32]; + uint32_t pid; + uint8_t pad2[76]; + S390xUserRegs regs; + uint8_t pad3[16]; +} QEMU_PACKED; + +typedef struct S390xElfPrstatusStruct S390xElfPrstatus; + +struct S390xElfFpregsetStruct { + uint32_t fpc; + uint32_t pad; + uint64_t fprs[16]; +} QEMU_PACKED; + +typedef struct S390xElfFpregsetStruct S390xElfFpregset; + +typedef struct noteStruct { + Elf64_Nhdr hdr; + char name[5]; + char pad3[3]; + union { + S390xElfPrstatus prstatus; + S390xElfFpregset fpregset; + uint32_t prefix; + uint64_t timer; + uint64_t todcmp; + uint32_t todpreg; + uint64_t ctrs[16]; + } contents; +} QEMU_PACKED Note; + +static void s390x_write_elf64_prstatus(Note *note, S390CPU *cpu) +{ + int i; + S390xUserRegs *regs; + + note->hdr.n_type = cpu_to_be32(NT_PRSTATUS); + + regs = &(note->contents.prstatus.regs); + regs->psw[0] = cpu_to_be64(cpu->env.psw.mask); + regs->psw[1] = cpu_to_be64(cpu->env.psw.addr); + for (i = 0; i <= 15; i++) { + regs->acrs[i] = cpu_to_be32(cpu->env.aregs[i]); + regs->gprs[i] = cpu_to_be64(cpu->env.regs[i]); + } +} + +static void s390x_write_elf64_fpregset(Note *note, S390CPU *cpu) +{ + int i; + + note->hdr.n_type = cpu_to_be32(NT_FPREGSET); + note->contents.fpregset.fpc = cpu_to_be32(cpu->env.fpc); + for (i = 0; i <= 15; i++) { + note->contents.fpregset.fprs[i] = cpu_to_be64(cpu->env.fregs[i].ll); + } +} + + +static void s390x_write_elf64_timer(Note *note, S390CPU *cpu) +{ + note->hdr.n_type = cpu_to_be32(NT_S390_TIMER); + note->contents.timer = cpu_to_be64((uint64_t)(cpu->env.cputm)); +} + +static void s390x_write_elf64_todcmp(Note *note, S390CPU *cpu) +{ + note->hdr.n_type = cpu_to_be32(NT_S390_TODCMP); + note->contents.todcmp = cpu_to_be64((uint64_t)(cpu->env.ckc)); +} + +static void s390x_write_elf64_todpreg(Note *note, S390CPU *cpu) +{ + note->hdr.n_type = cpu_to_be32(NT_S390_TODPREG); + note->contents.todpreg = cpu_to_be32((uint32_t)(cpu->env.todpr)); +} + +static void s390x_write_elf64_ctrs(Note *note, S390CPU *cpu) +{ + int i; + + note->hdr.n_type = cpu_to_be32(NT_S390_CTRS); + + for (i = 0; i <= 15; i++) { + note->contents.ctrs[i] = cpu_to_be64(cpu->env.cregs[i]); + } +} + +static void s390x_write_elf64_prefix(Note *note, S390CPU *cpu) +{ + note->hdr.n_type = cpu_to_be32(NT_S390_PREFIX); + note->contents.prefix = cpu_to_be32((uint32_t)(cpu->env.psa)); +} + + +struct NoteFuncDescStruct { + int contents_size; + void (*note_contents_func)(Note *note, S390CPU *cpu); +} note_func[] = { + {sizeof(((Note *)0)->contents.prstatus), s390x_write_elf64_prstatus}, + {sizeof(((Note *)0)->contents.prefix), s390x_write_elf64_prefix}, + {sizeof(((Note *)0)->contents.fpregset), s390x_write_elf64_fpregset}, + {sizeof(((Note *)0)->contents.ctrs), s390x_write_elf64_ctrs}, + {sizeof(((Note *)0)->contents.timer), s390x_write_elf64_timer}, + {sizeof(((Note *)0)->contents.todcmp), s390x_write_elf64_todcmp}, + {sizeof(((Note *)0)->contents.todpreg), s390x_write_elf64_todpreg}, + { 0, NULL} +}; + +typedef struct NoteFuncDescStruct NoteFuncDesc; + + +static int s390x_write_all_elf64_notes(const char *note_name, + WriteCoreDumpFunction f, + S390CPU *cpu, int id, + void *opaque) +{ + Note note; + NoteFuncDesc *nf; + int note_size; + int ret = -1; + + for (nf = note_func; nf->note_contents_func; nf++) { + note.hdr.n_namesz = cpu_to_be32(sizeof(note.name)); + note.hdr.n_descsz = cpu_to_be32(nf->contents_size); + strncpy(note.name, note_name, sizeof(note.name)); + (*nf->note_contents_func)(¬e, cpu); + + note_size = sizeof(note) - sizeof(note.contents) + nf->contents_size; + ret = f(¬e, note_size, opaque); + + if (ret < 0) { + return -1; + } + + } + + return 0; +} + + +int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, + int cpuid, void *opaque) +{ + S390CPU *cpu = S390_CPU(cs); + return s390x_write_all_elf64_notes("CORE", f, cpu, cpuid, opaque); +} + +int cpu_get_dump_info(ArchDumpInfo *info) +{ + info->d_machine = EM_S390; + info->d_endian = ELFDATA2MSB; + info->d_class = ELFCLASS64; + + return 0; +} + +ssize_t cpu_get_note_size(int class, int machine, int nr_cpus) +{ + int name_size = 8; /* "CORE" or "QEMU" rounded */ + size_t elf_note_size = 0; + int note_head_size; + NoteFuncDesc *nf; + + assert(class == ELFCLASS64); + assert(machine == EM_S390); + + note_head_size = sizeof(Elf64_Nhdr); + + for (nf = note_func; nf->note_contents_func; nf++) { + elf_note_size = elf_note_size + note_head_size + name_size + + nf->contents_size; + } + + return (elf_note_size) * nr_cpus; +} + +int s390_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, + CPUState *cpu, void *opaque) +{ + return 0; +} diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h index 0d63b1cf20..cbe2341b3b 100644 --- a/target-s390x/cpu-qom.h +++ b/target-s390x/cpu-qom.h @@ -74,6 +74,11 @@ static inline S390CPU *s390_env_get_cpu(CPUS390XState *env) void s390_cpu_do_interrupt(CPUState *cpu); void s390_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf, int flags); +int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, + int cpuid, void *opaque); + +int s390_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, + CPUState *cpu, void *opaque); hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); int s390_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c index 9b824957f6..6be6c084a7 100644 --- a/target-s390x/cpu.c +++ b/target-s390x/cpu.c @@ -178,6 +178,8 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) cc->gdb_write_register = s390_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY cc->get_phys_page_debug = s390_cpu_get_phys_page_debug; + cc->write_elf64_note = s390_cpu_write_elf64_note; + cc->write_elf64_qemunote = s390_cpu_write_elf64_qemunote; #endif dc->vmsd = &vmstate_s390_cpu; cc->gdb_num_core_regs = S390_NUM_REGS; diff --git a/target-s390x/ioinst.c b/target-s390x/ioinst.c index 28c508d541..85fd285736 100644 --- a/target-s390x/ioinst.c +++ b/target-s390x/ioinst.c @@ -151,23 +151,24 @@ int ioinst_handle_msch(CPUS390XState *env, uint64_t reg1, uint32_t ipb) int cc; hwaddr len = sizeof(*schib); - if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { - program_interrupt(env, PGM_OPERAND, 2); + addr = decode_basedisp_s(env, ipb); + if (addr & 3) { + program_interrupt(env, PGM_SPECIFICATION, 2); return -EIO; } - trace_ioinst_sch_id("msch", cssid, ssid, schid); - addr = decode_basedisp_s(env, ipb); schib = s390_cpu_physical_memory_map(env, addr, &len, 0); if (!schib || len != sizeof(*schib)) { - program_interrupt(env, PGM_SPECIFICATION, 2); + program_interrupt(env, PGM_ADDRESSING, 2); cc = -EIO; goto out; } - if (!ioinst_schib_valid(schib)) { + if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) || + !ioinst_schib_valid(schib)) { program_interrupt(env, PGM_OPERAND, 2); cc = -EIO; goto out; } + trace_ioinst_sch_id("msch", cssid, ssid, schid); sch = css_find_subch(m, cssid, ssid, schid); if (sch && css_subch_visible(sch)) { ret = css_do_msch(sch, schib); @@ -222,24 +223,25 @@ int ioinst_handle_ssch(CPUS390XState *env, uint64_t reg1, uint32_t ipb) int cc; hwaddr len = sizeof(*orig_orb); - if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { - program_interrupt(env, PGM_OPERAND, 2); + addr = decode_basedisp_s(env, ipb); + if (addr & 3) { + program_interrupt(env, PGM_SPECIFICATION, 2); return -EIO; } - trace_ioinst_sch_id("ssch", cssid, ssid, schid); - addr = decode_basedisp_s(env, ipb); orig_orb = s390_cpu_physical_memory_map(env, addr, &len, 0); if (!orig_orb || len != sizeof(*orig_orb)) { - program_interrupt(env, PGM_SPECIFICATION, 2); + program_interrupt(env, PGM_ADDRESSING, 2); cc = -EIO; goto out; } copy_orb_from_guest(&orb, orig_orb); - if (!ioinst_orb_valid(&orb)) { + if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) || + !ioinst_orb_valid(&orb)) { program_interrupt(env, PGM_OPERAND, 2); cc = -EIO; goto out; } + trace_ioinst_sch_id("ssch", cssid, ssid, schid); sch = css_find_subch(m, cssid, ssid, schid); if (sch && css_subch_visible(sch)) { ret = css_do_ssch(sch, &orb); @@ -272,9 +274,13 @@ int ioinst_handle_stcrw(CPUS390XState *env, uint32_t ipb) hwaddr len = sizeof(*crw); addr = decode_basedisp_s(env, ipb); + if (addr & 3) { + program_interrupt(env, PGM_SPECIFICATION, 2); + return -EIO; + } crw = s390_cpu_physical_memory_map(env, addr, &len, 1); if (!crw || len != sizeof(*crw)) { - program_interrupt(env, PGM_SPECIFICATION, 2); + program_interrupt(env, PGM_ADDRESSING, 2); cc = -EIO; goto out; } @@ -294,18 +300,24 @@ int ioinst_handle_stsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb) SCHIB *schib; hwaddr len = sizeof(*schib); - if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { - program_interrupt(env, PGM_OPERAND, 2); + addr = decode_basedisp_s(env, ipb); + if (addr & 3) { + program_interrupt(env, PGM_SPECIFICATION, 2); return -EIO; } - trace_ioinst_sch_id("stsch", cssid, ssid, schid); - addr = decode_basedisp_s(env, ipb); schib = s390_cpu_physical_memory_map(env, addr, &len, 1); if (!schib || len != sizeof(*schib)) { - program_interrupt(env, PGM_SPECIFICATION, 2); + program_interrupt(env, PGM_ADDRESSING, 2); + cc = -EIO; + goto out; + } + + if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { + program_interrupt(env, PGM_OPERAND, 2); cc = -EIO; goto out; } + trace_ioinst_sch_id("stsch", cssid, ssid, schid); sch = css_find_subch(m, cssid, ssid, schid); if (sch) { if (css_subch_visible(sch)) { @@ -345,9 +357,13 @@ int ioinst_handle_tsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb) } trace_ioinst_sch_id("tsch", cssid, ssid, schid); addr = decode_basedisp_s(env, ipb); + if (addr & 3) { + program_interrupt(env, PGM_SPECIFICATION, 2); + return -EIO; + } irb = s390_cpu_physical_memory_map(env, addr, &len, 1); if (!irb || len != sizeof(*irb)) { - program_interrupt(env, PGM_SPECIFICATION, 2); + program_interrupt(env, PGM_ADDRESSING, 2); cc = -EIO; goto out; } @@ -580,7 +596,7 @@ int ioinst_handle_chsc(CPUS390XState *env, uint32_t ipb) } req = s390_cpu_physical_memory_map(env, addr, &map_size, 1); if (!req || map_size != TARGET_PAGE_SIZE) { - program_interrupt(env, PGM_SPECIFICATION, 2); + program_interrupt(env, PGM_ADDRESSING, 2); ret = -EIO; goto out; } @@ -625,12 +641,17 @@ int ioinst_handle_tpi(CPUS390XState *env, uint32_t ipb) trace_ioinst("tpi"); addr = decode_basedisp_s(env, ipb); + if (addr & 3) { + program_interrupt(env, PGM_SPECIFICATION, 2); + return -EIO; + } + lowcore = addr ? 0 : 1; len = lowcore ? 8 /* two words */ : 12 /* three words */; orig_len = len; int_code = s390_cpu_physical_memory_map(env, addr, &len, 1); if (!int_code || (len != orig_len)) { - program_interrupt(env, PGM_SPECIFICATION, 2); + program_interrupt(env, PGM_ADDRESSING, 2); ret = -EIO; goto out; } @@ -663,7 +684,7 @@ int ioinst_handle_schm(CPUS390XState *env, uint64_t reg1, uint64_t reg2, update = SCHM_REG1_UPD(reg1); dct = SCHM_REG1_DCT(reg1); - if (update && (reg2 & 0x0000000000000fff)) { + if (update && (reg2 & 0x000000000000001f)) { program_interrupt(env, PGM_OPERAND, 2); return -EIO; } diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index ab0e2b505f..26d18e3bcf 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -528,50 +528,19 @@ static int kvm_handle_css_inst(S390CPU *cpu, struct kvm_run *run, no_cc = 1; r = ioinst_handle_sal(env, env->regs[1]); break; - default: - r = -1; + case PRIV_SIGA: + /* Not provided, set CC = 3 for subchannel not operational */ + r = 3; break; + default: + return -1; } - if (r >= 0) { - if (!no_cc) { - setcc(cpu, r); - } - r = 0; - } else if (r < -1) { - r = 0; + if (r >= 0 && !no_cc) { + setcc(cpu, r); } - return r; -} -static int is_ioinst(uint8_t ipa0, uint8_t ipa1, uint8_t ipb) -{ - int ret = 0; - uint16_t ipa = (ipa0 << 8) | ipa1; - - switch (ipa) { - case IPA0_B2 | PRIV_CSCH: - case IPA0_B2 | PRIV_HSCH: - case IPA0_B2 | PRIV_MSCH: - case IPA0_B2 | PRIV_SSCH: - case IPA0_B2 | PRIV_STSCH: - case IPA0_B2 | PRIV_TPI: - case IPA0_B2 | PRIV_SAL: - case IPA0_B2 | PRIV_RSCH: - case IPA0_B2 | PRIV_STCRW: - case IPA0_B2 | PRIV_STCPS: - case IPA0_B2 | PRIV_RCHP: - case IPA0_B2 | PRIV_SCHM: - case IPA0_B2 | PRIV_CHSC: - case IPA0_B2 | PRIV_SIGA: - case IPA0_B2 | PRIV_XSCH: - case IPA0_B9 | PRIV_EQBS: - case IPA0_EB | PRIV_SQBS: - ret = 1; - break; - } - - return ret; + return 0; } static int handle_priv(S390CPU *cpu, struct kvm_run *run, @@ -587,15 +556,9 @@ static int handle_priv(S390CPU *cpu, struct kvm_run *run, r = kvm_sclp_service_call(cpu, run, ipbh0); break; default: - if (is_ioinst(ipa0, ipa1, ipb)) { - r = kvm_handle_css_inst(cpu, run, ipa0, ipa1, ipb); - if (r == -1) { - setcc(cpu, 3); - r = 0; - } - } else { - DPRINTF("KVM: unknown PRIV: 0x%x\n", ipa1); - r = -1; + r = kvm_handle_css_inst(cpu, run, ipa0, ipa1, ipb); + if (r == -1) { + DPRINTF("KVM: unhandled PRIV: 0x%x\n", ipa1); } break; } @@ -730,7 +693,7 @@ out: return 0; } -static int handle_instruction(S390CPU *cpu, struct kvm_run *run) +static void handle_instruction(S390CPU *cpu, struct kvm_run *run) { unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00); uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff; @@ -756,7 +719,6 @@ static int handle_instruction(S390CPU *cpu, struct kvm_run *run) if (r < 0) { enter_pgmcheck(cpu, 0x0001); } - return 0; } static bool is_special_wait_psw(CPUState *cs) @@ -776,7 +738,7 @@ static int handle_intercept(S390CPU *cpu) (long)cs->kvm_run->psw_addr); switch (icpt_code) { case ICPT_INSTRUCTION: - r = handle_instruction(cpu, run); + handle_instruction(cpu, run); break; case ICPT_WAITPSW: /* disabled wait, since enabled wait is handled in kernel */ diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c index d1241b5692..e118bc7179 100644 --- a/tcg/tci/tcg-target.c +++ b/tcg/tci/tcg-target.c @@ -34,9 +34,6 @@ tcg_abort(); \ } while (0) -/* Single bit n. */ -#define BIT(n) (1 << (n)) - /* Bitfield n...m (in 32 bit value). */ #define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m) diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index b1d03c76a4..69e208c709 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -57,7 +57,7 @@ 048 img auto quick 049 rw auto 050 rw auto backing quick -051 rw auto +#051 rw auto 052 rw auto backing 053 rw auto 054 rw auto diff --git a/ui/spice-core.c b/ui/spice-core.c index 033fd8925b..bd7a248f91 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -48,6 +48,7 @@ static char *auth_passwd; static time_t auth_expires = TIME_MAX; static int spice_migration_completed; int using_spice = 0; +int spice_displays; static QemuThread me; @@ -836,6 +837,10 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin) qemu_add_vm_change_state_handler(vm_change_state_handler, NULL); } + if (strcmp(sin->sif->type, SPICE_INTERFACE_QXL) == 0) { + spice_displays++; + } + return spice_server_add_interface(spice_server, sin); } @@ -4387,7 +4387,7 @@ int main(int argc, char **argv, char **envp) } #endif #ifdef CONFIG_SPICE - if (using_spice && !qxl_enabled) { + if (using_spice && !spice_displays) { qemu_spice_display_init(ds); } #endif |