* [Qemu-devel] [PATCH v5 0/4] irqfds for s390x
@ 2014-05-08 13:03 Cornelia Huck
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 1/4] s390x: split flic into kvm and non-kvm parts Cornelia Huck
` (3 more replies)
0 siblings, 4 replies; 15+ messages in thread
From: Cornelia Huck @ 2014-05-08 13:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Cornelia Huck, borntraeger, agraf
Hi,
here's the next version of my patchset implementing irqfds for s390x.
This has been reworked to make use of flic methods; in order to make
this work, the flic had to be split into a kvm part (which basically
offers the same functionality as the 'old' flic) and a non-kvm part
(which basically does nothing).
Changes from v4:
- capability helpers are already upstream
- use flic methods for I/O adapter registration and mapping
- move direct interaction with the routing code from virtio-ccw to
the flic
Also available on
https://github.com/cohuck/qemu.git s390x-irqfd
Please review.
Cornelia Huck (4):
s390x: split flic into kvm and non-kvm parts
s390x: Add I/O adapter registration.
s390x/virtio-ccw: reference-counted indicators
s390x/virtio-ccw: Wire up irq routing and irqfds.
default-configs/s390x-softmmu.mak | 3 +-
hw/intc/Makefile.objs | 1 +
hw/intc/s390_flic.c | 325 +++++-----------------------
hw/intc/s390_flic_kvm.c | 420 +++++++++++++++++++++++++++++++++++++
hw/s390x/css.c | 50 +++++
hw/s390x/css.h | 4 +
hw/s390x/virtio-ccw.c | 237 ++++++++++++++++++---
hw/s390x/virtio-ccw.h | 16 +-
include/hw/s390x/adapter.h | 23 ++
include/hw/s390x/s390_flic.h | 65 +++++-
include/qemu/typedefs.h | 1 +
include/sysemu/kvm.h | 2 +
kvm-all.c | 38 +++-
kvm-stub.c | 5 +
target-s390x/kvm.c | 5 +
15 files changed, 880 insertions(+), 315 deletions(-)
create mode 100644 hw/intc/s390_flic_kvm.c
create mode 100644 include/hw/s390x/adapter.h
--
1.7.9.5
^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v5 1/4] s390x: split flic into kvm and non-kvm parts
2014-05-08 13:03 [Qemu-devel] [PATCH v5 0/4] irqfds for s390x Cornelia Huck
@ 2014-05-08 13:03 ` Cornelia Huck
2014-05-08 13:43 ` Alexander Graf
2014-05-12 8:01 ` Christian Borntraeger
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 2/4] s390x: Add I/O adapter registration Cornelia Huck
` (2 subsequent siblings)
3 siblings, 2 replies; 15+ messages in thread
From: Cornelia Huck @ 2014-05-08 13:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Cornelia Huck, borntraeger, agraf
Introduce a common parent class for both cases, where kvm and non-kvm
can hook up callbacks. This will be used by follow-on patches for
adapter registration and mapping.
We now always have a flic, regardless of whether we use kvm; the
non-kvm implementation just doesn't do anything.
Reviewed-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
default-configs/s390x-softmmu.mak | 3 +-
hw/intc/Makefile.objs | 1 +
hw/intc/s390_flic.c | 318 ++++--------------------------------
hw/intc/s390_flic_kvm.c | 325 +++++++++++++++++++++++++++++++++++++
include/hw/s390x/s390_flic.h | 51 ++++--
5 files changed, 399 insertions(+), 299 deletions(-)
create mode 100644 hw/intc/s390_flic_kvm.c
diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak
index d843dc0..126d88d 100644
--- a/default-configs/s390x-softmmu.mak
+++ b/default-configs/s390x-softmmu.mak
@@ -1,3 +1,4 @@
CONFIG_VIRTIO=y
CONFIG_SCLPCONSOLE=y
-CONFIG_S390_FLIC=$(CONFIG_KVM)
+CONFIG_S390_FLIC=y
+CONFIG_S390_FLIC_KVM=$(CONFIG_KVM)
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index c8a2318..843864a 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -26,3 +26,4 @@ obj-$(CONFIG_XICS) += xics.o
obj-$(CONFIG_XICS_KVM) += xics_kvm.o
obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
obj-$(CONFIG_S390_FLIC) += s390_flic.o
+obj-$(CONFIG_S390_FLIC_KVM) += s390_flic_kvm.o
diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
index b2ef3e3..7dc8c7d 100644
--- a/hw/intc/s390_flic.c
+++ b/hw/intc/s390_flic.c
@@ -1,322 +1,66 @@
/*
- * QEMU S390x KVM floating interrupt controller (flic)
+ * QEMU S390x floating interrupt controller (flic)
*
* Copyright 2014 IBM Corp.
* Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com>
+ * Cornelia Huck <cornelia.huck@de.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 <sys/ioctl.h>
#include "qemu/error-report.h"
#include "hw/sysbus.h"
-#include "sysemu/kvm.h"
#include "migration/qemu-file.h"
#include "hw/s390x/s390_flic.h"
#include "trace.h"
-#define FLIC_SAVE_INITIAL_SIZE getpagesize()
-#define FLIC_FAILED (-1UL)
-#define FLIC_SAVEVM_VERSION 1
-
-void s390_flic_init(void)
-{
- DeviceState *dev;
- int r;
-
- if (kvm_enabled()) {
- dev = qdev_create(NULL, "s390-flic");
- object_property_add_child(qdev_get_machine(), "s390-flic",
- OBJECT(dev), NULL);
- r = qdev_init(dev);
- if (r) {
- error_report("flic: couldn't create qdev");
- }
- }
-}
-
-/**
- * flic_get_all_irqs - store all pending irqs in buffer
- * @buf: pointer to buffer which is passed to kernel
- * @len: length of buffer
- * @flic: pointer to flic device state
- *
- * Returns: -ENOMEM if buffer is too small,
- * -EINVAL if attr.group is invalid,
- * -EFAULT if copying to userspace failed,
- * on success return number of stored interrupts
- */
-static int flic_get_all_irqs(KVMS390FLICState *flic,
- void *buf, int len)
-{
- struct kvm_device_attr attr = {
- .group = KVM_DEV_FLIC_GET_ALL_IRQS,
- .addr = (uint64_t) buf,
- .attr = len,
- };
- int rc;
-
- rc = ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr);
-
- return rc == -1 ? -errno : rc;
-}
-
-static void flic_enable_pfault(KVMS390FLICState *flic)
-{
- struct kvm_device_attr attr = {
- .group = KVM_DEV_FLIC_APF_ENABLE,
- };
- int rc;
-
- rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
-
- if (rc) {
- fprintf(stderr, "flic: couldn't enable pfault\n");
- }
-}
-
-static void flic_disable_wait_pfault(KVMS390FLICState *flic)
+S390FLICState *s390_get_flic(void)
{
- struct kvm_device_attr attr = {
- .group = KVM_DEV_FLIC_APF_DISABLE_WAIT,
- };
- int rc;
-
- rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
+ S390FLICState *fs;
- if (rc) {
- fprintf(stderr, "flic: couldn't disable pfault\n");
+ fs = S390_FLIC_COMMON(object_resolve_path(TYPE_KVM_S390_FLIC, NULL));
+ if (!fs) {
+ fs = S390_FLIC_COMMON(object_resolve_path(TYPE_QEMU_S390_FLIC, NULL));
}
+ return fs;
}
-/** flic_enqueue_irqs - returns 0 on success
- * @buf: pointer to buffer which is passed to kernel
- * @len: length of buffer
- * @flic: pointer to flic device state
- *
- * Returns: -EINVAL if attr.group is unknown
- */
-static int flic_enqueue_irqs(void *buf, uint64_t len,
- KVMS390FLICState *flic)
-{
- int rc;
- struct kvm_device_attr attr = {
- .group = KVM_DEV_FLIC_ENQUEUE,
- .addr = (uint64_t) buf,
- .attr = len,
- };
-
- 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
- * @buf: pointer to pointer to a buffer
- * @len: length of buffer
- *
- * Returns: return value of flic_get_all_irqs
- * Note: Retry and increase buffer size until flic_get_all_irqs
- * either returns a value >= 0 or a negative error code.
- * -ENOMEM is an exception, which means the buffer is too small
- * and we should try again. Other negative error codes can be
- * -EFAULT and -EINVAL which we ignore at this point
- */
-static int __get_all_irqs(KVMS390FLICState *flic,
- void **buf, int len)
+void s390_flic_init(void)
{
+ DeviceState *dev;
int r;
- do {
- /* returns -ENOMEM if buffer is too small and number
- * of queued interrupts on success */
- r = flic_get_all_irqs(flic, *buf, len);
- if (r >= 0) {
- break;
- }
- len *= 2;
- *buf = g_try_realloc(*buf, len);
- if (!buf) {
- return -ENOMEM;
- }
- } while (r == -ENOMEM && len <= KVM_S390_FLIC_MAX_BUFFER);
-
- return r;
-}
-
-/**
- * kvm_flic_save - Save pending floating interrupts
- * @f: QEMUFile containing migration state
- * @opaque: pointer to flic device state
- *
- * Note: Pass buf and len to kernel. Start with one page and
- * increase until buffer is sufficient or maxium size is
- * reached
- */
-static void kvm_flic_save(QEMUFile *f, void *opaque)
-{
- KVMS390FLICState *flic = opaque;
- int len = FLIC_SAVE_INITIAL_SIZE;
- void *buf;
- int count;
-
- flic_disable_wait_pfault((struct KVMS390FLICState *) opaque);
-
- buf = g_try_malloc0(len);
- if (!buf) {
- /* Storing FLIC_FAILED into the count field here will cause the
- * target system to fail when attempting to load irqs from the
- * migration state */
- error_report("flic: couldn't allocate memory");
- qemu_put_be64(f, FLIC_FAILED);
- return;
+ dev = s390_flic_kvm_create();
+ if (!dev) {
+ dev = qdev_create(NULL, TYPE_QEMU_S390_FLIC);
+ object_property_add_child(qdev_get_machine(), TYPE_QEMU_S390_FLIC,
+ OBJECT(dev), NULL);
}
-
- count = __get_all_irqs(flic, &buf, len);
- if (count < 0) {
- error_report("flic: couldn't retrieve irqs from kernel, rc %d",
- count);
- /* Storing FLIC_FAILED into the count field here will cause the
- * target system to fail when attempting to load irqs from the
- * migration state */
- qemu_put_be64(f, FLIC_FAILED);
- } else {
- qemu_put_be64(f, count);
- qemu_put_buffer(f, (uint8_t *) buf,
- count * sizeof(struct kvm_s390_irq));
+ r = qdev_init(dev);
+ if (r) {
+ error_report("flic: couldn't create qdev");
}
- g_free(buf);
}
-/**
- * kvm_flic_load - Load pending floating interrupts
- * @f: QEMUFile containing migration state
- * @opaque: pointer to flic device state
- * @version_id: version id for migration
- *
- * Returns: value of flic_enqueue_irqs, -EINVAL on error
- * Note: Do nothing when no interrupts where stored
- * in QEMUFile
- */
-static int kvm_flic_load(QEMUFile *f, void *opaque, int version_id)
-{
- uint64_t len = 0;
- uint64_t count = 0;
- void *buf = NULL;
- int r = 0;
-
- if (version_id != FLIC_SAVEVM_VERSION) {
- r = -EINVAL;
- goto out;
- }
-
- flic_enable_pfault((struct KVMS390FLICState *) opaque);
-
- count = qemu_get_be64(f);
- len = count * sizeof(struct kvm_s390_irq);
- if (count == FLIC_FAILED) {
- r = -EINVAL;
- goto out;
- }
- if (count == 0) {
- r = 0;
- goto out;
- }
- buf = g_try_malloc0(len);
- if (!buf) {
- r = -ENOMEM;
- goto out;
- }
-
- if (qemu_get_buffer(f, (uint8_t *) buf, len) != len) {
- r = -EINVAL;
- goto out_free;
- }
- r = flic_enqueue_irqs(buf, len, (struct KVMS390FLICState *) opaque);
-
-out_free:
- g_free(buf);
-out:
- 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)) {
- trace_flic_no_device_api(errno);
- return;
- }
-
- cd.type = KVM_DEV_TYPE_FLIC;
- ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd);
- if (ret < 0) {
- trace_flic_create_device(errno);
- return;
- }
- flic_state->fd = cd.fd;
-
- /* Register savevm handler for floating interrupts */
- register_savevm(NULL, "s390-flic", 0, 1, kvm_flic_save,
- kvm_flic_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), "s390-flic", flic_state);
-}
-
-static void kvm_s390_flic_reset(DeviceState *dev)
-{
- KVMS390FLICState *flic = KVM_S390_FLIC(dev);
- struct kvm_device_attr attr = {
- .group = KVM_DEV_FLIC_CLEAR_IRQS,
- };
- int rc = 0;
-
- if (flic->fd == -1) {
- return;
- }
-
- flic_disable_wait_pfault(flic);
-
- rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
- if (rc) {
- trace_flic_reset_failed(errno);
- }
-
- flic_enable_pfault(flic);
-}
-
-static void kvm_s390_flic_class_init(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
-
- dc->realize = kvm_s390_flic_realize;
- dc->unrealize = kvm_s390_flic_unrealize;
- dc->reset = kvm_s390_flic_reset;
-}
+static const TypeInfo qemu_s390_flic_info = {
+ .name = TYPE_QEMU_S390_FLIC,
+ .parent = TYPE_S390_FLIC_COMMON,
+ .instance_size = sizeof(QEMUS390FLICState),
+};
-static const TypeInfo kvm_s390_flic_info = {
- .name = TYPE_KVM_S390_FLIC,
+static const TypeInfo s390_flic_common_info = {
+ .name = TYPE_S390_FLIC_COMMON,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(KVMS390FLICState),
- .class_init = kvm_s390_flic_class_init,
+ .instance_size = sizeof(S390FLICState),
+ .class_size = sizeof(S390FLICStateClass),
};
-static void kvm_s390_flic_register_types(void)
+static void qemu_s390_flic_register_types(void)
{
- type_register_static(&kvm_s390_flic_info);
+ type_register_static(&s390_flic_common_info);
+ type_register_static(&qemu_s390_flic_info);
}
-type_init(kvm_s390_flic_register_types)
+type_init(qemu_s390_flic_register_types)
diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
new file mode 100644
index 0000000..70c1710
--- /dev/null
+++ b/hw/intc/s390_flic_kvm.c
@@ -0,0 +1,325 @@
+/*
+ * QEMU S390x KVM floating interrupt controller (flic)
+ *
+ * Copyright 2014 IBM Corp.
+ * Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com>
+ * Cornelia Huck <cornelia.huck@de.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 <sys/ioctl.h>
+#include "qemu/error-report.h"
+#include "hw/sysbus.h"
+#include "sysemu/kvm.h"
+#include "migration/qemu-file.h"
+#include "hw/s390x/s390_flic.h"
+#include "trace.h"
+
+#define FLIC_SAVE_INITIAL_SIZE getpagesize()
+#define FLIC_FAILED (-1UL)
+#define FLIC_SAVEVM_VERSION 1
+
+typedef struct KVMS390FLICState {
+ S390FLICState parent_obj;
+
+ uint32_t fd;
+} KVMS390FLICState;
+
+DeviceState *s390_flic_kvm_create(void)
+{
+ DeviceState *dev = NULL;
+
+ if (kvm_enabled()) {
+ dev = qdev_create(NULL, TYPE_KVM_S390_FLIC);
+ object_property_add_child(qdev_get_machine(), TYPE_KVM_S390_FLIC,
+ OBJECT(dev), NULL);
+ }
+ return dev;
+}
+
+/**
+ * flic_get_all_irqs - store all pending irqs in buffer
+ * @buf: pointer to buffer which is passed to kernel
+ * @len: length of buffer
+ * @flic: pointer to flic device state
+ *
+ * Returns: -ENOMEM if buffer is too small,
+ * -EINVAL if attr.group is invalid,
+ * -EFAULT if copying to userspace failed,
+ * on success return number of stored interrupts
+ */
+static int flic_get_all_irqs(KVMS390FLICState *flic,
+ void *buf, int len)
+{
+ struct kvm_device_attr attr = {
+ .group = KVM_DEV_FLIC_GET_ALL_IRQS,
+ .addr = (uint64_t) buf,
+ .attr = len,
+ };
+ int rc;
+
+ rc = ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr);
+
+ return rc == -1 ? -errno : rc;
+}
+
+static void flic_enable_pfault(KVMS390FLICState *flic)
+{
+ struct kvm_device_attr attr = {
+ .group = KVM_DEV_FLIC_APF_ENABLE,
+ };
+ int rc;
+
+ rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
+
+ if (rc) {
+ fprintf(stderr, "flic: couldn't enable pfault\n");
+ }
+}
+
+static void flic_disable_wait_pfault(KVMS390FLICState *flic)
+{
+ struct kvm_device_attr attr = {
+ .group = KVM_DEV_FLIC_APF_DISABLE_WAIT,
+ };
+ int rc;
+
+ rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
+
+ if (rc) {
+ fprintf(stderr, "flic: couldn't disable pfault\n");
+ }
+}
+
+/** flic_enqueue_irqs - returns 0 on success
+ * @buf: pointer to buffer which is passed to kernel
+ * @len: length of buffer
+ * @flic: pointer to flic device state
+ *
+ * Returns: -EINVAL if attr.group is unknown
+ */
+static int flic_enqueue_irqs(void *buf, uint64_t len,
+ KVMS390FLICState *flic)
+{
+ int rc;
+ struct kvm_device_attr attr = {
+ .group = KVM_DEV_FLIC_ENQUEUE,
+ .addr = (uint64_t) buf,
+ .attr = len,
+ };
+
+ 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
+ * @buf: pointer to pointer to a buffer
+ * @len: length of buffer
+ *
+ * Returns: return value of flic_get_all_irqs
+ * Note: Retry and increase buffer size until flic_get_all_irqs
+ * either returns a value >= 0 or a negative error code.
+ * -ENOMEM is an exception, which means the buffer is too small
+ * and we should try again. Other negative error codes can be
+ * -EFAULT and -EINVAL which we ignore at this point
+ */
+static int __get_all_irqs(KVMS390FLICState *flic,
+ void **buf, int len)
+{
+ int r;
+
+ do {
+ /* returns -ENOMEM if buffer is too small and number
+ * of queued interrupts on success */
+ r = flic_get_all_irqs(flic, *buf, len);
+ if (r >= 0) {
+ break;
+ }
+ len *= 2;
+ *buf = g_try_realloc(*buf, len);
+ if (!buf) {
+ return -ENOMEM;
+ }
+ } while (r == -ENOMEM && len <= KVM_S390_FLIC_MAX_BUFFER);
+
+ return r;
+}
+
+/**
+ * kvm_flic_save - Save pending floating interrupts
+ * @f: QEMUFile containing migration state
+ * @opaque: pointer to flic device state
+ *
+ * Note: Pass buf and len to kernel. Start with one page and
+ * increase until buffer is sufficient or maxium size is
+ * reached
+ */
+static void kvm_flic_save(QEMUFile *f, void *opaque)
+{
+ KVMS390FLICState *flic = opaque;
+ int len = FLIC_SAVE_INITIAL_SIZE;
+ void *buf;
+ int count;
+
+ flic_disable_wait_pfault((struct KVMS390FLICState *) opaque);
+
+ buf = g_try_malloc0(len);
+ if (!buf) {
+ /* Storing FLIC_FAILED into the count field here will cause the
+ * target system to fail when attempting to load irqs from the
+ * migration state */
+ error_report("flic: couldn't allocate memory");
+ qemu_put_be64(f, FLIC_FAILED);
+ return;
+ }
+
+ count = __get_all_irqs(flic, &buf, len);
+ if (count < 0) {
+ error_report("flic: couldn't retrieve irqs from kernel, rc %d",
+ count);
+ /* Storing FLIC_FAILED into the count field here will cause the
+ * target system to fail when attempting to load irqs from the
+ * migration state */
+ qemu_put_be64(f, FLIC_FAILED);
+ } else {
+ qemu_put_be64(f, count);
+ qemu_put_buffer(f, (uint8_t *) buf,
+ count * sizeof(struct kvm_s390_irq));
+ }
+ g_free(buf);
+}
+
+/**
+ * kvm_flic_load - Load pending floating interrupts
+ * @f: QEMUFile containing migration state
+ * @opaque: pointer to flic device state
+ * @version_id: version id for migration
+ *
+ * Returns: value of flic_enqueue_irqs, -EINVAL on error
+ * Note: Do nothing when no interrupts where stored
+ * in QEMUFile
+ */
+static int kvm_flic_load(QEMUFile *f, void *opaque, int version_id)
+{
+ uint64_t len = 0;
+ uint64_t count = 0;
+ void *buf = NULL;
+ int r = 0;
+
+ if (version_id != FLIC_SAVEVM_VERSION) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ flic_enable_pfault((struct KVMS390FLICState *) opaque);
+
+ count = qemu_get_be64(f);
+ len = count * sizeof(struct kvm_s390_irq);
+ if (count == FLIC_FAILED) {
+ r = -EINVAL;
+ goto out;
+ }
+ if (count == 0) {
+ r = 0;
+ goto out;
+ }
+ buf = g_try_malloc0(len);
+ if (!buf) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ if (qemu_get_buffer(f, (uint8_t *) buf, len) != len) {
+ r = -EINVAL;
+ goto out_free;
+ }
+ r = flic_enqueue_irqs(buf, len, (struct KVMS390FLICState *) opaque);
+
+out_free:
+ g_free(buf);
+out:
+ 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)) {
+ trace_flic_no_device_api(errno);
+ return;
+ }
+
+ cd.type = KVM_DEV_TYPE_FLIC;
+ ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd);
+ if (ret < 0) {
+ trace_flic_create_device(errno);
+ return;
+ }
+ flic_state->fd = cd.fd;
+
+ /* Register savevm handler for floating interrupts */
+ register_savevm(NULL, "s390-flic", 0, 1, kvm_flic_save,
+ kvm_flic_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), "s390-flic", flic_state);
+}
+
+static void kvm_s390_flic_reset(DeviceState *dev)
+{
+ KVMS390FLICState *flic = KVM_S390_FLIC(dev);
+ struct kvm_device_attr attr = {
+ .group = KVM_DEV_FLIC_CLEAR_IRQS,
+ };
+ int rc = 0;
+
+ if (flic->fd == -1) {
+ return;
+ }
+
+ flic_disable_wait_pfault(flic);
+
+ rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
+ if (rc) {
+ trace_flic_reset_failed(errno);
+ }
+
+ flic_enable_pfault(flic);
+}
+
+static void kvm_s390_flic_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = kvm_s390_flic_realize;
+ dc->unrealize = kvm_s390_flic_unrealize;
+ dc->reset = kvm_s390_flic_reset;
+}
+
+static const TypeInfo kvm_s390_flic_info = {
+ .name = TYPE_KVM_S390_FLIC,
+ .parent = TYPE_S390_FLIC_COMMON,
+ .instance_size = sizeof(KVMS390FLICState),
+ .class_init = kvm_s390_flic_class_init,
+};
+
+static void kvm_s390_flic_register_types(void)
+{
+ type_register_static(&kvm_s390_flic_info);
+}
+
+type_init(kvm_s390_flic_register_types)
diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h
index 497b219..3bc60fd 100644
--- a/include/hw/s390x/s390_flic.h
+++ b/include/hw/s390x/s390_flic.h
@@ -1,33 +1,62 @@
/*
- * QEMU S390x KVM floating interrupt controller (flic)
+ * QEMU S390x floating interrupt controller (flic)
*
* Copyright 2014 IBM Corp.
* Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com>
+ * Cornelia Huck <cornelia.huck@de.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.
*/
-#ifndef __KVM_S390_FLIC_H
-#define __KVM_S390_FLIC_H
+#ifndef __HW_S390_FLIC_H
+#define __HW_S390_FLIC_H
#include "hw/sysbus.h"
-#define TYPE_KVM_S390_FLIC "s390-flic"
+#define TYPE_S390_FLIC_COMMON "s390-flic"
+#define S390_FLIC_COMMON(obj) \
+ OBJECT_CHECK(S390FLICState, (obj), TYPE_S390_FLIC_COMMON)
+
+typedef struct S390FLICState {
+ SysBusDevice parent_obj;
+
+} S390FLICState;
+
+#define S390_FLIC_COMMON_CLASS(klass) \
+ OBJECT_CLASS_CHECK(S390FLICStateClass, (klass), TYPE_S390_FLIC_COMMON)
+#define S390_FLIC_COMMON_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(S390FLICStateClass, (obj), TYPE_S390_FLIC_COMMON)
+
+typedef struct S390FLICStateClass {
+ DeviceClass parent_class;
+
+} S390FLICStateClass;
+
+#define TYPE_KVM_S390_FLIC "s390-flic-kvm"
#define KVM_S390_FLIC(obj) \
OBJECT_CHECK(KVMS390FLICState, (obj), TYPE_KVM_S390_FLIC)
-typedef struct KVMS390FLICState {
- SysBusDevice parent_obj;
+#define TYPE_QEMU_S390_FLIC "s390-flic-qemu"
+#define QEMU_S390_FLIC(obj) \
+ OBJECT_CHECK(QEMUS390FLICState, (obj), TYPE_QEMU_S390_FLIC)
- uint32_t fd;
-} KVMS390FLICState;
+typedef struct QEMUS390FLICState {
+ S390FLICState parent_obj;
+} QEMUS390FLICState;
-#ifdef CONFIG_KVM
void s390_flic_init(void);
+
+S390FLICState *s390_get_flic(void);
+
+#ifdef CONFIG_KVM
+DeviceState *s390_flic_kvm_create(void);
#else
-static inline void s390_flic_init(void) { }
+static inline DeviceState *s390_flic_kvm_create(void)
+{
+ return NULL;
+}
#endif
-#endif /* __KVM_S390_FLIC_H */
+#endif /* __HW_S390_FLIC_H */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v5 2/4] s390x: Add I/O adapter registration.
2014-05-08 13:03 [Qemu-devel] [PATCH v5 0/4] irqfds for s390x Cornelia Huck
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 1/4] s390x: split flic into kvm and non-kvm parts Cornelia Huck
@ 2014-05-08 13:03 ` Cornelia Huck
2014-05-12 8:36 ` Christian Borntraeger
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 3/4] s390x/virtio-ccw: reference-counted indicators Cornelia Huck
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 4/4] s390x/virtio-ccw: Wire up irq routing and irqfds Cornelia Huck
3 siblings, 1 reply; 15+ messages in thread
From: Cornelia Huck @ 2014-05-08 13:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Cornelia Huck, borntraeger, agraf
Register an I/O adapter interrupt source for when virtio-ccw devices start
using adapter interrupts.
Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
hw/intc/s390_flic.c | 16 ++++++++++++++
hw/intc/s390_flic_kvm.c | 29 ++++++++++++++++++++++++
hw/s390x/css.c | 50 ++++++++++++++++++++++++++++++++++++++++++
hw/s390x/css.h | 4 ++++
hw/s390x/virtio-ccw.c | 4 ++++
hw/s390x/virtio-ccw.h | 1 +
include/hw/s390x/s390_flic.h | 2 ++
7 files changed, 106 insertions(+)
diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
index 7dc8c7d..2b56835 100644
--- a/hw/intc/s390_flic.c
+++ b/hw/intc/s390_flic.c
@@ -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 = {
diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
index 70c1710..cc4072e 100644
--- a/hw/intc/s390_flic_kvm.c
+++ b/hw/intc/s390_flic_kvm.c
@@ -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 = {
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 122cc7e..2678e44 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -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);
diff --git a/hw/s390x/css.h b/hw/s390x/css.h
index 220169e..6586106 100644
--- a/hw/s390x/css.h
+++ b/hw/s390x/css.h
@@ -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
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 1cb4e2c..e3b7120 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -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;
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 4393e44..0b70b91 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -85,6 +85,7 @@ struct VirtioCcwDevice {
bool ioeventfd_disabled;
uint32_t flags;
uint8_t thinint_isc;
+ uint32_t adapter_id;
/* Guest provided values: */
hwaddr indicators;
hwaddr indicators2;
diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h
index 3bc60fd..83913ec 100644
--- a/include/hw/s390x/s390_flic.h
+++ b/include/hw/s390x/s390_flic.h
@@ -32,6 +32,8 @@ typedef struct S390FLICState {
typedef struct S390FLICStateClass {
DeviceClass parent_class;
+ int (*register_io_adapter)(S390FLICState *fs, uint32_t id, uint8_t isc,
+ bool swap, bool maskable);
} S390FLICStateClass;
#define TYPE_KVM_S390_FLIC "s390-flic-kvm"
--
1.7.9.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v5 3/4] s390x/virtio-ccw: reference-counted indicators
2014-05-08 13:03 [Qemu-devel] [PATCH v5 0/4] irqfds for s390x Cornelia Huck
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 1/4] s390x: split flic into kvm and non-kvm parts Cornelia Huck
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 2/4] s390x: Add I/O adapter registration Cornelia Huck
@ 2014-05-08 13:03 ` Cornelia Huck
2014-05-12 8:17 ` Christian Borntraeger
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 4/4] s390x/virtio-ccw: Wire up irq routing and irqfds Cornelia Huck
3 siblings, 1 reply; 15+ messages in thread
From: Cornelia Huck @ 2014-05-08 13:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Cornelia Huck, borntraeger, agraf
Make code using the same indicators point to a single allocated structure
that is freed when the last user goes away.
This will be used by the irqfd code to unmap addresses after the last user
is gone.
Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
hw/s390x/virtio-ccw.c | 80 ++++++++++++++++++++++++++++++++++++++-----------
hw/s390x/virtio-ccw.h | 13 ++++++--
2 files changed, 73 insertions(+), 20 deletions(-)
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index e3b7120..d11a783 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -27,6 +27,38 @@
#include "virtio-ccw.h"
#include "trace.h"
+static QTAILQ_HEAD(, IndAddr) indicator_addresses =
+ QTAILQ_HEAD_INITIALIZER(indicator_addresses);
+
+static IndAddr *get_indicator(hwaddr ind_addr, int len)
+{
+ IndAddr *indicator;
+
+ QTAILQ_FOREACH(indicator, &indicator_addresses, sibling) {
+ if (indicator->addr == ind_addr) {
+ indicator->refcnt++;
+ return indicator;
+ }
+ }
+ indicator = g_new0(IndAddr, 1);
+ indicator->addr = ind_addr;
+ indicator->len = len;
+ indicator->refcnt = 1;
+ QTAILQ_INSERT_TAIL(&indicator_addresses, indicator, sibling);
+ return indicator;
+}
+
+static void release_indicator(IndAddr *indicator)
+{
+ assert(indicator->refcnt > 0);
+ indicator->refcnt--;
+ if (indicator->refcnt > 0) {
+ return;
+ }
+ QTAILQ_REMOVE(&indicator_addresses, indicator, sibling);
+ g_free(indicator);
+}
+
static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
VirtioCcwDevice *dev);
@@ -445,7 +477,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
ret = -EFAULT;
} else {
indicators = ldq_phys(&address_space_memory, ccw.cda);
- dev->indicators = indicators;
+ dev->indicators = get_indicator(indicators, sizeof(uint64_t));
sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
ret = 0;
}
@@ -465,7 +497,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
ret = -EFAULT;
} else {
indicators = ldq_phys(&address_space_memory, ccw.cda);
- dev->indicators2 = indicators;
+ dev->indicators2 = get_indicator(indicators, sizeof(uint64_t));
sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
ret = 0;
}
@@ -517,8 +549,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
ret = -EFAULT;
} else {
len = hw_len;
- dev->summary_indicator = thinint->summary_indicator;
- dev->indicators = thinint->device_indicator;
+ dev->summary_indicator =
+ get_indicator(thinint->summary_indicator, sizeof(uint8_t));
+ dev->indicators = get_indicator(thinint->device_indicator,
+ thinint->ind_bit / 8 + 1);
dev->thinint_isc = thinint->isc;
dev->ind_bit = thinint->ind_bit;
cpu_physical_memory_unmap(thinint, hw_len, 0, hw_len);
@@ -526,8 +560,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
dev->thinint_isc, true, false,
&dev->adapter_id);
assert(ret == 0);
- sch->thinint_active = ((dev->indicators != 0) &&
- (dev->summary_indicator != 0));
+ sch->thinint_active = ((dev->indicators != NULL) &&
+ (dev->summary_indicator != NULL));
sch->curr_status.scsw.count = ccw.count - len;
ret = 0;
}
@@ -558,7 +592,7 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
sch->driver_data = dev;
dev->sch = sch;
- dev->indicators = 0;
+ dev->indicators = NULL;
/* Initialize subchannel structure. */
sch->channel_prog = 0x0;
@@ -697,7 +731,10 @@ static int virtio_ccw_exit(VirtioCcwDevice *dev)
css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
g_free(sch);
}
- dev->indicators = 0;
+ if (dev->indicators) {
+ release_indicator(dev->indicators);
+ dev->indicators = NULL;
+ }
return 0;
}
@@ -954,17 +991,17 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
* ind_bit indicates the start of the indicators in a big
* endian notation.
*/
- virtio_set_ind_atomic(sch, dev->indicators +
+ virtio_set_ind_atomic(sch, dev->indicators->addr +
(dev->ind_bit + vector) / 8,
0x80 >> ((dev->ind_bit + vector) % 8));
- if (!virtio_set_ind_atomic(sch, dev->summary_indicator,
+ if (!virtio_set_ind_atomic(sch, dev->summary_indicator->addr,
0x01)) {
css_adapter_interrupt(dev->thinint_isc);
}
} else {
- indicators = ldq_phys(&address_space_memory, dev->indicators);
+ indicators = ldq_phys(&address_space_memory, dev->indicators->addr);
indicators |= 1ULL << vector;
- stq_phys(&address_space_memory, dev->indicators, indicators);
+ stq_phys(&address_space_memory, dev->indicators->addr, indicators);
css_conditional_io_interrupt(sch);
}
} else {
@@ -972,9 +1009,9 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
return;
}
vector = 0;
- indicators = ldq_phys(&address_space_memory, dev->indicators2);
+ indicators = ldq_phys(&address_space_memory, dev->indicators2->addr);
indicators |= 1ULL << vector;
- stq_phys(&address_space_memory, dev->indicators2, indicators);
+ stq_phys(&address_space_memory, dev->indicators2->addr, indicators);
css_conditional_io_interrupt(sch);
}
}
@@ -995,9 +1032,18 @@ static void virtio_ccw_reset(DeviceState *d)
virtio_ccw_stop_ioeventfd(dev);
virtio_reset(vdev);
css_reset_sch(dev->sch);
- dev->indicators = 0;
- dev->indicators2 = 0;
- dev->summary_indicator = 0;
+ if (dev->indicators) {
+ release_indicator(dev->indicators);
+ dev->indicators = NULL;
+ }
+ if (dev->indicators2) {
+ release_indicator(dev->indicators2);
+ dev->indicators2 = NULL;
+ }
+ if (dev->summary_indicator) {
+ release_indicator(dev->summary_indicator);
+ dev->summary_indicator = NULL;
+ }
}
static void virtio_ccw_vmstate_change(DeviceState *d, bool running)
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 0b70b91..d340bf4 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -75,6 +75,13 @@ typedef struct VirtIOCCWDeviceClass {
#define VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT 1
#define VIRTIO_CCW_FLAG_USE_IOEVENTFD (1 << VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT)
+typedef struct IndAddr {
+ hwaddr addr;
+ unsigned long refcnt;
+ int len;
+ QTAILQ_ENTRY(IndAddr) sibling;
+} IndAddr;
+
struct VirtioCcwDevice {
DeviceState parent_obj;
SubchDev *sch;
@@ -87,9 +94,9 @@ struct VirtioCcwDevice {
uint8_t thinint_isc;
uint32_t adapter_id;
/* Guest provided values: */
- hwaddr indicators;
- hwaddr indicators2;
- hwaddr summary_indicator;
+ IndAddr *indicators;
+ IndAddr *indicators2;
+ IndAddr *summary_indicator;
uint64_t ind_bit;
};
--
1.7.9.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH v5 4/4] s390x/virtio-ccw: Wire up irq routing and irqfds.
2014-05-08 13:03 [Qemu-devel] [PATCH v5 0/4] irqfds for s390x Cornelia Huck
` (2 preceding siblings ...)
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 3/4] s390x/virtio-ccw: reference-counted indicators Cornelia Huck
@ 2014-05-08 13:03 ` Cornelia Huck
2014-05-12 8:58 ` Christian Borntraeger
2014-05-15 13:19 ` Paolo Bonzini
3 siblings, 2 replies; 15+ messages in thread
From: Cornelia Huck @ 2014-05-08 13:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Cornelia Huck, borntraeger, agraf
Make use of the new s390 adapter irq routing support to enable real
in-kernel irqfds for virtio-ccw with adapter interrupts.
Note that s390 doesn't provide the common KVM_CAP_IRQCHIP capability, but
rather needs KVM_CAP_S390_IRQCHIP to be enabled. This is to ensure backward
compatibility.
Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
hw/intc/s390_flic.c | 21 ++++++
hw/intc/s390_flic_kvm.c | 66 +++++++++++++++++
hw/s390x/virtio-ccw.c | 165 ++++++++++++++++++++++++++++++++++++++----
hw/s390x/virtio-ccw.h | 4 +-
include/hw/s390x/adapter.h | 23 ++++++
include/hw/s390x/s390_flic.h | 12 +++
include/qemu/typedefs.h | 1 +
include/sysemu/kvm.h | 2 +
kvm-all.c | 38 +++++++++-
kvm-stub.c | 5 ++
target-s390x/kvm.c | 5 ++
11 files changed, 324 insertions(+), 18 deletions(-)
create mode 100644 include/hw/s390x/adapter.h
diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
index 2b56835..03c5e89 100644
--- a/hw/intc/s390_flic.c
+++ b/hw/intc/s390_flic.c
@@ -52,11 +52,32 @@ static int qemu_s390_register_io_adapter(S390FLICState *fs, uint32_t id,
return 0;
}
+static int qemu_s390_io_adapter_map(S390FLICState *fs, uint32_t id,
+ uint64_t map_addr, bool do_map)
+{
+ /* nothing to do */
+ return 0;
+}
+
+static int qemu_s390_add_adapter_routes(S390FLICState *fs,
+ AdapterRoutes *routes)
+{
+ return -ENOSYS;
+}
+
+static void qemu_s390_release_adapter_routes(S390FLICState *fs,
+ AdapterRoutes *routes)
+{
+}
+
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;
+ 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;
}
static const TypeInfo qemu_s390_flic_info = {
diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
index cc4072e..46c9e61 100644
--- a/hw/intc/s390_flic_kvm.c
+++ b/hw/intc/s390_flic_kvm.c
@@ -16,6 +16,7 @@
#include "sysemu/kvm.h"
#include "migration/qemu-file.h"
#include "hw/s390x/s390_flic.h"
+#include "hw/s390x/adapter.h"
#include "trace.h"
#define FLIC_SAVE_INITIAL_SIZE getpagesize()
@@ -178,6 +179,68 @@ static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id,
return ret;
}
+static int kvm_s390_io_adapter_map(S390FLICState *fs, uint32_t id,
+ uint64_t map_addr, bool do_map)
+{
+ struct kvm_s390_io_adapter_req req = {
+ .id = id,
+ .type = do_map ? KVM_S390_IO_ADAPTER_MAP : KVM_S390_IO_ADAPTER_UNMAP,
+ .addr = map_addr,
+ };
+ struct kvm_device_attr attr = {
+ .group = KVM_DEV_FLIC_ADAPTER_MODIFY,
+ .addr = (uint64_t)&req,
+ };
+ KVMS390FLICState *flic = KVM_S390_FLIC(fs);
+ int r;
+
+ if (!kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING)) {
+ return -ENOSYS;
+ }
+
+ r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
+ return r ? -errno : 0;
+}
+
+static int kvm_s390_add_adapter_routes(S390FLICState *fs,
+ AdapterRoutes *routes)
+{
+ int ret, i;
+ uint64_t ind_offset = routes->adapter.ind_offset;
+
+ for (i = 0; i < routes->num_routes; i++) {
+ ret = kvm_irqchip_add_adapter_route(kvm_state, &routes->adapter);
+ if (ret < 0) {
+ goto out_undo;
+ }
+ routes->gsi[i] = ret;
+ routes->adapter.ind_offset++;
+ }
+ /* Restore passed-in structure to original state. */
+ routes->adapter.ind_offset = ind_offset;
+ return 0;
+out_undo:
+ while (--i >= 0) {
+ kvm_irqchip_release_virq(kvm_state, routes->gsi[i]);
+ routes->gsi[i] = -1;
+ }
+ routes->adapter.ind_offset = ind_offset;
+ return ret;
+}
+
+static void kvm_s390_release_adapter_routes(S390FLICState *fs,
+ AdapterRoutes *routes)
+{
+ int i;
+
+ for (i = 0; i < routes->num_routes; i++) {
+ if (routes->gsi[i] >= 0) {
+ kvm_irqchip_release_virq(kvm_state, routes->gsi[i]);
+ routes->gsi[i] = -1;
+ }
+ }
+}
+
/**
* kvm_flic_save - Save pending floating interrupts
* @f: QEMUFile containing migration state
@@ -337,6 +400,9 @@ static void kvm_s390_flic_class_init(ObjectClass *oc, void *data)
dc->unrealize = kvm_s390_flic_unrealize;
dc->reset = kvm_s390_flic_reset;
fsc->register_io_adapter = kvm_s390_register_io_adapter;
+ 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;
}
static const TypeInfo kvm_s390_flic_info = {
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index d11a783..c4f21d3 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -21,6 +21,8 @@
#include "hw/sysbus.h"
#include "qemu/bitops.h"
#include "hw/virtio/virtio-bus.h"
+#include "hw/s390x/adapter.h"
+#include "hw/s390x/s390_flic.h"
#include "ioinst.h"
#include "css.h"
@@ -48,7 +50,16 @@ static IndAddr *get_indicator(hwaddr ind_addr, int len)
return indicator;
}
-static void release_indicator(IndAddr *indicator)
+static int s390_io_adapter_map(AdapterInfo *adapter, uint64_t map_addr,
+ bool do_map)
+{
+ S390FLICState *fs = s390_get_flic();
+ S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
+
+ return fsc->io_adapter_map(fs, adapter->adapter_id, map_addr, do_map);
+}
+
+static void release_indicator(AdapterInfo *adapter, IndAddr *indicator)
{
assert(indicator->refcnt > 0);
indicator->refcnt--;
@@ -56,9 +67,31 @@ static void release_indicator(IndAddr *indicator)
return;
}
QTAILQ_REMOVE(&indicator_addresses, indicator, sibling);
+ if (indicator->map) {
+ s390_io_adapter_map(adapter, indicator->map, false);
+ }
g_free(indicator);
}
+static int map_indicator(AdapterInfo *adapter, IndAddr *indicator)
+{
+ int ret;
+
+ if (indicator->map) {
+ return 0; /* already mapped is not an error */
+ }
+ indicator->map = indicator->addr;
+ ret = s390_io_adapter_map(adapter, indicator->map, true);
+ if ((ret != 0) && (ret != -ENOSYS)) {
+ goto out_err;
+ }
+ return 0;
+
+out_err:
+ indicator->map = 0;
+ return ret;
+}
+
static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
VirtioCcwDevice *dev);
@@ -554,11 +587,12 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
dev->indicators = get_indicator(thinint->device_indicator,
thinint->ind_bit / 8 + 1);
dev->thinint_isc = thinint->isc;
- dev->ind_bit = thinint->ind_bit;
+ dev->routes.adapter.ind_offset = thinint->ind_bit;
+ dev->routes.adapter.summary_offset = 7;
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);
+ &dev->routes.adapter.adapter_id);
assert(ret == 0);
sch->thinint_active = ((dev->indicators != NULL) &&
(dev->summary_indicator != NULL));
@@ -732,7 +766,7 @@ static int virtio_ccw_exit(VirtioCcwDevice *dev)
g_free(sch);
}
if (dev->indicators) {
- release_indicator(dev->indicators);
+ release_indicator(&dev->routes.adapter, dev->indicators);
dev->indicators = NULL;
}
return 0;
@@ -991,9 +1025,11 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
* ind_bit indicates the start of the indicators in a big
* endian notation.
*/
+ uint64_t ind_bit = dev->routes.adapter.ind_offset;
+
virtio_set_ind_atomic(sch, dev->indicators->addr +
- (dev->ind_bit + vector) / 8,
- 0x80 >> ((dev->ind_bit + vector) % 8));
+ (ind_bit + vector) / 8,
+ 0x80 >> ((ind_bit + vector) % 8));
if (!virtio_set_ind_atomic(sch, dev->summary_indicator->addr,
0x01)) {
css_adapter_interrupt(dev->thinint_isc);
@@ -1033,15 +1069,15 @@ static void virtio_ccw_reset(DeviceState *d)
virtio_reset(vdev);
css_reset_sch(dev->sch);
if (dev->indicators) {
- release_indicator(dev->indicators);
+ release_indicator(&dev->routes.adapter, dev->indicators);
dev->indicators = NULL;
}
if (dev->indicators2) {
- release_indicator(dev->indicators2);
+ release_indicator(&dev->routes.adapter, dev->indicators2);
dev->indicators2 = NULL;
}
if (dev->summary_indicator) {
- release_indicator(dev->summary_indicator);
+ release_indicator(&dev->routes.adapter, dev->summary_indicator);
dev->summary_indicator = NULL;
}
}
@@ -1077,6 +1113,79 @@ static int virtio_ccw_set_host_notifier(DeviceState *d, int n, bool assign)
return virtio_ccw_set_guest2host_notifier(dev, n, assign, false);
}
+static int virtio_ccw_get_mappings(VirtioCcwDevice *dev)
+{
+ int r;
+
+ if (!dev->sch->thinint_active) {
+ return -EINVAL;
+ }
+
+ r = map_indicator(&dev->routes.adapter, dev->summary_indicator);
+ if (r) {
+ return r;
+ }
+ r = map_indicator(&dev->routes.adapter, dev->indicators);
+ if (r) {
+ return r;
+ }
+ dev->routes.adapter.summary_addr = dev->summary_indicator->map;
+ dev->routes.adapter.ind_addr = dev->indicators->map;
+
+ return 0;
+}
+
+static int virtio_ccw_setup_irqroutes(VirtioCcwDevice *dev, int nvqs)
+{
+ int i;
+ VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
+ int ret;
+ S390FLICState *fs = s390_get_flic();
+ S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
+
+ ret = virtio_ccw_get_mappings(dev);
+ if (ret) {
+ return ret;
+ }
+ for (i = 0; i < nvqs; i++) {
+ if (!virtio_queue_get_num(vdev, i)) {
+ break;
+ }
+ }
+ dev->routes.num_routes = i;
+ return fsc->add_adapter_routes(fs, &dev->routes);
+}
+
+static void virtio_ccw_release_irqroutes(VirtioCcwDevice *dev, int nvqs)
+{
+ S390FLICState *fs = s390_get_flic();
+ S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
+
+ fsc->release_adapter_routes(fs, &dev->routes);
+}
+
+static int virtio_ccw_add_irqfd(VirtioCcwDevice *dev, int n)
+{
+ VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
+ VirtQueue *vq = virtio_get_queue(vdev, n);
+ EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
+
+ return kvm_irqchip_add_irqfd_notifier(kvm_state, notifier, NULL,
+ dev->routes.gsi[n]);
+}
+
+static void virtio_ccw_remove_irqfd(VirtioCcwDevice *dev, int n)
+{
+ VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
+ VirtQueue *vq = virtio_get_queue(vdev, n);
+ EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
+ int ret;
+
+ ret = kvm_irqchip_remove_irqfd_notifier(kvm_state, notifier,
+ dev->routes.gsi[n]);
+ assert(ret == 0);
+}
+
static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
bool assign, bool with_irqfd)
{
@@ -1092,11 +1201,17 @@ static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
return r;
}
virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
- /* We do not support irqfd for classic I/O interrupts, because the
- * classic interrupts are intermixed with the subchannel status, that
- * is queried with test subchannel. We want to use vhost, though.
- * Lets make sure to have vhost running and wire up the irq fd to
- * land in qemu (and only the irq fd) in this code.
+ if (with_irqfd) {
+ r = virtio_ccw_add_irqfd(dev, n);
+ if (r) {
+ virtio_queue_set_guest_notifier_fd_handler(vq, false,
+ with_irqfd);
+ return r;
+ }
+ }
+ /*
+ * We do not support individual masking for channel devices, so we
+ * need to manually trigger any guest masking callbacks here.
*/
if (k->guest_notifier_mask) {
k->guest_notifier_mask(vdev, n, false);
@@ -1110,6 +1225,9 @@ static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
if (k->guest_notifier_mask) {
k->guest_notifier_mask(vdev, n, true);
}
+ if (with_irqfd) {
+ virtio_ccw_remove_irqfd(dev, n);
+ }
virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
event_notifier_cleanup(notifier);
}
@@ -1121,24 +1239,39 @@ static int virtio_ccw_set_guest_notifiers(DeviceState *d, int nvqs,
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
+ bool with_irqfd = dev->sch->thinint_active && kvm_irqfds_enabled();
int r, n;
+ if (with_irqfd && assigned) {
+ /* irq routes need to be set up before assigning irqfds */
+ r = virtio_ccw_setup_irqroutes(dev, nvqs);
+ if (r < 0) {
+ goto irqroute_error;
+ }
+ }
for (n = 0; n < nvqs; n++) {
if (!virtio_queue_get_num(vdev, n)) {
break;
}
- /* false -> true, as soon as irqfd works */
- r = virtio_ccw_set_guest_notifier(dev, n, assigned, false);
+ r = virtio_ccw_set_guest_notifier(dev, n, assigned, with_irqfd);
if (r < 0) {
goto assign_error;
}
}
+ if (with_irqfd && !assigned) {
+ /* release irq routes after irqfds have been released */
+ virtio_ccw_release_irqroutes(dev, nvqs);
+ }
return 0;
assign_error:
while (--n >= 0) {
virtio_ccw_set_guest_notifier(dev, n, !assigned, false);
}
+irqroute_error:
+ if (with_irqfd && assigned) {
+ virtio_ccw_release_irqroutes(dev, nvqs);
+ }
return r;
}
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index d340bf4..b8b8a8a 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -22,6 +22,7 @@
#include <hw/virtio/virtio-balloon.h>
#include <hw/virtio/virtio-rng.h>
#include <hw/virtio/virtio-bus.h>
+#include <hw/s390x/s390_flic.h>
#define VIRTUAL_CSSID 0xfe
@@ -77,6 +78,7 @@ typedef struct VirtIOCCWDeviceClass {
typedef struct IndAddr {
hwaddr addr;
+ uint64_t map;
unsigned long refcnt;
int len;
QTAILQ_ENTRY(IndAddr) sibling;
@@ -92,7 +94,7 @@ struct VirtioCcwDevice {
bool ioeventfd_disabled;
uint32_t flags;
uint8_t thinint_isc;
- uint32_t adapter_id;
+ AdapterRoutes routes;
/* Guest provided values: */
IndAddr *indicators;
IndAddr *indicators2;
diff --git a/include/hw/s390x/adapter.h b/include/hw/s390x/adapter.h
new file mode 100644
index 0000000..7e56724
--- /dev/null
+++ b/include/hw/s390x/adapter.h
@@ -0,0 +1,23 @@
+/*
+ * s390 adapter definitions
+ *
+ * Copyright 2013 IBM Corp.
+ * Author(s): Cornelia Huck <cornelia.huck@de.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.
+ */
+
+#ifndef S390X_ADAPTER_H
+#define S390X_ADAPTER_H
+
+struct AdapterInfo {
+ uint64_t ind_addr;
+ uint64_t summary_addr;
+ uint64_t ind_offset;
+ uint32_t summary_offset;
+ uint32_t adapter_id;
+};
+
+#endif
diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h
index 83913ec..489d73b 100644
--- a/include/hw/s390x/s390_flic.h
+++ b/include/hw/s390x/s390_flic.h
@@ -14,6 +14,14 @@
#define __HW_S390_FLIC_H
#include "hw/sysbus.h"
+#include "hw/s390x/adapter.h"
+#include "hw/virtio/virtio.h"
+
+typedef struct AdapterRoutes {
+ AdapterInfo adapter;
+ int num_routes;
+ int gsi[VIRTIO_PCI_QUEUE_MAX];
+} AdapterRoutes;
#define TYPE_S390_FLIC_COMMON "s390-flic"
#define S390_FLIC_COMMON(obj) \
@@ -34,6 +42,10 @@ typedef struct S390FLICStateClass {
int (*register_io_adapter)(S390FLICState *fs, uint32_t id, uint8_t isc,
bool swap, bool maskable);
+ int (*io_adapter_map)(S390FLICState *fs, uint32_t id, uint64_t map_addr,
+ bool do_map);
+ int (*add_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes);
+ void (*release_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes);
} S390FLICStateClass;
#define TYPE_KVM_S390_FLIC "s390-flic-kvm"
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 86bab12..5f20b0e 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -74,5 +74,6 @@ typedef struct SHPCDevice SHPCDevice;
typedef struct FWCfgState FWCfgState;
typedef struct PcGuestInfo PcGuestInfo;
typedef struct Range Range;
+typedef struct AdapterInfo AdapterInfo;
#endif /* QEMU_TYPEDEFS_H */
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 5ad4e0e..d219246 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -365,6 +365,8 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg);
void kvm_irqchip_release_virq(KVMState *s, int virq);
+int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter);
+
int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
EventNotifier *rn, int virq);
int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
diff --git a/kvm-all.c b/kvm-all.c
index 5cb7f26..51983bf 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -27,6 +27,7 @@
#include "sysemu/sysemu.h"
#include "hw/hw.h"
#include "hw/pci/msi.h"
+#include "hw/s390x/adapter.h"
#include "exec/gdbstub.h"
#include "sysemu/kvm.h"
#include "qemu/bswap.h"
@@ -1247,6 +1248,35 @@ static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int rfd, int virq,
return kvm_vm_ioctl(s, KVM_IRQFD, &irqfd);
}
+int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter)
+{
+ struct kvm_irq_routing_entry kroute;
+ int virq;
+
+ if (!kvm_gsi_routing_enabled()) {
+ return -ENOSYS;
+ }
+
+ virq = kvm_irqchip_get_virq(s);
+ if (virq < 0) {
+ return virq;
+ }
+
+ kroute.gsi = virq;
+ kroute.type = KVM_IRQ_ROUTING_S390_ADAPTER;
+ kroute.flags = 0;
+ kroute.u.adapter.summary_addr = adapter->summary_addr;
+ kroute.u.adapter.ind_addr = adapter->ind_addr;
+ kroute.u.adapter.summary_offset = adapter->summary_offset;
+ kroute.u.adapter.ind_offset = adapter->ind_offset;
+ kroute.u.adapter.adapter_id = adapter->adapter_id;
+
+ kvm_add_routing_entry(s, &kroute);
+ kvm_irqchip_commit_routes(s);
+
+ return virq;
+}
+
#else /* !KVM_CAP_IRQ_ROUTING */
void kvm_init_irq_routing(KVMState *s)
@@ -1267,6 +1297,11 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
return -ENOSYS;
}
+int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter)
+{
+ return -ENOSYS;
+}
+
static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign)
{
abort();
@@ -1296,7 +1331,8 @@ static int kvm_irqchip_create(KVMState *s)
int ret;
if (!qemu_opt_get_bool(qemu_get_machine_opts(), "kernel_irqchip", true) ||
- !kvm_check_extension(s, KVM_CAP_IRQCHIP)) {
+ (!kvm_check_extension(s, KVM_CAP_IRQCHIP) &&
+ (kvm_vm_enable_cap(s, KVM_CAP_S390_IRQCHIP, 0) < 0))) {
return 0;
}
diff --git a/kvm-stub.c b/kvm-stub.c
index 8acda86..ac33d86 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -136,6 +136,11 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg)
return -ENOSYS;
}
+int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter)
+{
+ return -ENOSYS;
+}
+
int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
EventNotifier *rn, int virq)
{
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index b7b0edc..43859e9 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -938,6 +938,11 @@ void kvm_s390_enable_css_support(S390CPU *cpu)
void kvm_arch_init_irq_routing(KVMState *s)
{
+ if (kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) {
+ kvm_irqfds_allowed = true;
+ kvm_gsi_routing_allowed = true;
+ kvm_halt_in_kernel_allowed = false;
+ }
}
int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v5 1/4] s390x: split flic into kvm and non-kvm parts
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 1/4] s390x: split flic into kvm and non-kvm parts Cornelia Huck
@ 2014-05-08 13:43 ` Alexander Graf
2014-05-08 13:56 ` Cornelia Huck
2014-05-12 8:01 ` Christian Borntraeger
1 sibling, 1 reply; 15+ messages in thread
From: Alexander Graf @ 2014-05-08 13:43 UTC (permalink / raw)
To: Cornelia Huck; +Cc: borntraeger, qemu-devel
On 05/08/2014 03:03 PM, Cornelia Huck wrote:
> Introduce a common parent class for both cases, where kvm and non-kvm
> can hook up callbacks. This will be used by follow-on patches for
> adapter registration and mapping.
>
> We now always have a flic, regardless of whether we use kvm; the
> non-kvm implementation just doesn't do anything.
>
> Reviewed-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> ---
> default-configs/s390x-softmmu.mak | 3 +-
> hw/intc/Makefile.objs | 1 +
> hw/intc/s390_flic.c | 318 ++++--------------------------------
> hw/intc/s390_flic_kvm.c | 325 +++++++++++++++++++++++++++++++++++++
> include/hw/s390x/s390_flic.h | 51 ++++--
> 5 files changed, 399 insertions(+), 299 deletions(-)
> create mode 100644 hw/intc/s390_flic_kvm.c
>
> diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak
> index d843dc0..126d88d 100644
> --- a/default-configs/s390x-softmmu.mak
> +++ b/default-configs/s390x-softmmu.mak
> @@ -1,3 +1,4 @@
> CONFIG_VIRTIO=y
> CONFIG_SCLPCONSOLE=y
> -CONFIG_S390_FLIC=$(CONFIG_KVM)
> +CONFIG_S390_FLIC=y
> +CONFIG_S390_FLIC_KVM=$(CONFIG_KVM)
> diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
> index c8a2318..843864a 100644
> --- a/hw/intc/Makefile.objs
> +++ b/hw/intc/Makefile.objs
> @@ -26,3 +26,4 @@ obj-$(CONFIG_XICS) += xics.o
> obj-$(CONFIG_XICS_KVM) += xics_kvm.o
> obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
> obj-$(CONFIG_S390_FLIC) += s390_flic.o
> +obj-$(CONFIG_S390_FLIC_KVM) += s390_flic_kvm.o
> diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
> index b2ef3e3..7dc8c7d 100644
> --- a/hw/intc/s390_flic.c
> +++ b/hw/intc/s390_flic.c
> @@ -1,322 +1,66 @@
> /*
> - * QEMU S390x KVM floating interrupt controller (flic)
> + * QEMU S390x floating interrupt controller (flic)
> *
> * Copyright 2014 IBM Corp.
> * Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com>
> + * Cornelia Huck <cornelia.huck@de.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 <sys/ioctl.h>
> #include "qemu/error-report.h"
> #include "hw/sysbus.h"
> -#include "sysemu/kvm.h"
> #include "migration/qemu-file.h"
> #include "hw/s390x/s390_flic.h"
> #include "trace.h"
>
> -#define FLIC_SAVE_INITIAL_SIZE getpagesize()
> -#define FLIC_FAILED (-1UL)
> -#define FLIC_SAVEVM_VERSION 1
> -
> -void s390_flic_init(void)
> -{
> - DeviceState *dev;
> - int r;
> -
> - if (kvm_enabled()) {
> - dev = qdev_create(NULL, "s390-flic");
> - object_property_add_child(qdev_get_machine(), "s390-flic",
> - OBJECT(dev), NULL);
> - r = qdev_init(dev);
> - if (r) {
> - error_report("flic: couldn't create qdev");
> - }
> - }
> -}
> -
> -/**
> - * flic_get_all_irqs - store all pending irqs in buffer
> - * @buf: pointer to buffer which is passed to kernel
> - * @len: length of buffer
> - * @flic: pointer to flic device state
> - *
> - * Returns: -ENOMEM if buffer is too small,
> - * -EINVAL if attr.group is invalid,
> - * -EFAULT if copying to userspace failed,
> - * on success return number of stored interrupts
> - */
> -static int flic_get_all_irqs(KVMS390FLICState *flic,
> - void *buf, int len)
> -{
> - struct kvm_device_attr attr = {
> - .group = KVM_DEV_FLIC_GET_ALL_IRQS,
> - .addr = (uint64_t) buf,
> - .attr = len,
> - };
> - int rc;
> -
> - rc = ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr);
> -
> - return rc == -1 ? -errno : rc;
> -}
> -
> -static void flic_enable_pfault(KVMS390FLICState *flic)
> -{
> - struct kvm_device_attr attr = {
> - .group = KVM_DEV_FLIC_APF_ENABLE,
> - };
> - int rc;
> -
> - rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
> -
> - if (rc) {
> - fprintf(stderr, "flic: couldn't enable pfault\n");
> - }
> -}
> -
> -static void flic_disable_wait_pfault(KVMS390FLICState *flic)
> +S390FLICState *s390_get_flic(void)
> {
> - struct kvm_device_attr attr = {
> - .group = KVM_DEV_FLIC_APF_DISABLE_WAIT,
> - };
> - int rc;
> -
> - rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
> + S390FLICState *fs;
>
> - if (rc) {
> - fprintf(stderr, "flic: couldn't disable pfault\n");
> + fs = S390_FLIC_COMMON(object_resolve_path(TYPE_KVM_S390_FLIC, NULL));
> + if (!fs) {
> + fs = S390_FLIC_COMMON(object_resolve_path(TYPE_QEMU_S390_FLIC, NULL));
> }
> + return fs;
> }
>
> -/** flic_enqueue_irqs - returns 0 on success
> - * @buf: pointer to buffer which is passed to kernel
> - * @len: length of buffer
> - * @flic: pointer to flic device state
> - *
> - * Returns: -EINVAL if attr.group is unknown
> - */
> -static int flic_enqueue_irqs(void *buf, uint64_t len,
> - KVMS390FLICState *flic)
> -{
> - int rc;
> - struct kvm_device_attr attr = {
> - .group = KVM_DEV_FLIC_ENQUEUE,
> - .addr = (uint64_t) buf,
> - .attr = len,
> - };
> -
> - 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
> - * @buf: pointer to pointer to a buffer
> - * @len: length of buffer
> - *
> - * Returns: return value of flic_get_all_irqs
> - * Note: Retry and increase buffer size until flic_get_all_irqs
> - * either returns a value >= 0 or a negative error code.
> - * -ENOMEM is an exception, which means the buffer is too small
> - * and we should try again. Other negative error codes can be
> - * -EFAULT and -EINVAL which we ignore at this point
> - */
> -static int __get_all_irqs(KVMS390FLICState *flic,
> - void **buf, int len)
> +void s390_flic_init(void)
> {
> + DeviceState *dev;
> int r;
>
> - do {
> - /* returns -ENOMEM if buffer is too small and number
> - * of queued interrupts on success */
> - r = flic_get_all_irqs(flic, *buf, len);
> - if (r >= 0) {
> - break;
> - }
> - len *= 2;
> - *buf = g_try_realloc(*buf, len);
> - if (!buf) {
> - return -ENOMEM;
> - }
> - } while (r == -ENOMEM && len <= KVM_S390_FLIC_MAX_BUFFER);
> -
> - return r;
> -}
> -
> -/**
> - * kvm_flic_save - Save pending floating interrupts
> - * @f: QEMUFile containing migration state
> - * @opaque: pointer to flic device state
> - *
> - * Note: Pass buf and len to kernel. Start with one page and
> - * increase until buffer is sufficient or maxium size is
> - * reached
> - */
> -static void kvm_flic_save(QEMUFile *f, void *opaque)
> -{
> - KVMS390FLICState *flic = opaque;
> - int len = FLIC_SAVE_INITIAL_SIZE;
> - void *buf;
> - int count;
> -
> - flic_disable_wait_pfault((struct KVMS390FLICState *) opaque);
> -
> - buf = g_try_malloc0(len);
> - if (!buf) {
> - /* Storing FLIC_FAILED into the count field here will cause the
> - * target system to fail when attempting to load irqs from the
> - * migration state */
> - error_report("flic: couldn't allocate memory");
> - qemu_put_be64(f, FLIC_FAILED);
> - return;
> + dev = s390_flic_kvm_create();
Why have this helper? Can't that logic live in the board file?
Alex
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v5 1/4] s390x: split flic into kvm and non-kvm parts
2014-05-08 13:43 ` Alexander Graf
@ 2014-05-08 13:56 ` Cornelia Huck
0 siblings, 0 replies; 15+ messages in thread
From: Cornelia Huck @ 2014-05-08 13:56 UTC (permalink / raw)
To: Alexander Graf; +Cc: borntraeger, qemu-devel
On Thu, 08 May 2014 15:43:05 +0200
Alexander Graf <agraf@suse.de> wrote:
> On 05/08/2014 03:03 PM, Cornelia Huck wrote:
> > Introduce a common parent class for both cases, where kvm and non-kvm
> > can hook up callbacks. This will be used by follow-on patches for
> > adapter registration and mapping.
> >
> > We now always have a flic, regardless of whether we use kvm; the
> > non-kvm implementation just doesn't do anything.
> >
> > Reviewed-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
> > Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> > ---
> > default-configs/s390x-softmmu.mak | 3 +-
> > hw/intc/Makefile.objs | 1 +
> > hw/intc/s390_flic.c | 318 ++++--------------------------------
> > hw/intc/s390_flic_kvm.c | 325 +++++++++++++++++++++++++++++++++++++
> > include/hw/s390x/s390_flic.h | 51 ++++--
> > 5 files changed, 399 insertions(+), 299 deletions(-)
> > create mode 100644 hw/intc/s390_flic_kvm.c
> >
> > diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
> > index b2ef3e3..7dc8c7d 100644
> > --- a/hw/intc/s390_flic.c
> > +++ b/hw/intc/s390_flic.c
> > +void s390_flic_init(void)
> > {
> > + DeviceState *dev;
> > int r;
> > + dev = s390_flic_kvm_create();
>
> Why have this helper? Can't that logic live in the board file?
It could; but I think it is cleaner to contain this in the flic than to
have kvm-switches there.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v5 1/4] s390x: split flic into kvm and non-kvm parts
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 1/4] s390x: split flic into kvm and non-kvm parts Cornelia Huck
2014-05-08 13:43 ` Alexander Graf
@ 2014-05-12 8:01 ` Christian Borntraeger
2014-05-12 8:09 ` Cornelia Huck
1 sibling, 1 reply; 15+ messages in thread
From: Christian Borntraeger @ 2014-05-12 8:01 UTC (permalink / raw)
To: Cornelia Huck, qemu-devel; +Cc: agraf
On 08/05/14 15:03, Cornelia Huck wrote:
> Introduce a common parent class for both cases, where kvm and non-kvm
> can hook up callbacks. This will be used by follow-on patches for
> adapter registration and mapping.
>
> We now always have a flic, regardless of whether we use kvm; the
> non-kvm implementation just doesn't do anything.
>
> Reviewed-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> ---
> default-configs/s390x-softmmu.mak | 3 +-
> hw/intc/Makefile.objs | 1 +
> hw/intc/s390_flic.c | 318 ++++--------------------------------
> hw/intc/s390_flic_kvm.c | 325 +++++++++++++++++++++++++++++++++++++
> include/hw/s390x/s390_flic.h | 51 ++++--
Shouldnt we move this to include/hw/intc/ ?
Otherwise:
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
> 5 files changed, 399 insertions(+), 299 deletions(-)
> create mode 100644 hw/intc/s390_flic_kvm.c
>
> diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak
> index d843dc0..126d88d 100644
> --- a/default-configs/s390x-softmmu.mak
> +++ b/default-configs/s390x-softmmu.mak
> @@ -1,3 +1,4 @@
> CONFIG_VIRTIO=y
> CONFIG_SCLPCONSOLE=y
> -CONFIG_S390_FLIC=$(CONFIG_KVM)
> +CONFIG_S390_FLIC=y
> +CONFIG_S390_FLIC_KVM=$(CONFIG_KVM)
> diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
> index c8a2318..843864a 100644
> --- a/hw/intc/Makefile.objs
> +++ b/hw/intc/Makefile.objs
> @@ -26,3 +26,4 @@ obj-$(CONFIG_XICS) += xics.o
> obj-$(CONFIG_XICS_KVM) += xics_kvm.o
> obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
> obj-$(CONFIG_S390_FLIC) += s390_flic.o
> +obj-$(CONFIG_S390_FLIC_KVM) += s390_flic_kvm.o
> diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
> index b2ef3e3..7dc8c7d 100644
> --- a/hw/intc/s390_flic.c
> +++ b/hw/intc/s390_flic.c
> @@ -1,322 +1,66 @@
> /*
> - * QEMU S390x KVM floating interrupt controller (flic)
> + * QEMU S390x floating interrupt controller (flic)
> *
> * Copyright 2014 IBM Corp.
> * Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com>
> + * Cornelia Huck <cornelia.huck@de.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 <sys/ioctl.h>
> #include "qemu/error-report.h"
> #include "hw/sysbus.h"
> -#include "sysemu/kvm.h"
> #include "migration/qemu-file.h"
> #include "hw/s390x/s390_flic.h"
> #include "trace.h"
>
> -#define FLIC_SAVE_INITIAL_SIZE getpagesize()
> -#define FLIC_FAILED (-1UL)
> -#define FLIC_SAVEVM_VERSION 1
> -
> -void s390_flic_init(void)
> -{
> - DeviceState *dev;
> - int r;
> -
> - if (kvm_enabled()) {
> - dev = qdev_create(NULL, "s390-flic");
> - object_property_add_child(qdev_get_machine(), "s390-flic",
> - OBJECT(dev), NULL);
> - r = qdev_init(dev);
> - if (r) {
> - error_report("flic: couldn't create qdev");
> - }
> - }
> -}
> -
> -/**
> - * flic_get_all_irqs - store all pending irqs in buffer
> - * @buf: pointer to buffer which is passed to kernel
> - * @len: length of buffer
> - * @flic: pointer to flic device state
> - *
> - * Returns: -ENOMEM if buffer is too small,
> - * -EINVAL if attr.group is invalid,
> - * -EFAULT if copying to userspace failed,
> - * on success return number of stored interrupts
> - */
> -static int flic_get_all_irqs(KVMS390FLICState *flic,
> - void *buf, int len)
> -{
> - struct kvm_device_attr attr = {
> - .group = KVM_DEV_FLIC_GET_ALL_IRQS,
> - .addr = (uint64_t) buf,
> - .attr = len,
> - };
> - int rc;
> -
> - rc = ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr);
> -
> - return rc == -1 ? -errno : rc;
> -}
> -
> -static void flic_enable_pfault(KVMS390FLICState *flic)
> -{
> - struct kvm_device_attr attr = {
> - .group = KVM_DEV_FLIC_APF_ENABLE,
> - };
> - int rc;
> -
> - rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
> -
> - if (rc) {
> - fprintf(stderr, "flic: couldn't enable pfault\n");
> - }
> -}
> -
> -static void flic_disable_wait_pfault(KVMS390FLICState *flic)
> +S390FLICState *s390_get_flic(void)
> {
> - struct kvm_device_attr attr = {
> - .group = KVM_DEV_FLIC_APF_DISABLE_WAIT,
> - };
> - int rc;
> -
> - rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
> + S390FLICState *fs;
>
> - if (rc) {
> - fprintf(stderr, "flic: couldn't disable pfault\n");
> + fs = S390_FLIC_COMMON(object_resolve_path(TYPE_KVM_S390_FLIC, NULL));
> + if (!fs) {
> + fs = S390_FLIC_COMMON(object_resolve_path(TYPE_QEMU_S390_FLIC, NULL));
> }
> + return fs;
> }
>
> -/** flic_enqueue_irqs - returns 0 on success
> - * @buf: pointer to buffer which is passed to kernel
> - * @len: length of buffer
> - * @flic: pointer to flic device state
> - *
> - * Returns: -EINVAL if attr.group is unknown
> - */
> -static int flic_enqueue_irqs(void *buf, uint64_t len,
> - KVMS390FLICState *flic)
> -{
> - int rc;
> - struct kvm_device_attr attr = {
> - .group = KVM_DEV_FLIC_ENQUEUE,
> - .addr = (uint64_t) buf,
> - .attr = len,
> - };
> -
> - 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
> - * @buf: pointer to pointer to a buffer
> - * @len: length of buffer
> - *
> - * Returns: return value of flic_get_all_irqs
> - * Note: Retry and increase buffer size until flic_get_all_irqs
> - * either returns a value >= 0 or a negative error code.
> - * -ENOMEM is an exception, which means the buffer is too small
> - * and we should try again. Other negative error codes can be
> - * -EFAULT and -EINVAL which we ignore at this point
> - */
> -static int __get_all_irqs(KVMS390FLICState *flic,
> - void **buf, int len)
> +void s390_flic_init(void)
> {
> + DeviceState *dev;
> int r;
>
> - do {
> - /* returns -ENOMEM if buffer is too small and number
> - * of queued interrupts on success */
> - r = flic_get_all_irqs(flic, *buf, len);
> - if (r >= 0) {
> - break;
> - }
> - len *= 2;
> - *buf = g_try_realloc(*buf, len);
> - if (!buf) {
> - return -ENOMEM;
> - }
> - } while (r == -ENOMEM && len <= KVM_S390_FLIC_MAX_BUFFER);
> -
> - return r;
> -}
> -
> -/**
> - * kvm_flic_save - Save pending floating interrupts
> - * @f: QEMUFile containing migration state
> - * @opaque: pointer to flic device state
> - *
> - * Note: Pass buf and len to kernel. Start with one page and
> - * increase until buffer is sufficient or maxium size is
> - * reached
> - */
> -static void kvm_flic_save(QEMUFile *f, void *opaque)
> -{
> - KVMS390FLICState *flic = opaque;
> - int len = FLIC_SAVE_INITIAL_SIZE;
> - void *buf;
> - int count;
> -
> - flic_disable_wait_pfault((struct KVMS390FLICState *) opaque);
> -
> - buf = g_try_malloc0(len);
> - if (!buf) {
> - /* Storing FLIC_FAILED into the count field here will cause the
> - * target system to fail when attempting to load irqs from the
> - * migration state */
> - error_report("flic: couldn't allocate memory");
> - qemu_put_be64(f, FLIC_FAILED);
> - return;
> + dev = s390_flic_kvm_create();
> + if (!dev) {
> + dev = qdev_create(NULL, TYPE_QEMU_S390_FLIC);
> + object_property_add_child(qdev_get_machine(), TYPE_QEMU_S390_FLIC,
> + OBJECT(dev), NULL);
> }
> -
> - count = __get_all_irqs(flic, &buf, len);
> - if (count < 0) {
> - error_report("flic: couldn't retrieve irqs from kernel, rc %d",
> - count);
> - /* Storing FLIC_FAILED into the count field here will cause the
> - * target system to fail when attempting to load irqs from the
> - * migration state */
> - qemu_put_be64(f, FLIC_FAILED);
> - } else {
> - qemu_put_be64(f, count);
> - qemu_put_buffer(f, (uint8_t *) buf,
> - count * sizeof(struct kvm_s390_irq));
> + r = qdev_init(dev);
> + if (r) {
> + error_report("flic: couldn't create qdev");
> }
> - g_free(buf);
> }
>
> -/**
> - * kvm_flic_load - Load pending floating interrupts
> - * @f: QEMUFile containing migration state
> - * @opaque: pointer to flic device state
> - * @version_id: version id for migration
> - *
> - * Returns: value of flic_enqueue_irqs, -EINVAL on error
> - * Note: Do nothing when no interrupts where stored
> - * in QEMUFile
> - */
> -static int kvm_flic_load(QEMUFile *f, void *opaque, int version_id)
> -{
> - uint64_t len = 0;
> - uint64_t count = 0;
> - void *buf = NULL;
> - int r = 0;
> -
> - if (version_id != FLIC_SAVEVM_VERSION) {
> - r = -EINVAL;
> - goto out;
> - }
> -
> - flic_enable_pfault((struct KVMS390FLICState *) opaque);
> -
> - count = qemu_get_be64(f);
> - len = count * sizeof(struct kvm_s390_irq);
> - if (count == FLIC_FAILED) {
> - r = -EINVAL;
> - goto out;
> - }
> - if (count == 0) {
> - r = 0;
> - goto out;
> - }
> - buf = g_try_malloc0(len);
> - if (!buf) {
> - r = -ENOMEM;
> - goto out;
> - }
> -
> - if (qemu_get_buffer(f, (uint8_t *) buf, len) != len) {
> - r = -EINVAL;
> - goto out_free;
> - }
> - r = flic_enqueue_irqs(buf, len, (struct KVMS390FLICState *) opaque);
> -
> -out_free:
> - g_free(buf);
> -out:
> - 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)) {
> - trace_flic_no_device_api(errno);
> - return;
> - }
> -
> - cd.type = KVM_DEV_TYPE_FLIC;
> - ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd);
> - if (ret < 0) {
> - trace_flic_create_device(errno);
> - return;
> - }
> - flic_state->fd = cd.fd;
> -
> - /* Register savevm handler for floating interrupts */
> - register_savevm(NULL, "s390-flic", 0, 1, kvm_flic_save,
> - kvm_flic_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), "s390-flic", flic_state);
> -}
> -
> -static void kvm_s390_flic_reset(DeviceState *dev)
> -{
> - KVMS390FLICState *flic = KVM_S390_FLIC(dev);
> - struct kvm_device_attr attr = {
> - .group = KVM_DEV_FLIC_CLEAR_IRQS,
> - };
> - int rc = 0;
> -
> - if (flic->fd == -1) {
> - return;
> - }
> -
> - flic_disable_wait_pfault(flic);
> -
> - rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
> - if (rc) {
> - trace_flic_reset_failed(errno);
> - }
> -
> - flic_enable_pfault(flic);
> -}
> -
> -static void kvm_s390_flic_class_init(ObjectClass *oc, void *data)
> -{
> - DeviceClass *dc = DEVICE_CLASS(oc);
> -
> - dc->realize = kvm_s390_flic_realize;
> - dc->unrealize = kvm_s390_flic_unrealize;
> - dc->reset = kvm_s390_flic_reset;
> -}
> +static const TypeInfo qemu_s390_flic_info = {
> + .name = TYPE_QEMU_S390_FLIC,
> + .parent = TYPE_S390_FLIC_COMMON,
> + .instance_size = sizeof(QEMUS390FLICState),
> +};
>
> -static const TypeInfo kvm_s390_flic_info = {
> - .name = TYPE_KVM_S390_FLIC,
> +static const TypeInfo s390_flic_common_info = {
> + .name = TYPE_S390_FLIC_COMMON,
> .parent = TYPE_SYS_BUS_DEVICE,
> - .instance_size = sizeof(KVMS390FLICState),
> - .class_init = kvm_s390_flic_class_init,
> + .instance_size = sizeof(S390FLICState),
> + .class_size = sizeof(S390FLICStateClass),
> };
>
> -static void kvm_s390_flic_register_types(void)
> +static void qemu_s390_flic_register_types(void)
> {
> - type_register_static(&kvm_s390_flic_info);
> + type_register_static(&s390_flic_common_info);
> + type_register_static(&qemu_s390_flic_info);
> }
>
> -type_init(kvm_s390_flic_register_types)
> +type_init(qemu_s390_flic_register_types)
> diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
> new file mode 100644
> index 0000000..70c1710
> --- /dev/null
> +++ b/hw/intc/s390_flic_kvm.c
> @@ -0,0 +1,325 @@
> +/*
> + * QEMU S390x KVM floating interrupt controller (flic)
> + *
> + * Copyright 2014 IBM Corp.
> + * Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com>
> + * Cornelia Huck <cornelia.huck@de.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 <sys/ioctl.h>
> +#include "qemu/error-report.h"
> +#include "hw/sysbus.h"
> +#include "sysemu/kvm.h"
> +#include "migration/qemu-file.h"
> +#include "hw/s390x/s390_flic.h"
> +#include "trace.h"
> +
> +#define FLIC_SAVE_INITIAL_SIZE getpagesize()
> +#define FLIC_FAILED (-1UL)
> +#define FLIC_SAVEVM_VERSION 1
> +
> +typedef struct KVMS390FLICState {
> + S390FLICState parent_obj;
> +
> + uint32_t fd;
> +} KVMS390FLICState;
> +
> +DeviceState *s390_flic_kvm_create(void)
> +{
> + DeviceState *dev = NULL;
> +
> + if (kvm_enabled()) {
> + dev = qdev_create(NULL, TYPE_KVM_S390_FLIC);
> + object_property_add_child(qdev_get_machine(), TYPE_KVM_S390_FLIC,
> + OBJECT(dev), NULL);
> + }
> + return dev;
> +}
> +
> +/**
> + * flic_get_all_irqs - store all pending irqs in buffer
> + * @buf: pointer to buffer which is passed to kernel
> + * @len: length of buffer
> + * @flic: pointer to flic device state
> + *
> + * Returns: -ENOMEM if buffer is too small,
> + * -EINVAL if attr.group is invalid,
> + * -EFAULT if copying to userspace failed,
> + * on success return number of stored interrupts
> + */
> +static int flic_get_all_irqs(KVMS390FLICState *flic,
> + void *buf, int len)
> +{
> + struct kvm_device_attr attr = {
> + .group = KVM_DEV_FLIC_GET_ALL_IRQS,
> + .addr = (uint64_t) buf,
> + .attr = len,
> + };
> + int rc;
> +
> + rc = ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr);
> +
> + return rc == -1 ? -errno : rc;
> +}
> +
> +static void flic_enable_pfault(KVMS390FLICState *flic)
> +{
> + struct kvm_device_attr attr = {
> + .group = KVM_DEV_FLIC_APF_ENABLE,
> + };
> + int rc;
> +
> + rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
> +
> + if (rc) {
> + fprintf(stderr, "flic: couldn't enable pfault\n");
> + }
> +}
> +
> +static void flic_disable_wait_pfault(KVMS390FLICState *flic)
> +{
> + struct kvm_device_attr attr = {
> + .group = KVM_DEV_FLIC_APF_DISABLE_WAIT,
> + };
> + int rc;
> +
> + rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
> +
> + if (rc) {
> + fprintf(stderr, "flic: couldn't disable pfault\n");
> + }
> +}
> +
> +/** flic_enqueue_irqs - returns 0 on success
> + * @buf: pointer to buffer which is passed to kernel
> + * @len: length of buffer
> + * @flic: pointer to flic device state
> + *
> + * Returns: -EINVAL if attr.group is unknown
> + */
> +static int flic_enqueue_irqs(void *buf, uint64_t len,
> + KVMS390FLICState *flic)
> +{
> + int rc;
> + struct kvm_device_attr attr = {
> + .group = KVM_DEV_FLIC_ENQUEUE,
> + .addr = (uint64_t) buf,
> + .attr = len,
> + };
> +
> + 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
> + * @buf: pointer to pointer to a buffer
> + * @len: length of buffer
> + *
> + * Returns: return value of flic_get_all_irqs
> + * Note: Retry and increase buffer size until flic_get_all_irqs
> + * either returns a value >= 0 or a negative error code.
> + * -ENOMEM is an exception, which means the buffer is too small
> + * and we should try again. Other negative error codes can be
> + * -EFAULT and -EINVAL which we ignore at this point
> + */
> +static int __get_all_irqs(KVMS390FLICState *flic,
> + void **buf, int len)
> +{
> + int r;
> +
> + do {
> + /* returns -ENOMEM if buffer is too small and number
> + * of queued interrupts on success */
> + r = flic_get_all_irqs(flic, *buf, len);
> + if (r >= 0) {
> + break;
> + }
> + len *= 2;
> + *buf = g_try_realloc(*buf, len);
> + if (!buf) {
> + return -ENOMEM;
> + }
> + } while (r == -ENOMEM && len <= KVM_S390_FLIC_MAX_BUFFER);
> +
> + return r;
> +}
> +
> +/**
> + * kvm_flic_save - Save pending floating interrupts
> + * @f: QEMUFile containing migration state
> + * @opaque: pointer to flic device state
> + *
> + * Note: Pass buf and len to kernel. Start with one page and
> + * increase until buffer is sufficient or maxium size is
> + * reached
> + */
> +static void kvm_flic_save(QEMUFile *f, void *opaque)
> +{
> + KVMS390FLICState *flic = opaque;
> + int len = FLIC_SAVE_INITIAL_SIZE;
> + void *buf;
> + int count;
> +
> + flic_disable_wait_pfault((struct KVMS390FLICState *) opaque);
> +
> + buf = g_try_malloc0(len);
> + if (!buf) {
> + /* Storing FLIC_FAILED into the count field here will cause the
> + * target system to fail when attempting to load irqs from the
> + * migration state */
> + error_report("flic: couldn't allocate memory");
> + qemu_put_be64(f, FLIC_FAILED);
> + return;
> + }
> +
> + count = __get_all_irqs(flic, &buf, len);
> + if (count < 0) {
> + error_report("flic: couldn't retrieve irqs from kernel, rc %d",
> + count);
> + /* Storing FLIC_FAILED into the count field here will cause the
> + * target system to fail when attempting to load irqs from the
> + * migration state */
> + qemu_put_be64(f, FLIC_FAILED);
> + } else {
> + qemu_put_be64(f, count);
> + qemu_put_buffer(f, (uint8_t *) buf,
> + count * sizeof(struct kvm_s390_irq));
> + }
> + g_free(buf);
> +}
> +
> +/**
> + * kvm_flic_load - Load pending floating interrupts
> + * @f: QEMUFile containing migration state
> + * @opaque: pointer to flic device state
> + * @version_id: version id for migration
> + *
> + * Returns: value of flic_enqueue_irqs, -EINVAL on error
> + * Note: Do nothing when no interrupts where stored
> + * in QEMUFile
> + */
> +static int kvm_flic_load(QEMUFile *f, void *opaque, int version_id)
> +{
> + uint64_t len = 0;
> + uint64_t count = 0;
> + void *buf = NULL;
> + int r = 0;
> +
> + if (version_id != FLIC_SAVEVM_VERSION) {
> + r = -EINVAL;
> + goto out;
> + }
> +
> + flic_enable_pfault((struct KVMS390FLICState *) opaque);
> +
> + count = qemu_get_be64(f);
> + len = count * sizeof(struct kvm_s390_irq);
> + if (count == FLIC_FAILED) {
> + r = -EINVAL;
> + goto out;
> + }
> + if (count == 0) {
> + r = 0;
> + goto out;
> + }
> + buf = g_try_malloc0(len);
> + if (!buf) {
> + r = -ENOMEM;
> + goto out;
> + }
> +
> + if (qemu_get_buffer(f, (uint8_t *) buf, len) != len) {
> + r = -EINVAL;
> + goto out_free;
> + }
> + r = flic_enqueue_irqs(buf, len, (struct KVMS390FLICState *) opaque);
> +
> +out_free:
> + g_free(buf);
> +out:
> + 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)) {
> + trace_flic_no_device_api(errno);
> + return;
> + }
> +
> + cd.type = KVM_DEV_TYPE_FLIC;
> + ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd);
> + if (ret < 0) {
> + trace_flic_create_device(errno);
> + return;
> + }
> + flic_state->fd = cd.fd;
> +
> + /* Register savevm handler for floating interrupts */
> + register_savevm(NULL, "s390-flic", 0, 1, kvm_flic_save,
> + kvm_flic_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), "s390-flic", flic_state);
> +}
> +
> +static void kvm_s390_flic_reset(DeviceState *dev)
> +{
> + KVMS390FLICState *flic = KVM_S390_FLIC(dev);
> + struct kvm_device_attr attr = {
> + .group = KVM_DEV_FLIC_CLEAR_IRQS,
> + };
> + int rc = 0;
> +
> + if (flic->fd == -1) {
> + return;
> + }
> +
> + flic_disable_wait_pfault(flic);
> +
> + rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
> + if (rc) {
> + trace_flic_reset_failed(errno);
> + }
> +
> + flic_enable_pfault(flic);
> +}
> +
> +static void kvm_s390_flic_class_init(ObjectClass *oc, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(oc);
> +
> + dc->realize = kvm_s390_flic_realize;
> + dc->unrealize = kvm_s390_flic_unrealize;
> + dc->reset = kvm_s390_flic_reset;
> +}
> +
> +static const TypeInfo kvm_s390_flic_info = {
> + .name = TYPE_KVM_S390_FLIC,
> + .parent = TYPE_S390_FLIC_COMMON,
> + .instance_size = sizeof(KVMS390FLICState),
> + .class_init = kvm_s390_flic_class_init,
> +};
> +
> +static void kvm_s390_flic_register_types(void)
> +{
> + type_register_static(&kvm_s390_flic_info);
> +}
> +
> +type_init(kvm_s390_flic_register_types)
> diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h
> index 497b219..3bc60fd 100644
> --- a/include/hw/s390x/s390_flic.h
> +++ b/include/hw/s390x/s390_flic.h
> @@ -1,33 +1,62 @@
> /*
> - * QEMU S390x KVM floating interrupt controller (flic)
> + * QEMU S390x floating interrupt controller (flic)
> *
> * Copyright 2014 IBM Corp.
> * Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com>
> + * Cornelia Huck <cornelia.huck@de.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.
> */
>
> -#ifndef __KVM_S390_FLIC_H
> -#define __KVM_S390_FLIC_H
> +#ifndef __HW_S390_FLIC_H
> +#define __HW_S390_FLIC_H
>
> #include "hw/sysbus.h"
>
> -#define TYPE_KVM_S390_FLIC "s390-flic"
> +#define TYPE_S390_FLIC_COMMON "s390-flic"
> +#define S390_FLIC_COMMON(obj) \
> + OBJECT_CHECK(S390FLICState, (obj), TYPE_S390_FLIC_COMMON)
> +
> +typedef struct S390FLICState {
> + SysBusDevice parent_obj;
> +
> +} S390FLICState;
> +
> +#define S390_FLIC_COMMON_CLASS(klass) \
> + OBJECT_CLASS_CHECK(S390FLICStateClass, (klass), TYPE_S390_FLIC_COMMON)
> +#define S390_FLIC_COMMON_GET_CLASS(obj) \
> + OBJECT_GET_CLASS(S390FLICStateClass, (obj), TYPE_S390_FLIC_COMMON)
> +
> +typedef struct S390FLICStateClass {
> + DeviceClass parent_class;
> +
> +} S390FLICStateClass;
> +
> +#define TYPE_KVM_S390_FLIC "s390-flic-kvm"
> #define KVM_S390_FLIC(obj) \
> OBJECT_CHECK(KVMS390FLICState, (obj), TYPE_KVM_S390_FLIC)
>
> -typedef struct KVMS390FLICState {
> - SysBusDevice parent_obj;
> +#define TYPE_QEMU_S390_FLIC "s390-flic-qemu"
> +#define QEMU_S390_FLIC(obj) \
> + OBJECT_CHECK(QEMUS390FLICState, (obj), TYPE_QEMU_S390_FLIC)
>
> - uint32_t fd;
> -} KVMS390FLICState;
> +typedef struct QEMUS390FLICState {
> + S390FLICState parent_obj;
> +} QEMUS390FLICState;
>
> -#ifdef CONFIG_KVM
> void s390_flic_init(void);
> +
> +S390FLICState *s390_get_flic(void);
> +
> +#ifdef CONFIG_KVM
> +DeviceState *s390_flic_kvm_create(void);
> #else
> -static inline void s390_flic_init(void) { }
> +static inline DeviceState *s390_flic_kvm_create(void)
> +{
> + return NULL;
> +}
> #endif
>
> -#endif /* __KVM_S390_FLIC_H */
> +#endif /* __HW_S390_FLIC_H */
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v5 1/4] s390x: split flic into kvm and non-kvm parts
2014-05-12 8:01 ` Christian Borntraeger
@ 2014-05-12 8:09 ` Cornelia Huck
2014-05-12 8:11 ` Christian Borntraeger
0 siblings, 1 reply; 15+ messages in thread
From: Cornelia Huck @ 2014-05-12 8:09 UTC (permalink / raw)
To: Christian Borntraeger; +Cc: qemu-devel, agraf
On Mon, 12 May 2014 10:01:31 +0200
Christian Borntraeger <borntraeger@de.ibm.com> wrote:
> On 08/05/14 15:03, Cornelia Huck wrote:
> > Introduce a common parent class for both cases, where kvm and non-kvm
> > can hook up callbacks. This will be used by follow-on patches for
> > adapter registration and mapping.
> >
> > We now always have a flic, regardless of whether we use kvm; the
> > non-kvm implementation just doesn't do anything.
> >
> > Reviewed-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
> > Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> > ---
> > default-configs/s390x-softmmu.mak | 3 +-
> > hw/intc/Makefile.objs | 1 +
> > hw/intc/s390_flic.c | 318 ++++--------------------------------
> > hw/intc/s390_flic_kvm.c | 325 +++++++++++++++++++++++++++++++++++++
> > include/hw/s390x/s390_flic.h | 51 ++++--
>
> Shouldnt we move this to include/hw/intc/ ?
Current code is a bit undecided: Some interrupt controllers (like arm
gic) have their headers in include/hw/intc/, some (like openpic and
xics) in the architecture specific directories. Should we decide to
collect all of those headers in include/hw/intc/, I vote for doing that
in a general sweep.
>
> Otherwise:
> Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
>
>
> > 5 files changed, 399 insertions(+), 299 deletions(-)
> > create mode 100644 hw/intc/s390_flic_kvm.c
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v5 1/4] s390x: split flic into kvm and non-kvm parts
2014-05-12 8:09 ` Cornelia Huck
@ 2014-05-12 8:11 ` Christian Borntraeger
0 siblings, 0 replies; 15+ messages in thread
From: Christian Borntraeger @ 2014-05-12 8:11 UTC (permalink / raw)
To: Cornelia Huck; +Cc: qemu-devel, agraf
On 12/05/14 10:09, Cornelia Huck wrote:
> On Mon, 12 May 2014 10:01:31 +0200
> Christian Borntraeger <borntraeger@de.ibm.com> wrote:
>
>> On 08/05/14 15:03, Cornelia Huck wrote:
>>> Introduce a common parent class for both cases, where kvm and non-kvm
>>> can hook up callbacks. This will be used by follow-on patches for
>>> adapter registration and mapping.
>>>
>>> We now always have a flic, regardless of whether we use kvm; the
>>> non-kvm implementation just doesn't do anything.
>>>
>>> Reviewed-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
>>> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
>>> ---
>>> default-configs/s390x-softmmu.mak | 3 +-
>>> hw/intc/Makefile.objs | 1 +
>>> hw/intc/s390_flic.c | 318 ++++--------------------------------
>>> hw/intc/s390_flic_kvm.c | 325 +++++++++++++++++++++++++++++++++++++
>>> include/hw/s390x/s390_flic.h | 51 ++++--
>>
>> Shouldnt we move this to include/hw/intc/ ?
>
> Current code is a bit undecided: Some interrupt controllers (like arm
> gic) have their headers in include/hw/intc/, some (like openpic and
> xics) in the architecture specific directories. Should we decide to
> collect all of those headers in include/hw/intc/, I vote for doing that
> in a general sweep.
Makes a lot of sense.
>
>>
>> Otherwise:
>> Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
>>
>>
>>> 5 files changed, 399 insertions(+), 299 deletions(-)
>>> create mode 100644 hw/intc/s390_flic_kvm.c
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v5 3/4] s390x/virtio-ccw: reference-counted indicators
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 3/4] s390x/virtio-ccw: reference-counted indicators Cornelia Huck
@ 2014-05-12 8:17 ` Christian Borntraeger
0 siblings, 0 replies; 15+ messages in thread
From: Christian Borntraeger @ 2014-05-12 8:17 UTC (permalink / raw)
To: Cornelia Huck, qemu-devel; +Cc: agraf
On 08/05/14 15:03, Cornelia Huck wrote:
> Make code using the same indicators point to a single allocated structure
> that is freed when the last user goes away.
>
> This will be used by the irqfd code to unmap addresses after the last user
> is gone.
>
> Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
> ---
> hw/s390x/virtio-ccw.c | 80 ++++++++++++++++++++++++++++++++++++++-----------
> hw/s390x/virtio-ccw.h | 13 ++++++--
> 2 files changed, 73 insertions(+), 20 deletions(-)
>
> diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
> index e3b7120..d11a783 100644
> --- a/hw/s390x/virtio-ccw.c
> +++ b/hw/s390x/virtio-ccw.c
> @@ -27,6 +27,38 @@
> #include "virtio-ccw.h"
> #include "trace.h"
>
> +static QTAILQ_HEAD(, IndAddr) indicator_addresses =
> + QTAILQ_HEAD_INITIALIZER(indicator_addresses);
> +
> +static IndAddr *get_indicator(hwaddr ind_addr, int len)
> +{
> + IndAddr *indicator;
> +
> + QTAILQ_FOREACH(indicator, &indicator_addresses, sibling) {
> + if (indicator->addr == ind_addr) {
> + indicator->refcnt++;
> + return indicator;
> + }
> + }
> + indicator = g_new0(IndAddr, 1);
> + indicator->addr = ind_addr;
> + indicator->len = len;
> + indicator->refcnt = 1;
> + QTAILQ_INSERT_TAIL(&indicator_addresses, indicator, sibling);
> + return indicator;
> +}
> +
> +static void release_indicator(IndAddr *indicator)
> +{
> + assert(indicator->refcnt > 0);
> + indicator->refcnt--;
> + if (indicator->refcnt > 0) {
> + return;
> + }
> + QTAILQ_REMOVE(&indicator_addresses, indicator, sibling);
> + g_free(indicator);
> +}
> +
> static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
> VirtioCcwDevice *dev);
>
> @@ -445,7 +477,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
> ret = -EFAULT;
> } else {
> indicators = ldq_phys(&address_space_memory, ccw.cda);
> - dev->indicators = indicators;
> + dev->indicators = get_indicator(indicators, sizeof(uint64_t));
> sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
> ret = 0;
> }
> @@ -465,7 +497,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
> ret = -EFAULT;
> } else {
> indicators = ldq_phys(&address_space_memory, ccw.cda);
> - dev->indicators2 = indicators;
> + dev->indicators2 = get_indicator(indicators, sizeof(uint64_t));
> sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
> ret = 0;
> }
> @@ -517,8 +549,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
> ret = -EFAULT;
> } else {
> len = hw_len;
> - dev->summary_indicator = thinint->summary_indicator;
> - dev->indicators = thinint->device_indicator;
> + dev->summary_indicator =
> + get_indicator(thinint->summary_indicator, sizeof(uint8_t));
> + dev->indicators = get_indicator(thinint->device_indicator,
> + thinint->ind_bit / 8 + 1);
> dev->thinint_isc = thinint->isc;
> dev->ind_bit = thinint->ind_bit;
> cpu_physical_memory_unmap(thinint, hw_len, 0, hw_len);
> @@ -526,8 +560,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
> dev->thinint_isc, true, false,
> &dev->adapter_id);
> assert(ret == 0);
> - sch->thinint_active = ((dev->indicators != 0) &&
> - (dev->summary_indicator != 0));
> + sch->thinint_active = ((dev->indicators != NULL) &&
> + (dev->summary_indicator != NULL));
> sch->curr_status.scsw.count = ccw.count - len;
> ret = 0;
> }
> @@ -558,7 +592,7 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
> sch->driver_data = dev;
> dev->sch = sch;
>
> - dev->indicators = 0;
> + dev->indicators = NULL;
>
> /* Initialize subchannel structure. */
> sch->channel_prog = 0x0;
> @@ -697,7 +731,10 @@ static int virtio_ccw_exit(VirtioCcwDevice *dev)
> css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
> g_free(sch);
> }
> - dev->indicators = 0;
> + if (dev->indicators) {
> + release_indicator(dev->indicators);
> + dev->indicators = NULL;
> + }
> return 0;
> }
>
> @@ -954,17 +991,17 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
> * ind_bit indicates the start of the indicators in a big
> * endian notation.
> */
> - virtio_set_ind_atomic(sch, dev->indicators +
> + virtio_set_ind_atomic(sch, dev->indicators->addr +
> (dev->ind_bit + vector) / 8,
> 0x80 >> ((dev->ind_bit + vector) % 8));
> - if (!virtio_set_ind_atomic(sch, dev->summary_indicator,
> + if (!virtio_set_ind_atomic(sch, dev->summary_indicator->addr,
> 0x01)) {
> css_adapter_interrupt(dev->thinint_isc);
> }
> } else {
> - indicators = ldq_phys(&address_space_memory, dev->indicators);
> + indicators = ldq_phys(&address_space_memory, dev->indicators->addr);
> indicators |= 1ULL << vector;
> - stq_phys(&address_space_memory, dev->indicators, indicators);
> + stq_phys(&address_space_memory, dev->indicators->addr, indicators);
> css_conditional_io_interrupt(sch);
> }
> } else {
> @@ -972,9 +1009,9 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
> return;
> }
> vector = 0;
> - indicators = ldq_phys(&address_space_memory, dev->indicators2);
> + indicators = ldq_phys(&address_space_memory, dev->indicators2->addr);
> indicators |= 1ULL << vector;
> - stq_phys(&address_space_memory, dev->indicators2, indicators);
> + stq_phys(&address_space_memory, dev->indicators2->addr, indicators);
> css_conditional_io_interrupt(sch);
> }
> }
> @@ -995,9 +1032,18 @@ static void virtio_ccw_reset(DeviceState *d)
> virtio_ccw_stop_ioeventfd(dev);
> virtio_reset(vdev);
> css_reset_sch(dev->sch);
> - dev->indicators = 0;
> - dev->indicators2 = 0;
> - dev->summary_indicator = 0;
> + if (dev->indicators) {
> + release_indicator(dev->indicators);
> + dev->indicators = NULL;
> + }
> + if (dev->indicators2) {
> + release_indicator(dev->indicators2);
> + dev->indicators2 = NULL;
> + }
> + if (dev->summary_indicator) {
> + release_indicator(dev->summary_indicator);
> + dev->summary_indicator = NULL;
> + }
> }
>
> static void virtio_ccw_vmstate_change(DeviceState *d, bool running)
> diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
> index 0b70b91..d340bf4 100644
> --- a/hw/s390x/virtio-ccw.h
> +++ b/hw/s390x/virtio-ccw.h
> @@ -75,6 +75,13 @@ typedef struct VirtIOCCWDeviceClass {
> #define VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT 1
> #define VIRTIO_CCW_FLAG_USE_IOEVENTFD (1 << VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT)
>
> +typedef struct IndAddr {
> + hwaddr addr;
> + unsigned long refcnt;
> + int len;
> + QTAILQ_ENTRY(IndAddr) sibling;
> +} IndAddr;
> +
> struct VirtioCcwDevice {
> DeviceState parent_obj;
> SubchDev *sch;
> @@ -87,9 +94,9 @@ struct VirtioCcwDevice {
> uint8_t thinint_isc;
> uint32_t adapter_id;
> /* Guest provided values: */
> - hwaddr indicators;
> - hwaddr indicators2;
> - hwaddr summary_indicator;
> + IndAddr *indicators;
> + IndAddr *indicators2;
> + IndAddr *summary_indicator;
> uint64_t ind_bit;
> };
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v5 2/4] s390x: Add I/O adapter registration.
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 2/4] s390x: Add I/O adapter registration Cornelia Huck
@ 2014-05-12 8:36 ` Christian Borntraeger
0 siblings, 0 replies; 15+ messages in thread
From: Christian Borntraeger @ 2014-05-12 8:36 UTC (permalink / raw)
To: Cornelia Huck, qemu-devel; +Cc: agraf
On 08/05/14 15:03, Cornelia Huck wrote:
> Register an I/O adapter interrupt source for when virtio-ccw devices start
> using adapter interrupts.
>
> Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
> ---
> hw/intc/s390_flic.c | 16 ++++++++++++++
> hw/intc/s390_flic_kvm.c | 29 ++++++++++++++++++++++++
> hw/s390x/css.c | 50 ++++++++++++++++++++++++++++++++++++++++++
> hw/s390x/css.h | 4 ++++
> hw/s390x/virtio-ccw.c | 4 ++++
> hw/s390x/virtio-ccw.h | 1 +
> include/hw/s390x/s390_flic.h | 2 ++
> 7 files changed, 106 insertions(+)
>
> diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
> index 7dc8c7d..2b56835 100644
> --- a/hw/intc/s390_flic.c
> +++ b/hw/intc/s390_flic.c
> @@ -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 = {
> diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
> index 70c1710..cc4072e 100644
> --- a/hw/intc/s390_flic_kvm.c
> +++ b/hw/intc/s390_flic_kvm.c
> @@ -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 = {
> diff --git a/hw/s390x/css.c b/hw/s390x/css.c
> index 122cc7e..2678e44 100644
> --- a/hw/s390x/css.c
> +++ b/hw/s390x/css.c
> @@ -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);
>
> diff --git a/hw/s390x/css.h b/hw/s390x/css.h
> index 220169e..6586106 100644
> --- a/hw/s390x/css.h
> +++ b/hw/s390x/css.h
> @@ -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
> diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
> index 1cb4e2c..e3b7120 100644
> --- a/hw/s390x/virtio-ccw.c
> +++ b/hw/s390x/virtio-ccw.c
> @@ -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;
> diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
> index 4393e44..0b70b91 100644
> --- a/hw/s390x/virtio-ccw.h
> +++ b/hw/s390x/virtio-ccw.h
> @@ -85,6 +85,7 @@ struct VirtioCcwDevice {
> bool ioeventfd_disabled;
> uint32_t flags;
> uint8_t thinint_isc;
> + uint32_t adapter_id;
> /* Guest provided values: */
> hwaddr indicators;
> hwaddr indicators2;
> diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h
> index 3bc60fd..83913ec 100644
> --- a/include/hw/s390x/s390_flic.h
> +++ b/include/hw/s390x/s390_flic.h
> @@ -32,6 +32,8 @@ typedef struct S390FLICState {
> typedef struct S390FLICStateClass {
> DeviceClass parent_class;
>
> + int (*register_io_adapter)(S390FLICState *fs, uint32_t id, uint8_t isc,
> + bool swap, bool maskable);
> } S390FLICStateClass;
>
> #define TYPE_KVM_S390_FLIC "s390-flic-kvm"
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v5 4/4] s390x/virtio-ccw: Wire up irq routing and irqfds.
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 4/4] s390x/virtio-ccw: Wire up irq routing and irqfds Cornelia Huck
@ 2014-05-12 8:58 ` Christian Borntraeger
2014-05-12 13:24 ` Cornelia Huck
2014-05-15 13:19 ` Paolo Bonzini
1 sibling, 1 reply; 15+ messages in thread
From: Christian Borntraeger @ 2014-05-12 8:58 UTC (permalink / raw)
To: Cornelia Huck, qemu-devel; +Cc: Paolo Bonzini, agraf
On 08/05/14 15:03, Cornelia Huck wrote:
> Make use of the new s390 adapter irq routing support to enable real
> in-kernel irqfds for virtio-ccw with adapter interrupts.
>
> Note that s390 doesn't provide the common KVM_CAP_IRQCHIP capability, but
> rather needs KVM_CAP_S390_IRQCHIP to be enabled. This is to ensure backward
> compatibility.
>
> Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Small things, otherwise
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
[...]
> --- /dev/null
> +++ b/include/hw/s390x/adapter.h
> @@ -0,0 +1,23 @@
> +/*
> + * s390 adapter definitions
> + *
> + * Copyright 2013 IBM Corp.
2014 as well
[...]
> --- a/include/sysemu/kvm.h
> +++ b/include/sysemu/kvm.h
> @@ -365,6 +365,8 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
> int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg);
> void kvm_irqchip_release_virq(KVMState *s, int virq);
>
> +int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter);
> +
> int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
> EventNotifier *rn, int virq);
> int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
> diff --git a/kvm-all.c b/kvm-all.c
> index 5cb7f26..51983bf 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -27,6 +27,7 @@
> #include "sysemu/sysemu.h"
> #include "hw/hw.h"
> #include "hw/pci/msi.h"
> +#include "hw/s390x/adapter.h"
> #include "exec/gdbstub.h"
> #include "sysemu/kvm.h"
> #include "qemu/bswap.h"
> @@ -1247,6 +1248,35 @@ static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int rfd, int virq,
> return kvm_vm_ioctl(s, KVM_IRQFD, &irqfd);
> }
>
> +int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter)
> +{
> + struct kvm_irq_routing_entry kroute;
> + int virq;
> +
> + if (!kvm_gsi_routing_enabled()) {
> + return -ENOSYS;
> + }
> +
> + virq = kvm_irqchip_get_virq(s);
> + if (virq < 0) {
> + return virq;
> + }
> +
> + kroute.gsi = virq;
> + kroute.type = KVM_IRQ_ROUTING_S390_ADAPTER;
> + kroute.flags = 0;
> + kroute.u.adapter.summary_addr = adapter->summary_addr;
> + kroute.u.adapter.ind_addr = adapter->ind_addr;
> + kroute.u.adapter.summary_offset = adapter->summary_offset;
> + kroute.u.adapter.ind_offset = adapter->ind_offset;
> + kroute.u.adapter.adapter_id = adapter->adapter_id;
> +
> + kvm_add_routing_entry(s, &kroute);
> + kvm_irqchip_commit_routes(s);
> +
> + return virq;
> +}
> +
> #else /* !KVM_CAP_IRQ_ROUTING */
>
> void kvm_init_irq_routing(KVMState *s)
> @@ -1267,6 +1297,11 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
> return -ENOSYS;
> }
>
> +int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter)
> +{
> + return -ENOSYS;
> +}
> +
> static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign)
> {
> abort();
> @@ -1296,7 +1331,8 @@ static int kvm_irqchip_create(KVMState *s)
> int ret;
>
> if (!qemu_opt_get_bool(qemu_get_machine_opts(), "kernel_irqchip", true) ||
> - !kvm_check_extension(s, KVM_CAP_IRQCHIP)) {
> + (!kvm_check_extension(s, KVM_CAP_IRQCHIP) &&
> + (kvm_vm_enable_cap(s, KVM_CAP_S390_IRQCHIP, 0) < 0))) {
> return 0;
> }
Do we need a comment here and/or in target-s390x/kvm.c why kvm_halt_in_kernel_allowed does not work without breaking backward compatibility on s390?
>
> diff --git a/kvm-stub.c b/kvm-stub.c
> index 8acda86..ac33d86 100644
> --- a/kvm-stub.c
> +++ b/kvm-stub.c
> @@ -136,6 +136,11 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg)
> return -ENOSYS;
> }
>
> +int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter)
> +{
> + return -ENOSYS;
> +}
> +
> int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
> EventNotifier *rn, int virq)
> {
> diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
> index b7b0edc..43859e9 100644
> --- a/target-s390x/kvm.c
> +++ b/target-s390x/kvm.c
> @@ -938,6 +938,11 @@ void kvm_s390_enable_css_support(S390CPU *cpu)
>
> void kvm_arch_init_irq_routing(KVMState *s)
> {
> + if (kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) {
> + kvm_irqfds_allowed = true;
> + kvm_gsi_routing_allowed = true;
> + kvm_halt_in_kernel_allowed = false;
> + }
Do we need a comment here and/or in kvm-all why kvm_halt_in_kernel_allowed does not work without breaking backward compatibility on s390?
[...]
Should Paolo ack the common kvm changes? (CCed)
Christian
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v5 4/4] s390x/virtio-ccw: Wire up irq routing and irqfds.
2014-05-12 8:58 ` Christian Borntraeger
@ 2014-05-12 13:24 ` Cornelia Huck
0 siblings, 0 replies; 15+ messages in thread
From: Cornelia Huck @ 2014-05-12 13:24 UTC (permalink / raw)
To: Christian Borntraeger; +Cc: Paolo Bonzini, qemu-devel, agraf
On Mon, 12 May 2014 10:58:46 +0200
Christian Borntraeger <borntraeger@de.ibm.com> wrote:
> On 08/05/14 15:03, Cornelia Huck wrote:
> > Make use of the new s390 adapter irq routing support to enable real
> > in-kernel irqfds for virtio-ccw with adapter interrupts.
> >
> > Note that s390 doesn't provide the common KVM_CAP_IRQCHIP capability, but
> > rather needs KVM_CAP_S390_IRQCHIP to be enabled. This is to ensure backward
> > compatibility.
> >
> > Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
> > Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
>
> Small things, otherwise
>
> Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
>
>
> [...]
> > --- /dev/null
> > +++ b/include/hw/s390x/adapter.h
> > @@ -0,0 +1,23 @@
> > +/*
> > + * s390 adapter definitions
> > + *
> > + * Copyright 2013 IBM Corp.
>
> 2014 as well
ok
>
> [...]
> > diff --git a/kvm-all.c b/kvm-all.c
> > index 5cb7f26..51983bf 100644
> > --- a/kvm-all.c
> > +++ b/kvm-all.c
> > @@ -1267,6 +1297,11 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
> > return -ENOSYS;
> > }
> >
> > +int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter)
> > +{
> > + return -ENOSYS;
> > +}
> > +
> > static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign)
> > {
> > abort();
> > @@ -1296,7 +1331,8 @@ static int kvm_irqchip_create(KVMState *s)
> > int ret;
> >
> > if (!qemu_opt_get_bool(qemu_get_machine_opts(), "kernel_irqchip", true) ||
> > - !kvm_check_extension(s, KVM_CAP_IRQCHIP)) {
> > + (!kvm_check_extension(s, KVM_CAP_IRQCHIP) &&
> > + (kvm_vm_enable_cap(s, KVM_CAP_S390_IRQCHIP, 0) < 0))) {
> > return 0;
> > }
>
> Do we need a comment here and/or in target-s390x/kvm.c why kvm_halt_in_kernel_allowed does not work without breaking backward compatibility on s390?
Probably not here but...
>
>
> >
> > diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
> > index b7b0edc..43859e9 100644
> > --- a/target-s390x/kvm.c
> > +++ b/target-s390x/kvm.c
> > @@ -938,6 +938,11 @@ void kvm_s390_enable_css_support(S390CPU *cpu)
> >
> > void kvm_arch_init_irq_routing(KVMState *s)
> > {
> > + if (kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) {
> > + kvm_irqfds_allowed = true;
> > + kvm_gsi_routing_allowed = true;
> > + kvm_halt_in_kernel_allowed = false;
> > + }
>
> Do we need a comment here and/or in kvm-all why kvm_halt_in_kernel_allowed does not work without breaking backward compatibility on s390?
...I'll add the following here:
/*
* Note that while irqchip capabilities generally imply that cpustates
* are handled in-kernel, it is not true for s390 (yet); therefore, we
* have to override the common code kvm_halt_in_kernel_allowed setting.
*/
>
> [...]
>
>
> Should Paolo ack the common kvm changes? (CCed)
>
> Christian
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH v5 4/4] s390x/virtio-ccw: Wire up irq routing and irqfds.
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 4/4] s390x/virtio-ccw: Wire up irq routing and irqfds Cornelia Huck
2014-05-12 8:58 ` Christian Borntraeger
@ 2014-05-15 13:19 ` Paolo Bonzini
1 sibling, 0 replies; 15+ messages in thread
From: Paolo Bonzini @ 2014-05-15 13:19 UTC (permalink / raw)
To: Cornelia Huck, qemu-devel; +Cc: borntraeger, agraf
Il 08/05/2014 15:03, Cornelia Huck ha scritto:
> Make use of the new s390 adapter irq routing support to enable real
> in-kernel irqfds for virtio-ccw with adapter interrupts.
>
> Note that s390 doesn't provide the common KVM_CAP_IRQCHIP capability, but
> rather needs KVM_CAP_S390_IRQCHIP to be enabled. This is to ensure backward
> compatibility.
>
> Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> ---
> hw/intc/s390_flic.c | 21 ++++++
> hw/intc/s390_flic_kvm.c | 66 +++++++++++++++++
> hw/s390x/virtio-ccw.c | 165 ++++++++++++++++++++++++++++++++++++++----
> hw/s390x/virtio-ccw.h | 4 +-
> include/hw/s390x/adapter.h | 23 ++++++
> include/hw/s390x/s390_flic.h | 12 +++
> include/qemu/typedefs.h | 1 +
> include/sysemu/kvm.h | 2 +
> kvm-all.c | 38 +++++++++-
> kvm-stub.c | 5 ++
> target-s390x/kvm.c | 5 ++
> 11 files changed, 324 insertions(+), 18 deletions(-)
> create mode 100644 include/hw/s390x/adapter.h
>
> diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
> index 2b56835..03c5e89 100644
> --- a/hw/intc/s390_flic.c
> +++ b/hw/intc/s390_flic.c
> @@ -52,11 +52,32 @@ static int qemu_s390_register_io_adapter(S390FLICState *fs, uint32_t id,
> return 0;
> }
>
> +static int qemu_s390_io_adapter_map(S390FLICState *fs, uint32_t id,
> + uint64_t map_addr, bool do_map)
> +{
> + /* nothing to do */
> + return 0;
> +}
> +
> +static int qemu_s390_add_adapter_routes(S390FLICState *fs,
> + AdapterRoutes *routes)
> +{
> + return -ENOSYS;
> +}
> +
> +static void qemu_s390_release_adapter_routes(S390FLICState *fs,
> + AdapterRoutes *routes)
> +{
> +}
> +
> 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;
> + 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;
> }
>
> static const TypeInfo qemu_s390_flic_info = {
> diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
> index cc4072e..46c9e61 100644
> --- a/hw/intc/s390_flic_kvm.c
> +++ b/hw/intc/s390_flic_kvm.c
> @@ -16,6 +16,7 @@
> #include "sysemu/kvm.h"
> #include "migration/qemu-file.h"
> #include "hw/s390x/s390_flic.h"
> +#include "hw/s390x/adapter.h"
> #include "trace.h"
>
> #define FLIC_SAVE_INITIAL_SIZE getpagesize()
> @@ -178,6 +179,68 @@ static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id,
> return ret;
> }
>
> +static int kvm_s390_io_adapter_map(S390FLICState *fs, uint32_t id,
> + uint64_t map_addr, bool do_map)
> +{
> + struct kvm_s390_io_adapter_req req = {
> + .id = id,
> + .type = do_map ? KVM_S390_IO_ADAPTER_MAP : KVM_S390_IO_ADAPTER_UNMAP,
> + .addr = map_addr,
> + };
> + struct kvm_device_attr attr = {
> + .group = KVM_DEV_FLIC_ADAPTER_MODIFY,
> + .addr = (uint64_t)&req,
> + };
> + KVMS390FLICState *flic = KVM_S390_FLIC(fs);
> + int r;
> +
> + if (!kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING)) {
> + return -ENOSYS;
> + }
> +
> + r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
> + return r ? -errno : 0;
> +}
> +
> +static int kvm_s390_add_adapter_routes(S390FLICState *fs,
> + AdapterRoutes *routes)
> +{
> + int ret, i;
> + uint64_t ind_offset = routes->adapter.ind_offset;
> +
> + for (i = 0; i < routes->num_routes; i++) {
> + ret = kvm_irqchip_add_adapter_route(kvm_state, &routes->adapter);
> + if (ret < 0) {
> + goto out_undo;
> + }
> + routes->gsi[i] = ret;
> + routes->adapter.ind_offset++;
> + }
> + /* Restore passed-in structure to original state. */
> + routes->adapter.ind_offset = ind_offset;
> + return 0;
> +out_undo:
> + while (--i >= 0) {
> + kvm_irqchip_release_virq(kvm_state, routes->gsi[i]);
> + routes->gsi[i] = -1;
> + }
> + routes->adapter.ind_offset = ind_offset;
> + return ret;
> +}
> +
> +static void kvm_s390_release_adapter_routes(S390FLICState *fs,
> + AdapterRoutes *routes)
> +{
> + int i;
> +
> + for (i = 0; i < routes->num_routes; i++) {
> + if (routes->gsi[i] >= 0) {
> + kvm_irqchip_release_virq(kvm_state, routes->gsi[i]);
> + routes->gsi[i] = -1;
> + }
> + }
> +}
> +
> /**
> * kvm_flic_save - Save pending floating interrupts
> * @f: QEMUFile containing migration state
> @@ -337,6 +400,9 @@ static void kvm_s390_flic_class_init(ObjectClass *oc, void *data)
> dc->unrealize = kvm_s390_flic_unrealize;
> dc->reset = kvm_s390_flic_reset;
> fsc->register_io_adapter = kvm_s390_register_io_adapter;
> + 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;
> }
>
> static const TypeInfo kvm_s390_flic_info = {
> diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
> index d11a783..c4f21d3 100644
> --- a/hw/s390x/virtio-ccw.c
> +++ b/hw/s390x/virtio-ccw.c
> @@ -21,6 +21,8 @@
> #include "hw/sysbus.h"
> #include "qemu/bitops.h"
> #include "hw/virtio/virtio-bus.h"
> +#include "hw/s390x/adapter.h"
> +#include "hw/s390x/s390_flic.h"
>
> #include "ioinst.h"
> #include "css.h"
> @@ -48,7 +50,16 @@ static IndAddr *get_indicator(hwaddr ind_addr, int len)
> return indicator;
> }
>
> -static void release_indicator(IndAddr *indicator)
> +static int s390_io_adapter_map(AdapterInfo *adapter, uint64_t map_addr,
> + bool do_map)
> +{
> + S390FLICState *fs = s390_get_flic();
> + S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
> +
> + return fsc->io_adapter_map(fs, adapter->adapter_id, map_addr, do_map);
> +}
> +
> +static void release_indicator(AdapterInfo *adapter, IndAddr *indicator)
> {
> assert(indicator->refcnt > 0);
> indicator->refcnt--;
> @@ -56,9 +67,31 @@ static void release_indicator(IndAddr *indicator)
> return;
> }
> QTAILQ_REMOVE(&indicator_addresses, indicator, sibling);
> + if (indicator->map) {
> + s390_io_adapter_map(adapter, indicator->map, false);
> + }
> g_free(indicator);
> }
>
> +static int map_indicator(AdapterInfo *adapter, IndAddr *indicator)
> +{
> + int ret;
> +
> + if (indicator->map) {
> + return 0; /* already mapped is not an error */
> + }
> + indicator->map = indicator->addr;
> + ret = s390_io_adapter_map(adapter, indicator->map, true);
> + if ((ret != 0) && (ret != -ENOSYS)) {
> + goto out_err;
> + }
> + return 0;
> +
> +out_err:
> + indicator->map = 0;
> + return ret;
> +}
> +
> static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
> VirtioCcwDevice *dev);
>
> @@ -554,11 +587,12 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
> dev->indicators = get_indicator(thinint->device_indicator,
> thinint->ind_bit / 8 + 1);
> dev->thinint_isc = thinint->isc;
> - dev->ind_bit = thinint->ind_bit;
> + dev->routes.adapter.ind_offset = thinint->ind_bit;
> + dev->routes.adapter.summary_offset = 7;
> 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);
> + &dev->routes.adapter.adapter_id);
> assert(ret == 0);
> sch->thinint_active = ((dev->indicators != NULL) &&
> (dev->summary_indicator != NULL));
> @@ -732,7 +766,7 @@ static int virtio_ccw_exit(VirtioCcwDevice *dev)
> g_free(sch);
> }
> if (dev->indicators) {
> - release_indicator(dev->indicators);
> + release_indicator(&dev->routes.adapter, dev->indicators);
> dev->indicators = NULL;
> }
> return 0;
> @@ -991,9 +1025,11 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
> * ind_bit indicates the start of the indicators in a big
> * endian notation.
> */
> + uint64_t ind_bit = dev->routes.adapter.ind_offset;
> +
> virtio_set_ind_atomic(sch, dev->indicators->addr +
> - (dev->ind_bit + vector) / 8,
> - 0x80 >> ((dev->ind_bit + vector) % 8));
> + (ind_bit + vector) / 8,
> + 0x80 >> ((ind_bit + vector) % 8));
> if (!virtio_set_ind_atomic(sch, dev->summary_indicator->addr,
> 0x01)) {
> css_adapter_interrupt(dev->thinint_isc);
> @@ -1033,15 +1069,15 @@ static void virtio_ccw_reset(DeviceState *d)
> virtio_reset(vdev);
> css_reset_sch(dev->sch);
> if (dev->indicators) {
> - release_indicator(dev->indicators);
> + release_indicator(&dev->routes.adapter, dev->indicators);
> dev->indicators = NULL;
> }
> if (dev->indicators2) {
> - release_indicator(dev->indicators2);
> + release_indicator(&dev->routes.adapter, dev->indicators2);
> dev->indicators2 = NULL;
> }
> if (dev->summary_indicator) {
> - release_indicator(dev->summary_indicator);
> + release_indicator(&dev->routes.adapter, dev->summary_indicator);
> dev->summary_indicator = NULL;
> }
> }
> @@ -1077,6 +1113,79 @@ static int virtio_ccw_set_host_notifier(DeviceState *d, int n, bool assign)
> return virtio_ccw_set_guest2host_notifier(dev, n, assign, false);
> }
>
> +static int virtio_ccw_get_mappings(VirtioCcwDevice *dev)
> +{
> + int r;
> +
> + if (!dev->sch->thinint_active) {
> + return -EINVAL;
> + }
> +
> + r = map_indicator(&dev->routes.adapter, dev->summary_indicator);
> + if (r) {
> + return r;
> + }
> + r = map_indicator(&dev->routes.adapter, dev->indicators);
> + if (r) {
> + return r;
> + }
> + dev->routes.adapter.summary_addr = dev->summary_indicator->map;
> + dev->routes.adapter.ind_addr = dev->indicators->map;
> +
> + return 0;
> +}
> +
> +static int virtio_ccw_setup_irqroutes(VirtioCcwDevice *dev, int nvqs)
> +{
> + int i;
> + VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
> + int ret;
> + S390FLICState *fs = s390_get_flic();
> + S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
> +
> + ret = virtio_ccw_get_mappings(dev);
> + if (ret) {
> + return ret;
> + }
> + for (i = 0; i < nvqs; i++) {
> + if (!virtio_queue_get_num(vdev, i)) {
> + break;
> + }
> + }
> + dev->routes.num_routes = i;
> + return fsc->add_adapter_routes(fs, &dev->routes);
> +}
> +
> +static void virtio_ccw_release_irqroutes(VirtioCcwDevice *dev, int nvqs)
> +{
> + S390FLICState *fs = s390_get_flic();
> + S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
> +
> + fsc->release_adapter_routes(fs, &dev->routes);
> +}
> +
> +static int virtio_ccw_add_irqfd(VirtioCcwDevice *dev, int n)
> +{
> + VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
> + VirtQueue *vq = virtio_get_queue(vdev, n);
> + EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
> +
> + return kvm_irqchip_add_irqfd_notifier(kvm_state, notifier, NULL,
> + dev->routes.gsi[n]);
> +}
> +
> +static void virtio_ccw_remove_irqfd(VirtioCcwDevice *dev, int n)
> +{
> + VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
> + VirtQueue *vq = virtio_get_queue(vdev, n);
> + EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
> + int ret;
> +
> + ret = kvm_irqchip_remove_irqfd_notifier(kvm_state, notifier,
> + dev->routes.gsi[n]);
> + assert(ret == 0);
> +}
> +
> static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
> bool assign, bool with_irqfd)
> {
> @@ -1092,11 +1201,17 @@ static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
> return r;
> }
> virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
> - /* We do not support irqfd for classic I/O interrupts, because the
> - * classic interrupts are intermixed with the subchannel status, that
> - * is queried with test subchannel. We want to use vhost, though.
> - * Lets make sure to have vhost running and wire up the irq fd to
> - * land in qemu (and only the irq fd) in this code.
> + if (with_irqfd) {
> + r = virtio_ccw_add_irqfd(dev, n);
> + if (r) {
> + virtio_queue_set_guest_notifier_fd_handler(vq, false,
> + with_irqfd);
> + return r;
> + }
> + }
> + /*
> + * We do not support individual masking for channel devices, so we
> + * need to manually trigger any guest masking callbacks here.
> */
> if (k->guest_notifier_mask) {
> k->guest_notifier_mask(vdev, n, false);
> @@ -1110,6 +1225,9 @@ static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
> if (k->guest_notifier_mask) {
> k->guest_notifier_mask(vdev, n, true);
> }
> + if (with_irqfd) {
> + virtio_ccw_remove_irqfd(dev, n);
> + }
> virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
> event_notifier_cleanup(notifier);
> }
> @@ -1121,24 +1239,39 @@ static int virtio_ccw_set_guest_notifiers(DeviceState *d, int nvqs,
> {
> VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
> VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
> + bool with_irqfd = dev->sch->thinint_active && kvm_irqfds_enabled();
> int r, n;
>
> + if (with_irqfd && assigned) {
> + /* irq routes need to be set up before assigning irqfds */
> + r = virtio_ccw_setup_irqroutes(dev, nvqs);
> + if (r < 0) {
> + goto irqroute_error;
> + }
> + }
> for (n = 0; n < nvqs; n++) {
> if (!virtio_queue_get_num(vdev, n)) {
> break;
> }
> - /* false -> true, as soon as irqfd works */
> - r = virtio_ccw_set_guest_notifier(dev, n, assigned, false);
> + r = virtio_ccw_set_guest_notifier(dev, n, assigned, with_irqfd);
> if (r < 0) {
> goto assign_error;
> }
> }
> + if (with_irqfd && !assigned) {
> + /* release irq routes after irqfds have been released */
> + virtio_ccw_release_irqroutes(dev, nvqs);
> + }
> return 0;
>
> assign_error:
> while (--n >= 0) {
> virtio_ccw_set_guest_notifier(dev, n, !assigned, false);
> }
> +irqroute_error:
> + if (with_irqfd && assigned) {
> + virtio_ccw_release_irqroutes(dev, nvqs);
> + }
> return r;
> }
>
> diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
> index d340bf4..b8b8a8a 100644
> --- a/hw/s390x/virtio-ccw.h
> +++ b/hw/s390x/virtio-ccw.h
> @@ -22,6 +22,7 @@
> #include <hw/virtio/virtio-balloon.h>
> #include <hw/virtio/virtio-rng.h>
> #include <hw/virtio/virtio-bus.h>
> +#include <hw/s390x/s390_flic.h>
>
> #define VIRTUAL_CSSID 0xfe
>
> @@ -77,6 +78,7 @@ typedef struct VirtIOCCWDeviceClass {
>
> typedef struct IndAddr {
> hwaddr addr;
> + uint64_t map;
> unsigned long refcnt;
> int len;
> QTAILQ_ENTRY(IndAddr) sibling;
> @@ -92,7 +94,7 @@ struct VirtioCcwDevice {
> bool ioeventfd_disabled;
> uint32_t flags;
> uint8_t thinint_isc;
> - uint32_t adapter_id;
> + AdapterRoutes routes;
> /* Guest provided values: */
> IndAddr *indicators;
> IndAddr *indicators2;
> diff --git a/include/hw/s390x/adapter.h b/include/hw/s390x/adapter.h
> new file mode 100644
> index 0000000..7e56724
> --- /dev/null
> +++ b/include/hw/s390x/adapter.h
> @@ -0,0 +1,23 @@
> +/*
> + * s390 adapter definitions
> + *
> + * Copyright 2013 IBM Corp.
> + * Author(s): Cornelia Huck <cornelia.huck@de.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.
> + */
> +
> +#ifndef S390X_ADAPTER_H
> +#define S390X_ADAPTER_H
> +
> +struct AdapterInfo {
> + uint64_t ind_addr;
> + uint64_t summary_addr;
> + uint64_t ind_offset;
> + uint32_t summary_offset;
> + uint32_t adapter_id;
> +};
> +
> +#endif
> diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h
> index 83913ec..489d73b 100644
> --- a/include/hw/s390x/s390_flic.h
> +++ b/include/hw/s390x/s390_flic.h
> @@ -14,6 +14,14 @@
> #define __HW_S390_FLIC_H
>
> #include "hw/sysbus.h"
> +#include "hw/s390x/adapter.h"
> +#include "hw/virtio/virtio.h"
> +
> +typedef struct AdapterRoutes {
> + AdapterInfo adapter;
> + int num_routes;
> + int gsi[VIRTIO_PCI_QUEUE_MAX];
> +} AdapterRoutes;
>
> #define TYPE_S390_FLIC_COMMON "s390-flic"
> #define S390_FLIC_COMMON(obj) \
> @@ -34,6 +42,10 @@ typedef struct S390FLICStateClass {
>
> int (*register_io_adapter)(S390FLICState *fs, uint32_t id, uint8_t isc,
> bool swap, bool maskable);
> + int (*io_adapter_map)(S390FLICState *fs, uint32_t id, uint64_t map_addr,
> + bool do_map);
> + int (*add_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes);
> + void (*release_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes);
> } S390FLICStateClass;
>
> #define TYPE_KVM_S390_FLIC "s390-flic-kvm"
> diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
> index 86bab12..5f20b0e 100644
> --- a/include/qemu/typedefs.h
> +++ b/include/qemu/typedefs.h
> @@ -74,5 +74,6 @@ typedef struct SHPCDevice SHPCDevice;
> typedef struct FWCfgState FWCfgState;
> typedef struct PcGuestInfo PcGuestInfo;
> typedef struct Range Range;
> +typedef struct AdapterInfo AdapterInfo;
>
> #endif /* QEMU_TYPEDEFS_H */
> diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
> index 5ad4e0e..d219246 100644
> --- a/include/sysemu/kvm.h
> +++ b/include/sysemu/kvm.h
> @@ -365,6 +365,8 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
> int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg);
> void kvm_irqchip_release_virq(KVMState *s, int virq);
>
> +int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter);
> +
> int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
> EventNotifier *rn, int virq);
> int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
> diff --git a/kvm-all.c b/kvm-all.c
> index 5cb7f26..51983bf 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -27,6 +27,7 @@
> #include "sysemu/sysemu.h"
> #include "hw/hw.h"
> #include "hw/pci/msi.h"
> +#include "hw/s390x/adapter.h"
> #include "exec/gdbstub.h"
> #include "sysemu/kvm.h"
> #include "qemu/bswap.h"
> @@ -1247,6 +1248,35 @@ static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int rfd, int virq,
> return kvm_vm_ioctl(s, KVM_IRQFD, &irqfd);
> }
>
> +int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter)
> +{
> + struct kvm_irq_routing_entry kroute;
> + int virq;
> +
> + if (!kvm_gsi_routing_enabled()) {
> + return -ENOSYS;
> + }
> +
> + virq = kvm_irqchip_get_virq(s);
> + if (virq < 0) {
> + return virq;
> + }
> +
> + kroute.gsi = virq;
> + kroute.type = KVM_IRQ_ROUTING_S390_ADAPTER;
> + kroute.flags = 0;
> + kroute.u.adapter.summary_addr = adapter->summary_addr;
> + kroute.u.adapter.ind_addr = adapter->ind_addr;
> + kroute.u.adapter.summary_offset = adapter->summary_offset;
> + kroute.u.adapter.ind_offset = adapter->ind_offset;
> + kroute.u.adapter.adapter_id = adapter->adapter_id;
> +
> + kvm_add_routing_entry(s, &kroute);
> + kvm_irqchip_commit_routes(s);
> +
> + return virq;
> +}
> +
> #else /* !KVM_CAP_IRQ_ROUTING */
>
> void kvm_init_irq_routing(KVMState *s)
> @@ -1267,6 +1297,11 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
> return -ENOSYS;
> }
>
> +int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter)
> +{
> + return -ENOSYS;
> +}
> +
> static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign)
> {
> abort();
> @@ -1296,7 +1331,8 @@ static int kvm_irqchip_create(KVMState *s)
> int ret;
>
> if (!qemu_opt_get_bool(qemu_get_machine_opts(), "kernel_irqchip", true) ||
> - !kvm_check_extension(s, KVM_CAP_IRQCHIP)) {
> + (!kvm_check_extension(s, KVM_CAP_IRQCHIP) &&
> + (kvm_vm_enable_cap(s, KVM_CAP_S390_IRQCHIP, 0) < 0))) {
> return 0;
> }
>
> diff --git a/kvm-stub.c b/kvm-stub.c
> index 8acda86..ac33d86 100644
> --- a/kvm-stub.c
> +++ b/kvm-stub.c
> @@ -136,6 +136,11 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg)
> return -ENOSYS;
> }
>
> +int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter)
> +{
> + return -ENOSYS;
> +}
> +
> int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
> EventNotifier *rn, int virq)
> {
> diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
> index b7b0edc..43859e9 100644
> --- a/target-s390x/kvm.c
> +++ b/target-s390x/kvm.c
> @@ -938,6 +938,11 @@ void kvm_s390_enable_css_support(S390CPU *cpu)
>
> void kvm_arch_init_irq_routing(KVMState *s)
> {
> + if (kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) {
> + kvm_irqfds_allowed = true;
> + kvm_gsi_routing_allowed = true;
> + kvm_halt_in_kernel_allowed = false;
> + }
> }
>
> int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch,
>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Paolo
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2014-05-15 13:20 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-08 13:03 [Qemu-devel] [PATCH v5 0/4] irqfds for s390x Cornelia Huck
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 1/4] s390x: split flic into kvm and non-kvm parts Cornelia Huck
2014-05-08 13:43 ` Alexander Graf
2014-05-08 13:56 ` Cornelia Huck
2014-05-12 8:01 ` Christian Borntraeger
2014-05-12 8:09 ` Cornelia Huck
2014-05-12 8:11 ` Christian Borntraeger
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 2/4] s390x: Add I/O adapter registration Cornelia Huck
2014-05-12 8:36 ` Christian Borntraeger
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 3/4] s390x/virtio-ccw: reference-counted indicators Cornelia Huck
2014-05-12 8:17 ` Christian Borntraeger
2014-05-08 13:03 ` [Qemu-devel] [PATCH v5 4/4] s390x/virtio-ccw: Wire up irq routing and irqfds Cornelia Huck
2014-05-12 8:58 ` Christian Borntraeger
2014-05-12 13:24 ` Cornelia Huck
2014-05-15 13:19 ` Paolo Bonzini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).