diff mbox series

drm/i915: Implement read-only support in whitelist selftest

Message ID 20190618195421.31027-1-John.C.Harrison@Intel.com (mailing list archive)
State New, archived
Headers show
Series drm/i915: Implement read-only support in whitelist selftest | expand

Commit Message

John Harrison June 18, 2019, 7:54 p.m. UTC
From: John Harrison <John.C.Harrison@Intel.com>

Newer hardware supports extra feature in the whitelist registers. This
patch updates the selftest to test that entries marked as read only
are actually read only.

Also updated the read/write access definitions to make it clearer that
they are an enum field not a set of single bit flags.

Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
CC: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 drivers/gpu/drm/i915/gt/intel_workarounds.c   |  8 +--
 .../gpu/drm/i915/gt/selftest_workarounds.c    | 53 +++++++++++++------
 drivers/gpu/drm/i915/i915_reg.h               |  9 ++--
 3 files changed, 48 insertions(+), 22 deletions(-)

Comments

John Harrison June 18, 2019, 8:08 p.m. UTC | #1
Tvrtko, does this look plausible?

It seems to work for me in that it passes on ICL with the new read-only 
registers. I'm not sure if there is a valid way to detect whether the 
registers are actually readable though. How would the test know what is 
a valid value? If one assumes that one gets back zero from an invalid 
read, how does one know that the read-only register is not supposed to 
return zero at this point anyway?

Or is it worth just putting in a test for non-zero and if we do find a 
register that can validly return zero then we special case that one and 
ignore it?

John.


