26ba25
From 95bd55e26e97832288c088f2c0bd3618d9f9f7ff Mon Sep 17 00:00:00 2001
26ba25
From: Thomas Huth <thuth@redhat.com>
26ba25
Date: Mon, 15 Oct 2018 10:19:30 +0100
26ba25
Subject: [PATCH 5/6] s390x/vfio: ap: Introduce VFIO AP device
26ba25
26ba25
RH-Author: Thomas Huth <thuth@redhat.com>
26ba25
Message-id: <1539598771-16223-6-git-send-email-thuth@redhat.com>
26ba25
Patchwork-id: 82700
26ba25
O-Subject: [RHEL-8 qemu-kvm PATCH 5/6] s390x/vfio: ap: Introduce VFIO AP device
26ba25
Bugzilla: 1508142
26ba25
RH-Acked-by: David Hildenbrand <david@redhat.com>
26ba25
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
26ba25
RH-Acked-by: Jens Freimann <jfreimann@redhat.com>
26ba25
26ba25
From: Tony Krowiak <akrowiak@linux.ibm.com>
26ba25
26ba25
Introduces a VFIO based AP device. The device is defined via
26ba25
the QEMU command line by specifying:
26ba25
26ba25
    -device vfio-ap,sysfsdev=<path-to-mediated-matrix-device>
26ba25
26ba25
There may be only one vfio-ap device configured for a guest.
26ba25
26ba25
The mediated matrix device is created by the VFIO AP device
26ba25
driver by writing a UUID to a sysfs attribute file (see
26ba25
docs/vfio-ap.txt). The mediated matrix device will be named
26ba25
after the UUID. Symbolic links to the $uuid are created in
26ba25
many places, so the path to the mediated matrix device $uuid
26ba25
can be specified in any of the following ways:
26ba25
26ba25
/sys/devices/vfio_ap/matrix/$uuid
26ba25
/sys/devices/vfio_ap/matrix/mdev_supported_types/vfio_ap-passthrough/devices/$uuid
26ba25
/sys/bus/mdev/devices/$uuid
26ba25
/sys/bus/mdev/drivers/vfio_mdev/$uuid
26ba25
26ba25
When the vfio-ap device is realized, it acquires and opens the
26ba25
VFIO iommu group to which the mediated matrix device is
26ba25
bound. This causes a VFIO group notification event to be
26ba25
signaled. The vfio_ap device driver's group notification
26ba25
handler will get called at which time the device driver
26ba25
will configure the the AP devices to which the guest will
26ba25
be granted access.
26ba25
26ba25
Signed-off-by: Tony Krowiak <akrowiak@linux.ibm.com>
26ba25
Tested-by: Pierre Morel <pmorel@linux.ibm.com>
26ba25
Acked-by: Halil Pasic <pasic@linux.ibm.com>
26ba25
Tested-by: Pierre Morel <pmorel@linux.ibm.com>
26ba25
Tested-by: Christian Borntraeger <borntraeger@de.ibm.com>
26ba25
Message-Id: <20181010170309.12045-6-akrowiak@linux.ibm.com>
26ba25
Reviewed-by: Thomas Huth <thuth@redhat.com>
26ba25
[CH: added missing g_free and device category]
26ba25
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
26ba25
26ba25
(cherry picked from commit 2fe2942cd6ddad8ddd40fe5d16d67599c28959d7)
26ba25
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
26ba25
---
26ba25
 MAINTAINERS                       |   2 +
26ba25
 default-configs/s390x-softmmu.mak |   1 +
26ba25
 hw/vfio/Makefile.objs             |   1 +
26ba25
 hw/vfio/ap.c                      | 181 ++++++++++++++++++++++++++++++++++++++
26ba25
 include/hw/vfio/vfio-common.h     |   1 +
26ba25
 5 files changed, 186 insertions(+)
26ba25
 create mode 100644 hw/vfio/ap.c
