yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone

Blame SOURCES/kvm-vfio-ccw-Add-support-for-the-schib-region.patch

902636
From b73e3e52f76db823d7bffe3f705f575ca413863b Mon Sep 17 00:00:00 2001
902636
From: Cornelia Huck <cohuck@redhat.com>
902636
Date: Tue, 23 Jun 2020 09:25:39 -0400
902636
Subject: [PATCH 05/12] vfio-ccw: Add support for the schib region
902636
902636
RH-Author: Cornelia Huck <cohuck@redhat.com>
902636
Message-id: <20200623092543.358315-6-cohuck@redhat.com>
902636
Patchwork-id: 97697
902636
O-Subject: [RHEL-8.3.0 qemu-kvm PATCH 5/9] vfio-ccw: Add support for the schib region
902636
Bugzilla: 1660916
902636
RH-Acked-by: Claudio Imbrenda <cimbrend@redhat.com>
902636
RH-Acked-by: David Hildenbrand <david@redhat.com>
902636
RH-Acked-by: Thomas Huth <thuth@redhat.com>
902636
902636
From: Farhan Ali <alifm@linux.ibm.com>
902636
902636
The schib region can be used to obtain the latest SCHIB from the host
902636
passthrough subchannel. Since the guest SCHIB is virtualized,
902636
we currently only update the path related information so that the
902636
guest is aware of any path related changes when it issues the
902636
'stsch' instruction.
902636
902636
Signed-off-by: Farhan Ali <alifm@linux.ibm.com>
902636
Signed-off-by: Eric Farman <farman@linux.ibm.com>
902636
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
902636
Message-Id: <20200505125757.98209-4-farman@linux.ibm.com>
902636
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
902636
(cherry picked from commit 46ea3841edaff2a7657b8f6c7f474e5e3850cd62)
902636
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
902636
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
902636
---
902636
 hw/s390x/css.c              | 13 ++++++--
902636
 hw/s390x/s390-ccw.c         | 21 +++++++++++++
902636
 hw/vfio/ccw.c               | 63 +++++++++++++++++++++++++++++++++++++
902636
 include/hw/s390x/css.h      |  3 +-
902636
 include/hw/s390x/s390-ccw.h |  1 +
902636
 target/s390x/ioinst.c       |  3 +-
902636
 6 files changed, 99 insertions(+), 5 deletions(-)
902636
902636
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
902636
index 844caab408..71fd3f9a00 100644
902636
--- a/hw/s390x/css.c
902636
+++ b/hw/s390x/css.c
902636
@@ -1335,11 +1335,20 @@ static void copy_schib_to_guest(SCHIB *dest, const SCHIB *src)
902636
     }
902636
 }
902636
 
902636
-int css_do_stsch(SubchDev *sch, SCHIB *schib)
902636
+IOInstEnding css_do_stsch(SubchDev *sch, SCHIB *schib)
902636
 {
902636
+    int ret;
902636
+
902636
+    /*
902636
+     * For some subchannels, we may want to update parts of
902636
+     * the schib (e.g., update path masks from the host device
902636
+     * for passthrough subchannels).
902636
+     */
902636
+    ret = s390_ccw_store(sch);
902636
+
902636
     /* Use current status. */
902636
     copy_schib_to_guest(schib, &sch->curr_status);
902636
-    return 0;
902636
+    return ret;
902636
 }
902636
 
902636
 static void copy_pmcw_from_guest(PMCW *dest, const PMCW *src)
902636
diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
902636
index 0c5a5b60bd..75b788c95e 100644
902636
--- a/hw/s390x/s390-ccw.c
902636
+++ b/hw/s390x/s390-ccw.c
902636
@@ -51,6 +51,27 @@ int s390_ccw_clear(SubchDev *sch)
902636
     return cdc->handle_clear(sch);
902636
 }
902636
 
