diff mbox series

npu2: Use unfiltered mode in XTS tables

Message ID 1519940751-9022-1-git-send-email-arbab@linux.vnet.ibm.com
State Accepted
Headers show
Series npu2: Use unfiltered mode in XTS tables | expand

Commit Message

Reza Arbab March 1, 2018, 9:45 p.m. UTC
The XTS_PID context table is limited to 256 possible pids/contexts. To
relieve this limitation, make use of "unfiltered mode" instead.

If an entry in the XTS_BDF table has the bit for unfiltered mode set, we
can just use one context for that entire bdf/lpar, regardless of pid.
Instead of of searching the XTS_PID table, the NMMU checkout request
will simply use the entry indexed by lparshort id instead.

Change opal_npu_init_context() to create these lparshort-indexed
wildcard entries (0-15) instead of allocating one for each pid. Check
that multiple calls for the same bdf all specify the same msr value.

In opal_npu_destroy_context(), continue validating the bdf argument,
ensuring that it actually maps to an lpar, but no longer remove anything
from the XTS_PID table. If/when we start supporting virtualized GPUs, we
might consider actually removing these wildcard entries by keeping a
refcount, but keep things simple for now.

Signed-off-by: Reza Arbab <arbab@linux.vnet.ibm.com>
---
 hw/npu2.c           | 73 ++++++++++++++++++++++-------------------------------
 include/npu2-regs.h |  2 ++
 2 files changed, 32 insertions(+), 43 deletions(-)

Comments

Alistair Popple March 8, 2018, 11:33 p.m. UTC | #1
Thanks Reza!

I had one very minor thought below but it doesn't require a respin - everything
looks correct and seemed to work on our limited test setup. Note I was only able
to excersise the translation request path and not the shootdown path as we lack
an application stack to test ATSDs.

Acked-by: Alistair Popple <alistair@popple.id.au>

