From 9eccb8622c4dd9702d3bd3a7f1a60d744fe71a0b Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Wed, 27 Jan 2016 13:03:44 +0100 Subject: [PATCH] s390x/kvm: add interface for clearing IO irqs According to the platform specification, under certain conditions, pending IO interruptions have to be cleared. Let's add an interface for that. Signed-off-by: Halil Pasic Reviewed-by: Cornelia Huck Signed-off-by: Cornelia Huck --- hw/intc/s390_flic.c | 8 ++++++++ hw/intc/s390_flic_kvm.c | 26 ++++++++++++++++++++++++++ include/hw/s390x/s390_flic.h | 2 ++ 3 files changed, 36 insertions(+) diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c index bc75fa7d95..6ab29efc65 100644 --- a/hw/intc/s390_flic.c +++ b/hw/intc/s390_flic.c @@ -67,6 +67,13 @@ static void qemu_s390_release_adapter_routes(S390FLICState *fs, { } +static int qemu_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id, + uint16_t subchannel_nr) +{ + /* Fixme TCG */ + return -ENOSYS; +} + static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) { S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc); @@ -75,6 +82,7 @@ static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) fsc->io_adapter_map = qemu_s390_io_adapter_map; fsc->add_adapter_routes = qemu_s390_add_adapter_routes; fsc->release_adapter_routes = qemu_s390_release_adapter_routes; + fsc->clear_io_irq = qemu_s390_clear_io_flic; } static const TypeInfo qemu_s390_flic_info = { diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c index eed6325cde..680857f0c7 100644 --- a/hw/intc/s390_flic_kvm.c +++ b/hw/intc/s390_flic_kvm.c @@ -30,6 +30,7 @@ typedef struct KVMS390FLICState { S390FLICState parent_obj; uint32_t fd; + bool clear_io_supported; } KVMS390FLICState; DeviceState *s390_flic_kvm_create(void) @@ -130,6 +131,24 @@ int kvm_s390_inject_flic(struct kvm_s390_irq *irq) return flic_enqueue_irqs(irq, sizeof(*irq), flic); } +static int kvm_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id, + uint16_t subchannel_nr) +{ + KVMS390FLICState *flic = KVM_S390_FLIC(fs); + int rc; + uint32_t sid = subchannel_id << 16 | subchannel_nr; + struct kvm_device_attr attr = { + .group = KVM_DEV_FLIC_CLEAR_IO_IRQ, + .addr = (uint64_t) &sid, + .attr = sizeof(sid), + }; + if (unlikely(!flic->clear_io_supported)) { + return -ENOSYS; + } + rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); + return rc ? -errno : 0; +} + /** * __get_all_irqs - store all pending irqs in buffer * @flic: pointer to flic device state @@ -358,6 +377,7 @@ static void kvm_s390_flic_realize(DeviceState *dev, Error **errp) { KVMS390FLICState *flic_state = KVM_S390_FLIC(dev); struct kvm_create_device cd = {0}; + struct kvm_device_attr test_attr = {0}; int ret; flic_state->fd = -1; @@ -374,6 +394,11 @@ static void kvm_s390_flic_realize(DeviceState *dev, Error **errp) } flic_state->fd = cd.fd; + /* Check clear_io_irq support */ + test_attr.group = KVM_DEV_FLIC_CLEAR_IO_IRQ; + flic_state->clear_io_supported = !ioctl(flic_state->fd, + KVM_HAS_DEVICE_ATTR, test_attr); + /* Register savevm handler for floating interrupts */ register_savevm(NULL, "s390-flic", 0, 1, kvm_flic_save, kvm_flic_load, (void *) flic_state); @@ -420,6 +445,7 @@ static void kvm_s390_flic_class_init(ObjectClass *oc, void *data) fsc->io_adapter_map = kvm_s390_io_adapter_map; fsc->add_adapter_routes = kvm_s390_add_adapter_routes; fsc->release_adapter_routes = kvm_s390_release_adapter_routes; + fsc->clear_io_irq = kvm_s390_clear_io_flic; } static const TypeInfo kvm_s390_flic_info = { diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h index 200e7e93fa..1dac2ee48d 100644 --- a/include/hw/s390x/s390_flic.h +++ b/include/hw/s390x/s390_flic.h @@ -49,6 +49,8 @@ typedef struct S390FLICStateClass { bool do_map); int (*add_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes); void (*release_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes); + int (*clear_io_irq)(S390FLICState *fs, uint16_t subchannel_id, + uint16_t subchannel_nr); } S390FLICStateClass; #define TYPE_KVM_S390_FLIC "s390-flic-kvm"