902636
+IOInstEnding s390_ccw_store(SubchDev *sch)
902636
+{
902636
+    S390CCWDeviceClass *cdc = NULL;
902636
+    int ret = IOINST_CC_EXPECTED;
902636
+
902636
+    /*
902636
+     * This code is called for both virtual and passthrough devices,
902636
+     * but only applies to to the latter.  This ugly check makes that
902636
+     * distinction for us.
902636
+     */
902636
+    if (object_dynamic_cast(OBJECT(sch->driver_data), TYPE_S390_CCW)) {
902636
+        cdc = S390_CCW_DEVICE_GET_CLASS(sch->driver_data);
902636
+    }
902636
+
902636
+    if (cdc && cdc->handle_store) {
902636
+        ret = cdc->handle_store(sch);
902636
+    }
902636
+
902636
+    return ret;
902636
+}
902636
+
902636
 static void s390_ccw_get_dev_info(S390CCWDevice *cdev,
902636
                                   char *sysfsdev,
902636
                                   Error **errp)
902636
diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
902636
index 17eb4c4048..859ad646f1 100644
902636
--- a/hw/vfio/ccw.c
902636
+++ b/hw/vfio/ccw.c
902636
@@ -41,6 +41,9 @@ struct VFIOCCWDevice {
902636
     uint64_t async_cmd_region_size;
902636
     uint64_t async_cmd_region_offset;
902636
     struct ccw_cmd_region *async_cmd_region;
902636
+    uint64_t schib_region_size;
902636
+    uint64_t schib_region_offset;
902636
+    struct ccw_schib_region *schib_region;
902636
     EventNotifier io_notifier;
902636
     bool force_orb_pfch;
902636
     bool warned_orb_pfch;
902636
@@ -116,6 +119,51 @@ again:
902636
     }
902636
 }
902636
 
902636
+static IOInstEnding vfio_ccw_handle_store(SubchDev *sch)
902636
+{
902636
+    S390CCWDevice *cdev = sch->driver_data;
902636
+    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
902636
+    SCHIB *schib = &sch->curr_status;
902636
+    struct ccw_schib_region *region = vcdev->schib_region;
902636
+    SCHIB *s;
902636
+    int ret;
902636
+
902636
+    /* schib region not available so nothing else to do */
902636
+    if (!region) {
902636
+        return IOINST_CC_EXPECTED;
902636
+    }
902636
+
902636
+    memset(region, 0, sizeof(*region));
902636
+    ret = pread(vcdev->vdev.fd, region, vcdev->schib_region_size,
902636
+                vcdev->schib_region_offset);
902636
+
902636
+    if (ret == -1) {
902636
+        /*
902636
+         * Device is probably damaged, but store subchannel does not
902636
+         * have a nonzero cc defined for this scenario.  Log an error,
902636
+         * and presume things are otherwise fine.
902636
+         */
902636
+        error_report("vfio-ccw: store region read failed with errno=%d", errno);
902636
+        return IOINST_CC_EXPECTED;
902636
+    }
902636
+
902636
+    /*
902636
+     * Selectively copy path-related bits of the SCHIB,
902636
+     * rather than copying the entire struct.
902636
+     */
902636
+    s = (SCHIB *)region->schib_area;
902636
+    schib->pmcw.pnom = s->pmcw.pnom;
902636
+    schib->pmcw.lpum = s->pmcw.lpum;
902636
+    schib->pmcw.pam = s->pmcw.pam;
902636
+    schib->pmcw.pom = s->pmcw.pom;
902636
+
902636
+    if (s->scsw.flags & SCSW_FLAGS_MASK_PNO) {
902636
+        schib->scsw.flags |= SCSW_FLAGS_MASK_PNO;
902636
+    }
902636
+
902636
+    return IOINST_CC_EXPECTED;
902636
+}
902636
+
902636
 static int vfio_ccw_handle_clear(SubchDev *sch)
902636
 {
902636
     S390CCWDevice *cdev = sch->driver_data;
902636
@@ -382,10 +430,23 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
902636
         vcdev->async_cmd_region = g_malloc0(info->size);
902636
     }
902636
 
