summaryrefslogtreecommitdiff
path: root/hw/s390x
diff options
context:
space:
mode:
authorJason J. Herne <jjherne@us.ibm.com>2014-01-20 14:51:50 -0500
committerChristian Borntraeger <borntraeger@de.ibm.com>2014-01-21 16:48:39 +0100
commit492044581c26ba9ace3af5c6abb2a911a23ad188 (patch)
tree43b4efcfd659477cdb2710e5b4521107c4223f82 /hw/s390x
parent8cc3aecf8461bd38028ddb4a56a17d0a1583de36 (diff)
downloadqemu-492044581c26ba9ace3af5c6abb2a911a23ad188.tar.gz
s390-sclp: SCLP Event integration
Add an sclp event for "cpu was hot plugged". This allows Qemu to deliver an SCLP interrupt to the guest stating that the requested cpu hotplug was completed. Signed-off-by: Jason J. Herne <jjherne@us.ibm.com> Reviewed-by: Andreas Färber <afaerber@suse.de> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'hw/s390x')
-rw-r--r--hw/s390x/Makefile.objs1
-rw-r--r--hw/s390x/event-facility.c6
-rw-r--r--hw/s390x/sclpcpu.c112
3 files changed, 119 insertions, 0 deletions
diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs
index 77e1218447..1ba6c3ab70 100644
--- a/hw/s390x/Makefile.objs
+++ b/hw/s390x/Makefile.objs
@@ -3,6 +3,7 @@ obj-y += s390-virtio-hcall.o
obj-y += sclp.o
obj-y += event-facility.o
obj-y += sclpquiesce.o
+obj-y += sclpcpu.o
obj-y += ipl.o
obj-y += css.o
obj-y += s390-virtio-ccw.o
diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c
index 25951a020a..a73c0b924a 100644
--- a/hw/s390x/event-facility.c
+++ b/hw/s390x/event-facility.c
@@ -32,6 +32,8 @@ struct SCLPEventFacility {
unsigned int receive_mask;
};
+SCLPEvent cpu_hotplug;
+
/* return true if any child has event pending set */
static bool event_pending(SCLPEventFacility *ef)
{
@@ -335,6 +337,10 @@ static int init_event_facility(S390SCLPDevice *sdev)
}
qdev_init_nofail(quiesce);
+ object_initialize(&cpu_hotplug, sizeof(cpu_hotplug), TYPE_SCLP_CPU_HOTPLUG);
+ qdev_set_parent_bus(DEVICE(&cpu_hotplug), BUS(&event_facility->sbus));
+ object_property_set_bool(OBJECT(&cpu_hotplug), true, "realized", NULL);
+
return 0;
}
diff --git a/hw/s390x/sclpcpu.c b/hw/s390x/sclpcpu.c
new file mode 100644
index 0000000000..b9c238a0da
--- /dev/null
+++ b/hw/s390x/sclpcpu.c
@@ -0,0 +1,112 @@
+/*
+ * SCLP event type
+ * Signal CPU - Trigger SCLP interrupt for system CPU configure or
+ * de-configure
+ *
+ * Copyright IBM, Corp. 2013
+ *
+ * Authors:
+ * Thang Pham <thang.pham@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
+ * option) any later version. See the COPYING file in the top-level directory.
+ *
+ */
+#include "sysemu/sysemu.h"
+#include "hw/s390x/sclp.h"
+#include "hw/s390x/event-facility.h"
+#include "cpu.h"
+#include "sysemu/cpus.h"
+#include "sysemu/kvm.h"
+
+typedef struct ConfigMgtData {
+ EventBufferHeader ebh;
+ uint8_t reserved;
+ uint8_t event_qualifier;
+} QEMU_PACKED ConfigMgtData;
+
+static qemu_irq irq_cpu_hotplug; /* Only used in this file */
+
+#define EVENT_QUAL_CPU_CHANGE 1
+
+void raise_irq_cpu_hotplug(void)
+{
+ qemu_irq_raise(irq_cpu_hotplug);
+}
+
+static unsigned int send_mask(void)
+{
+ return SCLP_EVENT_MASK_CONFIG_MGT_DATA;
+}
+
+static unsigned int receive_mask(void)
+{
+ return 0;
+}
+
+static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
+ int *slen)
+{
+ ConfigMgtData *cdata = (ConfigMgtData *) evt_buf_hdr;
+ if (*slen < sizeof(ConfigMgtData)) {
+ return 0;
+ }
+
+ /* Event is no longer pending */
+ if (!event->event_pending) {
+ return 0;
+ }
+ event->event_pending = false;
+
+ /* Event header data */
+ cdata->ebh.length = cpu_to_be16(sizeof(ConfigMgtData));
+ cdata->ebh.type = SCLP_EVENT_CONFIG_MGT_DATA;
+ cdata->ebh.flags |= SCLP_EVENT_BUFFER_ACCEPTED;
+
+ /* Trigger a rescan of CPUs by setting event qualifier */
+ cdata->event_qualifier = EVENT_QUAL_CPU_CHANGE;
+ *slen -= sizeof(ConfigMgtData);
+
+ return 1;
+}
+
+static void trigger_signal(void *opaque, int n, int level)
+{
+ SCLPEvent *event = opaque;
+ event->event_pending = true;
+
+ /* Trigger SCLP read operation */
+ sclp_service_interrupt(0);
+}
+
+static int irq_cpu_hotplug_init(SCLPEvent *event)
+{
+ irq_cpu_hotplug = *qemu_allocate_irqs(trigger_signal, event, 1);
+ return 0;
+}
+
+static void cpu_class_init(ObjectClass *oc, void *data)
+{
+ SCLPEventClass *k = SCLP_EVENT_CLASS(oc);
+
+ k->init = irq_cpu_hotplug_init;
+ k->get_send_mask = send_mask;
+ k->get_receive_mask = receive_mask;
+ k->read_event_data = read_event_data;
+ k->write_event_data = NULL;
+}
+
+static const TypeInfo sclp_cpu_info = {
+ .name = "sclp-cpu-hotplug",
+ .parent = TYPE_SCLP_EVENT,
+ .instance_size = sizeof(SCLPEvent),
+ .class_init = cpu_class_init,
+ .class_size = sizeof(SCLPEventClass),
+};
+
+static void sclp_cpu_register_types(void)
+{
+ type_register_static(&sclp_cpu_info);
+}
+
+type_init(sclp_cpu_register_types)