26ba25
26ba25
diff --git a/MAINTAINERS b/MAINTAINERS
26ba25
index 31cf6ff..99694d8 100644
26ba25
--- a/MAINTAINERS
26ba25
+++ b/MAINTAINERS
26ba25
@@ -88,6 +88,7 @@ F: hw/char/terminal3270.c
26ba25
 F: hw/intc/s390_flic.c
26ba25
 F: hw/intc/s390_flic_kvm.c
26ba25
 F: hw/s390x/
26ba25
+F: hw/vfio/ap.c
26ba25
 F: hw/vfio/ccw.c
26ba25
 F: hw/watchdog/wdt_diag288.c
26ba25
 F: include/hw/s390x/
26ba25
@@ -1162,6 +1163,7 @@ F: hw/s390x/ap-device.c
26ba25
 F: hw/s390x/ap-bridge.c
26ba25
 F: include/hw/s390x/ap-device.h
26ba25
 F: include/hw/s390x/ap-bridge.h
26ba25
+F: hw/vfio/ap.c
26ba25
 L: qemu-s390x@nongnu.org
26ba25
 
26ba25
 vhost
26ba25
diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak
26ba25
index 17e871a..d6ab059 100644
26ba25
--- a/default-configs/s390x-softmmu.mak
26ba25
+++ b/default-configs/s390x-softmmu.mak
26ba25
@@ -10,3 +10,4 @@ CONFIG_S390_FLIC_KVM=$(CONFIG_KVM)
26ba25
 # Disabled for Red Hat Enterprise Linux:
26ba25
 # CONFIG_VFIO_CCW=$(CONFIG_LINUX)
26ba25
 CONFIG_WDT_DIAG288=y
26ba25
+CONFIG_VFIO_AP=$(CONFIG_LINUX)
26ba25
diff --git a/hw/vfio/Makefile.objs b/hw/vfio/Makefile.objs
26ba25
index b25ca64..a6b6039 100644
26ba25
--- a/hw/vfio/Makefile.objs
26ba25
+++ b/hw/vfio/Makefile.objs
26ba25
@@ -3,4 +3,5 @@ obj-$(CONFIG_SOFTMMU) += common.o
26ba25
 obj-$(CONFIG_PCI) += pci.o pci-quirks.o display.o
26ba25
 obj-$(CONFIG_VFIO_CCW) += ccw.o
26ba25
 obj-$(CONFIG_SOFTMMU) += spapr.o
26ba25
+obj-$(CONFIG_VFIO_AP) += ap.o
26ba25
 endif