902636
+    ret = vfio_get_dev_region_info(vdev, VFIO_REGION_TYPE_CCW,
902636
+                                   VFIO_REGION_SUBTYPE_CCW_SCHIB, &info;;
902636
+    if (!ret) {
902636
+        vcdev->schib_region_size = info->size;
902636
+        if (sizeof(*vcdev->schib_region) != vcdev->schib_region_size) {
902636
+            error_setg(errp, "vfio: Unexpected size of the schib region");
902636
+            goto out_err;
902636
+        }
902636
+        vcdev->schib_region_offset = info->offset;
902636
+        vcdev->schib_region = g_malloc(info->size);
902636
+    }
902636
+
902636
     g_free(info);
902636
     return;
902636
 
902636
 out_err:
902636
+    g_free(vcdev->schib_region);
902636
     g_free(vcdev->async_cmd_region);
902636
     g_free(vcdev->io_region);
902636
     g_free(info);
902636
@@ -394,6 +455,7 @@ out_err:
902636
 
902636
 static void vfio_ccw_put_region(VFIOCCWDevice *vcdev)
902636
 {
902636
+    g_free(vcdev->schib_region);
902636
     g_free(vcdev->async_cmd_region);
902636
     g_free(vcdev->io_region);
902636
 }
902636
@@ -569,6 +631,7 @@ static void vfio_ccw_class_init(ObjectClass *klass, void *data)
902636
     cdc->handle_request = vfio_ccw_handle_request;
902636
     cdc->handle_halt = vfio_ccw_handle_halt;
902636
     cdc->handle_clear = vfio_ccw_handle_clear;
902636
+    cdc->handle_store = vfio_ccw_handle_store;
902636
 }
902636
 
902636
 static const TypeInfo vfio_ccw_info = {
902636
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
902636
index f46bcafb16..7e3a5e7433 100644
902636
--- a/include/hw/s390x/css.h
902636
+++ b/include/hw/s390x/css.h
902636
@@ -218,6 +218,7 @@ IOInstEnding do_subchannel_work_passthrough(SubchDev *sub);
902636
 
902636
 int s390_ccw_halt(SubchDev *sch);
902636
 int s390_ccw_clear(SubchDev *sch);
902636
+IOInstEnding s390_ccw_store(SubchDev *sch);
902636
 
902636
 typedef enum {
902636
     CSS_IO_ADAPTER_VIRTIO = 0,
902636
@@ -242,7 +243,7 @@ SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid,
902636
                          uint16_t schid);
902636
 bool css_subch_visible(SubchDev *sch);
902636
 void css_conditional_io_interrupt(SubchDev *sch);
902636
-int css_do_stsch(SubchDev *sch, SCHIB *schib);
902636
+IOInstEnding css_do_stsch(SubchDev *sch, SCHIB *schib);
902636
 bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid);
902636
 IOInstEnding css_do_msch(SubchDev *sch, const SCHIB *schib);
902636
 IOInstEnding css_do_xsch(SubchDev *sch);
902636
diff --git a/include/hw/s390x/s390-ccw.h b/include/hw/s390x/s390-ccw.h
902636
index fffb54562f..4a43803ef2 100644
902636
--- a/include/hw/s390x/s390-ccw.h
902636
+++ b/include/hw/s390x/s390-ccw.h
902636
@@ -37,6 +37,7 @@ typedef struct S390CCWDeviceClass {
902636
     IOInstEnding (*handle_request) (SubchDev *sch);
902636
     int (*handle_halt) (SubchDev *sch);
902636
     int (*handle_clear) (SubchDev *sch);
902636
+    IOInstEnding (*handle_store) (SubchDev *sch);
902636
 } S390CCWDeviceClass;
902636
 
902636
 #endif
902636
diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c
902636
index f40c35c6ff..b6be300cc4 100644
902636
--- a/target/s390x/ioinst.c
902636
+++ b/target/s390x/ioinst.c
902636
@@ -292,8 +292,7 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
902636
     sch = css_find_subch(m, cssid, ssid, schid);
902636
     if (sch) {
902636
         if (css_subch_visible(sch)) {
902636
-            css_do_stsch(sch, &schib);
902636
-            cc = 0;
902636
+            cc = css_do_stsch(sch, &schib);
902636
         } else {
902636
             /* Indicate no more subchannels in this css/ss */
902636
             cc = 3;
902636
-- 
902636
2.27.0
902636