On 6/18/2019 12:54, John.C.Harrison@Intel.com wrote:
> From: John Harrison <John.C.Harrison@Intel.com>
>
> Newer hardware supports extra feature in the whitelist registers. This
> patch updates the selftest to test that entries marked as read only
> are actually read only.
>
> Also updated the read/write access definitions to make it clearer that
> they are an enum field not a set of single bit flags.
>
> Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
> CC: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> ---
>   drivers/gpu/drm/i915/gt/intel_workarounds.c   |  8 +--
>   .../gpu/drm/i915/gt/selftest_workarounds.c    | 53 +++++++++++++------
>   drivers/gpu/drm/i915/i915_reg.h               |  9 ++--
>   3 files changed, 48 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
> index 93caa7b6d7a9..4429ee08b20e 100644
> --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
> +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
> @@ -1028,7 +1028,7 @@ whitelist_reg_ext(struct i915_wa_list *wal, i915_reg_t reg, u32 flags)
>   static void
>   whitelist_reg(struct i915_wa_list *wal, i915_reg_t reg)
>   {
> -	whitelist_reg_ext(wal, reg, RING_FORCE_TO_NONPRIV_RW);
> +	whitelist_reg_ext(wal, reg, RING_FORCE_TO_NONPRIV_ACCESS_RW);
>   }
>   
>   static void gen9_whitelist_build(struct i915_wa_list *w)
> @@ -1134,13 +1134,13 @@ printk(KERN_INFO "%-32s:%4d> Boo! [engine = %s, instance = %d, base = 0x%X, reg
>   
>   		/* hucStatusRegOffset */
>   		whitelist_reg_ext(w, _MMIO(0x2000 + engine->mmio_base),
> -				  RING_FORCE_TO_NONPRIV_RD);
> +				  RING_FORCE_TO_NONPRIV_ACCESS_RD);
>   		/* hucUKernelHdrInfoRegOffset */
>   		whitelist_reg_ext(w, _MMIO(0x2014 + engine->mmio_base),
> -				  RING_FORCE_TO_NONPRIV_RD);
> +				  RING_FORCE_TO_NONPRIV_ACCESS_RD);
>   		/* hucStatus2RegOffset */
>   		whitelist_reg_ext(w, _MMIO(0x23B0 + engine->mmio_base),
> -				  RING_FORCE_TO_NONPRIV_RD);
> +				  RING_FORCE_TO_NONPRIV_ACCESS_RD);
>   		break;
>   
>   	default:
> diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
> index eb6d3aa2c8cc..a0a88ec66861 100644
> --- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c
> +++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
> @@ -399,6 +399,10 @@ static bool wo_register(struct intel_engine_cs *engine, u32 reg)
>   	enum intel_platform platform = INTEL_INFO(engine->i915)->platform;
>   	int i;
>   
> +	if ((reg & RING_FORCE_TO_NONPRIV_ACCESS_MASK) ==
> +	     RING_FORCE_TO_NONPRIV_ACCESS_WR)
> +		return true;
> +
>   	for (i = 0; i < ARRAY_SIZE(wo_registers); i++) {
>   		if (wo_registers[i].platform == platform &&
>   		    wo_registers[i].reg == reg)
> @@ -410,7 +414,8 @@ static bool wo_register(struct intel_engine_cs *engine, u32 reg)
>   
>   static bool ro_register(u32 reg)
>   {
> -	if (reg & RING_FORCE_TO_NONPRIV_RD)
> +	if ((reg & RING_FORCE_TO_NONPRIV_ACCESS_MASK) ==
> +	     RING_FORCE_TO_NONPRIV_ACCESS_RD)
>   		return true;
>   
>   	return false;
> @@ -482,12 +487,12 @@ static int check_dirty_whitelist(struct i915_gem_context *ctx,
>   		u32 srm, lrm, rsvd;
>   		u32 expect;
>   		int idx;
> +		bool ro_reg;
>   
>   		if (wo_register(engine, reg))
>   			continue;
>   
> -		if (ro_register(reg))
> -			continue;
> +		ro_reg = ro_register(reg);
>   
>   		srm = MI_STORE_REGISTER_MEM;
>   		lrm = MI_LOAD_REGISTER_MEM;
> @@ -588,24 +593,36 @@ static int check_dirty_whitelist(struct i915_gem_context *ctx,
>   		}
>   
>   		GEM_BUG_ON(values[ARRAY_SIZE(values) - 1] != 0xffffffff);
> -		rsvd = results[ARRAY_SIZE(values)]; /* detect write masking */
> -		if (!rsvd) {
> -			pr_err("%s: Unable to write to whitelisted register %x\n",
> -			       engine->name, reg);
> -			err = -EINVAL;
> -			goto out_unpin;
> +		if (ro_reg) {
> +			rsvd = 0xFFFFFFFF;
> +		} else {
> +			rsvd = results[ARRAY_SIZE(values)]; /* detect write masking */
> +			if (!rsvd) {
> +				pr_err("%s: Unable to write to whitelisted register %x\n",
> +				       engine->name, reg);
> +				err = -EINVAL;
> +				goto out_unpin;
> +			}
>   		}
>   
>   		expect = results[0];
>   		idx = 1;
>   		for (v = 0; v < ARRAY_SIZE(values); v++) {
> -			expect = reg_write(expect, values[v], rsvd);
> +			if (ro_reg)
> +				expect = results[0];
> +			else
> +				expect = reg_write(expect, values[v], rsvd);
> +
>   			if (results[idx] != expect)
>   				err++;
>   			idx++;
>   		}
>   		for (v = 0; v < ARRAY_SIZE(values); v++) {
> -			expect = reg_write(expect, ~values[v], rsvd);
> +			if (ro_reg)
> +				expect = results[0];
> +			else
> +				expect = reg_write(expect, ~values[v], rsvd);
> +
>   			if (results[idx] != expect)
>   				err++;
>   			idx++;
> @@ -622,7 +639,10 @@ static int check_dirty_whitelist(struct i915_gem_context *ctx,
>   			for (v = 0; v < ARRAY_SIZE(values); v++) {
>   				u32 w = values[v];
>   
> -				expect = reg_write(expect, w, rsvd);
> +				if (ro_reg)
> +					expect = results[0];
> +				else
> +					expect = reg_write(expect, w, rsvd);
>   				pr_info("Wrote %08x, read %08x, expect %08x\n",
>   					w, results[idx], expect);
>   				idx++;
> @@ -630,7 +650,10 @@ static int check_dirty_whitelist(struct i915_gem_context *ctx,
>   			for (v = 0; v < ARRAY_SIZE(values); v++) {
>   				u32 w = ~values[v];
>   
> -				expect = reg_write(expect, w, rsvd);
> +				if (ro_reg)
> +					expect = results[0];
> +				else
> +					expect = reg_write(expect, w, rsvd);
>   				pr_info("Wrote %08x, read %08x, expect %08x\n",
>   					w, results[idx], expect);
>   				idx++;
> @@ -762,8 +785,8 @@ static int read_whitelisted_registers(struct i915_gem_context *ctx,
>   		u64 offset = results->node.start + sizeof(u32) * i;
>   		u32 reg = i915_mmio_reg_offset(engine->whitelist.list[i].reg);
>   
> -		/* Clear RD only and WR only flags */
> -		reg &= ~(RING_FORCE_TO_NONPRIV_RD | RING_FORCE_TO_NONPRIV_WR);
> +		/* Clear access permission field */
> +		reg &= ~RING_FORCE_TO_NONPRIV_ACCESS_MASK;
>   
>   		*cs++ = srm;
>   		*cs++ = reg;
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index cc295a4f6e92..ba22e3b8f77e 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -2513,13 +2513,16 @@ enum i915_power_well_id {
>   #define   RING_WAIT_SEMAPHORE	(1 << 10) /* gen6+ */
>   
>   #define RING_FORCE_TO_NONPRIV(base, i) _MMIO(((base) + 0x4D0) + (i) * 4)
> -#define   RING_FORCE_TO_NONPRIV_RW		(0 << 28)    /* CFL+ & Gen11+ */
> -#define   RING_FORCE_TO_NONPRIV_RD		(1 << 28)
> -#define   RING_FORCE_TO_NONPRIV_WR		(2 << 28)
> +#define   RING_FORCE_TO_NONPRIV_ACCESS_RW	(0 << 28)    /* CFL+ & Gen11+ */
> +#define   RING_FORCE_TO_NONPRIV_ACCESS_RD	(1 << 28)
> +#define   RING_FORCE_TO_NONPRIV_ACCESS_WR	(2 << 28)
> +#define   RING_FORCE_TO_NONPRIV_ACCESS_INVALID	(3 << 28)
> +#define   RING_FORCE_TO_NONPRIV_ACCESS_MASK	(3 << 28)
>   #define   RING_FORCE_TO_NONPRIV_RANGE_1		(0 << 0)     /* CFL+ & Gen11+ */
>   #define   RING_FORCE_TO_NONPRIV_RANGE_4		(1 << 0)
>   #define   RING_FORCE_TO_NONPRIV_RANGE_16	(2 << 0)
>   #define   RING_FORCE_TO_NONPRIV_RANGE_64	(3 << 0)
> +#define   RING_FORCE_TO_NONPRIV_RANGE_MASK	(3 << 0)
>   #define   RING_MAX_NONPRIV_SLOTS  12
>   
>   #define GEN7_TLB_RD_ADDR	_MMIO(0x4700)
Tvrtko Ursulin June 19, 2019, 6:41 a.m. UTC | #2
On 18/06/2019 21:08, John Harrison wrote:
> Tvrtko, does this look plausible?
> 
> It seems to work for me in that it passes on ICL with the new read-only 
> registers. I'm not sure if there is a valid way to detect whether the 
> registers are actually readable though. How would the test know what is 
> a valid value? If one assumes that one gets back zero from an invalid 
> read, how does one know that the read-only register is not supposed to 
> return zero at this point anyway?
> 
> Or is it worth just putting in a test for non-zero and if we do find a 
> register that can validly return zero then we special case that one and 
> ignore it?

I was thinking we just read the register and then verify it is unchanged 
after every existing write to it.

Regards,

Tvrtko
Tvrtko Ursulin June 19, 2019, 6:49 a.m. UTC | #3
On 18/06/2019 20:54, John.C.Harrison@Intel.com wrote:
> From: John Harrison <John.C.Harrison@Intel.com>
> 
> Newer hardware supports extra feature in the whitelist registers. This
> patch updates the selftest to test that entries marked as read only
> are actually read only.
> 
> Also updated the read/write access definitions to make it clearer that
> they are an enum field not a set of single bit flags.
> 
> Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
> CC: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> ---
>   drivers/gpu/drm/i915/gt/intel_workarounds.c   |  8 +--
>   .../gpu/drm/i915/gt/selftest_workarounds.c    | 53 +++++++++++++------
>   drivers/gpu/drm/i915/i915_reg.h               |  9 ++--
>   3 files changed, 48 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
> index 93caa7b6d7a9..4429ee08b20e 100644
> --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
> +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
> @@ -1028,7 +1028,7 @@ whitelist_reg_ext(struct i915_wa_list *wal, i915_reg_t reg, u32 flags)

Reminder to add a GEM_BUG_ON if invalid flags are passed in.

>   static void
>   whitelist_reg(struct i915_wa_list *wal, i915_reg_t reg)
>   {
> -	whitelist_reg_ext(wal, reg, RING_FORCE_TO_NONPRIV_RW);
> +	whitelist_reg_ext(wal, reg, RING_FORCE_TO_NONPRIV_ACCESS_RW);
>   }
>   
>   static void gen9_whitelist_build(struct i915_wa_list *w)
> @@ -1134,13 +1134,13 @@ printk(KERN_INFO "%-32s:%4d> Boo! [engine = %s, instance = %d, base = 0x%X, reg
>   
>   		/* hucStatusRegOffset */
>   		whitelist_reg_ext(w, _MMIO(0x2000 + engine->mmio_base),
> -				  RING_FORCE_TO_NONPRIV_RD);
> +				  RING_FORCE_TO_NONPRIV_ACCESS_RD);
>   		/* hucUKernelHdrInfoRegOffset */
>   		whitelist_reg_ext(w, _MMIO(0x2014 + engine->mmio_base),
> -				  RING_FORCE_TO_NONPRIV_RD);
> +				  RING_FORCE_TO_NONPRIV_ACCESS_RD);
>   		/* hucStatus2RegOffset */
>   		whitelist_reg_ext(w, _MMIO(0x23B0 + engine->mmio_base),
> -				  RING_FORCE_TO_NONPRIV_RD);
> +				  RING_FORCE_TO_NONPRIV_ACCESS_RD);
>   		break;
>   
>   	default:
> diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
> index eb6d3aa2c8cc..a0a88ec66861 100644
> --- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c
> +++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
> @@ -399,6 +399,10 @@ static bool wo_register(struct intel_engine_cs *engine, u32 reg)
>   	enum intel_platform platform = INTEL_INFO(engine->i915)->platform;
>   	int i;
>   
> +	if ((reg & RING_FORCE_TO_NONPRIV_ACCESS_MASK) ==
> +	     RING_FORCE_TO_NONPRIV_ACCESS_WR)
> +		return true;
> +
>   	for (i = 0; i < ARRAY_SIZE(wo_registers); i++) {
>   		if (wo_registers[i].platform == platform &&
>   		    wo_registers[i].reg == reg)
> @@ -410,7 +414,8 @@ static bool wo_register(struct intel_engine_cs *engine, u32 reg)
>   
>   static bool ro_register(u32 reg)
>   {
> -	if (reg & RING_FORCE_TO_NONPRIV_RD)
> +	if ((reg & RING_FORCE_TO_NONPRIV_ACCESS_MASK) ==
> +	     RING_FORCE_TO_NONPRIV_ACCESS_RD)
>   		return true;
>   
>   	return false;
> @@ -482,12 +487,12 @@ static int check_dirty_whitelist(struct i915_gem_context *ctx,
>   		u32 srm, lrm, rsvd;
>   		u32 expect;
>   		int idx;
> +		bool ro_reg;
>   
>   		if (wo_register(engine, reg))
>   			continue;
>   
> -		if (ro_register(reg))
> -			continue;
> +		ro_reg = ro_register(reg);
>   
>   		srm = MI_STORE_REGISTER_MEM;
>   		lrm = MI_LOAD_REGISTER_MEM;
> @@ -588,24 +593,36 @@ static int check_dirty_whitelist(struct i915_gem_context *ctx,
>   		}
>   
>   		GEM_BUG_ON(values[ARRAY_SIZE(values) - 1] != 0xffffffff);
> -		rsvd = results[ARRAY_SIZE(values)]; /* detect write masking */
> -		if (!rsvd) {
> -			pr_err("%s: Unable to write to whitelisted register %x\n",
> -			       engine->name, reg);
> -			err = -EINVAL;
> -			goto out_unpin;
> +		if (ro_reg) {
> +			rsvd = 0xFFFFFFFF;

I guess it doesn't matter what value you set since it is only used on 
pr_info on ro_reg paths?

> +		} else {
> +			rsvd = results[ARRAY_SIZE(values)]; /* detect write masking */
> +			if (!rsvd) {
> +				pr_err("%s: Unable to write to whitelisted register %x\n",
> +				       engine->name, reg);
> +				err = -EINVAL;
> +				goto out_unpin;
> +			}
>   		}
>   
>   		expect = results[0];
>   		idx = 1;
>   		for (v = 0; v < ARRAY_SIZE(values); v++) {
> -			expect = reg_write(expect, values[v], rsvd);
> +			if (ro_reg)
> +				expect = results[0];
> +			else
> +				expect = reg_write(expect, values[v], rsvd);
> +
>   			if (results[idx] != expect)
>   				err++;
>   			idx++;
>   		}
>   		for (v = 0; v < ARRAY_SIZE(values); v++) {
> -			expect = reg_write(expect, ~values[v], rsvd);
> +			if (ro_reg)
> +				expect = results[0];
> +			else
> +				expect = reg_write(expect, ~values[v], rsvd);
> +
>   			if (results[idx] != expect)
>   				err++;
>   			idx++;
> @@ -622,7 +639,10 @@ static int check_dirty_whitelist(struct i915_gem_context *ctx,
>   			for (v = 0; v < ARRAY_SIZE(values); v++) {
>   				u32 w = values[v];
>   
> -				expect = reg_write(expect, w, rsvd);
> +				if (ro_reg)
> +					expect = results[0];
> +				else
> +					expect = reg_write(expect, w, rsvd);
>   				pr_info("Wrote %08x, read %08x, expect %08x\n",
>   					w, results[idx], expect);
>   				idx++;
> @@ -630,7 +650,10 @@ static int check_dirty_whitelist(struct i915_gem_context *ctx,
>   			for (v = 0; v < ARRAY_SIZE(values); v++) {
>   				u32 w = ~values[v];
>   
> -				expect = reg_write(expect, w, rsvd);
> +				if (ro_reg)
> +					expect = results[0];
> +				else
> +					expect = reg_write(expect, w, rsvd);
>   				pr_info("Wrote %08x, read %08x, expect %08x\n",
>   					w, results[idx], expect);
>   				idx++;
> @@ -762,8 +785,8 @@ static int read_whitelisted_registers(struct i915_gem_context *ctx,
>   		u64 offset = results->node.start + sizeof(u32) * i;
>   		u32 reg = i915_mmio_reg_offset(engine->whitelist.list[i].reg);
>   
> -		/* Clear RD only and WR only flags */
> -		reg &= ~(RING_FORCE_TO_NONPRIV_RD | RING_FORCE_TO_NONPRIV_WR);
> +		/* Clear access permission field */
> +		reg &= ~RING_FORCE_TO_NONPRIV_ACCESS_MASK;
>   
>   		*cs++ = srm;
>   		*cs++ = reg;
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index cc295a4f6e92..ba22e3b8f77e 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -2513,13 +2513,16 @@ enum i915_power_well_id {
>   #define   RING_WAIT_SEMAPHORE	(1 << 10) /* gen6+ */
>   
>   #define RING_FORCE_TO_NONPRIV(base, i) _MMIO(((base) + 0x4D0) + (i) * 4)
> -#define   RING_FORCE_TO_NONPRIV_RW		(0 << 28)    /* CFL+ & Gen11+ */
> -#define   RING_FORCE_TO_NONPRIV_RD		(1 << 28)
> -#define   RING_FORCE_TO_NONPRIV_WR		(2 << 28)
> +#define   RING_FORCE_TO_NONPRIV_ACCESS_RW	(0 << 28)    /* CFL+ & Gen11+ */
> +#define   RING_FORCE_TO_NONPRIV_ACCESS_RD	(1 << 28)
> +#define   RING_FORCE_TO_NONPRIV_ACCESS_WR	(2 << 28)
> +#define   RING_FORCE_TO_NONPRIV_ACCESS_INVALID	(3 << 28)
> +#define   RING_FORCE_TO_NONPRIV_ACCESS_MASK	(3 << 28)
>   #define   RING_FORCE_TO_NONPRIV_RANGE_1		(0 << 0)     /* CFL+ & Gen11+ */
>   #define   RING_FORCE_TO_NONPRIV_RANGE_4		(1 << 0)
>   #define   RING_FORCE_TO_NONPRIV_RANGE_16	(2 << 0)
>   #define   RING_FORCE_TO_NONPRIV_RANGE_64	(3 << 0)
> +#define   RING_FORCE_TO_NONPRIV_RANGE_MASK	(3 << 0)
>   #define   RING_MAX_NONPRIV_SLOTS  12
>   
>   #define GEN7_TLB_RD_ADDR	_MMIO(0x4700)
> 

This in fact looks fine to me.

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

Tvrtko
Tvrtko Ursulin June 20, 2019, 3:43 p.m. UTC | #4
Hi,

You will need to send this not as reply to this thread so it is picked 
up by CI and then can be merged.

But please also add a patch which adds that GEM_BUG_ON reg->flags check 
we talked about.

Regards,

Tvrtko

On 18/06/2019 20:54, John.C.Harrison@Intel.com wrote:
> From: John Harrison <John.C.Harrison@Intel.com>
> 
> Newer hardware supports extra feature in the whitelist registers. This
> patch updates the selftest to test that entries marked as read only
> are actually read only.
> 
> Also updated the read/write access definitions to make it clearer that
> they are an enum field not a set of single bit flags.
> 
> Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
> CC: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> ---
>   drivers/gpu/drm/i915/gt/intel_workarounds.c   |  8 +--
>   .../gpu/drm/i915/gt/selftest_workarounds.c    | 53 +++++++++++++------
>   drivers/gpu/drm/i915/i915_reg.h               |  9 ++--
>   3 files changed, 48 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
> index 93caa7b6d7a9..4429ee08b20e 100644
> --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
> +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
> @@ -1028,7 +1028,7 @@ whitelist_reg_ext(struct i915_wa_list *wal, i915_reg_t reg, u32 flags)
>   static void
>   whitelist_reg(struct i915_wa_list *wal, i915_reg_t reg)
>   {
> -	whitelist_reg_ext(wal, reg, RING_FORCE_TO_NONPRIV_RW);
> +	whitelist_reg_ext(wal, reg, RING_FORCE_TO_NONPRIV_ACCESS_RW);
>   }
>   
>   static void gen9_whitelist_build(struct i915_wa_list *w)
> @@ -1134,13 +1134,13 @@ printk(KERN_INFO "%-32s:%4d> Boo! [engine = %s, instance = %d, base = 0x%X, reg
>   
>   		/* hucStatusRegOffset */
>   		whitelist_reg_ext(w, _MMIO(0x2000 + engine->mmio_base),
> -				  RING_FORCE_TO_NONPRIV_RD);
> +				  RING_FORCE_TO_NONPRIV_ACCESS_RD);
>   		/* hucUKernelHdrInfoRegOffset */
>   		whitelist_reg_ext(w, _MMIO(0x2014 + engine->mmio_base),
> -				  RING_FORCE_TO_NONPRIV_RD);
> +				  RING_FORCE_TO_NONPRIV_ACCESS_RD);
>   		/* hucStatus2RegOffset */
>   		whitelist_reg_ext(w, _MMIO(0x23B0 + engine->mmio_base),
> -				  RING_FORCE_TO_NONPRIV_RD);
> +				  RING_FORCE_TO_NONPRIV_ACCESS_RD);
>   		break;
>   
>   	default:
> diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
> index eb6d3aa2c8cc..a0a88ec66861 100644
> --- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c
> +++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
> @@ -399,6 +399,10 @@ static bool wo_register(struct intel_engine_cs *engine, u32 reg)
>   	enum intel_platform platform = INTEL_INFO(engine->i915)->platform;
>   	int i;
>   
> +	if ((reg & RING_FORCE_TO_NONPRIV_ACCESS_MASK) ==
> +	     RING_FORCE_TO_NONPRIV_ACCESS_WR)
> +		return true;
> +
>   	for (i = 0; i < ARRAY_SIZE(wo_registers); i++) {
>   		if (wo_registers[i].platform == platform &&
>   		    wo_registers[i].reg == reg)
> @@ -410,7 +414,8 @@ static bool wo_register(struct intel_engine_cs *engine, u32 reg)
>   
>   static bool ro_register(u32 reg)
>   {
> -	if (reg & RING_FORCE_TO_NONPRIV_RD)
> +	if ((reg & RING_FORCE_TO_NONPRIV_ACCESS_MASK) ==
> +	     RING_FORCE_TO_NONPRIV_ACCESS_RD)
>   		return true;
>   
>   	return false;
> @@ -482,12 +487,12 @@ static int check_dirty_whitelist(struct i915_gem_context *ctx,
>   		u32 srm, lrm, rsvd;
>   		u32 expect;
>   		int idx;
> +		bool ro_reg;
>   
>   		if (wo_register(engine, reg))
>   			continue;
>   
> -		if (ro_register(reg))
> -			continue;
> +		ro_reg = ro_register(reg);
>   
>   		srm = MI_STORE_REGISTER_MEM;
>   		lrm = MI_LOAD_REGISTER_MEM;
> @@ -588,24 +593,36 @@ static int check_dirty_whitelist(struct i915_gem_context *ctx,
>   		}
>   
>   		GEM_BUG_ON(values[ARRAY_SIZE(values) - 1] != 0xffffffff);
> -		rsvd = results[ARRAY_SIZE(values)]; /* detect write masking */
> -		if (!rsvd) {
> -			pr_err("%s: Unable to write to whitelisted register %x\n",
> -			       engine->name, reg);
> -			err = -EINVAL;
> -			goto out_unpin;
> +		if (ro_reg) {
> +			rsvd = 0xFFFFFFFF;
> +		} else {
> +			rsvd = results[ARRAY_SIZE(values)]; /* detect write masking */
> +			if (!rsvd) {
> +				pr_err("%s: Unable to write to whitelisted register %x\n",
> +				       engine->name, reg);
> +				err = -EINVAL;
> +				goto out_unpin;
> +			}
>   		}
>   
>   		expect = results[0];
>   		idx = 1;
>   		for (v = 0; v < ARRAY_SIZE(values); v++) {
> -			expect = reg_write(expect, values[v], rsvd);
> +			if (ro_reg)
> +				expect = results[0];
> +			else
> +				expect = reg_write(expect, values[v], rsvd);
> +
>   			if (results[idx] != expect)
>   				err++;
>   			idx++;
>   		}
>   		for (v = 0; v < ARRAY_SIZE(values); v++) {
> -			expect = reg_write(expect, ~values[v], rsvd);
> +			if (ro_reg)
> +				expect = results[0];
> +			else
> +				expect = reg_write(expect, ~values[v], rsvd);
> +
>   			if (results[idx] != expect)
>   				err++;
>   			idx++;
> @@ -622,7 +639,10 @@ static int check_dirty_whitelist(struct i915_gem_context *ctx,
>   			for (v = 0; v < ARRAY_SIZE(values); v++) {
>   				u32 w = values[v];
>   
> -				expect = reg_write(expect, w, rsvd);
> +				if (ro_reg)
> +					expect = results[0];
> +				else
> +					expect = reg_write(expect, w, rsvd);
>   				pr_info("Wrote %08x, read %08x, expect %08x\n",
>   					w, results[idx], expect);
>   				idx++;
> @@ -630,7 +650,10 @@ static int check_dirty_whitelist(struct i915_gem_context *ctx,
>   			for (v = 0; v < ARRAY_SIZE(values); v++) {
>   				u32 w = ~values[v];
>   
> -				expect = reg_write(expect, w, rsvd);
> +				if (ro_reg)
> +					expect = results[0];
> +				else
> +					expect = reg_write(expect, w, rsvd);
>   				pr_info("Wrote %08x, read %08x, expect %08x\n",
>   					w, results[idx], expect);
>   				idx++;
> @@ -762,8 +785,8 @@ static int read_whitelisted_registers(struct i915_gem_context *ctx,
>   		u64 offset = results->node.start + sizeof(u32) * i;
>   		u32 reg = i915_mmio_reg_offset(engine->whitelist.list[i].reg);
>   
> -		/* Clear RD only and WR only flags */
> -		reg &= ~(RING_FORCE_TO_NONPRIV_RD | RING_FORCE_TO_NONPRIV_WR);
> +		/* Clear access permission field */
> +		reg &= ~RING_FORCE_TO_NONPRIV_ACCESS_MASK;
>   
>   		*cs++ = srm;
>   		*cs++ = reg;
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index cc295a4f6e92..ba22e3b8f77e 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -2513,13 +2513,16 @@ enum i915_power_well_id {
>   #define   RING_WAIT_SEMAPHORE	(1 << 10) /* gen6+ */
>   
>   #define RING_FORCE_TO_NONPRIV(base, i) _MMIO(((base) + 0x4D0) + (i) * 4)
> -#define   RING_FORCE_TO_NONPRIV_RW		(0 << 28)    /* CFL+ & Gen11+ */
> -#define   RING_FORCE_TO_NONPRIV_RD		(1 << 28)
> -#define   RING_FORCE_TO_NONPRIV_WR		(2 << 28)
> +#define   RING_FORCE_TO_NONPRIV_ACCESS_RW	(0 << 28)    /* CFL+ & Gen11+ */
> +#define   RING_FORCE_TO_NONPRIV_ACCESS_RD	(1 << 28)
> +#define   RING_FORCE_TO_NONPRIV_ACCESS_WR	(2 << 28)
> +#define   RING_FORCE_TO_NONPRIV_ACCESS_INVALID	(3 << 28)
> +#define   RING_FORCE_TO_NONPRIV_ACCESS_MASK	(3 << 28)
>   #define   RING_FORCE_TO_NONPRIV_RANGE_1		(0 << 0)     /* CFL+ & Gen11+ */
>   #define   RING_FORCE_TO_NONPRIV_RANGE_4		(1 << 0)
>   #define   RING_FORCE_TO_NONPRIV_RANGE_16	(2 << 0)
>   #define   RING_FORCE_TO_NONPRIV_RANGE_64	(3 << 0)
> +#define   RING_FORCE_TO_NONPRIV_RANGE_MASK	(3 << 0)
>   #define   RING_MAX_NONPRIV_SLOTS  12
>   
>   #define GEN7_TLB_RD_ADDR	_MMIO(0x4700)
>
Tvrtko Ursulin June 25, 2019, 8:33 a.m. UTC | #5
Ping.

We agreed to follow up with a test ASAP after merging.

Here's another feature request for you: Add engine->name logging to 
wa_init_start in intel_engine_init_whitelist. Because with the change to 
add whitelist on other engines there are now multiple identical lines in 
dmesg.

To sum up that's three todo items:

1. Resend the selftest for CI.
2. Add GEM_BUG_ON for reg->flags checking invalid flag usage.
3. Improve dmesg so we know which engine got how many whitelist entries.

Thanks,

Tvrtko

On 20/06/2019 16:43, Tvrtko Ursulin wrote:
> 
> Hi,
> 
> You will need to send this not as reply to this thread so it is picked 
> up by CI and then can be merged.
> 
> But please also add a patch which adds that GEM_BUG_ON reg->flags check 
> we talked about.
> 
> Regards,
> 
> Tvrtko
> 
> On 18/06/2019 20:54, John.C.Harrison@Intel.com wrote:
>> From: John Harrison <John.C.Harrison@Intel.com>
>>
>> Newer hardware supports extra feature in the whitelist registers. This
>> patch updates the selftest to test that entries marked as read only
>> are actually read only.
>>
>> Also updated the read/write access definitions to make it clearer that
>> they are an enum field not a set of single bit flags.
>>
>> Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
>> CC: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>> ---
>>   drivers/gpu/drm/i915/gt/intel_workarounds.c   |  8 +--
>>   .../gpu/drm/i915/gt/selftest_workarounds.c    | 53 +++++++++++++------
>>   drivers/gpu/drm/i915/i915_reg.h               |  9 ++--
>>   3 files changed, 48 insertions(+), 22 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c 
>> b/drivers/gpu/drm/i915/gt/intel_workarounds.c
>> index 93caa7b6d7a9..4429ee08b20e 100644
>> --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
>> +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
>> @@ -1028,7 +1028,7 @@ whitelist_reg_ext(struct i915_wa_list *wal, 
>> i915_reg_t reg, u32 flags)
>>   static void
>>   whitelist_reg(struct i915_wa_list *wal, i915_reg_t reg)
>>   {
>> -    whitelist_reg_ext(wal, reg, RING_FORCE_TO_NONPRIV_RW);
>> +    whitelist_reg_ext(wal, reg, RING_FORCE_TO_NONPRIV_ACCESS_RW);
>>   }
>>   static void gen9_whitelist_build(struct i915_wa_list *w)
>> @@ -1134,13 +1134,13 @@ printk(KERN_INFO "%-32s:%4d> Boo! [engine = 
>> %s, instance = %d, base = 0x%X, reg
>>           /* hucStatusRegOffset */
>>           whitelist_reg_ext(w, _MMIO(0x2000 + engine->mmio_base),
>> -                  RING_FORCE_TO_NONPRIV_RD);
>> +                  RING_FORCE_TO_NONPRIV_ACCESS_RD);
>>           /* hucUKernelHdrInfoRegOffset */
>>           whitelist_reg_ext(w, _MMIO(0x2014 + engine->mmio_base),
>> -                  RING_FORCE_TO_NONPRIV_RD);
>> +                  RING_FORCE_TO_NONPRIV_ACCESS_RD);
>>           /* hucStatus2RegOffset */
>>           whitelist_reg_ext(w, _MMIO(0x23B0 + engine->mmio_base),
>> -                  RING_FORCE_TO_NONPRIV_RD);
>> +                  RING_FORCE_TO_NONPRIV_ACCESS_RD);
>>           break;
>>       default:
>> diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c 
>> b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
>> index eb6d3aa2c8cc..a0a88ec66861 100644
>> --- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c
>> +++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
>> @@ -399,6 +399,10 @@ static bool wo_register(struct intel_engine_cs 
>> *engine, u32 reg)
>>       enum intel_platform platform = INTEL_INFO(engine->i915)->platform;
>>       int i;
>> +    if ((reg & RING_FORCE_TO_NONPRIV_ACCESS_MASK) ==
>> +         RING_FORCE_TO_NONPRIV_ACCESS_WR)
>> +        return true;
>> +
>>       for (i = 0; i < ARRAY_SIZE(wo_registers); i++) {
>>           if (wo_registers[i].platform == platform &&
>>               wo_registers[i].reg == reg)
>> @@ -410,7 +414,8 @@ static bool wo_register(struct intel_engine_cs 
>> *engine, u32 reg)
>>   static bool ro_register(u32 reg)
>>   {
>> -    if (reg & RING_FORCE_TO_NONPRIV_RD)
>> +    if ((reg & RING_FORCE_TO_NONPRIV_ACCESS_MASK) ==
>> +         RING_FORCE_TO_NONPRIV_ACCESS_RD)
>>           return true;
>>       return false;
>> @@ -482,12 +487,12 @@ static int check_dirty_whitelist(struct 
>> i915_gem_context *ctx,
>>           u32 srm, lrm, rsvd;
>>           u32 expect;
>>           int idx;
>> +        bool ro_reg;
>>           if (wo_register(engine, reg))
>>               continue;
>> -        if (ro_register(reg))
>> -            continue;
>> +        ro_reg = ro_register(reg);
>>           srm = MI_STORE_REGISTER_MEM;
>>           lrm = MI_LOAD_REGISTER_MEM;
>> @@ -588,24 +593,36 @@ static int check_dirty_whitelist(struct 
>> i915_gem_context *ctx,
>>           }
>>           GEM_BUG_ON(values[ARRAY_SIZE(values) - 1] != 0xffffffff);
>> -        rsvd = results[ARRAY_SIZE(values)]; /* detect write masking */
>> -        if (!rsvd) {
>> -            pr_err("%s: Unable to write to whitelisted register %x\n",
>> -                   engine->name, reg);
>> -            err = -EINVAL;
>> -            goto out_unpin;
>> +        if (ro_reg) {
>> +            rsvd = 0xFFFFFFFF;
>> +        } else {
>> +            rsvd = results[ARRAY_SIZE(values)]; /* detect write 
>> masking */
>> +            if (!rsvd) {
>> +                pr_err("%s: Unable to write to whitelisted register 
>> %x\n",
>> +                       engine->name, reg);
>> +                err = -EINVAL;
>> +                goto out_unpin;
>> +            }
>>           }
>>           expect = results[0];
>>           idx = 1;
>>           for (v = 0; v < ARRAY_SIZE(values); v++) {
>> -            expect = reg_write(expect, values[v], rsvd);
>> +            if (ro_reg)
>> +                expect = results[0];
>> +            else
>> +                expect = reg_write(expect, values[v], rsvd);
>> +
>>               if (results[idx] != expect)
>>                   err++;
>>               idx++;
>>           }
>>           for (v = 0; v < ARRAY_SIZE(values); v++) {
>> -            expect = reg_write(expect, ~values[v], rsvd);
>> +            if (ro_reg)
>> +                expect = results[0];
>> +            else
>> +                expect = reg_write(expect, ~values[v], rsvd);
>> +
>>               if (results[idx] != expect)
>>                   err++;
>>               idx++;
>> @@ -622,7 +639,10 @@ static int check_dirty_whitelist(struct 
>> i915_gem_context *ctx,
>>               for (v = 0; v < ARRAY_SIZE(values); v++) {
>>                   u32 w = values[v];
>> -                expect = reg_write(expect, w, rsvd);
>> +                if (ro_reg)
>> +                    expect = results[0];
>> +                else
>> +                    expect = reg_write(expect, w, rsvd);
>>                   pr_info("Wrote %08x, read %08x, expect %08x\n",
>>                       w, results[idx], expect);
>>                   idx++;
>> @@ -630,7 +650,10 @@ static int check_dirty_whitelist(struct 
>> i915_gem_context *ctx,
>>               for (v = 0; v < ARRAY_SIZE(values); v++) {
>>                   u32 w = ~values[v];
>> -                expect = reg_write(expect, w, rsvd);
>> +                if (ro_reg)
>> +                    expect = results[0];
>> +                else
>> +                    expect = reg_write(expect, w, rsvd);
>>                   pr_info("Wrote %08x, read %08x, expect %08x\n",
>>                       w, results[idx], expect);
>>                   idx++;
>> @@ -762,8 +785,8 @@ static int read_whitelisted_registers(struct 
>> i915_gem_context *ctx,
>>           u64 offset = results->node.start + sizeof(u32) * i;
>>           u32 reg = i915_mmio_reg_offset(engine->whitelist.list[i].reg);
>> -        /* Clear RD only and WR only flags */
>> -        reg &= ~(RING_FORCE_TO_NONPRIV_RD | RING_FORCE_TO_NONPRIV_WR);
>> +        /* Clear access permission field */
>> +        reg &= ~RING_FORCE_TO_NONPRIV_ACCESS_MASK;
>>           *cs++ = srm;
>>           *cs++ = reg;
>> diff --git a/drivers/gpu/drm/i915/i915_reg.h 
>> b/drivers/gpu/drm/i915/i915_reg.h
>> index cc295a4f6e92..ba22e3b8f77e 100644
>> --- a/drivers/gpu/drm/i915/i915_reg.h
>> +++ b/drivers/gpu/drm/i915/i915_reg.h
>> @@ -2513,13 +2513,16 @@ enum i915_power_well_id {
>>   #define   RING_WAIT_SEMAPHORE    (1 << 10) /* gen6+ */
>>   #define RING_FORCE_TO_NONPRIV(base, i) _MMIO(((base) + 0x4D0) + (i) 
>> * 4)
>> -#define   RING_FORCE_TO_NONPRIV_RW        (0 << 28)    /* CFL+ & 
>> Gen11+ */
>> -#define   RING_FORCE_TO_NONPRIV_RD        (1 << 28)
>> -#define   RING_FORCE_TO_NONPRIV_WR        (2 << 28)
>> +#define   RING_FORCE_TO_NONPRIV_ACCESS_RW    (0 << 28)    /* CFL+ & 
>> Gen11+ */
>> +#define   RING_FORCE_TO_NONPRIV_ACCESS_RD    (1 << 28)
>> +#define   RING_FORCE_TO_NONPRIV_ACCESS_WR    (2 << 28)
>> +#define   RING_FORCE_TO_NONPRIV_ACCESS_INVALID    (3 << 28)
>> +#define   RING_FORCE_TO_NONPRIV_ACCESS_MASK    (3 << 28)
>>   #define   RING_FORCE_TO_NONPRIV_RANGE_1        (0 << 0)     /* CFL+ 
>> & Gen11+ */
>>   #define   RING_FORCE_TO_NONPRIV_RANGE_4        (1 << 0)
>>   #define   RING_FORCE_TO_NONPRIV_RANGE_16    (2 << 0)
>>   #define   RING_FORCE_TO_NONPRIV_RANGE_64    (3 << 0)
>> +#define   RING_FORCE_TO_NONPRIV_RANGE_MASK    (3 << 0)
>>   #define   RING_MAX_NONPRIV_SLOTS  12
>>   #define GEN7_TLB_RD_ADDR    _MMIO(0x4700)
>>
John Harrison July 3, 2019, 2:20 a.m. UTC | #6
Patches sent.

I haven't made any changes to dmesg output as I'm not sure what you mean.

Ah, do you mean the debug print in wa_init_finish()? Sure, I can add the 
engine name to that.

John.


On 6/25/2019 01:33, Tvrtko Ursulin wrote:
>
> Ping.
>
> We agreed to follow up with a test ASAP after merging.
>
> Here's another feature request for you: Add engine->name logging to 
> wa_init_start in intel_engine_init_whitelist. Because with the change 
> to add whitelist on other engines there are now multiple identical 
> lines in dmesg.
>
> To sum up that's three todo items:
>
> 1. Resend the selftest for CI.
> 2. Add GEM_BUG_ON for reg->flags checking invalid flag usage.
> 3. Improve dmesg so we know which engine got how many whitelist entries.
>
> Thanks,
>
> Tvrtko
>
> On 20/06/2019 16:43, Tvrtko Ursulin wrote:
>>
>> Hi,
>>
>> You will need to send this not as reply to this thread so it is 
>> picked up by CI and then can be merged.
>>
>> But please also add a patch which adds that GEM_BUG_ON reg->flags 
>> check we talked about.
>>
>> Regards,
>>
>> Tvrtko
>>
>> On 18/06/2019 20:54, John.C.Harrison@Intel.com wrote:
>>> From: John Harrison <John.C.Harrison@Intel.com>
>>>
>>> Newer hardware supports extra feature in the whitelist registers. This
>>> patch updates the selftest to test that entries marked as read only
>>> are actually read only.
>>>
>>> Also updated the read/write access definitions to make it clearer that
>>> they are an enum field not a set of single bit flags.
>>>
>>> Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
>>> CC: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>>> ---
>>>   drivers/gpu/drm/i915/gt/intel_workarounds.c   |  8 +--
>>>   .../gpu/drm/i915/gt/selftest_workarounds.c    | 53 
>>> +++++++++++++------
>>>   drivers/gpu/drm/i915/i915_reg.h               |  9 ++--
>>>   3 files changed, 48 insertions(+), 22 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c 
>>> b/drivers/gpu/drm/i915/gt/intel_workarounds.c
>>> index 93caa7b6d7a9..4429ee08b20e 100644
>>> --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
>>> +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
>>> @@ -1028,7 +1028,7 @@ whitelist_reg_ext(struct i915_wa_list *wal, 
>>> i915_reg_t reg, u32 flags)
>>>   static void
>>>   whitelist_reg(struct i915_wa_list *wal, i915_reg_t reg)
>>>   {
>>> -    whitelist_reg_ext(wal, reg, RING_FORCE_TO_NONPRIV_RW);
>>> +    whitelist_reg_ext(wal, reg, RING_FORCE_TO_NONPRIV_ACCESS_RW);
>>>   }
>>>   static void gen9_whitelist_build(struct i915_wa_list *w)
>>> @@ -1134,13 +1134,13 @@ printk(KERN_INFO "%-32s:%4d> Boo! [engine = 
>>> %s, instance = %d, base = 0x%X, reg
>>>           /* hucStatusRegOffset */
>>>           whitelist_reg_ext(w, _MMIO(0x2000 + engine->mmio_base),
>>> -                  RING_FORCE_TO_NONPRIV_RD);
>>> +                  RING_FORCE_TO_NONPRIV_ACCESS_RD);
>>>           /* hucUKernelHdrInfoRegOffset */
>>>           whitelist_reg_ext(w, _MMIO(0x2014 + engine->mmio_base),
>>> -                  RING_FORCE_TO_NONPRIV_RD);
>>> +                  RING_FORCE_TO_NONPRIV_ACCESS_RD);
>>>           /* hucStatus2RegOffset */
>>>           whitelist_reg_ext(w, _MMIO(0x23B0 + engine->mmio_base),
>>> -                  RING_FORCE_TO_NONPRIV_RD);
>>> +                  RING_FORCE_TO_NONPRIV_ACCESS_RD);
>>>           break;
>>>       default:
>>> diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c 
>>> b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
>>> index eb6d3aa2c8cc..a0a88ec66861 100644
>>> --- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c
>>> +++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
>>> @@ -399,6 +399,10 @@ static bool wo_register(struct intel_engine_cs 
>>> *engine, u32 reg)
>>>       enum intel_platform platform = 
>>> INTEL_INFO(engine->i915)->platform;
>>>       int i;
>>> +    if ((reg & RING_FORCE_TO_NONPRIV_ACCESS_MASK) ==
>>> +         RING_FORCE_TO_NONPRIV_ACCESS_WR)
>>> +        return true;
>>> +
>>>       for (i = 0; i < ARRAY_SIZE(wo_registers); i++) {
>>>           if (wo_registers[i].platform == platform &&
>>>               wo_registers[i].reg == reg)
>>> @@ -410,7 +414,8 @@ static bool wo_register(struct intel_engine_cs 
>>> *engine, u32 reg)
>>>   static bool ro_register(u32 reg)
>>>   {
>>> -    if (reg & RING_FORCE_TO_NONPRIV_RD)
>>> +    if ((reg & RING_FORCE_TO_NONPRIV_ACCESS_MASK) ==
>>> +         RING_FORCE_TO_NONPRIV_ACCESS_RD)
>>>           return true;
>>>       return false;
>>> @@ -482,12 +487,12 @@ static int check_dirty_whitelist(struct 
>>> i915_gem_context *ctx,
>>>           u32 srm, lrm, rsvd;
>>>           u32 expect;
>>>           int idx;
>>> +        bool ro_reg;
>>>           if (wo_register(engine, reg))
>>>               continue;
>>> -        if (ro_register(reg))
>>> -            continue;
>>> +        ro_reg = ro_register(reg);
>>>           srm = MI_STORE_REGISTER_MEM;
>>>           lrm = MI_LOAD_REGISTER_MEM;
>>> @@ -588,24 +593,36 @@ static int check_dirty_whitelist(struct 
>>> i915_gem_context *ctx,
>>>           }
>>>           GEM_BUG_ON(values[ARRAY_SIZE(values) - 1] != 0xffffffff);
>>> -        rsvd = results[ARRAY_SIZE(values)]; /* detect write masking */
>>> -        if (!rsvd) {
>>> -            pr_err("%s: Unable to write to whitelisted register %x\n",
>>> -                   engine->name, reg);
>>> -            err = -EINVAL;
>>> -            goto out_unpin;
>>> +        if (ro_reg) {
>>> +            rsvd = 0xFFFFFFFF;
>>> +        } else {
>>> +            rsvd = results[ARRAY_SIZE(values)]; /* detect write 
>>> masking */
>>> +            if (!rsvd) {
>>> +                pr_err("%s: Unable to write to whitelisted register 
>>> %x\n",
>>> +                       engine->name, reg);
>>> +                err = -EINVAL;
>>> +                goto out_unpin;
>>> +            }
>>>           }
>>>           expect = results[0];
>>>           idx = 1;
>>>           for (v = 0; v < ARRAY_SIZE(values); v++) {
>>> -            expect = reg_write(expect, values[v], rsvd);
>>> +            if (ro_reg)
>>> +                expect = results[0];
>>> +            else
>>> +                expect = reg_write(expect, values[v], rsvd);
>>> +
>>>               if (results[idx] != expect)
>>>                   err++;
>>>               idx++;
>>>           }
>>>           for (v = 0; v < ARRAY_SIZE(values); v++) {
>>> -            expect = reg_write(expect, ~values[v], rsvd);
>>> +            if (ro_reg)
>>> +                expect = results[0];
>>> +            else
>>> +                expect = reg_write(expect, ~values[v], rsvd);
>>> +
>>>               if (results[idx] != expect)
>>>                   err++;
>>>               idx++;
>>> @@ -622,7 +639,10 @@ static int check_dirty_whitelist(struct 
>>> i915_gem_context *ctx,
>>>               for (v = 0; v < ARRAY_SIZE(values); v++) {
>>>                   u32 w = values[v];
>>> -                expect = reg_write(expect, w, rsvd);
>>> +                if (ro_reg)
>>> +                    expect = results[0];
>>> +                else
>>> +                    expect = reg_write(expect, w, rsvd);
>>>                   pr_info("Wrote %08x, read %08x, expect %08x\n",
>>>                       w, results[idx], expect);
>>>                   idx++;
>>> @@ -630,7 +650,10 @@ static int check_dirty_whitelist(struct 
>>> i915_gem_context *ctx,
>>>               for (v = 0; v < ARRAY_SIZE(values); v++) {
>>>                   u32 w = ~values[v];
>>> -                expect = reg_write(expect, w, rsvd);
>>> +                if (ro_reg)
>>> +                    expect = results[0];
>>> +                else
>>> +                    expect = reg_write(expect, w, rsvd);
>>>                   pr_info("Wrote %08x, read %08x, expect %08x\n",
>>>                       w, results[idx], expect);
>>>                   idx++;
>>> @@ -762,8 +785,8 @@ static int read_whitelisted_registers(struct 
>>> i915_gem_context *ctx,
>>>           u64 offset = results->node.start + sizeof(u32) * i;
>>>           u32 reg = 
>>> i915_mmio_reg_offset(engine->whitelist.list[i].reg);
>>> -        /* Clear RD only and WR only flags */
>>> -        reg &= ~(RING_FORCE_TO_NONPRIV_RD | RING_FORCE_TO_NONPRIV_WR);
>>> +        /* Clear access permission field */
>>> +        reg &= ~RING_FORCE_TO_NONPRIV_ACCESS_MASK;
>>>           *cs++ = srm;
>>>           *cs++ = reg;
>>> diff --git a/drivers/gpu/drm/i915/i915_reg.h 
>>> b/drivers/gpu/drm/i915/i915_reg.h
>>> index cc295a4f6e92..ba22e3b8f77e 100644
>>> --- a/drivers/gpu/drm/i915/i915_reg.h
>>> +++ b/drivers/gpu/drm/i915/i915_reg.h
>>> @@ -2513,13 +2513,16 @@ enum i915_power_well_id {
>>>   #define   RING_WAIT_SEMAPHORE    (1 << 10) /* gen6+ */
>>>   #define RING_FORCE_TO_NONPRIV(base, i) _MMIO(((base) + 0x4D0) + 
>>> (i) * 4)
>>> -#define   RING_FORCE_TO_NONPRIV_RW        (0 << 28) /* CFL+ & 
>>> Gen11+ */
>>> -#define   RING_FORCE_TO_NONPRIV_RD        (1 << 28)
>>> -#define   RING_FORCE_TO_NONPRIV_WR        (2 << 28)
>>> +#define   RING_FORCE_TO_NONPRIV_ACCESS_RW    (0 << 28)    /* CFL+ & 
>>> Gen11+ */
>>> +#define   RING_FORCE_TO_NONPRIV_ACCESS_RD    (1 << 28)
>>> +#define   RING_FORCE_TO_NONPRIV_ACCESS_WR    (2 << 28)
>>> +#define   RING_FORCE_TO_NONPRIV_ACCESS_INVALID    (3 << 28)
>>> +#define   RING_FORCE_TO_NONPRIV_ACCESS_MASK    (3 << 28)
>>>   #define   RING_FORCE_TO_NONPRIV_RANGE_1        (0 << 0)     /* 
>>> CFL+ & Gen11+ */
>>>   #define   RING_FORCE_TO_NONPRIV_RANGE_4        (1 << 0)
>>>   #define   RING_FORCE_TO_NONPRIV_RANGE_16    (2 << 0)
>>>   #define   RING_FORCE_TO_NONPRIV_RANGE_64    (3 << 0)
>>> +#define   RING_FORCE_TO_NONPRIV_RANGE_MASK    (3 << 0)
>>>   #define   RING_MAX_NONPRIV_SLOTS  12
>>>   #define GEN7_TLB_RD_ADDR    _MMIO(0x4700)
>>>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index 93caa7b6d7a9..4429ee08b20e 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -1028,7 +1028,7 @@  whitelist_reg_ext(struct i915_wa_list *wal, i915_reg_t reg, u32 flags)
 static void
 whitelist_reg(struct i915_wa_list *wal, i915_reg_t reg)
 {
-	whitelist_reg_ext(wal, reg, RING_FORCE_TO_NONPRIV_RW);
+	whitelist_reg_ext(wal, reg, RING_FORCE_TO_NONPRIV_ACCESS_RW);
 }
 
 static void gen9_whitelist_build(struct i915_wa_list *w)
@@ -1134,13 +1134,13 @@  printk(KERN_INFO "%-32s:%4d> Boo! [engine = %s, instance = %d, base = 0x%X, reg
 
 		/* hucStatusRegOffset */
 		whitelist_reg_ext(w, _MMIO(0x2000 + engine->mmio_base),
-				  RING_FORCE_TO_NONPRIV_RD);
+				  RING_FORCE_TO_NONPRIV_ACCESS_RD);
 		/* hucUKernelHdrInfoRegOffset */
 		whitelist_reg_ext(w, _MMIO(0x2014 + engine->mmio_base),
-				  RING_FORCE_TO_NONPRIV_RD);
+				  RING_FORCE_TO_NONPRIV_ACCESS_RD);
 		/* hucStatus2RegOffset */
 		whitelist_reg_ext(w, _MMIO(0x23B0 + engine->mmio_base),
-				  RING_FORCE_TO_NONPRIV_RD);
+				  RING_FORCE_TO_NONPRIV_ACCESS_RD);
 		break;
 
 	default:
diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
index eb6d3aa2c8cc..a0a88ec66861 100644
--- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
@@ -399,6 +399,10 @@  static bool wo_register(struct intel_engine_cs *engine, u32 reg)
 	enum intel_platform platform = INTEL_INFO(engine->i915)->platform;
 	int i;
 
+	if ((reg & RING_FORCE_TO_NONPRIV_ACCESS_MASK) ==
+	     RING_FORCE_TO_NONPRIV_ACCESS_WR)
+		return true;
+
 	for (i = 0; i < ARRAY_SIZE(wo_registers); i++) {
 		if (wo_registers[i].platform == platform &&
 		    wo_registers[i].reg == reg)
@@ -410,7 +414,8 @@  static bool wo_register(struct intel_engine_cs *engine, u32 reg)
 
 static bool ro_register(u32 reg)
 {
-	if (reg & RING_FORCE_TO_NONPRIV_RD)
+	if ((reg & RING_FORCE_TO_NONPRIV_ACCESS_MASK) ==
+	     RING_FORCE_TO_NONPRIV_ACCESS_RD)
 		return true;
 
 	return false;
@@ -482,12 +487,12 @@  static int check_dirty_whitelist(struct i915_gem_context *ctx,
 		u32 srm, lrm, rsvd;
 		u32 expect;
 		int idx;
+		bool ro_reg;
 
 		if (wo_register(engine, reg))
 			continue;
 
-		if (ro_register(reg))
-			continue;
+		ro_reg = ro_register(reg);
 
 		srm = MI_STORE_REGISTER_MEM;
 		lrm = MI_LOAD_REGISTER_MEM;
@@ -588,24 +593,36 @@  static int check_dirty_whitelist(struct i915_gem_context *ctx,
 		}
 
 		GEM_BUG_ON(values[ARRAY_SIZE(values) - 1] != 0xffffffff);
-		rsvd = results[ARRAY_SIZE(values)]; /* detect write masking */
-		if (!rsvd) {
-			pr_err("%s: Unable to write to whitelisted register %x\n",
-			       engine->name, reg);
-			err = -EINVAL;
-			goto out_unpin;
+		if (ro_reg) {
+			rsvd = 0xFFFFFFFF;
+		} else {
+			rsvd = results[ARRAY_SIZE(values)]; /* detect write masking */
+			if (!rsvd) {
+				pr_err("%s: Unable to write to whitelisted register %x\n",
+				       engine->name, reg);
+				err = -EINVAL;
+				goto out_unpin;
+			}
 		}
 
 		expect = results[0];
 		idx = 1;
 		for (v = 0; v < ARRAY_SIZE(values); v++) {
-			expect = reg_write(expect, values[v], rsvd);
+			if (ro_reg)
+				expect = results[0];
+			else
+				expect = reg_write(expect, values[v], rsvd);
+
 			if (results[idx] != expect)
 				err++;
 			idx++;
 		}
 		for (v = 0; v < ARRAY_SIZE(values); v++) {
-			expect = reg_write(expect, ~values[v], rsvd);
+			if (ro_reg)
+				expect = results[0];
+			else
+				expect = reg_write(expect, ~values[v], rsvd);
+
 			if (results[idx] != expect)
 				err++;
 			idx++;
@@ -622,7 +639,10 @@  static int check_dirty_whitelist(struct i915_gem_context *ctx,
 			for (v = 0; v < ARRAY_SIZE(values); v++) {
 				u32 w = values[v];
 
-				expect = reg_write(expect, w, rsvd);
+				if (ro_reg)
+					expect = results[0];
+				else
+					expect = reg_write(expect, w, rsvd);
 				pr_info("Wrote %08x, read %08x, expect %08x\n",
 					w, results[idx], expect);
 				idx++;
@@ -630,7 +650,10 @@  static int check_dirty_whitelist(struct i915_gem_context *ctx,
 			for (v = 0; v < ARRAY_SIZE(values); v++) {
 				u32 w = ~values[v];
 
-				expect = reg_write(expect, w, rsvd);
+				if (ro_reg)
+					expect = results[0];
+				else
+					expect = reg_write(expect, w, rsvd);
 				pr_info("Wrote %08x, read %08x, expect %08x\n",
 					w, results[idx], expect);
 				idx++;
@@ -762,8 +785,8 @@  static int read_whitelisted_registers(struct i915_gem_context *ctx,
 		u64 offset = results->node.start + sizeof(u32) * i;
 		u32 reg = i915_mmio_reg_offset(engine->whitelist.list[i].reg);
 
-		/* Clear RD only and WR only flags */
-		reg &= ~(RING_FORCE_TO_NONPRIV_RD | RING_FORCE_TO_NONPRIV_WR);
+		/* Clear access permission field */
+		reg &= ~RING_FORCE_TO_NONPRIV_ACCESS_MASK;
 
 		*cs++ = srm;
 		*cs++ = reg;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index cc295a4f6e92..ba22e3b8f77e 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2513,13 +2513,16 @@  enum i915_power_well_id {
 #define   RING_WAIT_SEMAPHORE	(1 << 10) /* gen6+ */
 
 #define RING_FORCE_TO_NONPRIV(base, i) _MMIO(((base) + 0x4D0) + (i) * 4)
-#define   RING_FORCE_TO_NONPRIV_RW		(0 << 28)    /* CFL+ & Gen11+ */
-#define   RING_FORCE_TO_NONPRIV_RD		(1 << 28)
-#define   RING_FORCE_TO_NONPRIV_WR		(2 << 28)
+#define   RING_FORCE_TO_NONPRIV_ACCESS_RW	(0 << 28)    /* CFL+ & Gen11+ */
+#define   RING_FORCE_TO_NONPRIV_ACCESS_RD	(1 << 28)
+#define   RING_FORCE_TO_NONPRIV_ACCESS_WR	(2 << 28)
+#define   RING_FORCE_TO_NONPRIV_ACCESS_INVALID	(3 << 28)
+#define   RING_FORCE_TO_NONPRIV_ACCESS_MASK	(3 << 28)
 #define   RING_FORCE_TO_NONPRIV_RANGE_1		(0 << 0)     /* CFL+ & Gen11+ */
 #define   RING_FORCE_TO_NONPRIV_RANGE_4		(1 << 0)
 #define   RING_FORCE_TO_NONPRIV_RANGE_16	(2 << 0)
 #define   RING_FORCE_TO_NONPRIV_RANGE_64	(3 << 0)
+#define   RING_FORCE_TO_NONPRIV_RANGE_MASK	(3 << 0)
 #define   RING_MAX_NONPRIV_SLOTS  12
 
 #define GEN7_TLB_RD_ADDR	_MMIO(0x4700)