From 7fa41e536b05865baa9d79c6fd72785f6841576a Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 23 Aug 2010 18:58:34 +0200 Subject: [PATCH 1/6] [S390] Add hotplug support I just submitted a few patches that enable the s390 virtio bus to receive a hotplug add event. This patch implements the qemu side of it, so that new hotplug events can be submitted to the guest. Signed-off-by: Alexander Graf --- v1 -> v2: - make s390 virtio hoplug code emulate-capable --- hw/s390-virtio-bus.c | 24 +++++++++++++++++++----- hw/s390-virtio-bus.h | 5 +++++ 2 files changed, 24 insertions(+), 5 deletions(-) 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; From 963d83c85420b39eb4ab6ae1ebdcd7f818221402 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 23 Aug 2010 23:40:28 +0200 Subject: [PATCH 2/6] Compile device-hotplug on all targets All guest targets could potentially implement hotplugging. With the next patches in this set I will also reflect this in the monitor interface. So let's always compile it in. It shouldn't hurt. Signed-off-by: Alexander Graf --- Makefile.target | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile.target b/Makefile.target index 3261383fd3..d70d911f34 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 From dd97aa8adc9a15fa509d5a0196002d309f6d21fd Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 23 Aug 2010 23:43:10 +0200 Subject: [PATCH 3/6] Add generic drive hotplugging The monitor command for hotplugging is in i386 specific code. This is just plain wrong, as S390 just learned how to do hotplugging too and needs to get drives for that. So let's add a generic copy to generic code that handles drive_add in a way that doesn't have pci dependencies. All pci specific code can then be handled in a pci specific function. Signed-off-by: Alexander Graf --- v1 -> v2: - align generic drive_add to pci specific one - rework to split between generic and pci code v2 -> v3: - remove comment --- hw/device-hotplug.c | 47 +++++++++++++++++++++++++++++++++++++++++++++ hw/pci-hotplug.c | 24 ++++------------------- sysemu.h | 6 +++++- 3 files changed, 56 insertions(+), 21 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/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, From 971ca4d906958fc09c8c69edde6f3caa4a843766 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 13 Jul 2011 14:08:32 +0200 Subject: [PATCH 4/6] Expose drive_add on all architectures All architectures can now use drive_add on the monitor. This of course does not mean that there is hotplug support for the specific platform, so in order to actually make use of the new drives you still need to have a hotplug capable device. Signed-off-by: Alexander Graf --- hmp-commands.hx | 2 -- 1 file changed, 2 deletions(-) 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 From 7d77793d6bf5ecb784040aef946ff7b4d52f2d2a Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 18 Nov 2011 16:45:54 +0100 Subject: [PATCH 5/6] s390x: add TR function for EXECUTE Newer gcc versions (or glibc?) also generate code that tries to EXECUTE the TR opcode. Implement it so that we don't break valid guests. Reported-by: Andreas Faerber Signed-off-by: Alexander Graf --- target-s390x/op_helper.c | 3 +++ 1 file changed, 3 insertions(+) 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; From 93116ac0cf9734e7b28886aedf03848b37d6785e Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Sun, 20 Nov 2011 23:12:03 +0000 Subject: [PATCH 6/6] s390: fix cpu hotplug / cpu activity on interrupts The add_del/running_cpu code and env->halted are tracking stopped cpus. Sleeping cpus (idle and enabled for interrupts) are waiting inside the kernel. No interrupt besides the restart can move a cpu from stopped to operational. This is already handled over there. So lets just remove the bogus wakup from the common interrupt delivery, otherwise any interrupt will wake up a cpu, even if this cpu is stopped (Thus leading to strange hangs on sigp restart) This fixes echo 0 > /sys/devices/system/cpu/cpu0/online echo 1 > /sys/devices/system/cpu/cpu0/online in the guest Signed-off-by: Christian Borntraeger Signed-off-by: Alexander Graf --- target-s390x/kvm.c | 3 --- 1 file changed, 3 deletions(-) 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;