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(-) (limited to 'drivers/s390/cio/vfio_ccw_cp.c') 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 v1.2.3 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(-) (limited to 'drivers/s390/cio/vfio_ccw_cp.c') 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 v1.2.3 From 408358b50deaf59b07c82a7bff8c7e7cce031fae Mon Sep 17 00:00:00 2001 From: "Jason J. Herne" Date: Tue, 7 Nov 2017 10:22:32 -0500 Subject: s390: vfio-ccw: Do not attempt to free no-op, test and tic cda. Because we do not make use of the cda (channel data address) for test, no-op ccws no address translation takes place. This means cda could contain a guest address which we do not want to attempt to free. Let's check the command type and skip cda free when it is not needed. For a TIC ccw, ccw->cda points to either a ccw in an existing chain or it points to a whole new allocated chain. In either case the data will be freed when the owning chain is freed. Signed-off-by: Jason J. Herne Reviewed-by: Dong Jia Shi Reviewed-by: Pierre Morel Message-Id: <1510068152-21988-1-git-send-email-jjherne@linux.vnet.ibm.com> Reviewed-by: Halil Pasic Acked-by: Christian Borntraeger Signed-off-by: Cornelia Huck --- drivers/s390/cio/vfio_ccw_cp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/s390/cio/vfio_ccw_cp.c') diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c index d8f98ad9b029..7ebbd8b482f5 100644 --- a/drivers/s390/cio/vfio_ccw_cp.c +++ b/drivers/s390/cio/vfio_ccw_cp.c @@ -332,6 +332,8 @@ static void ccwchain_cda_free(struct ccwchain *chain, int idx) { struct ccw1 *ccw = chain->ch_ccw + idx; + if (ccw_is_test(ccw) || ccw_is_noop(ccw) || ccw_is_tic(ccw)) + return; if (!ccw->count) return; -- cgit v1.2.3