kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PULL 00/14] more vfio-ccw updates for 5.3
@ 2019-06-21 14:33 Cornelia Huck
  2019-06-21 14:33 ` [PULL 01/14] s390/cio: Squash cp_free() and cp_unpin_free() Cornelia Huck
                   ` (13 more replies)
  0 siblings, 14 replies; 18+ messages in thread
From: Cornelia Huck @ 2019-06-21 14:33 UTC (permalink / raw)
  To: Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Eric Farman, Halil Pasic, linux-s390, kvm, Cornelia Huck

The following changes since commit 39c00378e337c869b0c9cd35e108fc0c8671d644:

  Update default configuration (2019-06-15 12:27:29 +0200)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/kvms390/vfio-ccw.git tags/vfio-ccw-20190621

for you to fetch changes up to 5223bee837e8d90d752de744c5702706a7bb13d9:

  vfio-ccw: Remove copy_ccw_from_iova() (2019-06-21 14:13:37 +0200)

----------------------------------------------------------------
Refactoring of the vfio-ccw cp handling, simplifying the
code and avoiding unneeded allocating/copying.

----------------------------------------------------------------

Eric Farman (14):
  s390/cio: Squash cp_free() and cp_unpin_free()
  s390/cio: Refactor the routine that handles TIC CCWs
  s390/cio: Generalize the TIC handler
  s390/cio: Use generalized CCW handler in cp_init()
  vfio-ccw: Rearrange pfn_array and pfn_array_table arrays
  vfio-ccw: Adjust the first IDAW outside of the nested loops
  vfio-ccw: Remove pfn_array_table
  vfio-ccw: Rearrange IDAL allocation in direct CCW
  s390/cio: Combine direct and indirect CCW paths
  vfio-ccw: Move guest_cp storage into common struct
  vfio-ccw: Skip second copy of guest cp to host
  vfio-ccw: Copy CCW data outside length calculation
  vfio-ccw: Factor out the ccw0-to-ccw1 transition
  vfio-ccw: Remove copy_ccw_from_iova()

 drivers/s390/cio/vfio_ccw_cp.c  | 415 +++++++++++---------------------
 drivers/s390/cio/vfio_ccw_cp.h  |   7 +
 drivers/s390/cio/vfio_ccw_drv.c |   7 +
 3 files changed, 151 insertions(+), 278 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PULL 01/14] s390/cio: Squash cp_free() and cp_unpin_free()
  2019-06-21 14:33 [PULL 00/14] more vfio-ccw updates for 5.3 Cornelia Huck
@ 2019-06-21 14:33 ` Cornelia Huck
  2019-06-21 14:33 ` [PULL 02/14] s390/cio: Refactor the routine that handles TIC CCWs Cornelia Huck
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Cornelia Huck @ 2019-06-21 14:33 UTC (permalink / raw)
  To: Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Eric Farman, Halil Pasic, linux-s390, kvm, Cornelia Huck

From: Eric Farman <farman@linux.ibm.com>

The routine cp_free() does nothing but call cp_unpin_free(), and while
most places call cp_free() there is one caller of cp_unpin_free() used
when the cp is guaranteed to have not been marked initialized.

This seems like a dubious way to make a distinction, so let's combine
these routines and make cp_free() do all the work.

Signed-off-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <20190606202831.44135-2-farman@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 drivers/s390/cio/vfio_ccw_cp.c | 36 +++++++++++++++-------------------
 1 file changed, 16 insertions(+), 20 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index f73cfcfdd032..47cd7f94f42f 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -412,23 +412,6 @@ static void ccwchain_cda_free(struct ccwchain *chain, int idx)
 	kfree((void *)(u64)ccw->cda);
 }
 
-/* Unpin the pages then free the memory resources. */
-static void cp_unpin_free(struct channel_program *cp)
-{
-	struct ccwchain *chain, *temp;
-	int i;
-
-	cp->initialized = false;
-	list_for_each_entry_safe(chain, temp, &cp->ccwchain_list, next) {
-		for (i = 0; i < chain->ch_len; i++) {
-			pfn_array_table_unpin_free(chain->ch_pat + i,
-						   cp->mdev);
-			ccwchain_cda_free(chain, i);
-		}
-		ccwchain_free(chain);
-	}
-}
-
 /**
  * ccwchain_calc_length - calculate the length of the ccw chain.
  * @iova: guest physical address of the target ccw chain
@@ -796,7 +779,7 @@ int cp_init(struct channel_program *cp, struct device *mdev, union orb *orb)
 	/* Now loop for its TICs. */
 	ret = ccwchain_loop_tic(chain, cp);
 	if (ret)
-		cp_unpin_free(cp);
+		cp_free(cp);
 	/* It is safe to force: if not set but idals used
 	 * ccwchain_calc_length returns an error.
 	 */
@@ -819,8 +802,21 @@ int cp_init(struct channel_program *cp, struct device *mdev, union orb *orb)
  */
 void cp_free(struct channel_program *cp)
 {
-	if (cp->initialized)
-		cp_unpin_free(cp);
+	struct ccwchain *chain, *temp;
+	int i;
+
+	if (!cp->initialized)
+		return;
+
+	cp->initialized = false;
+	list_for_each_entry_safe(chain, temp, &cp->ccwchain_list, next) {
+		for (i = 0; i < chain->ch_len; i++) {
+			pfn_array_table_unpin_free(chain->ch_pat + i,
+						   cp->mdev);
+			ccwchain_cda_free(chain, i);
+		}
+		ccwchain_free(chain);
+	}
 }
 
 /**
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PULL 02/14] s390/cio: Refactor the routine that handles TIC CCWs
  2019-06-21 14:33 [PULL 00/14] more vfio-ccw updates for 5.3 Cornelia Huck
  2019-06-21 14:33 ` [PULL 01/14] s390/cio: Squash cp_free() and cp_unpin_free() Cornelia Huck
@ 2019-06-21 14:33 ` Cornelia Huck
  2019-06-21 14:33 ` [PULL 03/14] s390/cio: Generalize the TIC handler Cornelia Huck
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Cornelia Huck @ 2019-06-21 14:33 UTC (permalink / raw)
  To: Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Eric Farman, Halil Pasic, linux-s390, kvm, Cornelia Huck

From: Eric Farman <farman@linux.ibm.com>

Extract the "does the target of this TIC already exist?" check from
ccwchain_handle_tic(), so that it's easier to refactor that function
into one that cp_init() is able to use.

Signed-off-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <20190606202831.44135-3-farman@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 drivers/s390/cio/vfio_ccw_cp.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 47cd7f94f42f..628daf1a8f9a 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -502,10 +502,6 @@ static int ccwchain_handle_tic(struct ccw1 *tic, struct channel_program *cp)
 	struct ccwchain *chain;
 	int len, ret;
 
-	/* May transfer to an existing chain. */
-	if (tic_target_chain_exists(tic, cp))
-		return 0;
-
 	/* Get chain length. */
 	len = ccwchain_calc_length(tic->cda, cp);
 	if (len < 0)
@@ -540,6 +536,10 @@ static int ccwchain_loop_tic(struct ccwchain *chain, struct channel_program *cp)
 		if (!ccw_is_tic(tic))
 			continue;
 
+		/* May transfer to an existing chain. */
+		if (tic_target_chain_exists(tic, cp))
+			continue;
+
 		ret = ccwchain_handle_tic(tic, cp);
 		if (ret)
 			return ret;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PULL 03/14] s390/cio: Generalize the TIC handler
  2019-06-21 14:33 [PULL 00/14] more vfio-ccw updates for 5.3 Cornelia Huck
  2019-06-21 14:33 ` [PULL 01/14] s390/cio: Squash cp_free() and cp_unpin_free() Cornelia Huck
  2019-06-21 14:33 ` [PULL 02/14] s390/cio: Refactor the routine that handles TIC CCWs Cornelia Huck
@ 2019-06-21 14:33 ` Cornelia Huck
  2019-06-21 14:33 ` [PULL 04/14] s390/cio: Use generalized CCW handler in cp_init() Cornelia Huck
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Cornelia Huck @ 2019-06-21 14:33 UTC (permalink / raw)
  To: Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Eric Farman, Halil Pasic, linux-s390, kvm, Cornelia Huck

From: Eric Farman <farman@linux.ibm.com>

Refactor ccwchain_handle_tic() into a routine that handles a channel
program address (which itself is a CCW pointer), rather than a CCW pointer
that is only a TIC CCW.  This will make it easier to reuse this code for
other CCW commands.

Signed-off-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <20190606202831.44135-4-farman@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 drivers/s390/cio/vfio_ccw_cp.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 628daf1a8f9a..52735cdb0270 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -497,13 +497,13 @@ static int tic_target_chain_exists(struct ccw1 *tic, struct channel_program *cp)
 static int ccwchain_loop_tic(struct ccwchain *chain,
 			     struct channel_program *cp);
 
-static int ccwchain_handle_tic(struct ccw1 *tic, struct channel_program *cp)
+static int ccwchain_handle_ccw(u32 cda, struct channel_program *cp)
 {
 	struct ccwchain *chain;
 	int len, ret;
 
 	/* Get chain length. */
-	len = ccwchain_calc_length(tic->cda, cp);
+	len = ccwchain_calc_length(cda, cp);
 	if (len < 0)
 		return len;
 
@@ -511,10 +511,10 @@ static int ccwchain_handle_tic(struct ccw1 *tic, struct channel_program *cp)
 	chain = ccwchain_alloc(cp, len);
 	if (!chain)
 		return -ENOMEM;
-	chain->ch_iova = tic->cda;
+	chain->ch_iova = cda;
 
 	/* Copy the new chain from user. */
-	ret = copy_ccw_from_iova(cp, chain->ch_ccw, tic->cda, len);
+	ret = copy_ccw_from_iova(cp, chain->ch_ccw, cda, len);
 	if (ret) {
 		ccwchain_free(chain);
 		return ret;
@@ -540,7 +540,8 @@ static int ccwchain_loop_tic(struct ccwchain *chain, struct channel_program *cp)
 		if (tic_target_chain_exists(tic, cp))
 			continue;
 
-		ret = ccwchain_handle_tic(tic, cp);
+		/* Build a ccwchain for the next segment */
+		ret = ccwchain_handle_ccw(tic->cda, cp);
 		if (ret)
 			return ret;
 	}
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PULL 04/14] s390/cio: Use generalized CCW handler in cp_init()
  2019-06-21 14:33 [PULL 00/14] more vfio-ccw updates for 5.3 Cornelia Huck
                   ` (2 preceding siblings ...)
  2019-06-21 14:33 ` [PULL 03/14] s390/cio: Generalize the TIC handler Cornelia Huck
