[Qemu-devel] [PATCH 2/2] s390x/kvm: implement floating-interrupt controller device
This patch implements a floating-interrupt controller device (flic) which interacts with the s390 flic kvm_device. It provides functionality to: * clear all pending floating interrupts in the kernel at device reset * inject/retrieve interrupts into the kernel (used for migration) Signed-off-by: Jens Freimann Reviewed-by: Thomas Huth --- default-configs/s390x-softmmu.mak | 1 + hw/intc/Makefile.objs | 1 + hw/intc/s390_flic.c | 164 ++ hw/s390x/s390-virtio-ccw.c| 8 +- hw/s390x/s390-virtio.c| 2 + include/hw/s390x/s390_flic.h | 31 +++ 6 files changed, 206 insertions(+), 1 deletion(-) diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak index 81fbc68..d843dc0 100644 --- a/default-configs/s390x-softmmu.mak +++ b/default-configs/s390x-softmmu.mak @@ -1,2 +1,3 @@ CONFIG_VIRTIO=y CONFIG_SCLPCONSOLE=y +CONFIG_S390_FLIC=$(CONFIG_KVM) diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs index 2851eed..b2305aa 100644 --- a/hw/intc/Makefile.objs +++ b/hw/intc/Makefile.objs @@ -23,3 +23,4 @@ obj-$(CONFIG_OMAP) += omap_intc.o obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o obj-$(CONFIG_SH4) += sh_intc.o obj-$(CONFIG_XICS) += xics.o +obj-$(CONFIG_S390_FLIC) += s390_flic.o diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c new file mode 100644 index 000..9dfaafa --- /dev/null +++ b/hw/intc/s390_flic.c @@ -0,0 +1,164 @@ +/* + * QEMU S390x KVM floating interrupt controller (flic) + * + * Copyright 2013 IBM Corp. + * Author(s): Jens Freimann + * + * 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 +#include "hw/sysbus.h" +#include "sysemu/kvm.h" +#include "migration/qemu-file.h" +#include "hw/s390x/s390_flic.h" + +void s390_flic_init(void) +{ +DeviceState *dev; + +if (kvm_enabled()) { +dev = qdev_create(NULL, "s390-flic"); +object_property_add_child(qdev_get_machine(), "s390-flic", + OBJECT(dev), NULL); +qdev_init_nofail(dev); +} +} + +static int flic_dequeue_irq(QEMUFile *f, struct kvm_s390_irq *s390irq, +KVMS390FLICState *flic) +{ +struct kvm_device_attr attr; +int rc; + +attr.group = KVM_DEV_FLIC_DEQUEUE; +attr.addr = (uint64_t) s390irq; + +rc = ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr); + +return rc ? -errno : 0; +} + +static int flic_enqueue_irq(QEMUFile *f, struct kvm_s390_irq *s390irq, +KVMS390FLICState *flic) +{ +int rc; +struct kvm_device_attr attr; + +attr.group = KVM_DEV_FLIC_ENQUEUE; +attr.addr = (uint64_t) s390irq; + +rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); + +return rc ? -errno : 0; +} + +/* Save pending floating interrupts. */ +static void kvm_floating_interrupt_save(QEMUFile *f, void *opaque) +{ +struct kvm_s390_irq s390irq = {0}; +int r = 0; + +while (!r) { +r = flic_dequeue_irq(f, &s390irq, opaque); +if (r == -ENODATA) { +/* At end of list: write special marker */ +memset(&s390irq, 0, sizeof(s390irq)); +s390irq.type = 0x; +} +qemu_put_buffer(f, (uint8_t *) &s390irq, sizeof(s390irq)); +} +} + +/* Load pending floating interrupts. */ +static int kvm_floating_interrupt_load(QEMUFile *f, void *opaque, int version_id) +{ +int r = 0; +struct kvm_s390_irq s390irq = {0}; + +while (!r) { +qemu_get_buffer(f, (uint8_t *) &s390irq, sizeof(s390irq)); +/* Watch for marker indicating end of list */ +if (s390irq.type == 0x) { +return 0; +} +r = flic_enqueue_irq(f, &s390irq, (struct KVMS390FLICState *) opaque); +} + +return r; +} + +static void kvm_s390_flic_realize(DeviceState *dev, Error **errp) +{ +KVMS390FLICState *flic_state = KVM_S390_FLIC(dev); +struct kvm_create_device cd = {0}; +int ret; + +flic_state->fd = -1; +if (!kvm_check_extension(kvm_state, KVM_CAP_DEVICE_CTRL)) { +return; +} + +cd.type = KVM_DEV_TYPE_FLIC; +ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd); +if (ret < 0) { +perror("flic: couldn't create kvm_device"); +return; +} +flic_state->fd = cd.fd; + +/* Register savevm handler for floating interrupts */ +register_savevm(NULL, "floatingint", 0, 1, kvm_floating_interrupt_save, +kvm_floating_interrupt_load, (void *) flic_state); +} + +static void kvm_s390_flic_unrealize(DeviceState *dev, Error **errp) +{ +KVMS390FLICState *flic_state = KVM_S390_FLIC(dev); + +unregister_savevm(DEVICE(flic_state), "floatingint", flic_state); +} + +static void kvm_s390_flic_reset(DeviceState *dev) +{ +KVMS390FLICState *flic = KVM_S390_FLIC(dev); +struct kvm_device_attr att
Re: [Qemu-devel] [PATCH 2/2] s390x/kvm: implement floating-interrupt controller device
On 06/09/13 14:19, Jens Freimann wrote: > This patch implements a floating-interrupt controller device (flic) > which interacts with the s390 flic kvm_device. > > It provides functionality to: > * clear all pending floating interrupts in the kernel at device reset > * inject/retrieve interrupts into the kernel (used for migration) > > Signed-off-by: Jens Freimann > Reviewed-by: Thomas Huth Acked-by: Christian Borntraeger > > --- > default-configs/s390x-softmmu.mak | 1 + > hw/intc/Makefile.objs | 1 + > hw/intc/s390_flic.c | 164 > ++ > hw/s390x/s390-virtio-ccw.c| 8 +- > hw/s390x/s390-virtio.c| 2 + > include/hw/s390x/s390_flic.h | 31 +++ > 6 files changed, 206 insertions(+), 1 deletion(-) > > diff --git a/default-configs/s390x-softmmu.mak > b/default-configs/s390x-softmmu.mak > index 81fbc68..d843dc0 100644 > --- a/default-configs/s390x-softmmu.mak > +++ b/default-configs/s390x-softmmu.mak > @@ -1,2 +1,3 @@ > CONFIG_VIRTIO=y > CONFIG_SCLPCONSOLE=y > +CONFIG_S390_FLIC=$(CONFIG_KVM) > diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs > index 2851eed..b2305aa 100644 > --- a/hw/intc/Makefile.objs > +++ b/hw/intc/Makefile.objs > @@ -23,3 +23,4 @@ obj-$(CONFIG_OMAP) += omap_intc.o > obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o > obj-$(CONFIG_SH4) += sh_intc.o > obj-$(CONFIG_XICS) += xics.o > +obj-$(CONFIG_S390_FLIC) += s390_flic.o > diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c > new file mode 100644 > index 000..9dfaafa > --- /dev/null > +++ b/hw/intc/s390_flic.c > @@ -0,0 +1,164 @@ > +/* > + * QEMU S390x KVM floating interrupt controller (flic) > + * > + * Copyright 2013 IBM Corp. > + * Author(s): Jens Freimann > + * > + * 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 > +#include "hw/sysbus.h" > +#include "sysemu/kvm.h" > +#include "migration/qemu-file.h" > +#include "hw/s390x/s390_flic.h" > + > +void s390_flic_init(void) > +{ > +DeviceState *dev; > + > +if (kvm_enabled()) { > +dev = qdev_create(NULL, "s390-flic"); > +object_property_add_child(qdev_get_machine(), "s390-flic", > + OBJECT(dev), NULL); > +qdev_init_nofail(dev); > +} > +} > + > +static int flic_dequeue_irq(QEMUFile *f, struct kvm_s390_irq *s390irq, > +KVMS390FLICState *flic) > +{ > +struct kvm_device_attr attr; > +int rc; > + > +attr.group = KVM_DEV_FLIC_DEQUEUE; > +attr.addr = (uint64_t) s390irq; > + > +rc = ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr); > + > +return rc ? -errno : 0; > +} > + > +static int flic_enqueue_irq(QEMUFile *f, struct kvm_s390_irq *s390irq, > +KVMS390FLICState *flic) > +{ > +int rc; > +struct kvm_device_attr attr; > + > +attr.group = KVM_DEV_FLIC_ENQUEUE; > +attr.addr = (uint64_t) s390irq; > + > +rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); > + > +return rc ? -errno : 0; > +} > + > +/* Save pending floating interrupts. */ > +static void kvm_floating_interrupt_save(QEMUFile *f, void *opaque) > +{ > +struct kvm_s390_irq s390irq = {0}; > +int r = 0; > + > +while (!r) { > +r = flic_dequeue_irq(f, &s390irq, opaque); > +if (r == -ENODATA) { > +/* At end of list: write special marker */ > +memset(&s390irq, 0, sizeof(s390irq)); > +s390irq.type = 0x; > +} > +qemu_put_buffer(f, (uint8_t *) &s390irq, sizeof(s390irq)); > +} > +} > + > +/* Load pending floating interrupts. */ > +static int kvm_floating_interrupt_load(QEMUFile *f, void *opaque, int > version_id) > +{ > +int r = 0; > +struct kvm_s390_irq s390irq = {0}; > + > +while (!r) { > +qemu_get_buffer(f, (uint8_t *) &s390irq, sizeof(s390irq)); > +/* Watch for marker indicating end of list */ > +if (s390irq.type == 0x) { > +return 0; > +} > +r = flic_enqueue_irq(f, &s390irq, (struct KVMS390FLICState *) > opaque); > +} > + > +return r; > +} > + > +static void kvm_s390_flic_realize(DeviceState *dev, Error **errp) > +{ > +KVMS390FLICState *flic_state = KVM_S390_FLIC(dev); > +struct kvm_create_device cd = {0}; > +int ret; > + > +flic_state->fd = -1; > +if (!kvm_check_extension(kvm_state, KVM_CAP_DEVICE_CTRL)) { > +return; > +} > + > +cd.type = KVM_DEV_TYPE_FLIC; > +ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd); > +if (ret < 0) { > +perror("flic: couldn't create kvm_device"); > +return; > +} > +flic_state->fd = cd.fd; > + > +/* Register savevm handler for floating interrupts */ > +register_savevm(NULL, "floatingint", 0, 1, kvm_floating_interrupt_save, > +