Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915: Allow user to set cache at BO creation

To comply with the design that buffer objects shall have immutable
cache setting through out their life cycle, {set, get}_caching ioctl's
are no longer supported from MTL onward. With that change caching
policy can only be set at object creation time. The current code
applies a default (platform dependent) cache setting for all objects.
However this is not optimal for performance tuning. The patch extends
the existing gem_create uAPI to let user set PAT index for the object
at creation time.
The new extension is platform independent, so UMD's can switch to using
this extension for older platforms as well, while {set, get}_caching are
still supported on these legacy paltforms for compatibility reason.
However, since PAT index was not clearly defined for platforms prior to
GEN12 (TGL), so we are limiting this externsion to GEN12+ platforms
only. See ext_set_pat() in for the implementation details.

The documentation related to the PAT/MOCS tables is currently available
for Tiger Lake here:
https://www.intel.com/content/www/us/en/docs/graphics-for-linux/developer-reference/1-0/tiger-lake.html

The documentation for other platforms is currently being updated.

BSpec: 45101

Mesa support has been submitted in this merge request:
https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22878

The media driver supprt has bin submitted in this merge request:
https://github.com/intel/media-driver/pull/1680

The IGT test related to this change is
igt@gem_create@create-ext-set-pat

Signed-off-by: Fei Yang <fei.yang@intel.com>
Cc: Chris Wilson <chris.p.wilson@linux.intel.com>
Cc: Matt Roper <matthew.d.roper@intel.com>
Cc: Andi Shyti <andi.shyti@linux.intel.com>
Reviewed-by: Andi Shyti <andi.shyti@linux.intel.com>
Acked-by: Jordan Justen <jordan.l.justen@intel.com>
Tested-by: Jordan Justen <jordan.l.justen@intel.com>
Acked-by: Carl Zhang <carl.zhang@intel.com>
Tested-by: Lihao Gu <lihao.gu@intel.com>
Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
Acked-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Acked-by: Slawomir Milczarek <slawomir.milczarek@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230606100042.482345-2-andi.shyti@linux.intel.com

authored by

Fei Yang and committed by
Andi Shyti
81b1b599 1b842f73

