summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/device-hotplug.c47
-rw-r--r--hw/pci-hotplug.c24
-rw-r--r--hw/s390-virtio-bus.c24
-rw-r--r--hw/s390-virtio-bus.h5
4 files changed, 75 insertions, 25 deletions
diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index 8b2ed7a492..2bdc615b49 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -26,6 +26,9 @@
#include "boards.h"
#include "net.h"
#include "blockdev.h"
+#include "qemu-config.h"
+#include "sysemu.h"
+#include "monitor.h"
DriveInfo *add_init_drive(const char *optstr)
{
@@ -44,3 +47,47 @@ DriveInfo *add_init_drive(const char *optstr)
return dinfo;
}
+
+#if !defined(TARGET_I386)
+int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
+ DriveInfo *dinfo, int type)
+{
+ /* On non-x86 we don't do PCI hotplug */
+ monitor_printf(mon, "Can't hot-add drive to type %d\n", type);
+ return -1;
+}
+#endif
+
+void drive_hot_add(Monitor *mon, const QDict *qdict)
+{
+ int type;
+ DriveInfo *dinfo = NULL;
+ const char *opts = qdict_get_str(qdict, "opts");
+
+ dinfo = add_init_drive(opts);
+ if (!dinfo) {
+ goto err;
+ }
+ if (dinfo->devaddr) {
+ monitor_printf(mon, "Parameter addr not supported\n");
+ goto err;
+ }
+ type = dinfo->type;
+
+ switch (type) {
+ case IF_NONE:
+ monitor_printf(mon, "OK\n");
+ break;
+ default:
+ if (pci_drive_hot_add(mon, qdict, dinfo, type)) {
+ goto err;
+ }
+ }
+ return;
+
+err:
+ if (dinfo) {
+ drive_put_ref(dinfo);
+ }
+ return;
+}
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 12f61fea6e..5c6307fa5d 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -104,24 +104,13 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
return 0;
}
-void drive_hot_add(Monitor *mon, const QDict *qdict)
+int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
+ DriveInfo *dinfo, int type)
{
int dom, pci_bus;
unsigned slot;
- int type;
PCIDevice *dev;
- DriveInfo *dinfo = NULL;
const char *pci_addr = qdict_get_str(qdict, "pci_addr");
- const char *opts = qdict_get_str(qdict, "opts");
-
- dinfo = add_init_drive(opts);
- if (!dinfo)
- goto err;
- if (dinfo->devaddr) {
- monitor_printf(mon, "Parameter addr not supported\n");
- goto err;
- }
- type = dinfo->type;
switch (type) {
case IF_SCSI:
@@ -138,19 +127,14 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
goto err;
}
break;
- case IF_NONE:
- monitor_printf(mon, "OK\n");
- break;
default:
monitor_printf(mon, "Can't hot-add drive to type %d\n", type);
goto err;
}
- return;
+ return 0;
err:
- if (dinfo)
- drive_put_ref(dinfo);
- return;
+ return -1;
}
static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index c4b9a99e6e..2efea9f184 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -82,12 +82,24 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
bus->dev_offs = bus->dev_page;
bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE;
+ /* Enable hotplugging */
+ _bus->allow_hotplug = 1;
+
/* Allocate RAM for VirtIO device pages (descriptors, queues, rings) */
*ram_size += S390_DEVICE_PAGES * TARGET_PAGE_SIZE;
return bus;
}
+static void s390_virtio_irq(CPUState *env, int config_change, uint64_t token)
+{
+ if (kvm_enabled()) {
+ kvm_s390_virtio_irq(env, config_change, token);
+ } else {
+ cpu_inject_ext(env, VIRTIO_EXT_CODE, config_change, token);
+ }
+}
+
static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
{
VirtIOS390Bus *bus;
@@ -109,6 +121,11 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
dev->host_features = vdev->get_features(vdev, dev->host_features);
s390_virtio_device_sync(dev);
+ if (dev->qdev.hotplugged) {
+ CPUState *env = s390_cpu_addr2state(0);
+ s390_virtio_irq(env, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
+ }
+
return 0;
}
@@ -310,11 +327,7 @@ static void virtio_s390_notify(void *opaque, uint16_t vector)
uint64_t token = s390_virtio_device_vq_token(dev, vector);
CPUState *env = s390_cpu_addr2state(0);
- if (kvm_enabled()) {
- kvm_s390_virtio_irq(env, 0, token);
- } else {
- cpu_inject_ext(env, VIRTIO_EXT_CODE, 0, token);
- }
+ s390_virtio_irq(env, 0, token);
}
static unsigned virtio_s390_get_features(void *opaque)
@@ -382,6 +395,7 @@ static void s390_virtio_bus_register_withprop(VirtIOS390DeviceInfo *info)
{
info->qdev.init = s390_virtio_busdev_init;
info->qdev.bus_info = &s390_virtio_bus_info;
+ info->qdev.unplug = qdev_simple_unplug_cb;
assert(info->qdev.size >= sizeof(VirtIOS390Device));
qdev_register(&info->qdev);
diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h
index f1bece738b..d02a90709d 100644
--- a/hw/s390-virtio-bus.h
+++ b/hw/s390-virtio-bus.h
@@ -35,6 +35,11 @@
#define VIRTIO_RING_LEN (TARGET_PAGE_SIZE * 3)
#define S390_DEVICE_PAGES 512
+#define VIRTIO_PARAM_MASK 0xff
+#define VIRTIO_PARAM_VRING_INTERRUPT 0x0
+#define VIRTIO_PARAM_CONFIG_CHANGED 0x1
+#define VIRTIO_PARAM_DEV_ADD 0x2
+
typedef struct VirtIOS390Device {
DeviceState qdev;
ram_addr_t dev_offs;