diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/core/Makefile.objs | 2 | ||||
-rw-r--r-- | hw/i386/pc.c | 11 | ||||
-rw-r--r-- | hw/misc/Makefile.objs | 4 | ||||
-rw-r--r-- | hw/pci-bridge/Makefile.objs | 5 | ||||
-rw-r--r-- | hw/pci/pci-hotplug-old.c | 2 | ||||
-rw-r--r-- | hw/scsi/scsi-bus.c | 5 | ||||
-rw-r--r-- | hw/scsi/virtio-scsi-dataplane.c | 4 | ||||
-rw-r--r-- | hw/scsi/virtio-scsi.c | 19 | ||||
-rw-r--r-- | hw/usb/dev-network.c | 4 | ||||
-rw-r--r-- | hw/usb/dev-storage.c | 6 | ||||
-rw-r--r-- | hw/usb/hcd-xhci.c | 15 | ||||
-rw-r--r-- | hw/vfio/common.c | 10 | ||||
-rw-r--r-- | hw/vfio/pci.c | 101 | ||||
-rw-r--r-- | hw/watchdog/watchdog.c | 2 |
14 files changed, 149 insertions, 41 deletions
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs index 9dce1bc..abb3560 100644 --- a/hw/core/Makefile.objs +++ b/hw/core/Makefile.objs @@ -14,4 +14,4 @@ common-obj-$(CONFIG_SOFTMMU) += machine.o common-obj-$(CONFIG_SOFTMMU) += null-machine.o common-obj-$(CONFIG_SOFTMMU) += loader.o common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o -common-obj-$(CONFIG_SOFTMMU) += platform-bus.o +common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 03dc007..b229856 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1138,15 +1138,11 @@ void pc_acpi_init(const char *default_dsdt) if (filename == NULL) { fprintf(stderr, "WARNING: failed to find %s\n", default_dsdt); } else { - char *arg; - QemuOpts *opts; + QemuOpts *opts = qemu_opts_create(qemu_find_opts("acpi"), NULL, 0, + &error_abort); Error *err = NULL; - arg = g_strdup_printf("file=%s", filename); - - /* creates a deep copy of "arg" */ - opts = qemu_opts_parse(qemu_find_opts("acpi"), arg, 0); - g_assert(opts != NULL); + qemu_opt_set(opts, "file", filename, &error_abort); acpi_table_add_builtin(opts, &err); if (err) { @@ -1154,7 +1150,6 @@ void pc_acpi_init(const char *default_dsdt) error_get_pretty(err)); error_free(err); } - g_free(arg); g_free(filename); } } diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 029a56f..6c6e296 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -19,9 +19,7 @@ common-obj-$(CONFIG_PUV3) += puv3_pm.o common-obj-$(CONFIG_MACIO) += macio/ -ifeq ($(CONFIG_PCI), y) -obj-$(CONFIG_KVM) += ivshmem.o -endif +obj-$(CONFIG_IVSHMEM) += ivshmem.o obj-$(CONFIG_REALVIEW) += arm_sysctl.o obj-$(CONFIG_NSERIES) += cbus.o diff --git a/hw/pci-bridge/Makefile.objs b/hw/pci-bridge/Makefile.objs index 968b369..96c596e 100644 --- a/hw/pci-bridge/Makefile.objs +++ b/hw/pci-bridge/Makefile.objs @@ -1,5 +1,6 @@ common-obj-y += pci_bridge_dev.o -common-obj-y += ioh3420.o xio3130_upstream.o xio3130_downstream.o -common-obj-y += i82801b11.o +common-obj-$(CONFIG_XIO3130) += xio3130_upstream.o xio3130_downstream.o +common-obj-$(CONFIG_IOH3420) += ioh3420.o +common-obj-$(CONFIG_I82801B11) += i82801b11.o # NewWorld PowerMac common-obj-$(CONFIG_DEC_PCI) += dec.o diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c index beea6d2..501a918 100644 --- a/hw/pci/pci-hotplug-old.c +++ b/hw/pci/pci-hotplug-old.c @@ -87,7 +87,7 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon, return NULL; } - qemu_opt_set(opts, "type", "nic"); + qemu_opt_set(opts, "type", "nic", &error_abort); ret = net_client_init(opts, 0, &local_err); if (local_err) { diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index db39ae0..dca9576 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -221,11 +221,16 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk, const char *serial, Error **errp) { const char *driver; + char *name; DeviceState *dev; Error *err = NULL; driver = blk_is_sg(blk) ? "scsi-generic" : "scsi-disk"; dev = qdev_create(&bus->qbus, driver); + name = g_strdup_printf("legacy[%d]", unit); + object_property_add_child(OBJECT(bus), name, OBJECT(dev), NULL); + g_free(name); + qdev_prop_set_uint32(dev, "scsi-id", unit); if (bootindex >= 0) { object_property_set_int(OBJECT(dev), bootindex, "bootindex", diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index 418d73b..3f40ff0 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -211,8 +211,6 @@ void virtio_scsi_dataplane_start(VirtIOSCSI *s) s->dataplane_starting = true; - assert(!s->blocker); - error_setg(&s->blocker, "block device is in use by data plane"); /* Set up guest notifier (irq) */ rc = k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, true); if (rc != 0) { @@ -279,8 +277,6 @@ void virtio_scsi_dataplane_stop(VirtIOSCSI *s) if (!s->dataplane_started || s->dataplane_stopping) { return; } - error_free(s->blocker); - s->blocker = NULL; s->dataplane_stopping = true; assert(s->ctx == iothread_get_aio_context(vs->conf.iothread)); diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 9e2c718..4db3b23 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -254,10 +254,8 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req) int target; int ret = 0; - if (s->dataplane_started && blk_get_aio_context(d->conf.blk) != s->ctx) { - aio_context_acquire(s->ctx); - blk_set_aio_context(d->conf.blk, s->ctx); - aio_context_release(s->ctx); + if (s->dataplane_started) { + assert(blk_get_aio_context(d->conf.blk) == s->ctx); } /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */ req->resp.tmf.response = VIRTIO_SCSI_S_OK; @@ -540,10 +538,8 @@ bool virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req) virtio_scsi_complete_cmd_req(req); return false; } - if (s->dataplane_started && blk_get_aio_context(d->conf.blk) != s->ctx) { - aio_context_acquire(s->ctx); - blk_set_aio_context(d->conf.blk, s->ctx); - aio_context_release(s->ctx); + if (s->dataplane_started) { + assert(blk_get_aio_context(d->conf.blk) == s->ctx); } req->sreq = scsi_req_new(d, req->req.cmd.tag, virtio_scsi_get_lun(req->req.cmd.lun), @@ -767,6 +763,9 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, return; } blk_op_block_all(sd->conf.blk, s->blocker); + aio_context_acquire(s->ctx); + blk_set_aio_context(sd->conf.blk, s->ctx); + aio_context_release(s->ctx); } if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { @@ -904,6 +903,8 @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp) virtio_scsi_save, virtio_scsi_load, s); s->migration_state_notifier.notify = virtio_scsi_migration_state_changed; add_migration_state_change_notifier(&s->migration_state_notifier); + + error_setg(&s->blocker, "block device is in use by data plane"); } static void virtio_scsi_instance_init(Object *obj) @@ -929,6 +930,8 @@ static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp) { VirtIOSCSI *s = VIRTIO_SCSI(dev); + error_free(s->blocker); + unregister_savevm(dev, "virtio-scsi", s); remove_migration_state_change_notifier(&s->migration_state_notifier); diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index b27b1f4..1866991 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -1394,8 +1394,8 @@ static USBDevice *usb_net_init(USBBus *bus, const char *cmdline) if (!opts) { return NULL; } - qemu_opt_set(opts, "type", "nic"); - qemu_opt_set(opts, "model", "usb"); + qemu_opt_set(opts, "type", "nic", &error_abort); + qemu_opt_set(opts, "model", "usb", &error_abort); idx = net_client_init(opts, 0, &local_err); if (local_err) { diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index af2e1b9..65d9aa6 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -683,7 +683,7 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename) if (strstart(filename, "format=", &p2)) { int len = MIN(p1 - p2, sizeof(fmt)); pstrcpy(fmt, len, p2); - qemu_opt_set(opts, "format", fmt); + qemu_opt_set(opts, "format", fmt, &error_abort); } else if (*filename != ':') { error_report("unrecognized USB mass-storage option %s", filename); return NULL; @@ -694,8 +694,8 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename) error_report("block device specification needed"); return NULL; } - qemu_opt_set(opts, "file", filename); - qemu_opt_set(opts, "if", "none"); + qemu_opt_set(opts, "file", filename, &error_abort); + qemu_opt_set(opts, "if", "none", &error_abort); /* create host drive */ dinfo = drive_new(opts, 0); diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 776699b..828c2a7 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1767,9 +1767,18 @@ static void xhci_xfer_report(XHCITransfer *xfer) break; } - if (!reported && ((trb->control & TRB_TR_IOC) || - (shortpkt && (trb->control & TRB_TR_ISP)) || - (xfer->status != CC_SUCCESS && left == 0))) { + /* + * XHCI 1.1, 4.11.3.1 Transfer Event TRB -- "each Transfer TRB + * encountered with its IOC flag set to '1' shall generate a Transfer + * Event." + * + * Otherwise, longer transfers can have multiple data TRBs (for scatter + * gather). Short transfers and errors should be reported once per + * transfer only. + */ + if ((trb->control & TRB_TR_IOC) || + (!reported && ((shortpkt && (trb->control & TRB_TR_ISP)) || + (xfer->status != CC_SUCCESS && left == 0)))) { event.slotid = xfer->slotid; event.epid = xfer->epid; event.length = (trb->status & 0x1ffff) - chunk; diff --git a/hw/vfio/common.c b/hw/vfio/common.c index c5d1551..9db7d8d 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -475,12 +475,12 @@ static void vfio_listener_region_del(MemoryListener *listener, } } -const MemoryListener vfio_memory_listener = { +static const MemoryListener vfio_memory_listener = { .region_add = vfio_listener_region_add, .region_del = vfio_listener_region_del, }; -void vfio_listener_release(VFIOContainer *container) +static void vfio_listener_release(VFIOContainer *container) { memory_listener_unregister(&container->iommu_data.type1.listener); } @@ -493,7 +493,7 @@ int vfio_mmap_region(Object *obj, VFIORegion *region, int ret = 0; VFIODevice *vbasedev = region->vbasedev; - if (VFIO_ALLOW_MMAP && size && region->flags & + if (vbasedev->allow_mmap && size && region->flags & VFIO_REGION_INFO_FLAG_MMAP) { int prot = 0; @@ -932,8 +932,8 @@ static int vfio_container_do_ioctl(AddressSpace *as, int32_t groupid, if (group->container) { ret = ioctl(container->fd, req, param); if (ret < 0) { - error_report("vfio: failed to ioctl container: ret=%d, %s", - ret, strerror(errno)); + error_report("vfio: failed to ioctl %d to container: ret=%d, %s", + _IOC_NR(req) - VFIO_BASE, ret, strerror(errno)); } } diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 84e9d99..6b80539 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -153,13 +153,17 @@ typedef struct VFIOPCIDevice { VFIOVGA vga; /* 0xa0000, 0x3b0, 0x3c0 */ PCIHostDeviceAddress host; EventNotifier err_notifier; + EventNotifier req_notifier; uint32_t features; #define VFIO_FEATURE_ENABLE_VGA_BIT 0 #define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT) +#define VFIO_FEATURE_ENABLE_REQ_BIT 1 +#define VFIO_FEATURE_ENABLE_REQ (1 << VFIO_FEATURE_ENABLE_REQ_BIT) int32_t bootindex; uint8_t pm_cap; bool has_vga; bool pci_aer; + bool req_enabled; bool has_flr; bool has_pm_reset; bool rom_read_failed; @@ -3088,6 +3092,7 @@ static int vfio_populate_device(VFIOPCIDevice *vdev) vdev->has_vga = true; } + irq_info.index = VFIO_PCI_ERR_IRQ_INDEX; ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info); @@ -3223,6 +3228,97 @@ static void vfio_unregister_err_notifier(VFIOPCIDevice *vdev) event_notifier_cleanup(&vdev->err_notifier); } +static void vfio_req_notifier_handler(void *opaque) +{ + VFIOPCIDevice *vdev = opaque; + + if (!event_notifier_test_and_clear(&vdev->req_notifier)) { + return; + } + + qdev_unplug(&vdev->pdev.qdev, NULL); +} + +static void vfio_register_req_notifier(VFIOPCIDevice *vdev) +{ + struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info), + .index = VFIO_PCI_REQ_IRQ_INDEX }; + int argsz; + struct vfio_irq_set *irq_set; + int32_t *pfd; + + if (!(vdev->features & VFIO_FEATURE_ENABLE_REQ)) { + return; + } + + if (ioctl(vdev->vbasedev.fd, + VFIO_DEVICE_GET_IRQ_INFO, &irq_info) < 0 || irq_info.count < 1) { + return; + } + + if (event_notifier_init(&vdev->req_notifier, 0)) { + error_report("vfio: Unable to init event notifier for device request"); + return; + } + + argsz = sizeof(*irq_set) + sizeof(*pfd); + + irq_set = g_malloc0(argsz); + irq_set->argsz = argsz; + irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | + VFIO_IRQ_SET_ACTION_TRIGGER; + irq_set->index = VFIO_PCI_REQ_IRQ_INDEX; + irq_set->start = 0; + irq_set->count = 1; + pfd = (int32_t *)&irq_set->data; + + *pfd = event_notifier_get_fd(&vdev->req_notifier); + qemu_set_fd_handler(*pfd, vfio_req_notifier_handler, NULL, vdev); + + if (ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set)) { + error_report("vfio: Failed to set up device request notification"); + qemu_set_fd_handler(*pfd, NULL, NULL, vdev); + event_notifier_cleanup(&vdev->req_notifier); + } else { + vdev->req_enabled = true; + } + + g_free(irq_set); +} + +static void vfio_unregister_req_notifier(VFIOPCIDevice *vdev) +{ + int argsz; + struct vfio_irq_set *irq_set; + int32_t *pfd; + + if (!vdev->req_enabled) { + return; + } + + argsz = sizeof(*irq_set) + sizeof(*pfd); + + irq_set = g_malloc0(argsz); + irq_set->argsz = argsz; + irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | + VFIO_IRQ_SET_ACTION_TRIGGER; + irq_set->index = VFIO_PCI_REQ_IRQ_INDEX; + irq_set->start = 0; + irq_set->count = 1; + pfd = (int32_t *)&irq_set->data; + *pfd = -1; + + if (ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set)) { + error_report("vfio: Failed to de-assign device request fd: %m"); + } + g_free(irq_set); + qemu_set_fd_handler(event_notifier_get_fd(&vdev->req_notifier), + NULL, NULL, vdev); + event_notifier_cleanup(&vdev->req_notifier); + + vdev->req_enabled = false; +} + static int vfio_initfn(PCIDevice *pdev) { VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev); @@ -3370,6 +3466,7 @@ static int vfio_initfn(PCIDevice *pdev) } vfio_register_err_notifier(vdev); + vfio_register_req_notifier(vdev); return 0; @@ -3397,6 +3494,7 @@ static void vfio_exitfn(PCIDevice *pdev) { VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev); + vfio_unregister_req_notifier(vdev); vfio_unregister_err_notifier(vdev); pci_device_set_intx_routing_notifier(&vdev->pdev, NULL); vfio_disable_interrupts(vdev); @@ -3455,7 +3553,10 @@ static Property vfio_pci_dev_properties[] = { intx.mmap_timeout, 1100), DEFINE_PROP_BIT("x-vga", VFIOPCIDevice, features, VFIO_FEATURE_ENABLE_VGA_BIT, false), + DEFINE_PROP_BIT("x-req", VFIOPCIDevice, features, + VFIO_FEATURE_ENABLE_REQ_BIT, true), DEFINE_PROP_INT32("bootindex", VFIOPCIDevice, bootindex, -1), + DEFINE_PROP_BOOL("x-mmap", VFIOPCIDevice, vbasedev.allow_mmap, true), /* * TODO - support passed fds... is this necessary? * DEFINE_PROP_STRING("vfiofd", VFIOPCIDevice, vfiofd_name), diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c index c307f9b..54440c9 100644 --- a/hw/watchdog/watchdog.c +++ b/hw/watchdog/watchdog.c @@ -68,7 +68,7 @@ int select_watchdog(const char *p) /* add the device */ opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0, &error_abort); - qemu_opt_set(opts, "driver", p); + qemu_opt_set(opts, "driver", p, &error_abort); return 0; } } |