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>
This commit is contained in:
Jason J. Herne 2014-01-20 14:51:50 -05:00 committed by Christian Borntraeger
parent 8cc3aecf84
commit 492044581c
5 changed files with 125 additions and 0 deletions

112
hw/s390x/sclpcpu.c Normal file
View file

@ -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)