@ 2019-06-21 14:33 ` Cornelia Huck
  2019-06-21 14:33 ` [PULL 05/14] vfio-ccw: Rearrange pfn_array and pfn_array_table arrays Cornelia Huck
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Cornelia Huck @ 2019-06-21 14:33 UTC (permalink / raw)
  To: Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Eric Farman, Halil Pasic, linux-s390, kvm, Cornelia Huck

From: Eric Farman <farman@linux.ibm.com>

It is now pretty apparent that ccwchain_handle_ccw()
(nee ccwchain_handle_tic()) does everything that cp_init()
wants to do.

Let's remove that duplicated code from cp_init() and let
ccwchain_handle_ccw() handle it itself.

Signed-off-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <20190606202831.44135-5-farman@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 drivers/s390/cio/vfio_ccw_cp.c | 27 ++++-----------------------
 1 file changed, 4 insertions(+), 23 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 52735cdb0270..5b98bea433b7 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -744,9 +744,7 @@ static int ccwchain_fetch_one(struct ccwchain *chain,
  */
 int cp_init(struct channel_program *cp, struct device *mdev, union orb *orb)
 {
-	u64 iova = orb->cmd.cpa;
-	struct ccwchain *chain;
-	int len, ret;
+	int ret;
 
 	/*
 	 * XXX:
@@ -759,28 +757,11 @@ int cp_init(struct channel_program *cp, struct device *mdev, union orb *orb)
 	memcpy(&cp->orb, orb, sizeof(*orb));
 	cp->mdev = mdev;
 
-	/* Get chain length. */
-	len = ccwchain_calc_length(iova, cp);
-	if (len < 0)
-		return len;
-
-	/* Alloc mem for the head chain. */
-	chain = ccwchain_alloc(cp, len);
-	if (!chain)
-		return -ENOMEM;
-	chain->ch_iova = iova;
-
-	/* Copy the head chain from guest. */
-	ret = copy_ccw_from_iova(cp, chain->ch_ccw, iova, len);
-	if (ret) {
-		ccwchain_free(chain);
-		return ret;
-	}
-
-	/* Now loop for its TICs. */
-	ret = ccwchain_loop_tic(chain, cp);
+	/* Build a ccwchain for the first CCW segment */
+	ret = ccwchain_handle_ccw(orb->cmd.cpa, cp);
 	if (ret)
 		cp_free(cp);
+
 	/* It is safe to force: if not set but idals used
 	 * ccwchain_calc_length returns an error.
 	 */
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PULL 05/14] vfio-ccw: Rearrange pfn_array and pfn_array_table arrays
  2019-06-21 14:33 [PULL 00/14] more vfio-ccw updates for 5.3 Cornelia Huck
                   ` (3 preceding siblings ...)
  2019-06-21 14:33 ` [PULL 04/14] s390/cio: Use generalized CCW handler in cp_init() Cornelia Huck
@ 2019-06-21 14:33 ` Cornelia Huck
  2019-06-21 14:33 ` [PULL 06/14] vfio-ccw: Adjust the first IDAW outside of the nested loops Cornelia Huck
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Cornelia Huck @ 2019-06-21 14:33 UTC (permalink / raw)
  To: Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Eric Farman, Halil Pasic, linux-s390, kvm, Cornelia Huck

From: Eric Farman <farman@linux.ibm.com>

While processing a channel program, we currently have two nested
arrays that carry a slightly different structure.  The direct CCW
path creates this:

  ccwchain->pfn_array_table[1]->pfn_array[#pages]

while an IDA CCW creates:

  ccwchain->pfn_array_table[#idaws]->pfn_array[1]

The distinction appears to state that each pfn_array_table entry
points to an array of contiguous pages, represented by a pfn_array,
um, array.  Since the direct-addressed scenario can ONLY represent
contiguous pages, it makes the intermediate array necessary but
difficult to recognize.  Meanwhile, since an IDAL can contain
non-contiguous pages and there is no logic in vfio-ccw to detect
adjacent IDAWs, it is the second array that is necessary but appearing
to be superfluous.

I am not aware of any documentation that states the pfn_array[] needs
to be of contiguous pages; it is just what the code does today.
I don't see any reason for this either, let's just flip the IDA
codepath around so that it generates:

  ch_pat->pfn_array_table[1]->pfn_array[#idaws]

This will bring it in line with the direct-addressed codepath,
so that we can understand the behavior of this memory regardless
of what type of CCW is being processed.  And it means the casual
observer does not need to know/care whether the pfn_array[]
represents contiguous pages or not.

NB: The existing vfio-ccw code only supports 4K-block Format-2 IDAs,
so that "#pages" == "#idaws" in this area.  This means that we will
have difficulty with this overlap in terminology if support for
Format-1 or 2K-block Format-2 IDAs is ever added.  I don't think that
this patch changes our ability to make that distinction.

Signed-off-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <20190606202831.44135-6-farman@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 drivers/s390/cio/vfio_ccw_cp.c | 26 +++++++++++---------------
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 5b98bea433b7..86a0e76ef2b5 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -635,7 +635,6 @@ static int ccwchain_fetch_idal(struct ccwchain *chain,
 {
 	struct ccw1 *ccw;
 	struct pfn_array_table *pat;
-	struct pfn_array *pa;
 	unsigned long *idaws;
 	u64 idaw_iova;
 	unsigned int idaw_nr, idaw_len;
@@ -656,10 +655,14 @@ static int ccwchain_fetch_idal(struct ccwchain *chain,
 
 	/* Pin data page(s) in memory. */
 	pat = chain->ch_pat + idx;
-	ret = pfn_array_table_init(pat, idaw_nr);
+	ret = pfn_array_table_init(pat, 1);
 	if (ret)
 		goto out_init;
 
+	ret = pfn_array_alloc(pat->pat_pa, idaw_iova, bytes);
+	if (ret)
+		goto out_unpin;
+
 	/* Translate idal ccw to use new allocated idaws. */
 	idaws = kzalloc(idaw_len, GFP_DMA | GFP_KERNEL);
 	if (!idaws) {
@@ -673,22 +676,15 @@ static int ccwchain_fetch_idal(struct ccwchain *chain,
 
 	ccw->cda = virt_to_phys(idaws);
 
-	for (i = 0; i < idaw_nr; i++) {
-		idaw_iova = *(idaws + i);
-		pa = pat->pat_pa + i;
-
-		ret = pfn_array_alloc(pa, idaw_iova, 1);
-		if (ret < 0)
-			goto out_free_idaws;
-
-		if (!ccw_does_data_transfer(ccw)) {
-			pa->pa_nr = 0;
-			continue;
-		}
+	for (i = 0; i < idaw_nr; i++)
+		pat->pat_pa->pa_iova_pfn[i] = idaws[i] >> PAGE_SHIFT;
 
-		ret = pfn_array_pin(pa, cp->mdev);
+	if (ccw_does_data_transfer(ccw)) {
+		ret = pfn_array_pin(pat->pat_pa, cp->mdev);
 		if (ret < 0)
 			goto out_free_idaws;
+	} else {
+		pat->pat_pa->pa_nr = 0;
 	}
 
 	pfn_array_table_idal_create_words(pat, idaws);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PULL 06/14] vfio-ccw: Adjust the first IDAW outside of the nested loops
  2019-06-21 14:33 [PULL 00/14] more vfio-ccw updates for 5.3 Cornelia Huck
                   ` (4 preceding siblings ...)
  2019-06-21 14:33 ` [PULL 05/14] vfio-ccw: Rearrange pfn_array and pfn_array_table arrays Cornelia Huck
@ 2019-06-21 14:33 ` Cornelia Huck
  2019-06-21 14:33 ` [PULL 07/14] vfio-ccw: Remove pfn_array_table Cornelia Huck
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Cornelia Huck @ 2019-06-21 14:33 UTC (permalink / raw)
  To: Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Eric Farman, Halil Pasic, linux-s390, kvm, Cornelia Huck

From: Eric Farman <farman@linux.ibm.com>

Now that pfn_array_table[] is always an array of 1, it seems silly to
check for the very first entry in an array in the middle of two nested
loops, since we know it'll only ever happen once.

Let's move this outside the loops to simplify things, even though
the "k" variable is still necessary.

Signed-off-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <20190606202831.44135-7-farman@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 drivers/s390/cio/vfio_ccw_cp.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 86a0e76ef2b5..ab9f8f0d1b44 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -201,11 +201,12 @@ static inline void pfn_array_table_idal_create_words(
 		pa = pat->pat_pa + i;
 		for (j = 0; j < pa->pa_nr; j++) {
 			idaws[k] = pa->pa_pfn[j] << PAGE_SHIFT;
-			if (k == 0)
-				idaws[k] += pa->pa_iova & (PAGE_SIZE - 1);
 			k++;
 		}
 	}
+
+	/* Adjust the first IDAW, since it may not start on a page boundary */
+	idaws[0] += pat->pat_pa->pa_iova & (PAGE_SIZE - 1);
 }
 
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PULL 07/14] vfio-ccw: Remove pfn_array_table
  2019-06-21 14:33 [PULL 00/14] more vfio-ccw updates for 5.3 Cornelia Huck
                   ` (5 preceding siblings ...)
  2019-06-21 14:33 ` [PULL 06/14] vfio-ccw: Adjust the first IDAW outside of the nested loops Cornelia Huck
@ 2019-06-21 14:33 ` Cornelia Huck
  2019-06-21 19:13   ` Eric Farman
  2019-06-21 14:33 ` [PULL 08/14] vfio-ccw: Rearrange IDAL allocation in direct CCW Cornelia Huck
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 18+ messages in thread
From: Cornelia Huck @ 2019-06-21 14:33 UTC (permalink / raw)
  To: Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Eric Farman, Halil Pasic, linux-s390, kvm, Cornelia Huck

From: Eric Farman <farman@linux.ibm.com>

Now that both CCW codepaths build this nested array:

  ccwchain->pfn_array_table[1]->pfn_array[#idaws/#pages]

We can collapse this into simply:

  ccwchain->pfn_array[#idaws/#pages]

Let's do that, so that we don't have to continually navigate two
nested arrays when the first array always has a count of one.

Signed-off-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <20190606202831.44135-8-farman@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 drivers/s390/cio/vfio_ccw_cp.c | 118 +++++++++------------------------
 1 file changed, 33 insertions(+), 85 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index ab9f8f0d1b44..76ffcc823944 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -33,11 +33,6 @@ struct pfn_array {
 	int			pa_nr;
 };
 
-struct pfn_array_table {
-	struct pfn_array	*pat_pa;
-	int			pat_nr;
-};
-
 struct ccwchain {
 	struct list_head	next;
 	struct ccw1		*ch_ccw;
@@ -46,7 +41,7 @@ struct ccwchain {
 	/* Count of the valid ccws in chain. */
 	int			ch_len;
 	/* Pinned PAGEs for the original data. */
-	struct pfn_array_table	*ch_pat;
+	struct pfn_array	*ch_pa;
 };
 
 /*
@@ -139,55 +134,23 @@ static void pfn_array_unpin_free(struct pfn_array *pa, struct device *mdev)
 	kfree(pa->pa_iova_pfn);
 }
 
-static int pfn_array_table_init(struct pfn_array_table *pat, int nr)
-{
-	pat->pat_pa = kcalloc(nr, sizeof(*pat->pat_pa), GFP_KERNEL);
-	if (unlikely(ZERO_OR_NULL_PTR(pat->pat_pa))) {
-		pat->pat_nr = 0;
-		return -ENOMEM;
-	}
-
-	pat->pat_nr = nr;
-
-	return 0;
-}
-
-static void pfn_array_table_unpin_free(struct pfn_array_table *pat,
-				       struct device *mdev)
-{
-	int i;
-
-	for (i = 0; i < pat->pat_nr; i++)
-		pfn_array_unpin_free(pat->pat_pa + i, mdev);
-
-	if (pat->pat_nr) {
-		kfree(pat->pat_pa);
-		pat->pat_pa = NULL;
-		pat->pat_nr = 0;
-	}
-}
-
-static bool pfn_array_table_iova_pinned(struct pfn_array_table *pat,
-					unsigned long iova)
+static bool pfn_array_iova_pinned(struct pfn_array *pa, unsigned long iova)
 {
-	struct pfn_array *pa = pat->pat_pa;
 	unsigned long iova_pfn = iova >> PAGE_SHIFT;
-	int i, j;
+	int i;
 
-	for (i = 0; i < pat->pat_nr; i++, pa++)
-		for (j = 0; j < pa->pa_nr; j++)
-			if (pa->pa_iova_pfn[j] == iova_pfn)
-				return true;
+	for (i = 0; i < pa->pa_nr; i++)
+		if (pa->pa_iova_pfn[i] == iova_pfn)
+			return true;
 
 	return false;
 }
-/* Create the list idal words for a pfn_array_table. */
-static inline void pfn_array_table_idal_create_words(
-	struct pfn_array_table *pat,
+/* Create the list of IDAL words for a pfn_array. */
+static inline void pfn_array_idal_create_words(
+	struct pfn_array *pa,
 	unsigned long *idaws)
 {
-	struct pfn_array *pa;
-	int i, j, k;
+	int i;
 
 	/*
 	 * Idal words (execept the first one) rely on the memory being 4k
@@ -196,17 +159,12 @@ static inline void pfn_array_table_idal_create_words(
 	 * there will be no problem here to simply use the phys to create an
 	 * idaw.
 	 */
-	k = 0;
-	for (i = 0; i < pat->pat_nr; i++) {
-		pa = pat->pat_pa + i;
-		for (j = 0; j < pa->pa_nr; j++) {
-			idaws[k] = pa->pa_pfn[j] << PAGE_SHIFT;
-			k++;
-		}
-	}
+
+	for (i = 0; i < pa->pa_nr; i++)
+		idaws[i] = pa->pa_pfn[i] << PAGE_SHIFT;
 
 	/* Adjust the first IDAW, since it may not start on a page boundary */
-	idaws[0] += pat->pat_pa->pa_iova & (PAGE_SIZE - 1);
+	idaws[0] += pa->pa_iova & (PAGE_SIZE - 1);
 }
 
 
@@ -378,7 +336,7 @@ static struct ccwchain *ccwchain_alloc(struct channel_program *cp, int len)
 	/* Make ccw address aligned to 8. */
 	size = ((sizeof(*chain) + 7L) & -8L) +
 		sizeof(*chain->ch_ccw) * len +
-		sizeof(*chain->ch_pat) * len;
+		sizeof(*chain->ch_pa) * len;
 	chain = kzalloc(size, GFP_DMA | GFP_KERNEL);
 	if (!chain)
 		return NULL;
@@ -387,7 +345,7 @@ static struct ccwchain *ccwchain_alloc(struct channel_program *cp, int len)
 	chain->ch_ccw = (struct ccw1 *)data;
 
 	data = (u8 *)(chain->ch_ccw) + sizeof(*chain->ch_ccw) * len;
-	chain->ch_pat = (struct pfn_array_table *)data;
+	chain->ch_pa = (struct pfn_array *)data;
 
 	chain->ch_len = len;
 
@@ -575,7 +533,7 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
 				 struct channel_program *cp)
 {
 	struct ccw1 *ccw;
-	struct pfn_array_table *pat;
+	struct pfn_array *pa;
 	unsigned long *idaws;
 	int ret;
 	int bytes = 1;
@@ -593,21 +551,17 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
 	 * The number of pages actually is the count of the idaws which will be
 	 * needed when translating a direct ccw to a idal ccw.
 	 */
-	pat = chain->ch_pat + idx;
-	ret = pfn_array_table_init(pat, 1);
-	if (ret)
-		goto out_init;
-
-	ret = pfn_array_alloc(pat->pat_pa, ccw->cda, bytes);
+	pa = chain->ch_pa + idx;
+	ret = pfn_array_alloc(pa, ccw->cda, bytes);
 	if (ret < 0)
 		goto out_unpin;
 
 	if (ccw_does_data_transfer(ccw)) {
-		ret = pfn_array_pin(pat->pat_pa, cp->mdev);
+		ret = pfn_array_pin(pa, cp->mdev);
 		if (ret < 0)
 			goto out_unpin;
 	} else {
-		pat->pat_pa->pa_nr = 0;
+		pa->pa_nr = 0;
 	}
 
 	/* Translate this direct ccw to a idal ccw. */
@@ -619,12 +573,12 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
 	ccw->cda = (__u32) virt_to_phys(idaws);
 	ccw->flags |= CCW_FLAG_IDA;
 
-	pfn_array_table_idal_create_words(pat, idaws);
+	pfn_array_idal_create_words(pa, idaws);
 
 	return 0;
 
 out_unpin:
-	pfn_array_table_unpin_free(pat, cp->mdev);
+	pfn_array_unpin_free(pa, cp->mdev);
 out_init:
 	ccw->cda = 0;
 	return ret;
@@ -635,7 +589,7 @@ static int ccwchain_fetch_idal(struct ccwchain *chain,
 			       struct channel_program *cp)
 {
 	struct ccw1 *ccw;
-	struct pfn_array_table *pat;
+	struct pfn_array *pa;
 	unsigned long *idaws;
 	u64 idaw_iova;
 	unsigned int idaw_nr, idaw_len;
@@ -655,15 +609,11 @@ static int ccwchain_fetch_idal(struct ccwchain *chain,
 	idaw_len = idaw_nr * sizeof(*idaws);
 
 	/* Pin data page(s) in memory. */
-	pat = chain->ch_pat + idx;
-	ret = pfn_array_table_init(pat, 1);
+	pa = chain->ch_pa + idx;
+	ret = pfn_array_alloc(pa, idaw_iova, bytes);
 	if (ret)
 		goto out_init;
 
-	ret = pfn_array_alloc(pat->pat_pa, idaw_iova, bytes);
-	if (ret)
-		goto out_unpin;
-
 	/* Translate idal ccw to use new allocated idaws. */
 	idaws = kzalloc(idaw_len, GFP_DMA | GFP_KERNEL);
 	if (!idaws) {
@@ -678,24 +628,24 @@ static int ccwchain_fetch_idal(struct ccwchain *chain,
 	ccw->cda = virt_to_phys(idaws);
 
 	for (i = 0; i < idaw_nr; i++)
-		pat->pat_pa->pa_iova_pfn[i] = idaws[i] >> PAGE_SHIFT;
+		pa->pa_iova_pfn[i] = idaws[i] >> PAGE_SHIFT;
 
 	if (ccw_does_data_transfer(ccw)) {
-		ret = pfn_array_pin(pat->pat_pa, cp->mdev);
+		ret = pfn_array_pin(pa, cp->mdev);
 		if (ret < 0)
 			goto out_free_idaws;
 	} else {
-		pat->pat_pa->pa_nr = 0;
+		pa->pa_nr = 0;
 	}
 
-	pfn_array_table_idal_create_words(pat, idaws);
+	pfn_array_idal_create_words(pa, idaws);
 
 	return 0;
 
 out_free_idaws:
 	kfree(idaws);
 out_unpin:
-	pfn_array_table_unpin_free(pat, cp->mdev);
+	pfn_array_unpin_free(pa, cp->mdev);
 out_init:
 	ccw->cda = 0;
 	return ret;
@@ -790,8 +740,7 @@ void cp_free(struct channel_program *cp)
 	cp->initialized = false;
 	list_for_each_entry_safe(chain, temp, &cp->ccwchain_list, next) {
 		for (i = 0; i < chain->ch_len; i++) {
-			pfn_array_table_unpin_free(chain->ch_pat + i,
-						   cp->mdev);
+			pfn_array_unpin_free(chain->ch_pa + i, cp->mdev);
 			ccwchain_cda_free(chain, i);
 		}
 		ccwchain_free(chain);
@@ -967,8 +916,7 @@ bool cp_iova_pinned(struct channel_program *cp, u64 iova)
 
 	list_for_each_entry(chain, &cp->ccwchain_list, next) {
 		for (i = 0; i < chain->ch_len; i++)
-			if (pfn_array_table_iova_pinned(chain->ch_pat + i,
-							iova))
+			if (pfn_array_iova_pinned(chain->ch_pa + i, iova))
 				return true;
 	}
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PULL 08/14] vfio-ccw: Rearrange IDAL allocation in direct CCW
  2019-06-21 14:33 [PULL 00/14] more vfio-ccw updates for 5.3 Cornelia Huck
                   ` (6 preceding siblings ...)
  2019-06-21 14:33 ` [PULL 07/14] vfio-ccw: Remove pfn_array_table Cornelia Huck
@ 2019-06-21 14:33 ` Cornelia Huck
  2019-06-21 14:33 ` [PULL 09/14] s390/cio: Combine direct and indirect CCW paths Cornelia Huck
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Cornelia Huck @ 2019-06-21 14:33 UTC (permalink / raw)
  To: Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Eric Farman, Halil Pasic, linux-s390, kvm, Cornelia Huck

From: Eric Farman <farman@linux.ibm.com>

This is purely deck furniture, to help understand the merge of the
direct and indirect handlers.

Signed-off-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <20190606202831.44135-9-farman@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 drivers/s390/cio/vfio_ccw_cp.c | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 76ffcc823944..8205d0b527fc 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -537,13 +537,21 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
 	unsigned long *idaws;
 	int ret;
 	int bytes = 1;
-	int idaw_nr = 1;
+	int idaw_nr;
 
 	ccw = chain->ch_ccw + idx;
 
-	if (ccw->count) {
+	if (ccw->count)
 		bytes = ccw->count;
-		idaw_nr = idal_nr_words((void *)(u64)ccw->cda, ccw->count);
+
+	/* Calculate size of IDAL */
+	idaw_nr = idal_nr_words((void *)(u64)ccw->cda, bytes);
+
+	/* Allocate an IDAL from host storage */
+	idaws = kcalloc(idaw_nr, sizeof(*idaws), GFP_DMA | GFP_KERNEL);
+	if (!idaws) {
+		ret = -ENOMEM;
+		goto out_init;
 	}
 
 	/*
@@ -554,7 +562,7 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
 	pa = chain->ch_pa + idx;
 	ret = pfn_array_alloc(pa, ccw->cda, bytes);
 	if (ret < 0)
-		goto out_unpin;
+		goto out_free_idaws;
 
 	if (ccw_does_data_transfer(ccw)) {
 		ret = pfn_array_pin(pa, cp->mdev);
@@ -564,21 +572,18 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
 		pa->pa_nr = 0;
 	}
 
-	/* Translate this direct ccw to a idal ccw. */
-	idaws = kcalloc(idaw_nr, sizeof(*idaws), GFP_DMA | GFP_KERNEL);
-	if (!idaws) {
-		ret = -ENOMEM;
-		goto out_unpin;
-	}
 	ccw->cda = (__u32) virt_to_phys(idaws);
 	ccw->flags |= CCW_FLAG_IDA;
 
+	/* Populate the IDAL with pinned/translated addresses from pfn */
 	pfn_array_idal_create_words(pa, idaws);
 
 	return 0;
 
 out_unpin:
 	pfn_array_unpin_free(pa, cp->mdev);
+out_free_idaws:
+	kfree(idaws);
 out_init:
 	ccw->cda = 0;
 	return ret;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PULL 09/14] s390/cio: Combine direct and indirect CCW paths
  2019-06-21 14:33 [PULL 00/14] more vfio-ccw updates for 5.3 Cornelia Huck
                   ` (7 preceding siblings ...)
  2019-06-21 14:33 ` [PULL 08/14] vfio-ccw: Rearrange IDAL allocation in direct CCW Cornelia Huck
@ 2019-06-21 14:33 ` Cornelia Huck
  2019-06-21 14:33 ` [PULL 10/14] vfio-ccw: Move guest_cp storage into common struct Cornelia Huck
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Cornelia Huck @ 2019-06-21 14:33 UTC (permalink / raw)
  To: Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Eric Farman, Halil Pasic, linux-s390, kvm, Cornelia Huck

From: Eric Farman <farman@linux.ibm.com>

With both the direct-addressed and indirect-addressed CCW paths
simplified to this point, the amount of shared code between them is
(hopefully) more easily visible.  Move the processing of IDA-specific
bits into the direct-addressed path, and add some useful commentary of
what the individual pieces are doing.  This allows us to remove the
entire ccwchain_fetch_idal() routine and maintain a single function
for any non-TIC CCW.

Signed-off-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <20190606202831.44135-10-farman@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 drivers/s390/cio/vfio_ccw_cp.c | 115 +++++++++++----------------------
 1 file changed, 39 insertions(+), 76 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 8205d0b527fc..90d86e1354c1 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -534,10 +534,12 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
 {
 	struct ccw1 *ccw;
 	struct pfn_array *pa;
+	u64 iova;
 	unsigned long *idaws;
 	int ret;
 	int bytes = 1;
-	int idaw_nr;
+	int idaw_nr, idal_len;
+	int i;
 
 	ccw = chain->ch_ccw + idx;
 
@@ -545,7 +547,17 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
 		bytes = ccw->count;
 
 	/* Calculate size of IDAL */
-	idaw_nr = idal_nr_words((void *)(u64)ccw->cda, bytes);
+	if (ccw_is_idal(ccw)) {
+		/* Read first IDAW to see if it's 4K-aligned or not. */
+		/* All subsequent IDAws will be 4K-aligned. */
+		ret = copy_from_iova(cp->mdev, &iova, ccw->cda, sizeof(iova));
+		if (ret)
+			return ret;
+	} else {
+		iova = ccw->cda;
+	}
+	idaw_nr = idal_nr_words((void *)iova, bytes);
+	idal_len = idaw_nr * sizeof(*idaws);
 
 	/* Allocate an IDAL from host storage */
 	idaws = kcalloc(idaw_nr, sizeof(*idaws), GFP_DMA | GFP_KERNEL);
@@ -555,15 +567,36 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
 	}
 
 	/*
-	 * Pin data page(s) in memory.
-	 * The number of pages actually is the count of the idaws which will be
-	 * needed when translating a direct ccw to a idal ccw.
+	 * Allocate an array of pfn's for pages to pin/translate.
+	 * The number of pages is actually the count of the idaws
+	 * required for the data transfer, since we only only support
+	 * 4K IDAWs today.
 	 */
 	pa = chain->ch_pa + idx;
-	ret = pfn_array_alloc(pa, ccw->cda, bytes);
+	ret = pfn_array_alloc(pa, iova, bytes);
 	if (ret < 0)
 		goto out_free_idaws;
 
+	if (ccw_is_idal(ccw)) {
+		/* Copy guest IDAL into host IDAL */
+		ret = copy_from_iova(cp->mdev, idaws, ccw->cda, idal_len);
+		if (ret)
+			goto out_unpin;
+
+		/*
+		 * Copy guest IDAWs into pfn_array, in case the memory they
+		 * occupy is not contiguous.
+		 */
+		for (i = 0; i < idaw_nr; i++)
+			pa->pa_iova_pfn[i] = idaws[i] >> PAGE_SHIFT;
+	} else {
+		/*
+		 * No action is required here; the iova addresses in pfn_array
+		 * were initialized sequentially in pfn_array_alloc() beginning
+		 * with the contents of ccw->cda.
+		 */
+	}
+
 	if (ccw_does_data_transfer(ccw)) {
 		ret = pfn_array_pin(pa, cp->mdev);
 		if (ret < 0)
@@ -589,73 +622,6 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
 	return ret;
 }
 
-static int ccwchain_fetch_idal(struct ccwchain *chain,
-			       int idx,
-			       struct channel_program *cp)
-{
-	struct ccw1 *ccw;
-	struct pfn_array *pa;
-	unsigned long *idaws;
-	u64 idaw_iova;
-	unsigned int idaw_nr, idaw_len;
-	int i, ret;
-	int bytes = 1;
-
-	ccw = chain->ch_ccw + idx;
-
-	if (ccw->count)
-		bytes = ccw->count;
-
-	/* Calculate size of idaws. */
-	ret = copy_from_iova(cp->mdev, &idaw_iova, ccw->cda, sizeof(idaw_iova));
-	if (ret)
-		return ret;
-	idaw_nr = idal_nr_words((void *)(idaw_iova), bytes);
-	idaw_len = idaw_nr * sizeof(*idaws);
-
-	/* Pin data page(s) in memory. */
-	pa = chain->ch_pa + idx;
-	ret = pfn_array_alloc(pa, idaw_iova, bytes);
-	if (ret)
-		goto out_init;
-
-	/* Translate idal ccw to use new allocated idaws. */
-	idaws = kzalloc(idaw_len, GFP_DMA | GFP_KERNEL);
-	if (!idaws) {
-		ret = -ENOMEM;
-		goto out_unpin;
-	}
-
-	ret = copy_from_iova(cp->mdev, idaws, ccw->cda, idaw_len);
-	if (ret)
-		goto out_free_idaws;
-
-	ccw->cda = virt_to_phys(idaws);
-
-	for (i = 0; i < idaw_nr; i++)
-		pa->pa_iova_pfn[i] = idaws[i] >> PAGE_SHIFT;
-
-	if (ccw_does_data_transfer(ccw)) {
-		ret = pfn_array_pin(pa, cp->mdev);
-		if (ret < 0)
-			goto out_free_idaws;
-	} else {
-		pa->pa_nr = 0;
-	}
-
-	pfn_array_idal_create_words(pa, idaws);
-
-	return 0;
-
-out_free_idaws:
-	kfree(idaws);
-out_unpin:
-	pfn_array_unpin_free(pa, cp->mdev);
-out_init:
-	ccw->cda = 0;
-	return ret;
-}
-
 /*
  * Fetch one ccw.
  * To reduce memory copy, we'll pin the cda page in memory,
@@ -671,9 +637,6 @@ static int ccwchain_fetch_one(struct ccwchain *chain,
 	if (ccw_is_tic(ccw))
 		return ccwchain_fetch_tic(chain, idx, cp);
 
-	if (ccw_is_idal(ccw))
-		return ccwchain_fetch_idal(chain, idx, cp);
-
 	return ccwchain_fetch_direct(chain, idx, cp);
 }
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PULL 10/14] vfio-ccw: Move guest_cp storage into common struct
  2019-06-21 14:33 [PULL 00/14] more vfio-ccw updates for 5.3 Cornelia Huck
                   ` (8 preceding siblings ...)
  2019-06-21 14:33 ` [PULL 09/14] s390/cio: Combine direct and indirect CCW paths Cornelia Huck
@ 2019-06-21 14:33 ` Cornelia Huck
  2019-06-21 14:33 ` [PULL 11/14] vfio-ccw: Skip second copy of guest cp to host Cornelia Huck
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Cornelia Huck @ 2019-06-21 14:33 UTC (permalink / raw)
  To: Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Eric Farman, Halil Pasic, linux-s390, kvm, Cornelia Huck

From: Eric Farman <farman@linux.ibm.com>

Rather than allocating/freeing a piece of memory every time
we try to figure out how long a CCW chain is, let's use a piece
of memory allocated for each device.

The io_mutex added with commit 4f76617378ee9 ("vfio-ccw: protect
the I/O region") is held for the duration of the VFIO_CCW_EVENT_IO_REQ
event that accesses/uses this space, so there should be no race
concerns with another CPU attempting an (unexpected) SSCH for the
same device.

Suggested-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Eric Farman <farman@linux.ibm.com>
Message-Id: <20190618202352.39702-2-farman@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 drivers/s390/cio/vfio_ccw_cp.c  | 23 ++++-------------------
 drivers/s390/cio/vfio_ccw_cp.h  |  7 +++++++
 drivers/s390/cio/vfio_ccw_drv.c |  7 +++++++
 3 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 90d86e1354c1..f358502376be 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -16,12 +16,6 @@
 
 #include "vfio_ccw_cp.h"
 
-/*
- * Max length for ccw chain.
- * XXX: Limit to 256, need to check more?
- */
-#define CCWCHAIN_LEN_MAX	256
-
 struct pfn_array {
 	/* Starting guest physical I/O address. */
 	unsigned long		pa_iova;
@@ -386,7 +380,7 @@ static void ccwchain_cda_free(struct ccwchain *chain, int idx)
  */
 static int ccwchain_calc_length(u64 iova, struct channel_program *cp)
 {
-	struct ccw1 *ccw, *p;
+	struct ccw1 *ccw = cp->guest_cp;
 	int cnt;
 
 	/*
@@ -394,15 +388,9 @@ static int ccwchain_calc_length(u64 iova, struct channel_program *cp)
 	 * Currently the chain length is limited to CCWCHAIN_LEN_MAX (256).
 	 * So copying 2K is enough (safe).
 	 */
-	p = ccw = kcalloc(CCWCHAIN_LEN_MAX, sizeof(*ccw), GFP_KERNEL);
-	if (!ccw)
-		return -ENOMEM;
-
 	cnt = copy_ccw_from_iova(cp, ccw, iova, CCWCHAIN_LEN_MAX);
-	if (cnt) {
-		kfree(ccw);
+	if (cnt)
 		return cnt;
-	}
 
 	cnt = 0;
 	do {
@@ -413,10 +401,8 @@ static int ccwchain_calc_length(u64 iova, struct channel_program *cp)
 		 * orb specified one of the unsupported formats, we defer
 		 * checking for IDAWs in unsupported formats to here.
 		 */
-		if ((!cp->orb.cmd.c64 || cp->orb.cmd.i2k) && ccw_is_idal(ccw)) {
-			kfree(p);
+		if ((!cp->orb.cmd.c64 || cp->orb.cmd.i2k) && ccw_is_idal(ccw))
 			return -EOPNOTSUPP;
-		}
 
 		/*
 		 * We want to keep counting if the current CCW has the
@@ -435,7 +421,6 @@ static int ccwchain_calc_length(u64 iova, struct channel_program *cp)
 	if (cnt == CCWCHAIN_LEN_MAX + 1)
 		cnt = -EINVAL;
 
-	kfree(p);
 	return cnt;
 }
 
@@ -461,7 +446,7 @@ static int ccwchain_handle_ccw(u32 cda, struct channel_program *cp)
 	struct ccwchain *chain;
 	int len, ret;
 
-	/* Get chain length. */
+	/* Copy the chain from cda to cp, and count the CCWs in it */
 	len = ccwchain_calc_length(cda, cp);
 	if (len < 0)
 		return len;
diff --git a/drivers/s390/cio/vfio_ccw_cp.h b/drivers/s390/cio/vfio_ccw_cp.h
index 3c20cd208da5..7cdc38049033 100644
--- a/drivers/s390/cio/vfio_ccw_cp.h
+++ b/drivers/s390/cio/vfio_ccw_cp.h
@@ -16,6 +16,12 @@
 
 #include "orb.h"
 
+/*
+ * Max length for ccw chain.
+ * XXX: Limit to 256, need to check more?
+ */
+#define CCWCHAIN_LEN_MAX	256
+
 /**
  * struct channel_program - manage information for channel program
  * @ccwchain_list: list head of ccwchains
@@ -32,6 +38,7 @@ struct channel_program {
 	union orb orb;
 	struct device *mdev;
 	bool initialized;
+	struct ccw1 *guest_cp;
 };
 
 extern int cp_init(struct channel_program *cp, struct device *mdev,
diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
index 66a66ac1f3d1..34a9a5e3fd36 100644
--- a/drivers/s390/cio/vfio_ccw_drv.c
+++ b/drivers/s390/cio/vfio_ccw_drv.c
@@ -129,6 +129,11 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
 	if (!private)
 		return -ENOMEM;
 
+	private->cp.guest_cp = kcalloc(CCWCHAIN_LEN_MAX, sizeof(struct ccw1),
+				       GFP_KERNEL);
+	if (!private->cp.guest_cp)
+		goto out_free;
+
 	private->io_region = kmem_cache_zalloc(vfio_ccw_io_region,
 					       GFP_KERNEL | GFP_DMA);
 	if (!private->io_region)
@@ -169,6 +174,7 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
 		kmem_cache_free(vfio_ccw_cmd_region, private->cmd_region);
 	if (private->io_region)
 		kmem_cache_free(vfio_ccw_io_region, private->io_region);
+	kfree(private->cp.guest_cp);
 	kfree(private);
 	return ret;
 }
@@ -185,6 +191,7 @@ static int vfio_ccw_sch_remove(struct subchannel *sch)
 
 	kmem_cache_free(vfio_ccw_cmd_region, private->cmd_region);
 	kmem_cache_free(vfio_ccw_io_region, private->io_region);
+	kfree(private->cp.guest_cp);
 	kfree(private);
 
 	return 0;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PULL 11/14] vfio-ccw: Skip second copy of guest cp to host
  2019-06-21 14:33 [PULL 00/14] more vfio-ccw updates for 5.3 Cornelia Huck
                   ` (9 preceding siblings ...)
  2019-06-21 14:33 ` [PULL 10/14] vfio-ccw: Move guest_cp storage into common struct Cornelia Huck
@ 2019-06-21 14:33 ` Cornelia Huck
  2019-06-21 14:33 ` [PULL 12/14] vfio-ccw: Copy CCW data outside length calculation Cornelia Huck
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 18+ messages in thread
From: Cornelia Huck @ 2019-06-21 14:33 UTC (permalink / raw)
  To: Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Eric Farman, Halil Pasic, linux-s390, kvm, Cornelia Huck

From: Eric Farman <farman@linux.ibm.com>

We already pinned/copied/unpinned 2K (256 CCWs) of guest memory
to the host space anchored off vfio_ccw_private.  There's no need
to do that again once we have the length calculated, when we could
just copy the section we need to the "permanent" space for the I/O.

Signed-off-by: Eric Farman <farman@linux.ibm.com>
Message-Id: <20190618202352.39702-3-farman@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 drivers/s390/cio/vfio_ccw_cp.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index f358502376be..37d513e86530 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -444,7 +444,7 @@ static int ccwchain_loop_tic(struct ccwchain *chain,
 static int ccwchain_handle_ccw(u32 cda, struct channel_program *cp)
 {
 	struct ccwchain *chain;
-	int len, ret;
+	int len;
 
 	/* Copy the chain from cda to cp, and count the CCWs in it */
 	len = ccwchain_calc_length(cda, cp);
@@ -457,12 +457,8 @@ static int ccwchain_handle_ccw(u32 cda, struct channel_program *cp)
 		return -ENOMEM;
 	chain->ch_iova = cda;
 
-	/* Copy the new chain from user. */
-	ret = copy_ccw_from_iova(cp, chain->ch_ccw, cda, len);
-	if (ret) {
-		ccwchain_free(chain);
-		return ret;
-	}
+	/* Copy the actual CCWs into the new chain */
+	memcpy(chain->ch_ccw, cp->guest_cp, len * sizeof(struct ccw1));
 
 	/* Loop for tics on this new chain. */
 	return ccwchain_loop_tic(chain, cp);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PULL 12/14] vfio-ccw: Copy CCW data outside length calculation
  2019-06-21 14:33 [PULL 00/14] more vfio-ccw updates for 5.3 Cornelia Huck
                   ` (10 preceding siblings ...)
  2019-06-21 14:33 ` [PULL 11/14] vfio-ccw: Skip second copy of guest cp to host Cornelia Huck
@ 2019-06-21 14:33 ` Cornelia Huck
  2019-06-21 14:33 ` [PULL 13/14] vfio-ccw: Factor out the ccw0-to-ccw1 transition Cornelia Huck
  2019-06-21 14:33 ` [PULL 14/14] vfio-ccw: Remove copy_ccw_from_iova() Cornelia Huck
  13 siblings, 0 replies; 18+ messages in thread
From: Cornelia Huck @ 2019-06-21 14:33 UTC (permalink / raw)
  To: Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Eric Farman, Halil Pasic, linux-s390, kvm, Cornelia Huck

From: Eric Farman <farman@linux.ibm.com>

It doesn't make much sense to "hide" the copy to the channel_program
struct inside a routine that calculates the length of the chain.

Let's move it to the calling routine, which will later copy from
channel_program to the memory it allocated itself.

Signed-off-by: Eric Farman <farman@linux.ibm.com>
Message-Id: <20190618202352.39702-4-farman@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 drivers/s390/cio/vfio_ccw_cp.c | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 37d513e86530..a55f8d110920 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -381,18 +381,8 @@ static void ccwchain_cda_free(struct ccwchain *chain, int idx)
 static int ccwchain_calc_length(u64 iova, struct channel_program *cp)
 {
 	struct ccw1 *ccw = cp->guest_cp;
-	int cnt;
+	int cnt = 0;
 
-	/*
-	 * Copy current chain from guest to host kernel.
-	 * Currently the chain length is limited to CCWCHAIN_LEN_MAX (256).
-	 * So copying 2K is enough (safe).
-	 */
-	cnt = copy_ccw_from_iova(cp, ccw, iova, CCWCHAIN_LEN_MAX);
-	if (cnt)
-		return cnt;
-
-	cnt = 0;
 	do {
 		cnt++;
 
@@ -446,7 +436,12 @@ static int ccwchain_handle_ccw(u32 cda, struct channel_program *cp)
 	struct ccwchain *chain;
 	int len;
 
-	/* Copy the chain from cda to cp, and count the CCWs in it */
+	/* Copy 2K (the most we support today) of possible CCWs */
+	len = copy_ccw_from_iova(cp, cp->guest_cp, cda, CCWCHAIN_LEN_MAX);
+	if (len)
+		return len;
+
+	/* Count the CCWs in the current chain */
 	len = ccwchain_calc_length(cda, cp);
 	if (len < 0)
 		return len;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PULL 13/14] vfio-ccw: Factor out the ccw0-to-ccw1 transition
  2019-06-21 14:33 [PULL 00/14] more vfio-ccw updates for 5.3 Cornelia Huck
                   ` (11 preceding siblings ...)
  2019-06-21 14:33 ` [PULL 12/14] vfio-ccw: Copy CCW data outside length calculation Cornelia Huck
@ 2019-06-21 14:33 ` Cornelia Huck
  2019-06-21 19:13   ` Eric Farman
  2019-06-21 14:33 ` [PULL 14/14] vfio-ccw: Remove copy_ccw_from_iova() Cornelia Huck
  13 siblings, 1 reply; 18+ messages in thread
From: Cornelia Huck @ 2019-06-21 14:33 UTC (permalink / raw)
  To: Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Eric Farman, Halil Pasic, linux-s390, kvm, Cornelia Huck

From: Eric Farman <farman@linux.ibm.com>

This is a really useful function, but it's buried in the
copy_ccw_from_iova() routine so that ccwchain_calc_length()
can just work with Format-1 CCWs while doing its counting.
But it means we're translating a full 2K of "CCWs" to Format-1,
when in reality there's probably far fewer in that space.

Let's factor it out, so maybe we can do something with it later.

Signed-off-by: Eric Farman <farman@linux.ibm.com>
Message-Id: <20190618202352.39702-5-farman@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 drivers/s390/cio/vfio_ccw_cp.c | 48 ++++++++++++++++++----------------
 1 file changed, 25 insertions(+), 23 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index a55f8d110920..9a8bf06281e0 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -161,6 +161,27 @@ static inline void pfn_array_idal_create_words(
 	idaws[0] += pa->pa_iova & (PAGE_SIZE - 1);
 }
 
+void convert_ccw0_to_ccw1(struct ccw1 *source, unsigned long len)
+{
+	struct ccw0 ccw0;
+	struct ccw1 *pccw1 = source;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		ccw0 = *(struct ccw0 *)pccw1;
+		if ((pccw1->cmd_code & 0x0f) == CCW_CMD_TIC) {
+			pccw1->cmd_code = CCW_CMD_TIC;
+			pccw1->flags = 0;
+			pccw1->count = 0;
+		} else {
+			pccw1->cmd_code = ccw0.cmd_code;
+			pccw1->flags = ccw0.flags;
+			pccw1->count = ccw0.count;
+		}
+		pccw1->cda = ccw0.cda;
+		pccw1++;
+	}
+}
 
 /*
  * Within the domain (@mdev), copy @n bytes from a guest physical
@@ -211,32 +232,9 @@ static long copy_ccw_from_iova(struct channel_program *cp,
 			       struct ccw1 *to, u64 iova,
 			       unsigned long len)
 {
-	struct ccw0 ccw0;
-	struct ccw1 *pccw1;
 	int ret;
-	int i;
 
 	ret = copy_from_iova(cp->mdev, to, iova, len * sizeof(struct ccw1));
-	if (ret)
-		return ret;
-
-	if (!cp->orb.cmd.fmt) {
-		pccw1 = to;
-		for (i = 0; i < len; i++) {
-			ccw0 = *(struct ccw0 *)pccw1;
-			if ((pccw1->cmd_code & 0x0f) == CCW_CMD_TIC) {
-				pccw1->cmd_code = CCW_CMD_TIC;
-				pccw1->flags = 0;
-				pccw1->count = 0;
-			} else {
-				pccw1->cmd_code = ccw0.cmd_code;
-				pccw1->flags = ccw0.flags;
-				pccw1->count = ccw0.count;
-			}
-			pccw1->cda = ccw0.cda;
-			pccw1++;
-		}
-	}
 
 	return ret;
 }
@@ -441,6 +439,10 @@ static int ccwchain_handle_ccw(u32 cda, struct channel_program *cp)
 	if (len)
 		return len;
 
+	/* Convert any Format-0 CCWs to Format-1 */
+	if (!cp->orb.cmd.fmt)
+		convert_ccw0_to_ccw1(cp->guest_cp, len);
+
 	/* Count the CCWs in the current chain */
 	len = ccwchain_calc_length(cda, cp);
 	if (len < 0)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PULL 14/14] vfio-ccw: Remove copy_ccw_from_iova()
  2019-06-21 14:33 [PULL 00/14] more vfio-ccw updates for 5.3 Cornelia Huck
                   ` (12 preceding siblings ...)
  2019-06-21 14:33 ` [PULL 13/14] vfio-ccw: Factor out the ccw0-to-ccw1 transition Cornelia Huck
@ 2019-06-21 14:33 ` Cornelia Huck
  13 siblings, 0 replies; 18+ messages in thread
From: Cornelia Huck @ 2019-06-21 14:33 UTC (permalink / raw)
  To: Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Eric Farman, Halil Pasic, linux-s390, kvm, Cornelia Huck

From: Eric Farman <farman@linux.ibm.com>

Just to keep things tidy.

Signed-off-by: Eric Farman <farman@linux.ibm.com>
Message-Id: <20190618202352.39702-6-farman@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 drivers/s390/cio/vfio_ccw_cp.c | 14 ++------------
 1 file changed, 2 insertions(+), 12 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 9a8bf06281e0..9cddc1288059 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -228,17 +228,6 @@ static long copy_from_iova(struct device *mdev,
 	return l;
 }
 
-static long copy_ccw_from_iova(struct channel_program *cp,
-			       struct ccw1 *to, u64 iova,
-			       unsigned long len)
-{
-	int ret;
-
-	ret = copy_from_iova(cp->mdev, to, iova, len * sizeof(struct ccw1));
-
-	return ret;
-}
-
 /*
  * Helpers to operate ccwchain.
  */
@@ -435,7 +424,8 @@ static int ccwchain_handle_ccw(u32 cda, struct channel_program *cp)
 	int len;
 
 	/* Copy 2K (the most we support today) of possible CCWs */
-	len = copy_ccw_from_iova(cp, cp->guest_cp, cda, CCWCHAIN_LEN_MAX);
+	len = copy_from_iova(cp->mdev, cp->guest_cp, cda,
+			     CCWCHAIN_LEN_MAX * sizeof(struct ccw1));
 	if (len)
 		return len;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PULL 07/14] vfio-ccw: Remove pfn_array_table
  2019-06-21 14:33 ` [PULL 07/14] vfio-ccw: Remove pfn_array_table Cornelia Huck
@ 2019-06-21 19:13   ` Eric Farman
  0 siblings, 0 replies; 18+ messages in thread
From: Eric Farman @ 2019-06-21 19:13 UTC (permalink / raw)
  To: Cornelia Huck, Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Halil Pasic, linux-s390, kvm

Conny,

FYI, I missed a warning for unused label "out_init" after this patch
applies, which was fixed in patch 08.  This one needs the fixup below,
and patch 8 will still change it to "goto out_free_idaws;"

Not sure how to handle it on the pull request, but wanted to mention it.

My apologies,
Eric

On 6/21/19 10:33 AM, Cornelia Huck wrote:
> From: Eric Farman <farman@linux.ibm.com>
> 
> Now that both CCW codepaths build this nested array:
> 
>   ccwchain->pfn_array_table[1]->pfn_array[#idaws/#pages]
> 
> We can collapse this into simply:
> 
>   ccwchain->pfn_array[#idaws/#pages]
> 
> Let's do that, so that we don't have to continually navigate two
> nested arrays when the first array always has a count of one.
> 
> Signed-off-by: Eric Farman <farman@linux.ibm.com>
> Reviewed-by: Cornelia Huck <cohuck@redhat.com>
> Message-Id: <20190606202831.44135-8-farman@linux.ibm.com>
> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> ---
>  drivers/s390/cio/vfio_ccw_cp.c | 118 +++++++++------------------------
>  1 file changed, 33 insertions(+), 85 deletions(-)
> 
> diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
> index ab9f8f0d1b44..76ffcc823944 100644
> --- a/drivers/s390/cio/vfio_ccw_cp.c
> +++ b/drivers/s390/cio/vfio_ccw_cp.c
> @@ -33,11 +33,6 @@ struct pfn_array {
>  	int			pa_nr;
>  };
>  
> -struct pfn_array_table {
> -	struct pfn_array	*pat_pa;
> -	int			pat_nr;
> -};
> -
>  struct ccwchain {
>  	struct list_head	next;
>  	struct ccw1		*ch_ccw;
> @@ -46,7 +41,7 @@ struct ccwchain {
>  	/* Count of the valid ccws in chain. */
>  	int			ch_len;
>  	/* Pinned PAGEs for the original data. */
> -	struct pfn_array_table	*ch_pat;
> +	struct pfn_array	*ch_pa;
>  };
>  
>  /*
> @@ -139,55 +134,23 @@ static void pfn_array_unpin_free(struct pfn_array *pa, struct device *mdev)
>  	kfree(pa->pa_iova_pfn);
>  }
>  
> -static int pfn_array_table_init(struct pfn_array_table *pat, int nr)
> -{
> -	pat->pat_pa = kcalloc(nr, sizeof(*pat->pat_pa), GFP_KERNEL);
> -	if (unlikely(ZERO_OR_NULL_PTR(pat->pat_pa))) {
> -		pat->pat_nr = 0;
> -		return -ENOMEM;
> -	}
> -
> -	pat->pat_nr = nr;
> -
> -	return 0;
> -}
> -
> -static void pfn_array_table_unpin_free(struct pfn_array_table *pat,
> -				       struct device *mdev)
> -{
> -	int i;
> -
> -	for (i = 0; i < pat->pat_nr; i++)
> -		pfn_array_unpin_free(pat->pat_pa + i, mdev);
> -
> -	if (pat->pat_nr) {
> -		kfree(pat->pat_pa);
> -		pat->pat_pa = NULL;
> -		pat->pat_nr = 0;
> -	}
> -}
> -
> -static bool pfn_array_table_iova_pinned(struct pfn_array_table *pat,
> -					unsigned long iova)
> +static bool pfn_array_iova_pinned(struct pfn_array *pa, unsigned long iova)
>  {
> -	struct pfn_array *pa = pat->pat_pa;
>  	unsigned long iova_pfn = iova >> PAGE_SHIFT;
> -	int i, j;
> +	int i;
>  
> -	for (i = 0; i < pat->pat_nr; i++, pa++)
> -		for (j = 0; j < pa->pa_nr; j++)
> -			if (pa->pa_iova_pfn[j] == iova_pfn)
> -				return true;
> +	for (i = 0; i < pa->pa_nr; i++)
> +		if (pa->pa_iova_pfn[i] == iova_pfn)
> +			return true;
>  
>  	return false;
>  }
> -/* Create the list idal words for a pfn_array_table. */
> -static inline void pfn_array_table_idal_create_words(
> -	struct pfn_array_table *pat,
> +/* Create the list of IDAL words for a pfn_array. */
> +static inline void pfn_array_idal_create_words(
> +	struct pfn_array *pa,
>  	unsigned long *idaws)
>  {
> -	struct pfn_array *pa;
> -	int i, j, k;
> +	int i;
>  
>  	/*
>  	 * Idal words (execept the first one) rely on the memory being 4k
> @@ -196,17 +159,12 @@ static inline void pfn_array_table_idal_create_words(
>  	 * there will be no problem here to simply use the phys to create an
>  	 * idaw.
>  	 */
> -	k = 0;
> -	for (i = 0; i < pat->pat_nr; i++) {
> -		pa = pat->pat_pa + i;
> -		for (j = 0; j < pa->pa_nr; j++) {
> -			idaws[k] = pa->pa_pfn[j] << PAGE_SHIFT;
> -			k++;
> -		}
> -	}
> +
> +	for (i = 0; i < pa->pa_nr; i++)
> +		idaws[i] = pa->pa_pfn[i] << PAGE_SHIFT;
>  
>  	/* Adjust the first IDAW, since it may not start on a page boundary */
> -	idaws[0] += pat->pat_pa->pa_iova & (PAGE_SIZE - 1);
> +	idaws[0] += pa->pa_iova & (PAGE_SIZE - 1);
>  }
>  
>  
> @@ -378,7 +336,7 @@ static struct ccwchain *ccwchain_alloc(struct channel_program *cp, int len)
>  	/* Make ccw address aligned to 8. */
>  	size = ((sizeof(*chain) + 7L) & -8L) +
>  		sizeof(*chain->ch_ccw) * len +
> -		sizeof(*chain->ch_pat) * len;
> +		sizeof(*chain->ch_pa) * len;
>  	chain = kzalloc(size, GFP_DMA | GFP_KERNEL);
>  	if (!chain)
>  		return NULL;
> @@ -387,7 +345,7 @@ static struct ccwchain *ccwchain_alloc(struct channel_program *cp, int len)
>  	chain->ch_ccw = (struct ccw1 *)data;
>  
>  	data = (u8 *)(chain->ch_ccw) + sizeof(*chain->ch_ccw) * len;
> -	chain->ch_pat = (struct pfn_array_table *)data;
> +	chain->ch_pa = (struct pfn_array *)data;
>  
>  	chain->ch_len = len;
>  
> @@ -575,7 +533,7 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
>  				 struct channel_program *cp)
>  {
>  	struct ccw1 *ccw;
> -	struct pfn_array_table *pat;
> +	struct pfn_array *pa;
>  	unsigned long *idaws;
>  	int ret;
>  	int bytes = 1;
> @@ -593,21 +551,17 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
>  	 * The number of pages actually is the count of the idaws which will be
>  	 * needed when translating a direct ccw to a idal ccw.
>  	 */
> -	pat = chain->ch_pat + idx;
> -	ret = pfn_array_table_init(pat, 1);
> -	if (ret)
> -		goto out_init;
> -
> -	ret = pfn_array_alloc(pat->pat_pa, ccw->cda, bytes);
> +	pa = chain->ch_pa + idx;
> +	ret = pfn_array_alloc(pa, ccw->cda, bytes);
>  	if (ret < 0)
>  		goto out_unpin;

-		goto out_unpin;
+		goto out_init;

>  
>  	if (ccw_does_data_transfer(ccw)) {
> -		ret = pfn_array_pin(pat->pat_pa, cp->mdev);
> +		ret = pfn_array_pin(pa, cp->mdev);
>  		if (ret < 0)
>  			goto out_unpin;
>  	} else {
> -		pat->pat_pa->pa_nr = 0;
> +		pa->pa_nr = 0;
>  	}
>  
>  	/* Translate this direct ccw to a idal ccw. */
> @@ -619,12 +573,12 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
>  	ccw->cda = (__u32) virt_to_phys(idaws);
>  	ccw->flags |= CCW_FLAG_IDA;
>  
> -	pfn_array_table_idal_create_words(pat, idaws);
> +	pfn_array_idal_create_words(pa, idaws);
>  
>  	return 0;
>  
>  out_unpin:
> -	pfn_array_table_unpin_free(pat, cp->mdev);
> +	pfn_array_unpin_free(pa, cp->mdev);
>  out_init:
>  	ccw->cda = 0;
>  	return ret;
> @@ -635,7 +589,7 @@ static int ccwchain_fetch_idal(struct ccwchain *chain,
>  			       struct channel_program *cp)
>  {
>  	struct ccw1 *ccw;
> -	struct pfn_array_table *pat;
> +	struct pfn_array *pa;
>  	unsigned long *idaws;
>  	u64 idaw_iova;
>  	unsigned int idaw_nr, idaw_len;
> @@ -655,15 +609,11 @@ static int ccwchain_fetch_idal(struct ccwchain *chain,
>  	idaw_len = idaw_nr * sizeof(*idaws);
>  
>  	/* Pin data page(s) in memory. */
> -	pat = chain->ch_pat + idx;
> -	ret = pfn_array_table_init(pat, 1);
> +	pa = chain->ch_pa + idx;
> +	ret = pfn_array_alloc(pa, idaw_iova, bytes);
>  	if (ret)
>  		goto out_init;
>  
> -	ret = pfn_array_alloc(pat->pat_pa, idaw_iova, bytes);
> -	if (ret)
> -		goto out_unpin;
> -
>  	/* Translate idal ccw to use new allocated idaws. */
>  	idaws = kzalloc(idaw_len, GFP_DMA | GFP_KERNEL);
>  	if (!idaws) {
> @@ -678,24 +628,24 @@ static int ccwchain_fetch_idal(struct ccwchain *chain,
>  	ccw->cda = virt_to_phys(idaws);
>  
>  	for (i = 0; i < idaw_nr; i++)
> -		pat->pat_pa->pa_iova_pfn[i] = idaws[i] >> PAGE_SHIFT;
> +		pa->pa_iova_pfn[i] = idaws[i] >> PAGE_SHIFT;
>  
>  	if (ccw_does_data_transfer(ccw)) {
> -		ret = pfn_array_pin(pat->pat_pa, cp->mdev);
> +		ret = pfn_array_pin(pa, cp->mdev);
>  		if (ret < 0)
>  			goto out_free_idaws;
>  	} else {
> -		pat->pat_pa->pa_nr = 0;
> +		pa->pa_nr = 0;
>  	}
>  
> -	pfn_array_table_idal_create_words(pat, idaws);
> +	pfn_array_idal_create_words(pa, idaws);
>  
>  	return 0;
>  
>  out_free_idaws:
>  	kfree(idaws);
>  out_unpin:
> -	pfn_array_table_unpin_free(pat, cp->mdev);
> +	pfn_array_unpin_free(pa, cp->mdev);
>  out_init:
>  	ccw->cda = 0;
>  	return ret;
> @@ -790,8 +740,7 @@ void cp_free(struct channel_program *cp)
>  	cp->initialized = false;
>  	list_for_each_entry_safe(chain, temp, &cp->ccwchain_list, next) {
>  		for (i = 0; i < chain->ch_len; i++) {
> -			pfn_array_table_unpin_free(chain->ch_pat + i,
> -						   cp->mdev);
> +			pfn_array_unpin_free(chain->ch_pa + i, cp->mdev);
>  			ccwchain_cda_free(chain, i);
>  		}
>  		ccwchain_free(chain);
> @@ -967,8 +916,7 @@ bool cp_iova_pinned(struct channel_program *cp, u64 iova)
>  
>  	list_for_each_entry(chain, &cp->ccwchain_list, next) {
>  		for (i = 0; i < chain->ch_len; i++)
> -			if (pfn_array_table_iova_pinned(chain->ch_pat + i,
> -							iova))
> +			if (pfn_array_iova_pinned(chain->ch_pa + i, iova))
>  				return true;
>  	}
>  
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PULL 13/14] vfio-ccw: Factor out the ccw0-to-ccw1 transition
  2019-06-21 14:33 ` [PULL 13/14] vfio-ccw: Factor out the ccw0-to-ccw1 transition Cornelia Huck
@ 2019-06-21 19:13   ` Eric Farman
  2019-06-22  8:38     ` Heiko Carstens
  0 siblings, 1 reply; 18+ messages in thread
From: Eric Farman @ 2019-06-21 19:13 UTC (permalink / raw)
  To: Cornelia Huck, Heiko Carstens, Vasily Gorbik, Christian Borntraeger
  Cc: Farhan Ali, Halil Pasic, linux-s390, kvm

Conny,

I'm bad at things, because I thought for sure I had checked for and
fixed this before I sent the patches.  This one gets a sparse warning,
fixed below.

Eric

On 6/21/19 10:33 AM, Cornelia Huck wrote:
> From: Eric Farman <farman@linux.ibm.com>
> 
> This is a really useful function, but it's buried in the
> copy_ccw_from_iova() routine so that ccwchain_calc_length()
> can just work with Format-1 CCWs while doing its counting.
> But it means we're translating a full 2K of "CCWs" to Format-1,
> when in reality there's probably far fewer in that space.
> 
> Let's factor it out, so maybe we can do something with it later.
> 
> Signed-off-by: Eric Farman <farman@linux.ibm.com>
> Message-Id: <20190618202352.39702-5-farman@linux.ibm.com>
> Reviewed-by: Cornelia Huck <cohuck@redhat.com>
> Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> ---
>  drivers/s390/cio/vfio_ccw_cp.c | 48 ++++++++++++++++++----------------
>  1 file changed, 25 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
> index a55f8d110920..9a8bf06281e0 100644
> --- a/drivers/s390/cio/vfio_ccw_cp.c
> +++ b/drivers/s390/cio/vfio_ccw_cp.c
> @@ -161,6 +161,27 @@ static inline void pfn_array_idal_create_words(
>  	idaws[0] += pa->pa_iova & (PAGE_SIZE - 1);
>  }
>  
> +void convert_ccw0_to_ccw1(struct ccw1 *source, unsigned long len)

static void convert_...

> +{
> +	struct ccw0 ccw0;
> +	struct ccw1 *pccw1 = source;
> +	int i;
> +
> +	for (i = 0; i < len; i++) {
> +		ccw0 = *(struct ccw0 *)pccw1;
> +		if ((pccw1->cmd_code & 0x0f) == CCW_CMD_TIC) {
> +			pccw1->cmd_code = CCW_CMD_TIC;
> +			pccw1->flags = 0;
> +			pccw1->count = 0;
> +		} else {
> +			pccw1->cmd_code = ccw0.cmd_code;
> +			pccw1->flags = ccw0.flags;
> +			pccw1->count = ccw0.count;
> +		}
> +		pccw1->cda = ccw0.cda;
> +		pccw1++;
> +	}
> +}
>  
>  /*
>   * Within the domain (@mdev), copy @n bytes from a guest physical
> @@ -211,32 +232,9 @@ static long copy_ccw_from_iova(struct channel_program *cp,
>  			       struct ccw1 *to, u64 iova,
>  			       unsigned long len)
>  {
> -	struct ccw0 ccw0;
> -	struct ccw1 *pccw1;
>  	int ret;
> -	int i;
>  
>  	ret = copy_from_iova(cp->mdev, to, iova, len * sizeof(struct ccw1));
> -	if (ret)
> -		return ret;
> -
> -	if (!cp->orb.cmd.fmt) {
> -		pccw1 = to;
> -		for (i = 0; i < len; i++) {
> -			ccw0 = *(struct ccw0 *)pccw1;
> -			if ((pccw1->cmd_code & 0x0f) == CCW_CMD_TIC) {
> -				pccw1->cmd_code = CCW_CMD_TIC;
> -				pccw1->flags = 0;
> -				pccw1->count = 0;
> -			} else {
> -				pccw1->cmd_code = ccw0.cmd_code;
> -				pccw1->flags = ccw0.flags;
> -				pccw1->count = ccw0.count;
> -			}
> -			pccw1->cda = ccw0.cda;
> -			pccw1++;
> -		}
> -	}
>  
>  	return ret;
>  }
> @@ -441,6 +439,10 @@ static int ccwchain_handle_ccw(u32 cda, struct channel_program *cp)
>  	if (len)
>  		return len;
>  
> +	/* Convert any Format-0 CCWs to Format-1 */
> +	if (!cp->orb.cmd.fmt)
> +		convert_ccw0_to_ccw1(cp->guest_cp, len);
> +
>  	/* Count the CCWs in the current chain */
>  	len = ccwchain_calc_length(cda, cp);
>  	if (len < 0)
> 


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PULL 13/14] vfio-ccw: Factor out the ccw0-to-ccw1 transition
  2019-06-21 19:13   ` Eric Farman
@ 2019-06-22  8:38     ` Heiko Carstens
  0 siblings, 0 replies; 18+ messages in thread
From: Heiko Carstens @ 2019-06-22  8:38 UTC (permalink / raw)
  To: Eric Farman
  Cc: Cornelia Huck, Vasily Gorbik, Christian Borntraeger, Farhan Ali,
	Halil Pasic, linux-s390, kvm

On Fri, Jun 21, 2019 at 03:13:20PM -0400, Eric Farman wrote:
> Conny,
> 
> I'm bad at things, because I thought for sure I had checked for and
> fixed this before I sent the patches.  This one gets a sparse warning,
> fixed below.
> 
> Eric
> 
> On 6/21/19 10:33 AM, Cornelia Huck wrote:
> > From: Eric Farman <farman@linux.ibm.com>
> > 
> > This is a really useful function, but it's buried in the
> > copy_ccw_from_iova() routine so that ccwchain_calc_length()
> > can just work with Format-1 CCWs while doing its counting.
> > But it means we're translating a full 2K of "CCWs" to Format-1,
> > when in reality there's probably far fewer in that space.
> > 
> > Let's factor it out, so maybe we can do something with it later.
> > 
> > Signed-off-by: Eric Farman <farman@linux.ibm.com>
> > Message-Id: <20190618202352.39702-5-farman@linux.ibm.com>
> > Reviewed-by: Cornelia Huck <cohuck@redhat.com>
> > Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
> > Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> > ---
> >  drivers/s390/cio/vfio_ccw_cp.c | 48 ++++++++++++++++++----------------
> >  1 file changed, 25 insertions(+), 23 deletions(-)
> > 
> > diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
> > index a55f8d110920..9a8bf06281e0 100644
> > --- a/drivers/s390/cio/vfio_ccw_cp.c
> > +++ b/drivers/s390/cio/vfio_ccw_cp.c
> > @@ -161,6 +161,27 @@ static inline void pfn_array_idal_create_words(
> >  	idaws[0] += pa->pa_iova & (PAGE_SIZE - 1);
> >  }
> >  
> > +void convert_ccw0_to_ccw1(struct ccw1 *source, unsigned long len)
> 
> static void convert_...

Please send an add-on patch. Code is already in our internal tree for
testing purposes and will be push out next week.


^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2019-06-22  8:38 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-21 14:33 [PULL 00/14] more vfio-ccw updates for 5.3 Cornelia Huck
2019-06-21 14:33 ` [PULL 01/14] s390/cio: Squash cp_free() and cp_unpin_free() Cornelia Huck
2019-06-21 14:33 ` [PULL 02/14] s390/cio: Refactor the routine that handles TIC CCWs Cornelia Huck
2019-06-21 14:33 ` [PULL 03/14] s390/cio: Generalize the TIC handler Cornelia Huck
2019-06-21 14:33 ` [PULL 04/14] s390/cio: Use generalized CCW handler in cp_init() Cornelia Huck
2019-06-21 14:33 ` [PULL 05/14] vfio-ccw: Rearrange pfn_array and pfn_array_table arrays Cornelia Huck
2019-06-21 14:33 ` [PULL 06/14] vfio-ccw: Adjust the first IDAW outside of the nested loops Cornelia Huck
2019-06-21 14:33 ` [PULL 07/14] vfio-ccw: Remove pfn_array_table Cornelia Huck
2019-06-21 19:13   ` Eric Farman
2019-06-21 14:33 ` [PULL 08/14] vfio-ccw: Rearrange IDAL allocation in direct CCW Cornelia Huck
2019-06-21 14:33 ` [PULL 09/14] s390/cio: Combine direct and indirect CCW paths Cornelia Huck
2019-06-21 14:33 ` [PULL 10/14] vfio-ccw: Move guest_cp storage into common struct Cornelia Huck
2019-06-21 14:33 ` [PULL 11/14] vfio-ccw: Skip second copy of guest cp to host Cornelia Huck
2019-06-21 14:33 ` [PULL 12/14] vfio-ccw: Copy CCW data outside length calculation Cornelia Huck
2019-06-21 14:33 ` [PULL 13/14] vfio-ccw: Factor out the ccw0-to-ccw1 transition Cornelia Huck
2019-06-21 19:13   ` Eric Farman
2019-06-22  8:38     ` Heiko Carstens
2019-06-21 14:33 ` [PULL 14/14] vfio-ccw: Remove copy_ccw_from_iova() Cornelia Huck

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).