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