[Qemu-devel] [PATCH 2/2] s390x/kvm: implement floating-interrupt controller device

2013-09-06 Thread Jens Freimann
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

2013-09-06 Thread Christian Borntraeger
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,
> +