* [PATCH v10 1/6] drm/xe: add page size allocation control state to xe_device
2026-07-29 8:40 [PATCH v10 0/6] drm/xe: add page size allocation mode control and coverage Nareshkumar Gollakoti
@ 2026-07-29 8:40 ` Nareshkumar Gollakoti
2026-07-29 8:40 ` [PATCH v10 2/6] drm/xe/debugfs: add page-size allocation mode knob Nareshkumar Gollakoti
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Nareshkumar Gollakoti @ 2026-07-29 8:40 UTC (permalink / raw)
To: intel-xe; +Cc: himal.prasad.ghimiray, naresh.kumar.g
Introduce xe_page_size_alloc_ctrl_mode and add page_size_alloc_ctrl
state to struct xe_device along with mutex lock.
The new control supports forcing user BO allocations to 2M pages,
forcing them to 1G pages, or using a mixed round-robin mode across
4K, 64K, 2M, and 1G page sizes. Track the current mixed-mode index
in xe_device so allocation policy can be applied consistently.
v2
- make cur_index to atomic as update need in later patch to
avoid race/concurency (sashiko)
v3
- reworded comments
- protect mode/index updates with a mutex for proper concurrency handling
v4(sashiko)
- move xe_debug_page_size_alloc_ctrl_init() before drm_dev_register(),
so mutex and control states are initialized
before any userspace visibility
v5(Himal)
- Guard all the debug page size policy code under CONFIG
- Squash Kconfig patch to have Kconfig entry for DEBUG_PAGE_SIZE
- Add inline to check debug page size support and exact mode
configured if it is supported.
v6 (fix CI build)
v8 (Himal)
- use drmm_mutex_init to avoid leak with mutex_init
- call xe_debug_page_size_alloc_ctrl_init unconditionally
- Add missed mixed mode check on xe_debug_page_size_mode_not_none check
- Add xe_debug_page_size_mode_is_mixed() function
v9
- make xe_debug_page_size_alloc_ctrl_init() return int
- fail probe if drmm_mutex_init() for page_size_alloc_ctrl.lock fails
Signed-off-by: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Reviewed-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
drivers/gpu/drm/xe/Kconfig.debug | 16 ++++++++++
drivers/gpu/drm/xe/xe_device.c | 25 +++++++++++++++
drivers/gpu/drm/xe/xe_device.h | 48 ++++++++++++++++++++++++++++
drivers/gpu/drm/xe/xe_device_types.h | 31 ++++++++++++++++++
4 files changed, 120 insertions(+)
diff --git a/drivers/gpu/drm/xe/Kconfig.debug b/drivers/gpu/drm/xe/Kconfig.debug
index 01227c77f6d7..79118d9efd93 100644
--- a/drivers/gpu/drm/xe/Kconfig.debug
+++ b/drivers/gpu/drm/xe/Kconfig.debug
@@ -86,6 +86,22 @@ config DRM_XE_KUNIT_TEST
If in doubt, say "N".
+config DRM_XE_DEBUG_PAGE_SIZE
+ bool "Enable debug control for user BO page-size allocation"
+ depends on DRM_XE_DEBUG && DEBUG_FS
+ help
+ Expose a debugfs knob to override user BO page-size allocation
+ handling for validation and debug. Supported modes include forced
+ 2M, forced 1G, and a mixed mode that exercises 4K, 64K, 2M, and
+ 1G page-size paths on platforms that support them.
+
+ This is an unstable debugfs interface intended for development and
+ validation only. Its layout, contents, and existence may change or
+ be removed at any time with no regression warranty.
+
+ Recommended for driver developers only.
+ If in doubt, say "N".
+
config DRM_XE_DEBUG_GUC
bool "Enable extra GuC related debug options"
depends on DRM_XE_DEBUG
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 4eed9a251e65..7007b6113760 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -921,6 +921,27 @@ static void xe_device_wedged_fini(struct drm_device *drm, void *arg)
xe_pm_runtime_put(xe);
}
+#ifdef CONFIG_DRM_XE_DEBUG_PAGE_SIZE
+static int xe_debug_page_size_alloc_ctrl_init(struct xe_device *xe)
+{
+ int err;
+
+ err = drmm_mutex_init(&xe->drm, &xe->page_size_alloc_ctrl.lock);
+ if (err)
+ return err;
+
+ xe->page_size_alloc_ctrl.mode = XE_PAGE_SIZE_ALLOC_CTRL_MODE_NONE;
+ xe->page_size_alloc_ctrl.cur_index = 0;
+
+ return 0;
+}
+#else
+static int xe_debug_page_size_alloc_ctrl_init(struct xe_device *xe)
+{
+ return 0;
+}
+#endif
+
int xe_device_probe(struct xe_device *xe)
{
struct xe_tile *tile;
@@ -1073,6 +1094,10 @@ int xe_device_probe(struct xe_device *xe)
if (err)
return err;
+ err = xe_debug_page_size_alloc_ctrl_init(xe);
+ if (err)
+ return err;
+
err = drm_dev_register(&xe->drm, 0);
if (err)
return err;
diff --git a/drivers/gpu/drm/xe/xe_device.h b/drivers/gpu/drm/xe/xe_device.h
index a03760d0ce38..6c4cfaebc44a 100644
--- a/drivers/gpu/drm/xe/xe_device.h
+++ b/drivers/gpu/drm/xe/xe_device.h
@@ -212,6 +212,54 @@ static inline bool xe_device_wedged(struct xe_device *xe)
return atomic_read(&xe->wedged.flag);
}
+#ifdef CONFIG_DRM_XE_DEBUG_PAGE_SIZE
+static inline bool xe_debug_page_size_supported(struct xe_device *xe)
+{
+ return IS_DGFX(xe);
+}
+
+static inline bool xe_debug_page_size_mode_not_none(struct xe_device *xe)
+{
+ enum xe_page_size_alloc_ctrl_mode mode;
+
+ if (!xe_debug_page_size_supported(xe))
+ return false;
+
+ mode = READ_ONCE(xe->page_size_alloc_ctrl.mode);
+
+ return mode == XE_PAGE_SIZE_ALLOC_CTRL_MODE_ONLY_2M ||
+ mode == XE_PAGE_SIZE_ALLOC_CTRL_MODE_ONLY_1G ||
+ mode == XE_PAGE_SIZE_ALLOC_CTRL_MODE_MIXED;
+}
+
+static inline bool xe_debug_page_size_mode_is_mixed(struct xe_device *xe)
+{
+ enum xe_page_size_alloc_ctrl_mode mode;
+
+ if (!xe_debug_page_size_supported(xe))
+ return false;
+
+ mode = READ_ONCE(xe->page_size_alloc_ctrl.mode);
+
+ return mode == XE_PAGE_SIZE_ALLOC_CTRL_MODE_MIXED;
+}
+#else
+static inline bool xe_debug_page_size_supported(struct xe_device *xe)
+{
+ return false;
+}
+
+static inline bool xe_debug_page_size_mode_not_none(struct xe_device *xe)
+{
+ return false;
+}
+
+static inline bool xe_debug_page_size_mode_is_mixed(struct xe_device *xe)
+{
+ return false;
+}
+#endif
+
void xe_device_set_wedged_method(struct xe_device *xe, unsigned long method);
void xe_device_declare_wedged(struct xe_device *xe);
int xe_device_validate_wedged_mode(struct xe_device *xe, unsigned int mode);
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 860ad322237f..03a7bb08adf7 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -61,6 +61,23 @@ enum xe_wedged_mode {
XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET = 2,
};
+#ifdef CONFIG_DRM_XE_DEBUG_PAGE_SIZE
+/**
+ * enum xe_page_size_alloc_ctrl_mode - User BO page-size allocation control modes
+ * @XE_PAGE_SIZE_ALLOC_CTRL_MODE_NONE: Use the normal allocation policy
+ * @XE_PAGE_SIZE_ALLOC_CTRL_MODE_ONLY_2M: Force user BO allocations to 2M pages
+ * @XE_PAGE_SIZE_ALLOC_CTRL_MODE_ONLY_1G: Force user BO allocations to 1G pages
+ * @XE_PAGE_SIZE_ALLOC_CTRL_MODE_MIXED: Select page sizes in round-robin order
+ * (4K, 64K, 2M, 1G)
+ */
+enum xe_page_size_alloc_ctrl_mode {
+ XE_PAGE_SIZE_ALLOC_CTRL_MODE_NONE = 0,
+ XE_PAGE_SIZE_ALLOC_CTRL_MODE_ONLY_2M,
+ XE_PAGE_SIZE_ALLOC_CTRL_MODE_ONLY_1G,
+ XE_PAGE_SIZE_ALLOC_CTRL_MODE_MIXED
+};
+#endif
+
#define XE_BO_INVALID_OFFSET LONG_MAX
#define GRAPHICS_VER(xe) ((xe)->info.graphics_verx100 / 100)
@@ -478,6 +495,20 @@ struct xe_device {
/** @late_bind: xe mei late bind interface */
struct xe_late_bind late_bind;
+#ifdef CONFIG_DRM_XE_DEBUG_PAGE_SIZE
+ /**
+ * @page_size_alloc_ctrl: User BO page-size allocation
+ * debug control state
+ */
+ struct {
+ /** @page_size_alloc_ctrl.mode: xe page size allocation control mode */
+ enum xe_page_size_alloc_ctrl_mode mode;
+ /** @page_size_alloc_ctrl.cur_index: Round-robin index used by mixed mode */
+ u32 cur_index;
+ /** @page_size_alloc_ctrl.lock: Protects @mode and @cur_index */
+ struct mutex lock;
+ } page_size_alloc_ctrl;
+#endif
/** @oa: oa observation subsystem */
struct xe_oa oa;
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v10 2/6] drm/xe/debugfs: add page-size allocation mode knob
2026-07-29 8:40 [PATCH v10 0/6] drm/xe: add page size allocation mode control and coverage Nareshkumar Gollakoti
2026-07-29 8:40 ` [PATCH v10 1/6] drm/xe: add page size allocation control state to xe_device Nareshkumar Gollakoti
@ 2026-07-29 8:40 ` Nareshkumar Gollakoti
2026-07-29 8:40 ` [PATCH v10 3/6] drm/xe: add XE_BO_FLAG_NEEDS_1G for minimum page-size sizing Nareshkumar Gollakoti
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Nareshkumar Gollakoti @ 2026-07-29 8:40 UTC (permalink / raw)
To: intel-xe; +Cc: himal.prasad.ghimiray, naresh.kumar.g
Expose a debugfs control to override the page-size allocation mode used
for user BOs.
The interface allows switching between the default allocation policy,
forced 2M, forced 1G, and mixed allocation modes at runtime. This
provides a simple way to validate behavior and debug page-size-dependent
allocation flows.
The debugfs entry is built only when CONFIG_DRM_XE_DEBUG_PAGE_SIZE is
enabled.
v2
- update changelog to match mutex-based cur_index handling
- reset cur_index when switching to mixed mode (sashiko)
v3
- add CONFIG guard for page-size allocation debugfs support (Himal)
- create debugfs entry under CONFIG_DRM_XE_DEBUG_PAGE_SIZE
v4
- reorderd this patch with kconfig patch to ensure patch builds
- Gurding this debug knob for only discrete graphics
v5(Himal)
- Guard all page size calls with CONFIG_DRM_XE_DEBUG_PAGE_SIZE
v8(Himal)
- For read/show used READ_ONCE instead lock
- to match Reader used WRITE_ONCE under lock protection
- change modes to string format to read/writer for debugfs
v9(Himal)
- Add an OOB guard for mode in page_size_alloc_mode_show().
This check makes the function display "unknown" if mode has been
maliciously altered by KMD, preventing out-of-bounds access.
Under normal operation, values set through debugfs are validated,
so OOB values should not occur.
- simplify mode-to-string lookup using page_size_alloc_mode_names[]
- use sysfs_match_string() to parse page_size_alloc_mode writes
Signed-off-by: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>
Reviewed-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
drivers/gpu/drm/xe/xe_debugfs.c | 78 +++++++++++++++++++++++++++++++++
1 file changed, 78 insertions(+)
diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c
index 5a3877fcb0f0..8de78cd0aa03 100644
--- a/drivers/gpu/drm/xe/xe_debugfs.c
+++ b/drivers/gpu/drm/xe/xe_debugfs.c
@@ -614,6 +614,72 @@ static const struct file_operations disable_late_binding_fops = {
.write = disable_late_binding_set,
};
+#ifdef CONFIG_DRM_XE_DEBUG_PAGE_SIZE
+static const char * const page_size_alloc_mode_names[] = {
+ [XE_PAGE_SIZE_ALLOC_CTRL_MODE_NONE] = "none",
+ [XE_PAGE_SIZE_ALLOC_CTRL_MODE_ONLY_2M] = "only_2m",
+ [XE_PAGE_SIZE_ALLOC_CTRL_MODE_ONLY_1G] = "only_1g",
+ [XE_PAGE_SIZE_ALLOC_CTRL_MODE_MIXED] = "mixed",
+};
+
+static ssize_t page_size_alloc_mode_show(struct file *f, char __user *ubuf,
+ size_t size, loff_t *pos)
+{
+ struct xe_device *xe = file_inode(f)->i_private;
+ char buf[32];
+ int len;
+ enum xe_page_size_alloc_ctrl_mode mode;
+
+ mode = READ_ONCE(xe->page_size_alloc_ctrl.mode);
+ if (mode >= ARRAY_SIZE(page_size_alloc_mode_names) ||
+ !page_size_alloc_mode_names[mode])
+ len = scnprintf(buf, sizeof(buf), "unknown\n");
+ else
+ len = scnprintf(buf, sizeof(buf), "%s\n",
+ page_size_alloc_mode_names[mode]);
+ return simple_read_from_buffer(ubuf, size, pos, buf, len);
+}
+
+static ssize_t page_size_alloc_mode_set(struct file *f, const char __user *ubuf,
+ size_t size, loff_t *pos)
+{
+ struct xe_device *xe = file_inode(f)->i_private;
+ int ret;
+ char buf[32];
+ int mode;
+
+ if (*pos)
+ return -ESPIPE;
+
+ if (size > sizeof(buf) - 1)
+ return -EINVAL;
+
+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, pos, ubuf, size);
+ if (ret < 0)
+ return ret;
+ buf[ret] = '\0';
+
+ mode = sysfs_match_string(page_size_alloc_mode_names, buf);
+ if (mode < 0)
+ return mode;
+
+ mutex_lock(&xe->page_size_alloc_ctrl.lock);
+ if (mode == XE_PAGE_SIZE_ALLOC_CTRL_MODE_MIXED)
+ xe->page_size_alloc_ctrl.cur_index = 0;
+ WRITE_ONCE(xe->page_size_alloc_ctrl.mode,
+ (enum xe_page_size_alloc_ctrl_mode)mode);
+ mutex_unlock(&xe->page_size_alloc_ctrl.lock);
+
+ return size;
+}
+
+static const struct file_operations page_size_alloc_mode_fops = {
+ .owner = THIS_MODULE,
+ .read = page_size_alloc_mode_show,
+ .write = page_size_alloc_mode_set,
+};
+#endif
+
void xe_debugfs_register(struct xe_device *xe)
{
struct ttm_device *bdev = &xe->ttm;
@@ -665,6 +731,18 @@ void xe_debugfs_register(struct xe_device *xe)
debugfs_create_file("disable_late_binding", 0600, root, xe,
&disable_late_binding_fops);
+#ifdef CONFIG_DRM_XE_DEBUG_PAGE_SIZE
+ /*
+ * Expose a debugfs knob to control user BO page-size allocation:
+ * "none" - default behavior
+ * "only_2m" - force 2M page allocations
+ * "only_1g" - force 1G page allocations
+ * "mixed" - select 4K, 64K, 2M, and 1G in round-robin order
+ */
+ if (xe_debug_page_size_supported(xe))
+ debugfs_create_file("page_size_alloc_mode", 0600, root, xe,
+ &page_size_alloc_mode_fops);
+#endif
/*
* Don't expose page reclaim configuration file if not supported by the
* hardware initially.
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v10 3/6] drm/xe: add XE_BO_FLAG_NEEDS_1G for minimum page-size sizing
2026-07-29 8:40 [PATCH v10 0/6] drm/xe: add page size allocation mode control and coverage Nareshkumar Gollakoti
2026-07-29 8:40 ` [PATCH v10 1/6] drm/xe: add page size allocation control state to xe_device Nareshkumar Gollakoti
2026-07-29 8:40 ` [PATCH v10 2/6] drm/xe/debugfs: add page-size allocation mode knob Nareshkumar Gollakoti
@ 2026-07-29 8:40 ` Nareshkumar Gollakoti
2026-07-29 8:40 ` [PATCH v10 4/6] drm/xe: apply debug page-size allocation policy to user BOs Nareshkumar Gollakoti
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Nareshkumar Gollakoti @ 2026-07-29 8:40 UTC (permalink / raw)
To: intel-xe; +Cc: himal.prasad.ghimiray, naresh.kumar.g
Add XE_BO_FLAG_NEEDS_1G to mark BOs that require 1G minimum page-size
sizing.
Update xe_bo_init_locked() to honor the new flag in the existing
VRAM/stolen-memory minimum page-size sizing path. When
XE_BO_FLAG_NEEDS_1G is set, the BO size is rounded up to 1G. Otherwise,
the existing 2M and 64K sizing behavior is preserved.
If multiple minimum page-size flags are set, the largest requirement
takes precedence: 1G over 2M over 64K.
v3
- commit message reworded
Signed-off-by: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>
Reviewed-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
drivers/gpu/drm/xe/xe_bo.c | 12 ++++++++++--
drivers/gpu/drm/xe/xe_bo.h | 1 +
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index c266fa6bade1..cf0b7b35c331 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -2340,8 +2340,16 @@ struct xe_bo *xe_bo_init_locked(struct xe_device *xe, struct xe_bo *bo,
if (flags & (XE_BO_FLAG_VRAM_MASK | XE_BO_FLAG_STOLEN) &&
!(flags & XE_BO_FLAG_IGNORE_MIN_PAGE_SIZE) &&
((xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K) ||
- (flags & (XE_BO_FLAG_NEEDS_64K | XE_BO_FLAG_NEEDS_2M)))) {
- size_t align = flags & XE_BO_FLAG_NEEDS_2M ? SZ_2M : SZ_64K;
+ (flags & (XE_BO_FLAG_NEEDS_64K | XE_BO_FLAG_NEEDS_2M |
+ XE_BO_FLAG_NEEDS_1G)))) {
+ size_t align;
+
+ if (flags & XE_BO_FLAG_NEEDS_1G)
+ align = SZ_1G;
+ else if (flags & XE_BO_FLAG_NEEDS_2M)
+ align = SZ_2M;
+ else
+ align = SZ_64K;
aligned_size = ALIGN(size, align);
if (type != ttm_bo_type_device)
diff --git a/drivers/gpu/drm/xe/xe_bo.h b/drivers/gpu/drm/xe/xe_bo.h
index 7ae1d9ac0574..c6d80e1bd6e7 100644
--- a/drivers/gpu/drm/xe/xe_bo.h
+++ b/drivers/gpu/drm/xe/xe_bo.h
@@ -52,6 +52,7 @@
#define XE_BO_FLAG_CPU_ADDR_MIRROR BIT(24)
#define XE_BO_FLAG_FORCE_USER_VRAM BIT(25)
#define XE_BO_FLAG_NO_COMPRESSION BIT(26)
+#define XE_BO_FLAG_NEEDS_1G BIT(27)
/* this one is trigger internally only */
#define XE_BO_FLAG_INTERNAL_TEST BIT(30)
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v10 4/6] drm/xe: apply debug page-size allocation policy to user BOs
2026-07-29 8:40 [PATCH v10 0/6] drm/xe: add page size allocation mode control and coverage Nareshkumar Gollakoti
` (2 preceding siblings ...)
2026-07-29 8:40 ` [PATCH v10 3/6] drm/xe: add XE_BO_FLAG_NEEDS_1G for minimum page-size sizing Nareshkumar Gollakoti
@ 2026-07-29 8:40 ` Nareshkumar Gollakoti
2026-07-29 8:40 ` [PATCH v10 5/6] drm/xe/pt: allow selecting the bind leaf PTE level Nareshkumar Gollakoti
2026-07-29 8:40 ` [PATCH v10 6/6] drm/xe/tests: add live KUnit coverage for BO page-size allocation modes Nareshkumar Gollakoti
5 siblings, 0 replies; 8+ messages in thread
From: Nareshkumar Gollakoti @ 2026-07-29 8:40 UTC (permalink / raw)
To: intel-xe; +Cc: himal.prasad.ghimiray, naresh.kumar.g
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>
---
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 cf0b7b35c331..929669f18788 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -2640,6 +2640,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.
@@ -2660,9 +2799,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,
@@ -3477,6 +3623,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
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v10 5/6] drm/xe/pt: allow selecting the bind leaf PTE level
2026-07-29 8:40 [PATCH v10 0/6] drm/xe: add page size allocation mode control and coverage Nareshkumar Gollakoti
` (3 preceding siblings ...)
2026-07-29 8:40 ` [PATCH v10 4/6] drm/xe: apply debug page-size allocation policy to user BOs Nareshkumar Gollakoti
@ 2026-07-29 8:40 ` Nareshkumar Gollakoti
2026-07-29 8:40 ` [PATCH v10 6/6] drm/xe/tests: add live KUnit coverage for BO page-size allocation modes Nareshkumar Gollakoti
5 siblings, 0 replies; 8+ messages in thread
From: Nareshkumar Gollakoti @ 2026-07-29 8:40 UTC (permalink / raw)
To: intel-xe; +Cc: himal.prasad.ghimiray, naresh.kumar.g
Add a target_leaf_level field to the page-table bind walk and use it to
control the level at which leaf entries are emitted.
By default, the bind walk emits level-0 leaf PTEs and relies on
xe_pt_hugepte_possible() to select huge mappings when possible. Add an
explicit target leaf level so the walk can stop earlier when the VMA
requests a larger mapping size.
Use level 1 for 2M PDE mappings and level 2 for 1G PDP mappings, while
keeping level 0 for normal mappings. The existing huge-page heuristic
is preserved for the default level-0 path.
This allows the bind path to emit 2M and 1G leaf entries when requested
by the VMA, while still validating alignment and size requirements.
v2
- avoid using max_level to control walk depth
- use target_leaf_level to preserve the normal walk behavior
- keep the default huge-page heuristic only for the level-0 path
- refine commit message
v3
- reword commit message
v4
- allow fallback to smaller huge-page levels for non-zero
target_leaf_level
- avoid constraining clear_pt walks by target_leaf_level
v5(Himal)
- Restrict only intended level in debug page size policy mode
- Allow the normal path to proceed smoothly when
no debug page-size mode is selected.
v8 (Himal)
- Drop
https://patchwork.freedesktop.org/patch/740059/?series=168905&rev=5
patch and populate target_leaf_level from bo flags
- populate target_leaf_level if it is in debug page size mode
otherwise fill with 0 which is having no effect on the normal
flow
v10 (Himal)
- use xe_bo_is_vram() instead of raw VRAM flag checks
so huge-page selection is based on BO VRAM placement.
Signed-off-by: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>
Reviewed-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
drivers/gpu/drm/xe/xe_pt.c | 76 +++++++++++++++++++++++++++++++++++++-
1 file changed, 74 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index 598c6b2571e7..9517968ed414 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -302,6 +302,14 @@ struct xe_pt_stage_bind_walk {
bool needs_64K;
/** @clear_pt: clear page table entries during the bind walk */
bool clear_pt;
+ /**
+ * @target_leaf_level: Page-table level at which to emit leaf PTEs
+ * 0 for normal 4K/64K mappings, 1 for 2M huge pages, and 2 for 1G huge
+ * pages. The walk still traverses from the root down; this field tells
+ * xe_pt_stage_bind_entry() to treat the selected level as a leaf instead
+ * of descending further.
+ */
+ u32 target_leaf_level;
/**
* @vma: VMA being mapped
*/
@@ -514,6 +522,39 @@ xe_pt_is_pte_ps64K(u64 addr, u64 next, struct xe_pt_stage_bind_walk *xe_walk)
return xe_walk->found_64K;
}
+static bool xe_pt_huge_leaf_allowed(u64 addr, u64 next, unsigned int level,
+ struct xe_pt_stage_bind_walk *xe_walk)
+{
+ if (xe_walk->clear_pt)
+ return xe_pt_hugepte_possible(addr, next, level, xe_walk);
+
+ if (!xe_debug_page_size_supported(xe_walk->vm->xe))
+ return xe_pt_hugepte_possible(addr, next, level, xe_walk);
+
+ if (!xe_walk->target_leaf_level)
+ return xe_pt_hugepte_possible(addr, next, level, xe_walk);
+
+ if (level == xe_walk->target_leaf_level)
+ return xe_pt_hugepte_possible(addr, next, level, xe_walk);
+
+ return false;
+}
+
+static bool xe_pt_exact_leaf_required_but_invalid(u64 addr, u64 next,
+ unsigned int level,
+ struct xe_pt_stage_bind_walk *xe_walk)
+{
+ struct xe_device *xe = xe_walk->vm->xe;
+
+ if (!xe_debug_page_size_mode_not_none(xe))
+ return false;
+
+ return !xe_walk->clear_pt &&
+ xe_walk->target_leaf_level &&
+ level == xe_walk->target_leaf_level &&
+ !xe_pt_hugepte_possible(addr, next, level, xe_walk);
+}
+
static int
xe_pt_stage_bind_entry(struct xe_ptw *parent, pgoff_t offset,
unsigned int level, u64 addr, u64 next,
@@ -531,8 +572,18 @@ xe_pt_stage_bind_entry(struct xe_ptw *parent, pgoff_t offset,
int ret = 0;
u64 pte;
- /* Is this a leaf entry ?*/
- if (level == 0 || xe_pt_hugepte_possible(addr, next, level, xe_walk)) {
+ if (xe_pt_exact_leaf_required_but_invalid(addr, next, level, xe_walk))
+ return -EINVAL;
+
+ /*
+ * Is this a leaf entry?
+ * Always create a 4K leaf at level 0. For huge pages (level > 0),
+ * validate alignment and size with xe_pt_hugepte_possible().
+ * When target_leaf_level is non-zero, only that huge-page level is
+ * accepted for normal bind walks. Clear walks remain unconstrained so
+ * existing huge leaves can be cleared without descending further.
+ */
+ if (level == 0 || xe_pt_huge_leaf_allowed(addr, next, level, xe_walk)) {
struct xe_res_cursor *curs = xe_walk->curs;
struct xe_bo *bo = xe_vma_bo(xe_walk->vma);
bool is_null_or_purged = xe_vma_is_null(xe_walk->vma) ||
@@ -682,6 +733,26 @@ static bool xe_atomic_for_system(struct xe_vm *vm, struct xe_vma *vma)
(bo && xe_bo_has_single_placement(bo))));
}
+static u32 xe_pt_target_leaf_level_from_bo(struct xe_device *xe,
+ struct xe_vma *vma)
+{
+ struct xe_bo *bo = xe_vma_bo(vma);
+
+ if (!xe_debug_page_size_mode_not_none(xe))
+ return 0;
+
+ if (!bo || !xe_bo_is_vram(bo) || !(bo->flags & XE_BO_FLAG_USER))
+ return 0;
+
+ if (bo->flags & XE_BO_FLAG_NEEDS_1G)
+ return 2;
+
+ if (bo->flags & XE_BO_FLAG_NEEDS_2M)
+ return 1;
+
+ return 0;
+}
+
/**
* xe_pt_stage_bind() - Build a disconnected page-table tree for a given address
* range.
@@ -774,6 +845,7 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
xe_svm_notifier_unlock(vm);
}
+ xe_walk.target_leaf_level = xe_pt_target_leaf_level_from_bo(xe, vma);
xe_walk.needs_64K = (vm->flags & XE_VM_FLAG_64K);
if (clear_pt)
goto walk_pt;
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v10 6/6] drm/xe/tests: add live KUnit coverage for BO page-size allocation modes
2026-07-29 8:40 [PATCH v10 0/6] drm/xe: add page size allocation mode control and coverage Nareshkumar Gollakoti
` (4 preceding siblings ...)
2026-07-29 8:40 ` [PATCH v10 5/6] drm/xe/pt: allow selecting the bind leaf PTE level Nareshkumar Gollakoti
@ 2026-07-29 8:40 ` Nareshkumar Gollakoti
5 siblings, 0 replies; 8+ messages in thread
From: Nareshkumar Gollakoti @ 2026-07-29 8:40 UTC (permalink / raw)
To: intel-xe; +Cc: himal.prasad.ghimiray, naresh.kumar.g
Add live KUnit coverage for the debug-controlled BO
page-size allocation modes.
The new tests cover forced 2M mode, forced 1G mode,
and mixed mode. They verify that user BO creation applies
the expected NEEDS_* flags, that no unexpected page-size flags are
added in the forced modes, that BO size is rounded as expected, and
that page_alignment matches the selected leaf size.
The mixed-mode test does not assume a strict per-allocation rotation
sequence, since the device-global mixed-mode index may be perturbed by
concurrent BO creation on a live system. Instead,
it validates that each allocation results in
one valid mixed-mode page-size outcome.
Treat transient VRAM allocation failures as skipped test cases so the
tests can run in varying live environments without producing false
failures.
v3
- address review comments
- rework mixed-mode test to avoid assuming strict rotation order
- reword commit message
v4
- skip VRAM-targeted live tests on non-dGFX devices
v5
- advance the mixed-mode index in the test
v6
- Gaurd kunit tests under CONFIG_DRM_XE_DEBUG_PAGE_SIZE
v9
- consider XE_VRAM_FLAGS_NEED64K in mixed mode for certain
platoform min alignment expectations.
Signed-off-by: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>
Reviewed-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
---
drivers/gpu/drm/xe/tests/xe_bo.c | 242 ++++++++++++++++++++
drivers/gpu/drm/xe/tests/xe_live_test_mod.c | 6 +
2 files changed, 248 insertions(+)
diff --git a/drivers/gpu/drm/xe/tests/xe_bo.c b/drivers/gpu/drm/xe/tests/xe_bo.c
index 49c95ed67d7e..6a17e13d58cf 100644
--- a/drivers/gpu/drm/xe/tests/xe_bo.c
+++ b/drivers/gpu/drm/xe/tests/xe_bo.c
@@ -22,6 +22,231 @@
#include "xe_pci.h"
#include "xe_pm.h"
+#ifdef CONFIG_DRM_XE_DEBUG_PAGE_SIZE
+struct page_size_alloc_saved {
+ enum xe_page_size_alloc_ctrl_mode mode;
+ u32 cur_index;
+};
+
+/* Caller must hold xe->page_size_alloc_ctrl.lock. */
+static void page_size_alloc_save(struct xe_device *xe,
+ struct page_size_alloc_saved *s)
+{
+ s->mode = xe->page_size_alloc_ctrl.mode;
+ s->cur_index = xe->page_size_alloc_ctrl.cur_index;
+}
+
+static void page_size_alloc_restore(struct xe_device *xe,
+ const struct page_size_alloc_saved *s)
+{
+ mutex_lock(&xe->page_size_alloc_ctrl.lock);
+ xe->page_size_alloc_ctrl.mode = s->mode;
+ xe->page_size_alloc_ctrl.cur_index = s->cur_index;
+ mutex_unlock(&xe->page_size_alloc_ctrl.lock);
+}
+
+/* Expected properties for a forced page-size allocation mode. */
+struct leaf_info {
+ u64 leaf;
+ u64 alloc_size;
+ u32 flag;
+ const char *name;
+};
+
+static const struct leaf_info leaf_2m = {
+ .leaf = SZ_2M,
+ .alloc_size = SZ_2M - PAGE_SIZE,
+ .flag = XE_BO_FLAG_NEEDS_2M,
+ .name = "2M",
+};
+
+static const struct leaf_info leaf_1g = {
+ .leaf = SZ_1G,
+ .alloc_size = SZ_1G - PAGE_SIZE,
+ .flag = XE_BO_FLAG_NEEDS_1G,
+ .name = "1G",
+};
+
+static void run_only_leaf(struct kunit *test,
+ enum xe_page_size_alloc_ctrl_mode mode,
+ const struct leaf_info *li)
+{
+ struct xe_device *xe = test->priv;
+ struct page_size_alloc_saved saved;
+ struct xe_bo *bo;
+ struct ttm_buffer_object *ttm_bo;
+ u32 other_flags;
+
+ if (!IS_DGFX(xe)) {
+ kunit_skip(test, "requires dGFX VRAM");
+ return;
+ }
+
+ mutex_lock(&xe->page_size_alloc_ctrl.lock);
+ page_size_alloc_save(xe, &saved);
+ xe->page_size_alloc_ctrl.mode = mode;
+ mutex_unlock(&xe->page_size_alloc_ctrl.lock);
+
+ bo = xe_bo_create_user(xe, NULL, li->alloc_size,
+ DRM_XE_GEM_CPU_CACHING_WC,
+ XE_BO_FLAG_VRAM0, NULL);
+ if (IS_ERR(bo)) {
+ page_size_alloc_restore(xe, &saved);
+ if (PTR_ERR(bo) == -ENOSPC) {
+ kunit_skip(test,
+ "no contiguous %s VRAM available right now",
+ li->name);
+ return;
+ }
+
+ KUNIT_FAIL(test, "%s BO alloc failed: %pe", li->name, bo);
+ return;
+ }
+
+ ttm_bo = &bo->ttm;
+
+ /* 1) The mode added the right NEEDS_* flag. */
+ KUNIT_EXPECT_TRUE_MSG(test, bo->flags & li->flag,
+ "%s: flag missing, flags=0x%x",
+ li->name, bo->flags);
+
+ /* 2) No other NEEDS_* flags accidentally tagged on. */
+ other_flags = (XE_BO_FLAG_NEEDS_64K |
+ XE_BO_FLAG_NEEDS_2M |
+ XE_BO_FLAG_NEEDS_1G) & ~li->flag;
+ KUNIT_EXPECT_FALSE_MSG(test, bo->flags & other_flags,
+ "%s: stray flags=0x%x",
+ li->name, bo->flags);
+ /* 3) BO size was rounded up to the expected leaf size. */
+ KUNIT_EXPECT_EQ_MSG(test, xe_bo_size(bo), li->leaf,
+ "%s: bo size=%llu expected=%llu",
+ li->name,
+ (u64)xe_bo_size(bo),
+ (u64)li->leaf);
+ /*
+ * 4) Allocator honored the requested alignment.
+ * ttm_bo->page_alignment is stored in PAGE_SIZE units, so compare against
+ * the expected leaf size converted with >> PAGE_SHIFT.
+ */
+ KUNIT_EXPECT_EQ_MSG(test, ttm_bo->page_alignment,
+ li->leaf >> PAGE_SHIFT,
+ "%s: page_alignment=%u pages expected=%llu pages",
+ li->name, ttm_bo->page_alignment,
+ (u64)(li->leaf >> PAGE_SHIFT));
+
+ xe_bo_put(bo);
+ page_size_alloc_restore(xe, &saved);
+}
+
+static void xe_bo_page_size_alloc_only_2m(struct kunit *test)
+{
+ run_only_leaf(test, XE_PAGE_SIZE_ALLOC_CTRL_MODE_ONLY_2M, &leaf_2m);
+}
+
+static void xe_bo_page_size_alloc_only_1g(struct kunit *test)
+{
+ run_only_leaf(test, XE_PAGE_SIZE_ALLOC_CTRL_MODE_ONLY_1G, &leaf_1g);
+}
+
+static void xe_bo_page_size_alloc_mixed_bos(struct kunit *test)
+{
+ struct xe_device *xe = test->priv;
+ struct page_size_alloc_saved saved;
+ struct xe_bo *bo;
+ struct ttm_buffer_object *ttm_bo;
+ u32 all_flags = XE_BO_FLAG_NEEDS_64K | XE_BO_FLAG_NEEDS_2M |
+ XE_BO_FLAG_NEEDS_1G;
+ u32 flags;
+ u64 expected_align;
+ int i;
+ const int n = 4;
+
+ if (!IS_DGFX(xe)) {
+ kunit_skip(test, "requires dGFX VRAM");
+ return;
+ }
+
+ mutex_lock(&xe->page_size_alloc_ctrl.lock);
+ page_size_alloc_save(xe, &saved);
+ mutex_unlock(&xe->page_size_alloc_ctrl.lock);
+
+ for (i = 0; i < n; i++) {
+ mutex_lock(&xe->page_size_alloc_ctrl.lock);
+ xe->page_size_alloc_ctrl.mode = XE_PAGE_SIZE_ALLOC_CTRL_MODE_MIXED;
+ xe->page_size_alloc_ctrl.cur_index = i;
+ mutex_unlock(&xe->page_size_alloc_ctrl.lock);
+ /*
+ * Request a size valid for any mixed-mode slot. Since cur_index is
+ * device-global and may be perturbed by concurrent allocations on
+ * a live system, do not assume this iteration will see a specific
+ * slot.
+ */
+ bo = xe_bo_create_user(xe, NULL, SZ_1G,
+ DRM_XE_GEM_CPU_CACHING_WC,
+ XE_BO_FLAG_VRAM0, NULL);
+ if (IS_ERR(bo)) {
+ int err = PTR_ERR(bo);
+
+ page_size_alloc_restore(xe, &saved);
+ if (err == -ENOSPC) {
+ kunit_skip(test,
+ "mixed mode BO allocation unavailable: %d",
+ err);
+ return;
+ }
+ KUNIT_FAIL(test, "iter=%d alloc failed: %pe", i, bo);
+ return;
+ }
+
+ ttm_bo = &bo->ttm;
+ flags = bo->flags & all_flags;
+ /*
+ * Mixed mode may result in:
+ * 0-> default platform VRAM alignment
+ * XE_BO_FLAG_NEEDS_64K
+ * XE_BO_FLAG_NEEDS_2M
+ * XE_BO_FLAG_NEEDS_1G
+ * Any other combination is invalid.
+ */
+ if (flags == 0) {
+ expected_align = SZ_4K;
+ if (xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K)
+ expected_align = SZ_64K;
+ } else if (flags == XE_BO_FLAG_NEEDS_64K) {
+ expected_align = SZ_64K;
+ } else if (flags == XE_BO_FLAG_NEEDS_2M) {
+ expected_align = SZ_2M;
+ } else if (flags == XE_BO_FLAG_NEEDS_1G) {
+ expected_align = SZ_1G;
+ } else {
+ KUNIT_FAIL(test,
+ "iter=%d invalid mixed-mode flags: 0x%x",
+ i, flags);
+ xe_bo_put(bo);
+ page_size_alloc_restore(xe, &saved);
+ return;
+ }
+ /*
+ * BO size should remain valid for the selected mode. Since the
+ * request is SZ_1G, it should remain unchanged regardless of the
+ * selected page-size policy.
+ */
+ KUNIT_EXPECT_EQ_MSG(test, xe_bo_size(bo), (u64)SZ_1G,
+ "iter=%d size=%llu expected=%llu",
+ i,
+ (u64)xe_bo_size(bo),
+ (u64)SZ_1G);
+ KUNIT_EXPECT_EQ_MSG(test, ttm_bo->page_alignment,
+ expected_align >> PAGE_SHIFT,
+ "iter=%d flags=0x%x page_alignment=%u pages expected=%llu pages",
+ i, flags, ttm_bo->page_alignment,
+ (u64)(expected_align >> PAGE_SHIFT));
+ xe_bo_put(bo);
+ }
+ page_size_alloc_restore(xe, &saved);
+}
+#endif
+
static int ccs_test_migrate(struct xe_tile *tile, struct xe_bo *bo,
bool clear, u64 get_val, u64 assign_val,
struct kunit *test, struct drm_exec *exec)
@@ -609,6 +834,23 @@ static struct kunit_case xe_bo_tests[] = {
{}
};
+#ifdef CONFIG_DRM_XE_DEBUG_PAGE_SIZE
+static struct kunit_case xe_bo_page_size_alloc_cases[] = {
+ KUNIT_CASE_PARAM(xe_bo_page_size_alloc_only_2m, xe_pci_live_device_gen_param),
+ KUNIT_CASE_PARAM(xe_bo_page_size_alloc_only_1g, xe_pci_live_device_gen_param),
+ KUNIT_CASE_PARAM(xe_bo_page_size_alloc_mixed_bos, xe_pci_live_device_gen_param),
+ {}
+};
+
+VISIBLE_IF_KUNIT
+struct kunit_suite xe_bo_page_size_alloc_suite = {
+ .name = "xe_bo_page_size_alloc",
+ .test_cases = xe_bo_page_size_alloc_cases,
+ .init = xe_kunit_helper_xe_device_live_test_init,
+};
+EXPORT_SYMBOL_IF_KUNIT(xe_bo_page_size_alloc_suite);
+#endif
+
VISIBLE_IF_KUNIT
struct kunit_suite xe_bo_test_suite = {
.name = "xe_bo",
diff --git a/drivers/gpu/drm/xe/tests/xe_live_test_mod.c b/drivers/gpu/drm/xe/tests/xe_live_test_mod.c
index c55e46f1ae92..87cd7db20e5f 100644
--- a/drivers/gpu/drm/xe/tests/xe_live_test_mod.c
+++ b/drivers/gpu/drm/xe/tests/xe_live_test_mod.c
@@ -11,6 +11,9 @@ extern struct kunit_suite xe_dma_buf_test_suite;
extern struct kunit_suite xe_migrate_test_suite;
extern struct kunit_suite xe_mocs_test_suite;
extern struct kunit_suite xe_guc_g2g_test_suite;
+#ifdef CONFIG_DRM_XE_DEBUG_PAGE_SIZE
+extern struct kunit_suite xe_bo_page_size_alloc_suite;
+#endif
kunit_test_suite(xe_bo_test_suite);
kunit_test_suite(xe_bo_shrink_test_suite);
@@ -18,6 +21,9 @@ kunit_test_suite(xe_dma_buf_test_suite);
kunit_test_suite(xe_migrate_test_suite);
kunit_test_suite(xe_mocs_test_suite);
kunit_test_suite(xe_guc_g2g_test_suite);
+#ifdef CONFIG_DRM_XE_DEBUG_PAGE_SIZE
+kunit_test_suite(xe_bo_page_size_alloc_suite);
+#endif
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("GPL");
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread