summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Makefile.target5
-rw-r--r--hmp-commands.hx2
-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
-rw-r--r--sysemu.h6
-rw-r--r--target-s390x/kvm.c3
-rw-r--r--target-s390x/op_helper.c3
9 files changed, 87 insertions, 32 deletions
diff --git a/Makefile.target b/Makefile.target
index 18be6243f7..06d79b8028 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -220,12 +220,15 @@ ifeq ($(CONFIG_KVM), y)
 endif
 obj-$(CONFIG_IVSHMEM) += ivshmem.o
 
+# Generic hotplugging
+obj-y += device-hotplug.o
+
 # Hardware support
 obj-i386-y += vga.o
 obj-i386-y += mc146818rtc.o pc.o
 obj-i386-y += cirrus_vga.o sga.o apic.o ioapic.o piix_pci.o
 obj-i386-y += vmport.o
-obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
+obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
 obj-i386-y += pc_piix.o
 obj-i386-$(CONFIG_KVM) += kvmclock.o
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 14838b7fae..a586498495 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -846,7 +846,6 @@ STEXI
 Snapshot device, using snapshot file as target if provided
 ETEXI
 
-#if defined(TARGET_I386)
     {
         .name       = "drive_add",
         .args_type  = "pci_addr:s,opts:s",
@@ -859,7 +858,6 @@ ETEXI
         .help       = "add drive to PCI storage controller",
         .mhandler.cmd = drive_hot_add,
     },
-#endif
 
 STEXI
 @item drive_add
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;
diff --git a/sysemu.h b/sysemu.h
index 3806901fba..ddef2bb0c1 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -143,9 +143,13 @@ extern unsigned int nb_prom_envs;
 
 /* pci-hotplug */
 void pci_device_hot_add(Monitor *mon, const QDict *qdict);
-void drive_hot_add(Monitor *mon, const QDict *qdict);
+int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
+                      DriveInfo *dinfo, int type);
 void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict);
 
+/* generic hotplug */
+void drive_hot_add(Monitor *mon, const QDict *qdict);
+
 /* pcie aer error injection */
 void pcie_aer_inject_error_print(Monitor *mon, const QObject *data);
 int do_pcie_aer_inject_error(Monitor *mon,
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 40b0ab1922..b1404bfd2f 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -185,9 +185,6 @@ void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
         return;
     }
 
-    s390_add_running_cpu(env);
-    qemu_cpu_kick(env);
-
     kvmint.type = type;
     kvmint.parm = parm;
     kvmint.parm64 = parm64;
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index b8a1a8a54f..cf26b29ee9 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -636,6 +636,9 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
         case 0x700:
             cc = helper_xc(l, get_address(0, b1, d1), get_address(0, b2, d2));
             break;
+        case 0xc00:
+            helper_tr(l, get_address(0, b1, d1), get_address(0, b2, d2));
+            break;
         default:
             goto abort;
             break;