cryptospore / rpms / qemu-kvm

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