26ba25
diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c
26ba25
new file mode 100644
26ba25
index 0000000..3962bb7
26ba25
--- /dev/null
26ba25
+++ b/hw/vfio/ap.c
26ba25
@@ -0,0 +1,181 @@
26ba25
+/*
26ba25
+ * VFIO based AP matrix device assignment
26ba25
+ *
26ba25
+ * Copyright 2018 IBM Corp.
26ba25
+ * Author(s): Tony Krowiak <akrowiak@linux.ibm.com>
26ba25
+ *            Halil Pasic <pasic@linux.ibm.com>
26ba25
+ *
26ba25
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
26ba25
+ * your option) any later version. See the COPYING file in the top-level
26ba25
+ * directory.
26ba25
+ */
26ba25
+
26ba25
+#include <linux/vfio.h>
26ba25
+#include <sys/ioctl.h>
26ba25
+#include "qemu/osdep.h"
26ba25
+#include "qapi/error.h"
26ba25
+#include "hw/sysbus.h"
26ba25
+#include "hw/vfio/vfio.h"
26ba25
+#include "hw/vfio/vfio-common.h"
26ba25
+#include "hw/s390x/ap-device.h"
26ba25
+#include "qemu/error-report.h"
26ba25
+#include "qemu/queue.h"
26ba25
+#include "qemu/option.h"
26ba25
+#include "qemu/config-file.h"
26ba25
+#include "cpu.h"
26ba25
+#include "kvm_s390x.h"
26ba25
+#include "sysemu/sysemu.h"
26ba25
+#include "hw/s390x/ap-bridge.h"
26ba25
+#include "exec/address-spaces.h"
26ba25
+
26ba25
+#define VFIO_AP_DEVICE_TYPE      "vfio-ap"
26ba25
+
26ba25
+typedef struct VFIOAPDevice {
26ba25
+    APDevice apdev;
26ba25
+    VFIODevice vdev;
26ba25
+} VFIOAPDevice;
26ba25
+
26ba25
+#define VFIO_AP_DEVICE(obj) \
26ba25
+        OBJECT_CHECK(VFIOAPDevice, (obj), VFIO_AP_DEVICE_TYPE)
26ba25
+
26ba25
+static void vfio_ap_compute_needs_reset(VFIODevice *vdev)
26ba25
+{
26ba25
+    vdev->needs_reset = false;
26ba25
+}
26ba25
+
26ba25
+/*
26ba25
+ * We don't need vfio_hot_reset_multi and vfio_eoi operations for
26ba25
+ * vfio-ap device now.
26ba25
+ */
26ba25
+struct VFIODeviceOps vfio_ap_ops = {
26ba25
+    .vfio_compute_needs_reset = vfio_ap_compute_needs_reset,
26ba25
+};
26ba25
+
26ba25
+static void vfio_ap_put_device(VFIOAPDevice *vapdev)
26ba25
+{
26ba25
+    g_free(vapdev->vdev.name);
26ba25
+    vfio_put_base_device(&vapdev->vdev);
26ba25
+}
26ba25
+
26ba25
+static VFIOGroup *vfio_ap_get_group(VFIOAPDevice *vapdev, Error **errp)
26ba25
+{
26ba25
+    GError *gerror = NULL;
26ba25
+    char *symlink, *group_path;
26ba25
+    int groupid;
26ba25
+
26ba25
+    symlink = g_strdup_printf("%s/iommu_group", vapdev->vdev.sysfsdev);
26ba25
+    group_path = g_file_read_link(symlink, &gerror);
26ba25
+    g_free(symlink);
26ba25
+
26ba25
+    if (!group_path) {
26ba25
+        error_setg(errp, "%s: no iommu_group found for %s: %s",
26ba25
+                   VFIO_AP_DEVICE_TYPE, vapdev->vdev.sysfsdev, gerror->message);
26ba25
+        return NULL;
26ba25
+    }
26ba25
+
26ba25
+    if (sscanf(basename(group_path), "%d", &groupid) != 1) {
26ba25
+        error_setg(errp, "vfio: failed to read %s", group_path);
26ba25
+        g_free(group_path);
26ba25
+        return NULL;
26ba25
+    }
26ba25
+
26ba25
+    g_free(group_path);
26ba25
+
26ba25
+    return vfio_get_group(groupid, &address_space_memory, errp);
26ba25
+}
26ba25
+
26ba25
+static void vfio_ap_realize(DeviceState *dev, Error **errp)
26ba25
+{
26ba25
+    int ret;
26ba25
+    char *mdevid;
26ba25
+    Error *local_err = NULL;
26ba25
+    VFIOGroup *vfio_group;
26ba25
+    APDevice *apdev = AP_DEVICE(dev);
26ba25
+    VFIOAPDevice *vapdev = VFIO_AP_DEVICE(apdev);
26ba25
+
26ba25
+    vfio_group = vfio_ap_get_group(vapdev, &local_err);
26ba25
+    if (!vfio_group) {
26ba25
+        goto out_err;
26ba25
+    }
26ba25
+
26ba25
+    vapdev->vdev.ops = &vfio_ap_ops;
26ba25
+    vapdev->vdev.type = VFIO_DEVICE_TYPE_AP;
26ba25
+    mdevid = basename(vapdev->vdev.sysfsdev);
26ba25
+    vapdev->vdev.name = g_strdup_printf("%s", mdevid);
26ba25
+    vapdev->vdev.dev = dev;
26ba25
+
26ba25
+    ret = vfio_get_device(vfio_group, mdevid, &vapdev->vdev, &local_err);
26ba25
+    if (ret) {
26ba25
+        goto out_get_dev_err;
26ba25
+    }
26ba25
+
26ba25
+    return;
26ba25
+
26ba25
+out_get_dev_err:
26ba25
+    vfio_ap_put_device(vapdev);
26ba25
+    vfio_put_group(vfio_group);
26ba25
+out_err:
26ba25
+    error_propagate(errp, local_err);
26ba25
+}
26ba25
+
26ba25
+static void vfio_ap_unrealize(DeviceState *dev, Error **errp)
26ba25
+{
26ba25
+    APDevice *apdev = AP_DEVICE(dev);
26ba25
+    VFIOAPDevice *vapdev = VFIO_AP_DEVICE(apdev);
26ba25
+    VFIOGroup *group = vapdev->vdev.group;
26ba25
+
26ba25
+    vfio_ap_put_device(vapdev);
26ba25
+    vfio_put_group(group);
26ba25
+}
26ba25
+
26ba25
+static Property vfio_ap_properties[] = {
26ba25
+    DEFINE_PROP_STRING("sysfsdev", VFIOAPDevice, vdev.sysfsdev),
26ba25
+    DEFINE_PROP_END_OF_LIST(),
26ba25
+};
26ba25
+
26ba25
+static void vfio_ap_reset(DeviceState *dev)
26ba25
+{
26ba25
+    int ret;
26ba25
+    APDevice *apdev = AP_DEVICE(dev);
26ba25
+    VFIOAPDevice *vapdev = VFIO_AP_DEVICE(apdev);
26ba25
+
26ba25
+    ret = ioctl(vapdev->vdev.fd, VFIO_DEVICE_RESET);
26ba25
+    if (ret) {
26ba25
+        error_report("%s: failed to reset %s device: %s", __func__,
26ba25
+                     vapdev->vdev.name, strerror(ret));
26ba25
+    }
26ba25
+}
26ba25
+
26ba25
+static const VMStateDescription vfio_ap_vmstate = {
26ba25
+    .name = VFIO_AP_DEVICE_TYPE,
26ba25
+    .unmigratable = 1,
26ba25
+};
26ba25
+
26ba25
+static void vfio_ap_class_init(ObjectClass *klass, void *data)
26ba25
+{
26ba25
+    DeviceClass *dc = DEVICE_CLASS(klass);
26ba25
+
26ba25
+    dc->props = vfio_ap_properties;
26ba25
+    dc->vmsd = &vfio_ap_vmstate;
26ba25
+    dc->desc = "VFIO-based AP device assignment";
26ba25
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
26ba25
+    dc->realize = vfio_ap_realize;
26ba25
+    dc->unrealize = vfio_ap_unrealize;
26ba25
+    dc->hotpluggable = false;
26ba25
+    dc->reset = vfio_ap_reset;
26ba25
+    dc->bus_type = TYPE_AP_BUS;
26ba25
+}
26ba25
+
26ba25
+static const TypeInfo vfio_ap_info = {
26ba25
+    .name = VFIO_AP_DEVICE_TYPE,
26ba25
+    .parent = AP_DEVICE_TYPE,
26ba25
+    .instance_size = sizeof(VFIOAPDevice),
26ba25
+    .class_init = vfio_ap_class_init,
26ba25
+};
26ba25
+
26ba25
+static void vfio_ap_type_init(void)
26ba25
+{
26ba25
+    type_register_static(&vfio_ap_info);
26ba25
+}
26ba25
+
26ba25
+type_init(vfio_ap_type_init)
26ba25
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
26ba25
index d936014..f29df6e 100644
26ba25
--- a/include/hw/vfio/vfio-common.h
26ba25
+++ b/include/hw/vfio/vfio-common.h
26ba25
@@ -47,6 +47,7 @@ enum {
26ba25
     VFIO_DEVICE_TYPE_PCI = 0,
26ba25
     VFIO_DEVICE_TYPE_PLATFORM = 1,
26ba25
     VFIO_DEVICE_TYPE_CCW = 2,
26ba25
+    VFIO_DEVICE_TYPE_AP = 3,
26ba25
 };
26ba25
 
26ba25
 typedef struct VFIOMmap {
26ba25
-- 
26ba25
1.8.3.1
26ba25