Commit 03cf077a authored by Cornelia Huck's avatar Cornelia Huck
Browse files

s390x: add I/O adapter registration



Register an I/O adapter interrupt source for when virtio-ccw devices start
using adapter interrupts.

Reviewed-by: default avatarThomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
parent 7b35d0c4
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -44,10 +44,26 @@ void s390_flic_init(void)
    }
}

static int qemu_s390_register_io_adapter(S390FLICState *fs, uint32_t id,
                                         uint8_t isc, bool swap,
                                         bool is_maskable)
{
    /* nothing to do */
    return 0;
}

static void qemu_s390_flic_class_init(ObjectClass *oc, void *data)
{
    S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc);

    fsc->register_io_adapter = qemu_s390_register_io_adapter;
}

static const TypeInfo qemu_s390_flic_info = {
    .name          = TYPE_QEMU_S390_FLIC,
    .parent        = TYPE_S390_FLIC_COMMON,
    .instance_size = sizeof(QEMUS390FLICState),
    .class_init    = qemu_s390_flic_class_init,
};

static const TypeInfo s390_flic_common_info = {
+29 −0
Original line number Diff line number Diff line
@@ -151,6 +151,33 @@ static int __get_all_irqs(KVMS390FLICState *flic,
    return r;
}

static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id,
                                        uint8_t isc, bool swap,
                                        bool is_maskable)
{
    struct kvm_s390_io_adapter adapter = {
        .id = id,
        .isc = isc,
        .maskable = is_maskable,
        .swap = swap,
    };
    KVMS390FLICState *flic = KVM_S390_FLIC(fs);
    int r, ret;
    struct kvm_device_attr attr = {
        .group = KVM_DEV_FLIC_ADAPTER_REGISTER,
        .addr = (uint64_t)&adapter,
    };

    if (!kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING)) {
        return -ENOSYS;
    }

    r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);

    ret = r ? -errno : 0;
    return ret;
}

/**
 * kvm_flic_save - Save pending floating interrupts
 * @f: QEMUFile containing migration state
@@ -304,10 +331,12 @@ static void kvm_s390_flic_reset(DeviceState *dev)
static void kvm_s390_flic_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);
    S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc);

    dc->realize = kvm_s390_flic_realize;
    dc->unrealize = kvm_s390_flic_unrealize;
    dc->reset = kvm_s390_flic_reset;
    fsc->register_io_adapter = kvm_s390_register_io_adapter;
}

static const TypeInfo kvm_s390_flic_info = {
+50 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include "ioinst.h"
#include "css.h"
#include "trace.h"
#include "hw/s390x/s390_flic.h"

typedef struct CrwContainer {
    CRW crw;
@@ -39,6 +40,13 @@ typedef struct CssImage {
    ChpInfo chpids[MAX_CHPID + 1];
} CssImage;

typedef struct IoAdapter {
    uint32_t id;
    uint8_t type;
    uint8_t isc;
    QTAILQ_ENTRY(IoAdapter) sibling;
} IoAdapter;

typedef struct ChannelSubSys {
    QTAILQ_HEAD(, CrwContainer) pending_crws;
    bool do_crw_mchk;
@@ -49,6 +57,7 @@ typedef struct ChannelSubSys {
    uint64_t chnmon_area;
    CssImage *css[MAX_CSSID + 1];
    uint8_t default_cssid;
    QTAILQ_HEAD(, IoAdapter) io_adapters;
} ChannelSubSys;

static ChannelSubSys *channel_subsys;
@@ -69,6 +78,46 @@ int css_create_css_image(uint8_t cssid, bool default_image)
    return 0;
}

int css_register_io_adapter(uint8_t type, uint8_t isc, bool swap,
                            bool maskable, uint32_t *id)
{
    IoAdapter *adapter;
    bool found = false;
    int ret;
    S390FLICState *fs = s390_get_flic();
    S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);

    *id = 0;
    QTAILQ_FOREACH(adapter, &channel_subsys->io_adapters, sibling) {
        if ((adapter->type == type) && (adapter->isc == isc)) {
            *id = adapter->id;
            found = true;
            ret = 0;
            break;
        }
        if (adapter->id >= *id) {
            *id = adapter->id + 1;
        }
    }
    if (found) {
        goto out;
    }
    adapter = g_new0(IoAdapter, 1);
    ret = fsc->register_io_adapter(fs, *id, isc, swap, maskable);
    if (ret == 0) {
        adapter->id = *id;
        adapter->isc = isc;
        adapter->type = type;
        QTAILQ_INSERT_TAIL(&channel_subsys->io_adapters, adapter, sibling);
    } else {
        g_free(adapter);
        fprintf(stderr, "Unexpected error %d when registering adapter %d\n",
                ret, *id);
    }
out:
    return ret;
}

uint16_t css_build_subchannel_id(SubchDev *sch)
{
    if (channel_subsys->max_cssid > 0) {
@@ -1235,6 +1284,7 @@ static void css_init(void)
    channel_subsys->do_crw_mchk = true;
    channel_subsys->crws_lost = false;
    channel_subsys->chnmon_active = false;
    QTAILQ_INIT(&channel_subsys->io_adapters);
}
machine_init(css_init);

+4 −0
Original line number Diff line number Diff line
@@ -98,4 +98,8 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid,
                           int hotplugged, int add);
void css_generate_chp_crws(uint8_t cssid, uint8_t chpid);
void css_adapter_interrupt(uint8_t isc);

#define CSS_IO_ADAPTER_VIRTIO 1
int css_register_io_adapter(uint8_t type, uint8_t isc, bool swap,
                            bool maskable, uint32_t *id);
#endif
+4 −0
Original line number Diff line number Diff line
@@ -522,6 +522,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
                dev->thinint_isc = thinint->isc;
                dev->ind_bit = thinint->ind_bit;
                cpu_physical_memory_unmap(thinint, hw_len, 0, hw_len);
                ret = css_register_io_adapter(CSS_IO_ADAPTER_VIRTIO,
                                              dev->thinint_isc, true, false,
                                              &dev->adapter_id);
                assert(ret == 0);
                sch->thinint_active = ((dev->indicators != 0) &&
                                       (dev->summary_indicator != 0));
                sch->curr_status.scsw.count = ccw.count - len;
Loading