Commit 667e5dba authored by Eric Farman's avatar Eric Farman Committed by Heiko Carstens

vfio/ccw: read only one Format-1 IDAW

The intention is to read the first IDAW to determine the starting
location of an I/O operation, knowing that the second and any/all
subsequent IDAWs will be aligned per architecture. But, this read
receives 64-bits of data, which is the size of a Format-2 IDAW.

In the event that Format-1 IDAWs are presented, adjust the size
of the read to 32-bits. The data will end up occupying the upper
word of the target iova variable, so shift it down to the lower
word for use as an address. (By definition, this IDAW format
uses a 31-bit address, so the "sign" bit will always be off and
there is no concern about sign extension.)
Signed-off-by: default avatarEric Farman <farman@linux.ibm.com>
Reviewed-by: default avatarMatthew Rosato <mjrosato@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent b21f9cb1
...@@ -509,6 +509,7 @@ static int ccw_count_idaws(struct ccw1 *ccw, ...@@ -509,6 +509,7 @@ static int ccw_count_idaws(struct ccw1 *ccw,
struct vfio_device *vdev = struct vfio_device *vdev =
&container_of(cp, struct vfio_ccw_private, cp)->vdev; &container_of(cp, struct vfio_ccw_private, cp)->vdev;
u64 iova; u64 iova;
int size = cp->orb.cmd.c64 ? sizeof(u64) : sizeof(u32);
int ret; int ret;
int bytes = 1; int bytes = 1;
...@@ -516,11 +517,18 @@ static int ccw_count_idaws(struct ccw1 *ccw, ...@@ -516,11 +517,18 @@ static int ccw_count_idaws(struct ccw1 *ccw,
bytes = ccw->count; bytes = ccw->count;
if (ccw_is_idal(ccw)) { if (ccw_is_idal(ccw)) {
/* Read first IDAW to see if it's 4K-aligned or not. */ /* Read first IDAW to check its starting address. */
/* All subsequent IDAws will be 4K-aligned. */ /* All subsequent IDAWs will be 2K- or 4K-aligned. */
ret = vfio_dma_rw(vdev, ccw->cda, &iova, sizeof(iova), false); ret = vfio_dma_rw(vdev, ccw->cda, &iova, size, false);
if (ret) if (ret)
return ret; return ret;
/*
* Format-1 IDAWs only occupy the first 32 bits,
* and bit 0 is always off.
*/
if (!cp->orb.cmd.c64)
iova = iova >> 32;
} else { } else {
iova = ccw->cda; iova = ccw->cda;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment