[Intel-gfx] [RFC 4/4] drm/i915: Expose RPCS (SSEU) configuration to userspace

Oscar Mateo oscar.mateo at intel.com
Tue May 2 10:33:19 UTC 2017



On 05/02/2017 11:49 AM, Chris Wilson wrote:
> We want to allow userspace to reconfigure the subslice configuration for
> its own use case. To do so, we expose a context parameter to allow
> adjustment of the RPCS register stored within the context image (and
> currently not accessible via LRI).

Userspace could also do this by themselves via LRI if we simply 
whitelist GEN8_R_PWR_CLK_STATE.

Hardware people suggested this programming model:

- PIPECONTROL - Stalling flish, flush all caches (color, depth, DC$)
- LOAD_REGISTER_IMMEDIATE - R_PWR_CLK_STATE
- Reprogram complete state

> If the context is adjusted before
> first use, the adjustment is for "free"; otherwise if the context is
> active we flush the context off the GPU (stalling all users) and forcing
> the GPU to save the context to memory where we can modify it and so
> ensure that the register is reloaded on next execution.

There is another cost associated with the adjustment: slice poweron and 
shutdown do take some time to happen (in the order of tens of usecs). I 
have been playing with an i-g-t benchmark to measure this delay, I'll 
send it to the mailing list.

> The overhead of managing additional EU subslices can be significant,
> especially in multi-context workloads. Non-GPGPU contexts should
> preferably disable the subslices it is not using, and others should
> fine-tune the number to match their workload.
>
> We expose complete control over the RPCS register, allowing
> configuration of slice/subslice, via masks packed into a u64 for
> simplicity. For example,
>
> 	struct drm_i915_gem_context_param arg;
>
> 	memset(&arg, 0, sizeof(arg));
> 	arg.ctx_id = ctx;
> 	arg.param = I915_CONTEXT_PARAM_SSEU;
> 	if (drmIoctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &arg) == 0) {
> 		union drm_i915_gem_context_param_sseu *sseu = &arg.value;
>
> 		sseu->packed.subslice_mask = 0;
>
> 		drmIoctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &arg);
> 	}
>
> could be used to disable all subslices where supported.
>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=100899
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Dmitry Rogozhkin <dmitry.v.rogozhkin at intel.com>
> CC: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
> CC: Zhipeng Gong <zhipeng.gong at intel.com>
> CC: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
> ---
>   drivers/gpu/drm/i915/i915_gem_context.c | 12 +++++++
>   drivers/gpu/drm/i915/intel_lrc.c        | 63 +++++++++++++++++++++++++++++++++
>   drivers/gpu/drm/i915/intel_lrc.h        |  3 ++
>   include/uapi/drm/i915_drm.h             | 11 ++++++
>   4 files changed, 89 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
> index 71ca74bcf170..0b72f9f62ddb 100644
> --- a/drivers/gpu/drm/i915/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/i915_gem_context.c
> @@ -1044,6 +1044,9 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
>   	case I915_CONTEXT_PARAM_PRIORITY:
>   		args->value = ctx->priority;
>   		break;
> +	case I915_CONTEXT_PARAM_SSEU:
> +		args->value = intel_lr_context_get_sseu(ctx);
> +		break;
>   	default:
>   		ret = -EINVAL;
>   		break;
> @@ -1120,6 +1123,15 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
>   		}
>   		break;
>   
> +	case I915_CONTEXT_PARAM_SSEU:
> +		if (args->size)
> +			ret = -EINVAL;
> +		else if (!i915.enable_execlists)
> +			ret = -ENODEV;
> +		else
> +			ret = intel_lr_context_set_sseu(ctx, args->value);
> +		break;
> +
>   	default:
>   		ret = -EINVAL;
>   		break;
> diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
> index a3183298b993..e4e2eefd4854 100644
> --- a/drivers/gpu/drm/i915/intel_lrc.c
> +++ b/drivers/gpu/drm/i915/intel_lrc.c
> @@ -2064,3 +2064,66 @@ void intel_lr_context_resume(struct drm_i915_private *dev_priv)
>   		}
>   	}
>   }
> +
> +int intel_lr_context_set_sseu(struct i915_gem_context *ctx, u64 value)
> +{
> +	union drm_i915_gem_context_param_sseu user = { .value = value };
> +	struct drm_i915_private *i915 = ctx->i915;
> +	struct intel_context *ce = &ctx->engine[RCS];
> +	struct sseu_dev_info sseu = ctx->sseu;
> +	int ret;
> +
> +	lockdep_assert_held(&i915->drm.struct_mutex);
> +
> +	sseu.slice_mask =
> +		user.packed.slice_mask & INTEL_INFO(i915)->sseu.slice_mask;
> +	sseu.subslice_mask =
> +		user.packed.subslice_mask & INTEL_INFO(i915)->sseu.subslice_mask;
> +	sseu.min_eu_per_subslice =
> +		max(user.packed.min_eu_per_subslice,
> +		    INTEL_INFO(i915)->sseu.min_eu_per_subslice);
> +	sseu.max_eu_per_subslice =
> +		min(user.packed.max_eu_per_subslice,
> +		    INTEL_INFO(i915)->sseu.max_eu_per_subslice);
> +
> +	if (memcmp(&sseu, &ctx->sseu, sizeof(sseu)) == 0)
> +		return 0;
> +
> +	if (ce->pin_count) { /* Assume that the context is active! */
> +		ret = i915_gem_switch_to_kernel_context(i915);
> +		if (ret)
> +			return ret;
> +
> +		ret = i915_gem_wait_for_idle(i915,
> +					     I915_WAIT_INTERRUPTIBLE |
> +					     I915_WAIT_LOCKED);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	if (ce->state) {
> +		u32 *regs;
> +
> +		regs = i915_gem_object_pin_map(ce->state->obj, I915_MAP_WB);
> +		if (IS_ERR(regs))
> +			return PTR_ERR(regs);
> +
> +		regs[CTX_R_PWR_CLK_STATE + 1] = make_rpcs(&sseu);
> +		i915_gem_object_unpin_map(ce->state->obj);
> +	}
> +
> +	ctx->sseu = sseu;
> +	return 0;
> +}
> +
> +u64 intel_lr_context_get_sseu(struct i915_gem_context *ctx)
> +{
> +	union drm_i915_gem_context_param_sseu user;
> +
> +	user.packed.slice_mask = ctx->sseu.slice_mask;
> +	user.packed.subslice_mask = ctx->sseu.subslice_mask;
> +	user.packed.min_eu_per_subslice = ctx->sseu.min_eu_per_subslice;
> +	user.packed.max_eu_per_subslice = ctx->sseu.max_eu_per_subslice;
> +
> +	return user.value;
> +}
> diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
> index 52b3a1fd4059..e4d811892382 100644
> --- a/drivers/gpu/drm/i915/intel_lrc.h
> +++ b/drivers/gpu/drm/i915/intel_lrc.h
> @@ -82,6 +82,9 @@ void intel_lr_context_resume(struct drm_i915_private *dev_priv);
>   uint64_t intel_lr_context_descriptor(struct i915_gem_context *ctx,
>   				     struct intel_engine_cs *engine);
>   
> +int intel_lr_context_set_sseu(struct i915_gem_context *ctx, u64 value);
> +u64 intel_lr_context_get_sseu(struct i915_gem_context *ctx);
> +
>   /* Execlists */
>   int intel_sanitize_enable_execlists(struct drm_i915_private *dev_priv,
>   				    int enable_execlists);
> diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
> index 34ee011f08ac..106d9140d65e 100644
> --- a/include/uapi/drm/i915_drm.h
> +++ b/include/uapi/drm/i915_drm.h
> @@ -1327,6 +1327,17 @@ struct drm_i915_gem_context_param {
>   #define   I915_CONTEXT_MAX_USER_PRIORITY	1023 /* inclusive */
>   #define   I915_CONTEXT_DEFAULT_PRIORITY		0
>   #define   I915_CONTEXT_MIN_USER_PRIORITY	-1023 /* inclusive */
> +#define I915_CONTEXT_PARAM_SSEU		0x7
> +	__u64 value;
> +};
> +
> +union drm_i915_gem_context_param_sseu {
> +	struct {
> +		u8 slice_mask;
> +		u8 subslice_mask;
> +		u8 min_eu_per_subslice;
> +		u8 max_eu_per_subslice;
> +	} packed;
>   	__u64 value;
>   };
>   



More information about the Intel-gfx mailing list