drm/xe: apply debug page-size allocation policy to user BOs

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 <naresh.kumar.g@intel.com>
Reviewed-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Link: https://patch.msgid.link/20260729121843.1255891-5-naresh.kumar.g@intel.com
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
This commit is contained in:
Nareshkumar Gollakoti 2026-07-29 17:48:41 +05:30 committed by Himal Prasad Ghimiray
parent caf4fd4eb8
commit 2285c120e1

View File

@ -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;