> -static int opal_npu_destroy_context(uint64_t phb_id, uint64_t pid, uint64_t bdf)
> +static int opal_npu_destroy_context(uint64_t phb_id, uint64_t pid __unused,
> +				    uint64_t bdf)
>  {
>  	struct phb *phb = pci_get_phb(phb_id);
>  	struct npu2 *p = phb_to_npu2(phb);
> -	uint64_t xts_bdf, xts_bdf_pid;
> -	uint64_t lparshort;
> -	int id, rc = 0;
> +	uint64_t xts_bdf;
> +	int rc = 0;
>  
>  	if (!phb || phb->phb_type != phb_type_npu_v2)
>  		return OPAL_PARAMETER;
> @@ -2137,26 +2136,13 @@ static int opal_npu_destroy_context(uint64_t phb_id, uint64_t pid, uint64_t bdf)
>  			     &xts_bdf, NPU2_XTS_BDF_MAP_BDF) < 0) {
>  		NPU2ERR(p, "LPARID not associated with any GPU\n");

I guess this check is still somewhat useful to catch a buggy device driver out
but I'm not convinced it provides much value - we could just as easily remove it
as well.

>  		rc = OPAL_PARAMETER;
> -		goto out;
>  	}
>  
> -	lparshort = GETFIELD(NPU2_XTS_BDF_MAP_LPARSHORT, xts_bdf);
> -	NPU2DBG(p, "Found LPARSHORT = 0x%llx destroy context for BDF = 0x%03llx PID = 0x%llx\n",
> -		lparshort, bdf, pid);
> -
> -	/* Now find the entry in the bdf/pid table */
> -	xts_bdf_pid = SETFIELD(NPU2_XTS_PID_MAP_LPARSHORT, 0ul, lparshort);
> -	xts_bdf_pid = SETFIELD(NPU2_XTS_PID_MAP_PASID, xts_bdf_pid, pid);
> -	id = npu_table_search(p, NPU2_XTS_PID_MAP, 0x20, NPU2_XTS_PID_MAP_SIZE, &xts_bdf_pid,
> -			      NPU2_XTS_PID_MAP_LPARSHORT | NPU2_XTS_PID_MAP_PASID);
> -	if (id < 0) {
> -		rc = OPAL_PARAMETER;
> -		goto out;
> -	}
> +	/*
> +	 * The bdf/pid table only contains wildcard entries, so we don't
> +	 * need to remove anything here.
> +	 */
>  
> -	/* And zero the entry */
> -	npu2_write(p, NPU2_XTS_PID_MAP + id*0x20, 0);
> -out:
>  	unlock(&p->lock);
>  	return rc;
>  }
> @@ -2208,6 +2194,7 @@ static int opal_npu_map_lpar(uint64_t phb_id, uint64_t bdf, uint64_t lparid,
>  	}
>  
>  	xts_bdf_lpar = SETFIELD(NPU2_XTS_BDF_MAP_VALID, 0UL, 1);
> +	xts_bdf_lpar = SETFIELD(NPU2_XTS_BDF_MAP_UNFILT, xts_bdf_lpar, 1);
>  	xts_bdf_lpar = SETFIELD(NPU2_XTS_BDF_MAP_BDF, xts_bdf_lpar, bdf);
>  
>  	/* We only support radix for the moment */
> diff --git a/include/npu2-regs.h b/include/npu2-regs.h
> index 73925f9..fd249f4 100644
> --- a/include/npu2-regs.h
> +++ b/include/npu2-regs.h
> @@ -425,6 +425,7 @@ void npu2_write_mask(struct npu2 *p, uint64_t reg, uint64_t val, uint64_t mask);
>  #define NPU2_XTS_MMIO_ATSD7_LPARID		NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_XTS, 0x138)
>  #define NPU2_XTS_BDF_MAP			NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_XTS, 0x4000)
>  #define   NPU2_XTS_BDF_MAP_VALID		PPC_BIT(0)
> +#define   NPU2_XTS_BDF_MAP_UNFILT		PPC_BIT(1)
>  #define   NPU2_XTS_BDF_MAP_STACK		PPC_BITMASK(4, 6)
>  #define   NPU2_XTS_BDF_MAP_BRICK		PPC_BIT(7)
>  #define   NPU2_XTS_BDF_MAP_BDF			PPC_BITMASK(16, 31)
> @@ -437,6 +438,7 @@ void npu2_write_mask(struct npu2 *p, uint64_t reg, uint64_t val, uint64_t mask);
>  #define   NPU2_XTS_PID_MAP_VALID_ATRGPA0	PPC_BIT(0)
>  #define   NPU2_XTS_PID_MAP_VALID_ATRGPA1	PPC_BIT(1)
>  #define   NPU2_XTS_PID_MAP_VALID_ATSD		PPC_BIT(2)
> +#define   NPU2_XTS_PID_MAP_MSR			PPC_BITMASK(25,31)
>  #define   NPU2_XTS_PID_MAP_MSR_DR		PPC_BIT(25)
>  #define   NPU2_XTS_PID_MAP_MSR_TA		PPC_BIT(26)
>  #define   NPU2_XTS_PID_MAP_MSR_HV		PPC_BIT(27)
>
Reza Arbab March 9, 2018, 12:09 a.m. UTC | #2
On Fri, Mar 09, 2018 at 10:33:51AM +1100, Alistair Popple wrote: 
>> -static int opal_npu_destroy_context(uint64_t phb_id, uint64_t pid, uint64_t bdf)
>> +static int opal_npu_destroy_context(uint64_t phb_id, uint64_t pid __unused,
>> +				    uint64_t bdf)
>>  {
>>  	struct phb *phb = pci_get_phb(phb_id);
>>  	struct npu2 *p = phb_to_npu2(phb);
>> -	uint64_t xts_bdf, xts_bdf_pid;
>> -	uint64_t lparshort;
>> -	int id, rc = 0;
>> +	uint64_t xts_bdf;
>> +	int rc = 0;
>>
>>  	if (!phb || phb->phb_type != phb_type_npu_v2)
>>  		return OPAL_PARAMETER;
>> @@ -2137,26 +2136,13 @@ static int opal_npu_destroy_context(uint64_t phb_id, uint64_t pid, uint64_t bdf)
>>  			     &xts_bdf, NPU2_XTS_BDF_MAP_BDF) < 0) {
>>  		NPU2ERR(p, "LPARID not associated with any GPU\n");
>
>I guess this check is still somewhat useful to catch a buggy device driver out
>but I'm not convinced it provides much value - we could just as easily remove it
>as well.

Yeah, I wavered on it a bit and figured if nothing else, the function 
could still keep validating that argument. There are some words to that 
effect in the commit log.
Alistair Popple March 9, 2018, 12:29 a.m. UTC | #3
> Yeah, I wavered on it a bit and figured if nothing else, the function 
> could still keep validating that argument. There are some words to that 
> effect in the commit log.

Yeah, I saw that. Good work on the commit log btw - it's a good description of
what we're doing here.

- Alistair
Stewart Smith March 13, 2018, 4:32 a.m. UTC | #4
Reza Arbab <arbab@linux.vnet.ibm.com> writes:
> The XTS_PID context table is limited to 256 possible pids/contexts. To
> relieve this limitation, make use of "unfiltered mode" instead.
>
> If an entry in the XTS_BDF table has the bit for unfiltered mode set, we
> can just use one context for that entire bdf/lpar, regardless of pid.
> Instead of of searching the XTS_PID table, the NMMU checkout request
> will simply use the entry indexed by lparshort id instead.
>
> Change opal_npu_init_context() to create these lparshort-indexed
> wildcard entries (0-15) instead of allocating one for each pid. Check
> that multiple calls for the same bdf all specify the same msr value.
>
> In opal_npu_destroy_context(), continue validating the bdf argument,
> ensuring that it actually maps to an lpar, but no longer remove anything
> from the XTS_PID table. If/when we start supporting virtualized GPUs, we
> might consider actually removing these wildcard entries by keeping a
> refcount, but keep things simple for now.
>
> Signed-off-by: Reza Arbab <arbab@linux.vnet.ibm.com>
> ---
>  hw/npu2.c           | 73 ++++++++++++++++++++++-------------------------------
>  include/npu2-regs.h |  2 ++
>  2 files changed, 32 insertions(+), 43 deletions(-)

Thanks, merged to master as of 105d80f85b071e1aefefaa4e15beaee027a45fd6
diff mbox series

Patch

diff --git a/hw/npu2.c b/hw/npu2.c
index fad53c4..2a56ac6 100644
--- a/hw/npu2.c
+++ b/hw/npu2.c
@@ -2039,13 +2039,13 @@  static int npu_table_search(struct npu2 *p, uint64_t table_addr, int stride,
  * allocated.
  */
 #define NPU2_VALID_ATS_MSR_BITS (MSR_DR | MSR_HV | MSR_PR | MSR_SF)
-static int64_t opal_npu_init_context(uint64_t phb_id, int pasid, uint64_t msr,
-				     uint64_t bdf)
+static int64_t opal_npu_init_context(uint64_t phb_id, int pasid __unused,
+				     uint64_t msr, uint64_t bdf)
 {
 	struct phb *phb = pci_get_phb(phb_id);
 	struct npu2 *p = phb_to_npu2(phb);
-	uint64_t xts_bdf, xts_bdf_pid = 0;
-	int id, lparshort;
+	uint64_t xts_bdf, old_xts_bdf_pid, xts_bdf_pid;
+	int id;
 
 	if (!phb || phb->phb_type != phb_type_npu_v2)
 		return OPAL_PARAMETER;
@@ -2069,20 +2069,8 @@  static int64_t opal_npu_init_context(uint64_t phb_id, int pasid, uint64_t msr,
 		goto out;
 	}
 
-	lparshort = GETFIELD(NPU2_XTS_BDF_MAP_LPARSHORT, xts_bdf);
-	NPU2DBG(p, "Found LPARSHORT = 0x%x for BDF = 0x%03llx\n", lparshort,
-		bdf);
-
-	/*
-	 * Need to find a free context.
-	 */
-	id = npu_table_search(p, NPU2_XTS_PID_MAP, 0x20, NPU2_XTS_PID_MAP_SIZE,
-			      &xts_bdf_pid, -1UL);
-	if (id < 0) {
-		NPU2ERR(p, "No XTS contexts available\n");
-		id = OPAL_RESOURCE;
-		goto out;
-	}
+	id = GETFIELD(NPU2_XTS_BDF_MAP_LPARSHORT, xts_bdf);
+	NPU2DBG(p, "Found LPARSHORT = 0x%x for BDF = 0x%03llx\n", id, bdf);
 
 	/* Enable this mapping for both real and virtual addresses */
 	xts_bdf_pid = SETFIELD(NPU2_XTS_PID_MAP_VALID_ATRGPA0, 0UL, 1);
@@ -2090,8 +2078,7 @@  static int64_t opal_npu_init_context(uint64_t phb_id, int pasid, uint64_t msr,
 
 	/* Enables TLBIE/MMIOSD forwarding for this entry */
 	xts_bdf_pid = SETFIELD(NPU2_XTS_PID_MAP_VALID_ATSD, xts_bdf_pid, 1);
-	xts_bdf_pid = SETFIELD(NPU2_XTS_PID_MAP_LPARSHORT, xts_bdf_pid,
-			       lparshort);
+	xts_bdf_pid = SETFIELD(NPU2_XTS_PID_MAP_LPARSHORT, xts_bdf_pid, id);
 
 	/* Set the relevant MSR bits */
 	xts_bdf_pid = SETFIELD(NPU2_XTS_PID_MAP_MSR_DR, xts_bdf_pid,
@@ -2105,8 +2092,20 @@  static int64_t opal_npu_init_context(uint64_t phb_id, int pasid, uint64_t msr,
 	 * it here */
 	xts_bdf_pid = SETFIELD(NPU2_XTS_PID_MAP_MSR_SF, xts_bdf_pid, 1);
 
-	/* Finally set the PID/PASID */
-	xts_bdf_pid = SETFIELD(NPU2_XTS_PID_MAP_PASID, xts_bdf_pid, pasid);
+	/*
+	 * Throw an error if the wildcard entry for this bdf is already set
+	 * with different msr bits.
+	 */
+	old_xts_bdf_pid = npu2_read(p, NPU2_XTS_PID_MAP + id*0x20);
+	if (old_xts_bdf_pid) {
+		if (GETFIELD(NPU2_XTS_PID_MAP_MSR, old_xts_bdf_pid) !=
+		    GETFIELD(NPU2_XTS_PID_MAP_MSR, xts_bdf_pid)) {
+			NPU2ERR(p, "%s: Unexpected MSR value\n", __func__);
+			id = OPAL_PARAMETER;
+		}
+
+		goto out;
+	}
 
 	/* Write the entry */
 	NPU2DBG(p, "XTS_PID_MAP[%03d] = 0x%08llx\n", id, xts_bdf_pid);
@@ -2118,13 +2117,13 @@  out:
 }
 opal_call(OPAL_NPU_INIT_CONTEXT, opal_npu_init_context, 4);
 
-static int opal_npu_destroy_context(uint64_t phb_id, uint64_t pid, uint64_t bdf)
+static int opal_npu_destroy_context(uint64_t phb_id, uint64_t pid __unused,
+				    uint64_t bdf)
 {
 	struct phb *phb = pci_get_phb(phb_id);
 	struct npu2 *p = phb_to_npu2(phb);
-	uint64_t xts_bdf, xts_bdf_pid;
-	uint64_t lparshort;
-	int id, rc = 0;
+	uint64_t xts_bdf;
+	int rc = 0;
 
 	if (!phb || phb->phb_type != phb_type_npu_v2)
 		return OPAL_PARAMETER;
@@ -2137,26 +2136,13 @@  static int opal_npu_destroy_context(uint64_t phb_id, uint64_t pid, uint64_t bdf)
 			     &xts_bdf, NPU2_XTS_BDF_MAP_BDF) < 0) {
 		NPU2ERR(p, "LPARID not associated with any GPU\n");
 		rc = OPAL_PARAMETER;
-		goto out;
 	}
 
-	lparshort = GETFIELD(NPU2_XTS_BDF_MAP_LPARSHORT, xts_bdf);
-	NPU2DBG(p, "Found LPARSHORT = 0x%llx destroy context for BDF = 0x%03llx PID = 0x%llx\n",
-		lparshort, bdf, pid);
-
-	/* Now find the entry in the bdf/pid table */
-	xts_bdf_pid = SETFIELD(NPU2_XTS_PID_MAP_LPARSHORT, 0ul, lparshort);
-	xts_bdf_pid = SETFIELD(NPU2_XTS_PID_MAP_PASID, xts_bdf_pid, pid);
-	id = npu_table_search(p, NPU2_XTS_PID_MAP, 0x20, NPU2_XTS_PID_MAP_SIZE, &xts_bdf_pid,
-			      NPU2_XTS_PID_MAP_LPARSHORT | NPU2_XTS_PID_MAP_PASID);
-	if (id < 0) {
-		rc = OPAL_PARAMETER;
-		goto out;
-	}
+	/*
+	 * The bdf/pid table only contains wildcard entries, so we don't
+	 * need to remove anything here.
+	 */
 
-	/* And zero the entry */
-	npu2_write(p, NPU2_XTS_PID_MAP + id*0x20, 0);
-out:
 	unlock(&p->lock);
 	return rc;
 }
@@ -2208,6 +2194,7 @@  static int opal_npu_map_lpar(uint64_t phb_id, uint64_t bdf, uint64_t lparid,
 	}
 
 	xts_bdf_lpar = SETFIELD(NPU2_XTS_BDF_MAP_VALID, 0UL, 1);
+	xts_bdf_lpar = SETFIELD(NPU2_XTS_BDF_MAP_UNFILT, xts_bdf_lpar, 1);
 	xts_bdf_lpar = SETFIELD(NPU2_XTS_BDF_MAP_BDF, xts_bdf_lpar, bdf);
 
 	/* We only support radix for the moment */
diff --git a/include/npu2-regs.h b/include/npu2-regs.h
index 73925f9..fd249f4 100644
--- a/include/npu2-regs.h
+++ b/include/npu2-regs.h
@@ -425,6 +425,7 @@  void npu2_write_mask(struct npu2 *p, uint64_t reg, uint64_t val, uint64_t mask);
 #define NPU2_XTS_MMIO_ATSD7_LPARID		NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_XTS, 0x138)
 #define NPU2_XTS_BDF_MAP			NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_XTS, 0x4000)
 #define   NPU2_XTS_BDF_MAP_VALID		PPC_BIT(0)
+#define   NPU2_XTS_BDF_MAP_UNFILT		PPC_BIT(1)
 #define   NPU2_XTS_BDF_MAP_STACK		PPC_BITMASK(4, 6)
 #define   NPU2_XTS_BDF_MAP_BRICK		PPC_BIT(7)
 #define   NPU2_XTS_BDF_MAP_BDF			PPC_BITMASK(16, 31)
@@ -437,6 +438,7 @@  void npu2_write_mask(struct npu2 *p, uint64_t reg, uint64_t val, uint64_t mask);
 #define   NPU2_XTS_PID_MAP_VALID_ATRGPA0	PPC_BIT(0)
 #define   NPU2_XTS_PID_MAP_VALID_ATRGPA1	PPC_BIT(1)
 #define   NPU2_XTS_PID_MAP_VALID_ATSD		PPC_BIT(2)
+#define   NPU2_XTS_PID_MAP_MSR			PPC_BITMASK(25,31)
 #define   NPU2_XTS_PID_MAP_MSR_DR		PPC_BIT(25)
 #define   NPU2_XTS_PID_MAP_MSR_TA		PPC_BIT(26)
 #define   NPU2_XTS_PID_MAP_MSR_HV		PPC_BIT(27)