[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