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