From 688c29533ffc969773bc860d07d3a5f1995f5878 Mon Sep 17 00:00:00 2001 From: Dong Jia Shi Date: Wed, 11 Oct 2017 04:38:21 +0200 Subject: vfio: ccw: bypass bad idaw address when fetching IDAL ccws We currently return the same error code (-EFAULT) to indicate two different error cases: 1. a bug in vfio-ccw implementation has been found. 2. a buggy channel program has been detected. This brings difficulty for userland program (specifically Qemu) to handle. Let's use -EFAULT to only indicate the first case. For the second case, we simply hand over the ccws to lower level for further handling. Notice: Once a bad idaw address is detected, the current behavior is to suppress the ssch. With this fix, the channel program will be accepted, and part of the channel program (the part ahead of the bad idaw) could possibly be executed by the device before I/O conclusion. Suggested-by: Halil Pasic Reviewed-by: Pierre Morel Signed-off-by: Dong Jia Shi Message-Id: <20171011023822.42948-2-bjsdjshi@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck --- drivers/s390/cio/vfio_ccw_cp.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c index 5ccfdc80d0ec..722f8b8c7273 100644 --- a/drivers/s390/cio/vfio_ccw_cp.c +++ b/drivers/s390/cio/vfio_ccw_cp.c @@ -569,10 +569,6 @@ static int ccwchain_fetch_idal(struct ccwchain *chain, for (i = 0; i < idaw_nr; i++) { idaw_iova = *(idaws + i); - if (IS_ERR_VALUE(idaw_iova)) { - ret = -EFAULT; - goto out_free_idaws; - } ret = pfn_array_alloc_pin(pat->pat_pa + i, cp->mdev, idaw_iova, 1); -- cgit From 4cebc5d6a6ff41c0266d235aa4854b062d34ad09 Mon Sep 17 00:00:00 2001 From: Dong Jia Shi Date: Wed, 11 Oct 2017 04:38:22 +0200 Subject: vfio: ccw: validate the count field of a ccw before pinning If the count field of a ccw is zero, there is no need to try to pin page(s) for it. Let's check the count value before starting pinning operations. Reviewed-by: Pierre Morel Signed-off-by: Dong Jia Shi Message-Id: <20171011023822.42948-3-bjsdjshi@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck --- drivers/s390/cio/vfio_ccw_cp.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c index 722f8b8c7273..d8f98ad9b029 100644 --- a/drivers/s390/cio/vfio_ccw_cp.c +++ b/drivers/s390/cio/vfio_ccw_cp.c @@ -105,7 +105,10 @@ static int pfn_array_alloc_pin(struct pfn_array *pa, struct device *mdev, { int ret = 0; - if (!len || pa->pa_nr) + if (!len) + return 0; + + if (pa->pa_nr) return -EINVAL; pa->pa_iova = iova; @@ -501,6 +504,16 @@ static int ccwchain_fetch_direct(struct ccwchain *chain, ccw = chain->ch_ccw + idx; + if (!ccw->count) { + /* + * We just want the translation result of any direct ccw + * to be an IDA ccw, so let's add the IDA flag for it. + * Although the flag will be ignored by firmware. + */ + ccw->flags |= CCW_FLAG_IDA; + return 0; + } + /* * Pin data page(s) in memory. * The number of pages actually is the count of the idaws which will be @@ -541,6 +554,9 @@ static int ccwchain_fetch_idal(struct ccwchain *chain, ccw = chain->ch_ccw + idx; + if (!ccw->count) + return 0; + /* Calculate size of idaws. */ ret = copy_from_iova(cp->mdev, &idaw_iova, ccw->cda, sizeof(idaw_iova)); if (ret) -- cgit