[PATCH v10 4/6] drm/xe: apply debug page-size allocation policy to user BOs
Nareshkumar Gollakoti <[email protected]>
| Newsgroups | org.freedesktop.lists.intel-xe |
|---|---|
| Message-ID | <[email protected]> |
Apply the debug page-size allocation policy during user BO creation. When page-size allocation control is enabled, override the user BO page-size selection flags based on the selected debug mode and round the requested size up to the corresponding granularity: - 2M mode selects 2M handling - 1G mode selects 1G handling - mixed mode selects the page size from the current mixed-mode index This is intended for internal debug and validation flows. When the control mode is left at the default setting, the normal user BO creation path is unchanged. v2 - ensure debug page-size allocation does not affect the default path (sashiko) - rework synchronization for concurrent access (sashiko) - refactor commit message for readability v3 - update user BO size alignment based on debug policy mode - reword commit message - ensure normal user flow is unchanged when debug policy is disabled v4(sashiko) - limit debug page-size policy application to VRAM BOs - do not override preexisting page-size requirement flags - advance mixed-mode index only after successful BO create ioctl completion - add overflow checks before ALIGN() in debug page-size handling - ensure CONFIG_DRM_XE_DEBUG_PAGE_SIZE enabled and it is dgfx v5(Himal) v5: - Guard debug page-size policy paths with CONFIG_DRM_XE_DEBUG_PAGE_SIZE - Leave the normal BO creation path unchanged when no debug mode is selected v8(Himal) - Avoid current index increment for system BO's - Simplify mixed mode align logic by changing array to struct array - Have a inline check if it is on debug mode or not - Avoid condition compiled debug in function code blocks Signed-off-by: Nareshkumar Gollakoti <[email protected]> Reviewed-by: Himal Prasad Ghimiray <[email protected]> --- drivers/gpu/drm/xe/xe_bo.c | 148 +++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index 1c0b34c2c4ac..dde309821237 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -2652,6 +2652,145 @@ static struct xe_bo *xe_bo_create_novm(struct xe_device *xe, struct xe_tile *til return ret ? ERR_PTR(ret) : bo; } +#ifdef CONFIG_DRM_XE_DEBUG_PAGE_SIZE +static void xe_bo_debug_mixed_mode_cur_index_advance(struct xe_device *xe, struct xe_bo *bo) +{ + if (!xe_debug_page_size_mode_is_mixed(xe)) + return; + + if (!(bo->flags & XE_BO_FLAG_VRAM_MASK) || + !(bo->flags & XE_BO_FLAG_USER)) + return; + + mutex_lock(&xe->page_size_alloc_ctrl.lock); + if (xe->page_size_alloc_ctrl.mode == XE_PAGE_SIZE_ALLOC_CTRL_MODE_MIXED) + xe->page_size_alloc_ctrl.cur_index++; + mutex_unlock(&xe->page_size_alloc_ctrl.lock); +} + +static bool xe_size_align_overflows(size_t size, size_t align) +{ + return size > SIZE_MAX - (align - 1); +} + +static u32 get_flag_from_cur_index_in_mixed_mode(struct xe_device *xe, size_t *align_size, + int *err) +{ + static const struct { + u32 flag; + size_t align; + } map[] = { + { 0, SZ_4K }, /* default: 4K, no flag */ + { XE_BO_FLAG_NEEDS_64K, SZ_64K }, + { XE_BO_FLAG_NEEDS_2M, SZ_2M }, + { XE_BO_FLAG_NEEDS_1G, SZ_1G }, + }; + u32 idx; + const typeof(*map) *entry; + + lockdep_assert_held(&xe->page_size_alloc_ctrl.lock); + + *err = 0; + idx = xe->page_size_alloc_ctrl.cur_index % ARRAY_SIZE(map); + + entry = &map[idx]; + + if (!entry->flag) + return 0; + + if (xe_size_align_overflows(*align_size, entry->align)) { + *err = -EINVAL; + return 0; + } + *align_size = ALIGN(*align_size, entry->align); + + return entry->flag; +} + +static int xe_bo_apply_debug_page_size_policy(struct xe_device *xe, + u32 *bo_flags, + size_t *size) +{ + enum xe_page_size_alloc_ctrl_mode mode; + u32 want = 0; + size_t align_size = *size; + int err = 0; + + /* + * The debug page-size policy is only meaningful for BOs placed in + * VRAM, where the downstream BO init path can + * actually honor the corresponding minimum page-size requirement. + */ + if (!(*bo_flags & XE_BO_FLAG_VRAM_MASK)) + return 0; + + /* + * Do not override existing page-size requirement flags, since they + * may reflect functional requirements for specific BO types. + */ + if (*bo_flags & (XE_BO_FLAG_NEEDS_64K | + XE_BO_FLAG_NEEDS_2M | + XE_BO_FLAG_NEEDS_1G)) + return 0; + + if (!READ_ONCE(xe->page_size_alloc_ctrl.mode)) + return 0; + + mutex_lock(&xe->page_size_alloc_ctrl.lock); + + mode = xe->page_size_alloc_ctrl.mode; + if (mode == XE_PAGE_SIZE_ALLOC_CTRL_MODE_NONE) { + goto out_unlock; + } else if (mode == XE_PAGE_SIZE_ALLOC_CTRL_MODE_ONLY_2M) { + if (xe_size_align_overflows(align_size, SZ_2M)) { + err = -EINVAL; + goto out_unlock; + } + want = XE_BO_FLAG_NEEDS_2M; + align_size = ALIGN(align_size, SZ_2M); + } else if (mode == XE_PAGE_SIZE_ALLOC_CTRL_MODE_ONLY_1G) { + if (xe_size_align_overflows(align_size, SZ_1G)) { + err = -EINVAL; + goto out_unlock; + } + want = XE_BO_FLAG_NEEDS_1G; + align_size = ALIGN(align_size, SZ_1G); + } else if (mode == XE_PAGE_SIZE_ALLOC_CTRL_MODE_MIXED) { + want = get_flag_from_cur_index_in_mixed_mode(xe, &align_size, &err); + if (err) + goto out_unlock; + } else { + goto out_unlock; + } + + mutex_unlock(&xe->page_size_alloc_ctrl.lock); + + *bo_flags |= want; + /* + * Apply the debug page-size policy by rounding the user BO size up to + * the selected granularity. + */ + *size = align_size; + return err; + +out_unlock: + mutex_unlock(&xe->page_size_alloc_ctrl.lock); + return err; +} +#else +static int xe_bo_apply_debug_page_size_policy(struct xe_device *xe, + u32 *bo_flags, + size_t *size) +{ + return 0; +} + +static void xe_bo_debug_mixed_mode_cur_index_advance(struct xe_device *xe, + struct xe_bo *bo) +{ +} +#endif + /** * xe_bo_create_user() - Create a user BO * @xe: The xe device. @@ -2672,9 +2811,16 @@ struct xe_bo *xe_bo_create_user(struct xe_device *xe, u32 flags, struct drm_exec *exec) { struct xe_bo *bo; + int err = 0; flags |= XE_BO_FLAG_USER; + if (xe_debug_page_size_mode_not_none(xe)) { + err = xe_bo_apply_debug_page_size_policy(xe, &flags, &size); + if (err) + return ERR_PTR(err); + } + if (vm || exec) { xe_assert(xe, exec); bo = __xe_bo_create_locked(xe, NULL, vm, size, 0, ~0ULL, @@ -3489,6 +3635,8 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data, if (err) goto out_bulk; + xe_bo_debug_mixed_mode_cur_index_advance(xe, bo); + args->handle = handle; goto out_put; -- 2.43.0