+87
+40
drivers/gpu/drm/i915/gem/i915_gem_create.c
··· 245 245 unsigned int n_placements; 246 246 unsigned int placement_mask; 247 247 unsigned long flags; 248 + unsigned int pat_index; 248 249 }; 249 250 250 251 static void repr_placements(char *buf, size_t size, ··· 395 394 return 0; 396 395 } 397 396 397 + static int ext_set_pat(struct i915_user_extension __user *base, void *data) 398 + { 399 + struct create_ext *ext_data = data; 400 + struct drm_i915_private *i915 = ext_data->i915; 401 + struct drm_i915_gem_create_ext_set_pat ext; 402 + unsigned int max_pat_index; 403 + 404 + BUILD_BUG_ON(sizeof(struct drm_i915_gem_create_ext_set_pat) != 405 + offsetofend(struct drm_i915_gem_create_ext_set_pat, rsvd)); 406 + 407 + /* Limiting the extension only to Meteor Lake */ 408 + if (!IS_METEORLAKE(i915)) 409 + return -ENODEV; 410 + 411 + if (copy_from_user(&ext, base, sizeof(ext))) 412 + return -EFAULT; 413 + 414 + max_pat_index = INTEL_INFO(i915)->max_pat_index; 415 + 416 + if (ext.pat_index > max_pat_index) { 417 + drm_dbg(&i915->drm, "PAT index is invalid: %u\n", 418 + ext.pat_index); 419 + return -EINVAL; 420 + } 421 + 422 + ext_data->pat_index = ext.pat_index; 423 + 424 + return 0; 425 + } 426 + 398 427 static const i915_user_extension_fn create_extensions[] = { 399 428 [I915_GEM_CREATE_EXT_MEMORY_REGIONS] = ext_set_placements, 400 429 [I915_GEM_CREATE_EXT_PROTECTED_CONTENT] = ext_set_protected, 430 + [I915_GEM_CREATE_EXT_SET_PAT] = ext_set_pat, 401 431 }; 402 432 433 + #define PAT_INDEX_NOT_SET 0xffff 403 434 /** 404 435 * i915_gem_create_ext_ioctl - Creates a new mm object and returns a handle to it. 405 436 * @dev: drm device pointer ··· 451 418 if (args->flags & ~I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS) 452 419 return -EINVAL; 453 420 421 + ext_data.pat_index = PAT_INDEX_NOT_SET; 454 422 ret = i915_user_extensions(u64_to_user_ptr(args->extensions), 455 423 create_extensions, 456 424 ARRAY_SIZE(create_extensions), ··· 487 453 ext_data.flags); 488 454 if (IS_ERR(obj)) 489 455 return PTR_ERR(obj); 456 + 457 + if (ext_data.pat_index != PAT_INDEX_NOT_SET) { 458 + i915_gem_object_set_pat_index(obj, ext_data.pat_index); 459 + /* Mark pat_index is set by UMD */ 460 + obj->pat_set_by_user = true; 461 + } 490 462 491 463 return i915_gem_publish(obj, file, &args->size, &args->handle); 492 464 }
+6
drivers/gpu/drm/i915/gem/i915_gem_object.c
··· 209 209 return false; 210 210 211 211 /* 212 + * Always flush cache for UMD objects at creation time. 213 + */ 214 + if (obj->pat_set_by_user) 215 + return true; 216 + 217 + /* 212 218 * EHL and JSL add the 'Bypass LLC' MOCS entry, which should make it 213 219 * possible for userspace to bypass the GTT caching bits set by the 214 220 * kernel, as per the given object cache_level. This is troublesome
+41
include/uapi/drm/i915_drm.h
··· 3680 3680 * 3681 3681 * For I915_GEM_CREATE_EXT_PROTECTED_CONTENT usage see 3682 3682 * struct drm_i915_gem_create_ext_protected_content. 3683 + * 3684 + * For I915_GEM_CREATE_EXT_SET_PAT usage see 3685 + * struct drm_i915_gem_create_ext_set_pat. 3683 3686 */ 3684 3687 #define I915_GEM_CREATE_EXT_MEMORY_REGIONS 0 3685 3688 #define I915_GEM_CREATE_EXT_PROTECTED_CONTENT 1 3689 + #define I915_GEM_CREATE_EXT_SET_PAT 2 3686 3690 __u64 extensions; 3687 3691 }; 3688 3692 ··· 3799 3795 struct i915_user_extension base; 3800 3796 /** @flags: reserved for future usage, currently MBZ */ 3801 3797 __u32 flags; 3798 + }; 3799 + 3800 + /** 3801 + * struct drm_i915_gem_create_ext_set_pat - The 3802 + * I915_GEM_CREATE_EXT_SET_PAT extension. 3803 + * 3804 + * If this extension is provided, the specified caching policy (PAT index) is 3805 + * applied to the buffer object. 3806 + * 3807 + * Below is an example on how to create an object with specific caching policy: 3808 + * 3809 + * .. code-block:: C 3810 + * 3811 + * struct drm_i915_gem_create_ext_set_pat set_pat_ext = { 3812 + * .base = { .name = I915_GEM_CREATE_EXT_SET_PAT }, 3813 + * .pat_index = 0, 3814 + * }; 3815 + * struct drm_i915_gem_create_ext create_ext = { 3816 + * .size = PAGE_SIZE, 3817 + * .extensions = (uintptr_t)&set_pat_ext, 3818 + * }; 3819 + * 3820 + * int err = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE_EXT, &create_ext); 3821 + * if (err) ... 3822 + */ 3823 + struct drm_i915_gem_create_ext_set_pat { 3824 + /** @base: Extension link. See struct i915_user_extension. */ 3825 + struct i915_user_extension base; 3826 + /** 3827 + * @pat_index: PAT index to be set 3828 + * PAT index is a bit field in Page Table Entry to control caching 3829 + * behaviors for GPU accesses. The definition of PAT index is 3830 + * platform dependent and can be found in hardware specifications, 3831 + */ 3832 + __u32 pat_index; 3833 + /** @rsvd: reserved for future use */ 3834 + __u32 rsvd; 3802 3835 }; 3803 3836 3804 3837 /* ID of the protected content session managed by i915 when PXP is active */