aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/core/Makefile.objs2
-rw-r--r--hw/i386/pc.c11
-rw-r--r--hw/misc/Makefile.objs4
-rw-r--r--hw/pci-bridge/Makefile.objs5
-rw-r--r--hw/pci/pci-hotplug-old.c2
-rw-r--r--hw/scsi/scsi-bus.c5
-rw-r--r--hw/scsi/virtio-scsi-dataplane.c4
-rw-r--r--hw/scsi/virtio-scsi.c19
-rw-r--r--hw/usb/dev-network.c4
-rw-r--r--hw/usb/dev-storage.c6
-rw-r--r--hw/usb/hcd-xhci.c15
-rw-r--r--hw/vfio/common.c10
-rw-r--r--hw/vfio/pci.c101
-rw-r--r--hw/watchdog/watchdog.c2
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;
}
}