Commit 2b2449f7 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/borntraeger/tags/kvm-s390-20140131' into staging



This patch set contains the sclp defines and events for cpu hotplug,
the initial sclp defines (without code yet) for standby memory (some
sort of memory hotplug) as well as a cleanup of the kvm register
synchronization.

# gpg: Signature made Fri 31 Jan 2014 08:54:29 GMT using RSA key ID B5A61C7C
# gpg: Can't check signature: public key not found

* remotes/borntraeger/tags/kvm-s390-20140131:
  s390x/kvm: cleanup partial register handling
  sclp-s390: Define new SCLP codes and structures
  s390-sclp: SCLP Event integration
  s390-sclp: SCLP CPU Info
  s390-sclp: Define New SCLP Codes

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 9396b05a 44c68de0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+6 −0
Original line number Diff line number Diff line
@@ -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;
}

+52 −1
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include "cpu.h"
#include "sysemu/kvm.h"
#include "exec/memory.h"
#include "sysemu/sysemu.h"

#include "hw/s390x/sclp.h"

@@ -31,7 +32,26 @@ static inline S390SCLPDevice *get_event_facility(void)
static void read_SCP_info(SCCB *sccb)
{
    ReadInfo *read_info = (ReadInfo *) sccb;
    CPUState *cpu;
    int shift = 0;
    int cpu_count = 0;
    int i = 0;

    CPU_FOREACH(cpu) {
        cpu_count++;
    }

    /* CPU information */
    read_info->entries_cpu = cpu_to_be16(cpu_count);
    read_info->offset_cpu = cpu_to_be16(offsetof(ReadInfo, entries));
    read_info->highest_cpu = cpu_to_be16(max_cpus);

    for (i = 0; i < cpu_count; i++) {
        read_info->entries[i].address = i;
        read_info->entries[i].type = 0;
    }

    read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO);

    while ((ram_size >> (20 + shift)) > 65535) {
        shift++;
@@ -41,15 +61,46 @@ static void read_SCP_info(SCCB *sccb)
    sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
}

/* Provide information about the CPU */
static void sclp_read_cpu_info(SCCB *sccb)
{
    ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb;
    CPUState *cpu;
    int cpu_count = 0;
    int i = 0;

    CPU_FOREACH(cpu) {
        cpu_count++;
    }

    cpu_info->nr_configured = cpu_to_be16(cpu_count);
    cpu_info->offset_configured = cpu_to_be16(offsetof(ReadCpuInfo, entries));
    cpu_info->nr_standby = cpu_to_be16(0);

    /* The standby offset is 16-byte for each CPU */
    cpu_info->offset_standby = cpu_to_be16(cpu_info->offset_configured
        + cpu_info->nr_configured*sizeof(CPUEntry));

    for (i = 0; i < cpu_count; i++) {
        cpu_info->entries[i].address = i;
        cpu_info->entries[i].type = 0;
    }

    sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
}

static void sclp_execute(SCCB *sccb, uint64_t code)
{
    S390SCLPDevice *sdev = get_event_facility();

    switch (code) {
    switch (code & SCLP_CMD_CODE_MASK) {
    case SCLP_CMDW_READ_SCP_INFO:
    case SCLP_CMDW_READ_SCP_INFO_FORCED:
        read_SCP_info(sccb);
        break;
    case SCLP_CMDW_READ_CPU_INFO:
        sclp_read_cpu_info(sccb);
        break;
    default:
        sdev->sclp_command_handler(sdev->ef, sccb, code);
        break;

hw/s390x/sclpcpu.c

0 → 100644
+112 −0
Original line number Diff line number Diff line
/*
 * 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)
+5 −0
Original line number Diff line number Diff line
@@ -17,10 +17,12 @@

#include <hw/qdev.h>
#include "qemu/thread.h"
#include "hw/s390x/sclp.h"

/* SCLP event types */
#define SCLP_EVENT_OPRTNS_COMMAND               0x01
#define SCLP_EVENT_MESSAGE                      0x02
#define SCLP_EVENT_CONFIG_MGT_DATA              0x04
#define SCLP_EVENT_PMSGCMD                      0x09
#define SCLP_EVENT_ASCII_CONSOLE_DATA           0x1a
#define SCLP_EVENT_SIGNAL_QUIESCE               0x1d
@@ -28,6 +30,7 @@
/* SCLP event masks */
#define SCLP_EVENT_MASK_SIGNAL_QUIESCE          0x00000008
#define SCLP_EVENT_MASK_MSG_ASCII               0x00000040
#define SCLP_EVENT_MASK_CONFIG_MGT_DATA         0x10000000
#define SCLP_EVENT_MASK_OP_CMD                  0x80000000
#define SCLP_EVENT_MASK_MSG                     0x40000000
#define SCLP_EVENT_MASK_PMSGCMD                 0x00800000
@@ -43,6 +46,8 @@
#define SCLP_EVENT_GET_CLASS(obj) \
     OBJECT_GET_CLASS(SCLPEventClass, (obj), TYPE_SCLP_EVENT)

#define TYPE_SCLP_CPU_HOTPLUG "sclp-cpu-hotplug"

typedef struct WriteEventMask {
    SCCBHeader h;
    uint16_t _reserved;
Loading