Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/7] Introduce purpose-specific VRAM pools
@ 2026-10-02 10:40 Piórkowski, Piotr
  2026-10-02 10:40 ` [PATCH v1 1/7] drm/xe: Define partitioned VRAM manager types Piórkowski, Piotr
                   ` (8 more replies)
  0 siblings, 9 replies; 11+ messages in thread
From: Piórkowski, Piotr @ 2026-10-02 10:40 UTC (permalink / raw)
  To: intel-xe; +Cc: Piotr Piórkowski, Matthew Brost

From: Piotr Piórkowski <piotr.piorkowski@intel.com>

This series separates VRAM regions, which own physical resources, from
VRAM pools, which represent allocation domains within those regions.
A region can then be split into hard partitions for different purposes
without requiring each allocation path to manage the physical range
directly.

Each pool is backed by its own buddy allocator. BO creation and
migration resolve the pool for an allocation consistently, and pool
placement narrows caller-provided ranges while rejecting fixed placements
that do not intersect the pool. VRAM usage and CPU-visible memory
accounting are tracked per partition, and the PF reports free memory
from the pool backing VF LMEM.

The series introduces the partition and pool types, routes allocations
through pools, adds region splitting, and includes KUnit coverage for
manager partitioning, accounting, pool setup, splitting, and TTM
placement.

Normal initialization still uses one pool spanning each region’s usable
range, so the new abstraction does not yet change allocation policy.
The series also makes the VRAM manager handle lpfn == 0 according
to TTM’s unbounded-range semantics.

Cc: Matthew Brost <matthew.brost@intel.com>

Piotr Piórkowski (7):
  drm/xe: Define partitioned VRAM manager types
  drm/xe: Define VRAM regions and pools
  drm/xe/vram: Make VRAM pools the allocation handle
  drm/xe/ttm: Back each VRAM pool with its own buddy allocator
  drm/xe/vram: Allow splitting a region into pools
  drm/xe/kunit: Test partitioned VRAM manager
  drm/xe/kunit: Test VRAM pool allocation

 drivers/gpu/drm/xe/display/xe_fb_pin.c        |   2 +-
 drivers/gpu/drm/xe/display/xe_initial_plane.c |   2 +-
 drivers/gpu/drm/xe/display/xe_panic.c         |   4 +-
 .../xe/tests/xe_gt_sriov_pf_config_kunit.c    |   8 +-
 drivers/gpu/drm/xe/tests/xe_ttm_vram_mgr.c    | 147 +++++++
 drivers/gpu/drm/xe/tests/xe_vram.c            | 155 +++++++
 drivers/gpu/drm/xe/xe_assert.h                |   3 +-
 drivers/gpu/drm/xe/xe_bo.c                    |  86 ++--
 drivers/gpu/drm/xe/xe_bo.h                    |   2 +-
 drivers/gpu/drm/xe/xe_debugfs.c               |   2 +-
 drivers/gpu/drm/xe/xe_device.c                |   2 +-
 drivers/gpu/drm/xe/xe_device_types.h          |   2 +-
 drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c    |   7 +-
 drivers/gpu/drm/xe/xe_migrate.c               |   2 +-
 drivers/gpu/drm/xe/xe_pagefault.c             |   2 +-
 drivers/gpu/drm/xe/xe_query.c                 |  27 +-
 drivers/gpu/drm/xe/xe_res_cursor.h            |  45 +-
 drivers/gpu/drm/xe/xe_svm.c                   |  18 +-
 drivers/gpu/drm/xe/xe_tile.c                  |  22 +-
 drivers/gpu/drm/xe/xe_tile.h                  |   6 +-
 drivers/gpu/drm/xe/xe_tile_debugfs.c          |   4 +-
 drivers/gpu/drm/xe/xe_tile_types.h            |   8 +-
 drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c        |   2 +-
 drivers/gpu/drm/xe/xe_ttm_vram_mgr.c          | 398 ++++++++++++++----
 drivers/gpu/drm/xe/xe_ttm_vram_mgr.h          |  54 ++-
 drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h    |  48 ++-
 drivers/gpu/drm/xe/xe_vram.c                  | 271 +++++++++++-
 drivers/gpu/drm/xe/xe_vram.h                  |  15 +-
 drivers/gpu/drm/xe/xe_vram_types.h            | 159 ++++++-
 29 files changed, 1272 insertions(+), 231 deletions(-)
 create mode 100644 drivers/gpu/drm/xe/tests/xe_ttm_vram_mgr.c
 create mode 100644 drivers/gpu/drm/xe/tests/xe_vram.c

-- 
2.34.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v1 1/7] drm/xe: Define partitioned VRAM manager types
  2026-10-02 10:40 [PATCH v1 0/7] Introduce purpose-specific VRAM pools Piórkowski, Piotr
@ 2026-10-02 10:40 ` Piórkowski, Piotr
  2026-10-02 10:40 ` [PATCH v1 2/7] drm/xe: Define VRAM regions and pools Piórkowski, Piotr
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Piórkowski, Piotr @ 2026-10-02 10:40 UTC (permalink / raw)
  To: intel-xe; +Cc: Piotr Piórkowski, Matthew Brost

From: Piotr Piórkowski <piotr.piorkowski@intel.com>

A VRAM region may need to be split into hard partitions, e.g. to keep
kernel allocations in a dedicated low range of VRAM. Expressing such a
split purely as a placement range would turn every VRAM allocation into
a %GPU_BUDDY_RANGE_ALLOCATION, which constrains the buddy algorithm for
what is really a hard, statically known split.

Describe the types needed to manage each partition with a buddy
allocator of its own instead. struct xe_ttm_vram_mgr_part ties a buddy
allocator to the VRAM pool it backs, the manager holds up to
XE_TTM_VRAM_MGR_MAX_PARTS of them, and resources and offlined pages
record the partition their blocks were allocated from, as buddy offsets
become partition relative.

Each partition also tracks the CPU visible memory allocated from it, so
that usage can be reported per pool purpose, and the alignment a
partition base must honour is defined next to the partition itself.

Suggested-by: Matthew Brost <matthew.brost@intel.com>
Assisted-by: Claude Opus 5.5
Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
---
 drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h | 46 ++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h b/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h
index efcf3e1d4e80c..6af179b2b95b5 100644
--- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h
+++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h
@@ -7,8 +7,46 @@
 #define _XE_TTM_VRAM_MGR_TYPES_H_
 
 #include <linux/gpu_buddy.h>
+#include <linux/sizes.h>
 #include <drm/ttm/ttm_device.h>
 
+struct xe_vram_pool;
+
+/**
+ * struct xe_ttm_vram_mgr_part - Partition of a VRAM region
+ *
+ * A VRAM region may be split into disjoint partitions, each managed by its
+ * own buddy allocator. An allocation belongs to exactly one partition and
+ * cannot span partition boundaries. This lets the manager allocate directly
+ * from the requested partition without resorting to
+ * %GPU_BUDDY_RANGE_ALLOCATION, which constrains the buddy allocation
+ * algorithm.
+ */
+struct xe_ttm_vram_mgr_part {
+	/**
+	 * @pool: VRAM pool backed by this partition
+	 *
+	 * Once the manager is initialized, pool->part points back here.
+	 */
+	struct xe_vram_pool *pool;
+	/** @mm: DRM buddy allocator which manages this partition */
+	struct gpu_buddy mm;
+	/** @used_visible: CPU visible bytes allocated from this partition */
+	u64 used_visible;
+};
+
+/** XE_TTM_VRAM_MGR_MAX_PARTS - Max partitions of a single VRAM region */
+#define XE_TTM_VRAM_MGR_MAX_PARTS	2
+
+/**
+ * XE_TTM_VRAM_MGR_PART_ALIGN - Required alignment of a partition base
+ *
+ * Buddy offsets are partition relative, so a partition base has to be
+ * aligned to the largest VRAM page size in regular use, otherwise an aligned
+ * buddy allocation is not aligned in the region.
+ */
+#define XE_TTM_VRAM_MGR_PART_ALIGN	SZ_2M
+
 /**
  * struct xe_ttm_vram_mgr - Xe TTM VRAM manager
  *
@@ -19,6 +57,10 @@ struct xe_ttm_vram_mgr {
 	struct ttm_resource_manager manager;
 	/** @mm: DRM buddy allocator which manages the VRAM */
 	struct gpu_buddy mm;
+	/** @parts: Partitions this VRAM region is split into */
+	struct xe_ttm_vram_mgr_part parts[XE_TTM_VRAM_MGR_MAX_PARTS];
+	/** @num_parts: Number of initialized entries in @parts */
+	unsigned int num_parts;
 	/** @offlined_pages: List of offlined pages */
 	struct list_head offlined_pages;
 	/** @n_offlined_pages: Number of offlined pages */
@@ -49,6 +91,8 @@ struct xe_ttm_vram_mgr_resource {
 	struct ttm_resource base;
 	/** @blocks: list of DRM buddy blocks */
 	struct list_head blocks;
+	/** @part: Partition owning @blocks, set on successful allocation */
+	struct xe_ttm_vram_mgr_part *part;
 	/** @used_visible_size: How many CPU visible bytes this resource is using */
 	u64 used_visible_size;
 	/** @flags: flags associated with the resource */
@@ -75,6 +119,8 @@ struct xe_ttm_vram_offline_resource {
 	struct list_head queued_link;
 	/** @blocks: Buddy blocks reserved for this page */
 	struct list_head blocks;
+	/** @part: Partition owning @blocks, set on successful reservation */
+	struct xe_ttm_vram_mgr_part *part;
 	/** @used_visible_size: CPU-visible bytes consumed */
 	u64 used_visible_size;
 	/** @addr: Faulty DPA reported by HW */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v1 2/7] drm/xe: Define VRAM regions and pools
  2026-10-02 10:40 [PATCH v1 0/7] Introduce purpose-specific VRAM pools Piórkowski, Piotr
  2026-10-02 10:40 ` [PATCH v1 1/7] drm/xe: Define partitioned VRAM manager types Piórkowski, Piotr
@ 2026-10-02 10:40 ` Piórkowski, Piotr
  2026-10-02 10:40 ` [PATCH v1 3/7] drm/xe/vram: Make VRAM pools the allocation handle Piórkowski, Piotr
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Piórkowski, Piotr @ 2026-10-02 10:40 UTC (permalink / raw)
  To: intel-xe; +Cc: Piotr Piórkowski

From: Piotr Piórkowski <piotr.piorkowski@intel.com>

Allocation paths place memory through a struct xe_vram_region, which is
both the physical carrier of a VRAM range (BAR mapping, DPA range, TTM
manager) and the only handle for the purpose an allocation serves. That
makes it impossible to dedicate part of a region to a given purpose,
e.g. to keep kernel allocations such as LRCs and page tables in a range
of their own, away from VRAM that may be reachable by other agents.

Separate the two concepts. A struct xe_vram_pool represents an allocation
domain: it identifies the purpose served by a range within a VRAM region,
whether that range is available for general use or dedicated to
a particular purpose. A struct xe_vram_region owns the physical resources
and embeds its pools as partitions, keeping pool pointers published during
initialization stable when the region is later split. The region also
records its binding, distinguishing a device-wide aggregate from a tile
region, since both may use ID 0 for the first tile.

Assisted-by: Claude Opus 5.5
Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
---
 drivers/gpu/drm/xe/xe_vram_types.h | 159 ++++++++++++++++++++++++++++-
 1 file changed, 158 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xe/xe_vram_types.h b/drivers/gpu/drm/xe/xe_vram_types.h
index 646e3c12ae9f7..a3e421f2f32d4 100644
--- a/drivers/gpu/drm/xe/xe_vram_types.h
+++ b/drivers/gpu/drm/xe/xe_vram_types.h
@@ -15,6 +15,142 @@
 struct xe_device;
 struct xe_migrate;
 
+/**
+ * enum xe_vram_binding - VRAM region binding types
+ * @XE_VRAM_BINDING_NONE: no binding assigned, default value of a zeroed region
+ * @XE_VRAM_BINDING_DEVICE: device-level region aggregating all tile VRAM regions
+ * @XE_VRAM_BINDING_TILE: VRAM region bound to a tile
+ */
+enum xe_vram_binding {
+	XE_VRAM_BINDING_NONE = 0,
+	XE_VRAM_BINDING_DEVICE,
+	XE_VRAM_BINDING_TILE,
+};
+
+/**
+ * enum xe_vram_pool_purpose - What a VRAM pool serves
+ * @XE_VRAM_POOL_GENERAL: general-purpose memory, available to userspace
+ * @XE_VRAM_POOL_KERNEL: kernel-only memory, never exposed to userspace
+ */
+enum xe_vram_pool_purpose {
+	XE_VRAM_POOL_GENERAL = 0,
+	XE_VRAM_POOL_KERNEL,
+};
+
+/**
+ * XE_VRAM_MAX_PARTITIONS - Max partitions a single VRAM region can be split into
+ *
+ * A region currently holds its default pool and at most one pool dedicated
+ * to another purpose. The TTM manager mirrors the partitions of a region one
+ * by one, so a region cannot hold more of them than the manager can back.
+ */
+#define XE_VRAM_MAX_PARTITIONS	XE_TTM_VRAM_MGR_MAX_PARTS
+
+/**
+ * DOC: VRAM pools, regions and partitions
+ *
+ * Allocation paths place memory through a struct xe_vram_pool. A pool names
+ * a purpose (general-purpose, kernel-only ...) and resolves to a TTM
+ * placement plus the address range serving it, see xe_vram_pool_place().
+ * Whether that range is the whole region, or one of several partitions
+ * sharing a region, is a backend detail pool consumers do not need to know.
+ *
+ * A struct xe_vram_region is the physical carrier: it owns the BAR mapping,
+ * the DPA range and the TTM resource manager. A non-aggregate region
+ * initially contains one partition spanning its whole usable range. That
+ * partition is the region's default, general-purpose pool. It always
+ * occupies partitions[0].
+ *
+ * Each partition is described by a struct xe_vram_pool embedded in the
+ * region, so a pointer published during initialization remains valid if a
+ * later split changes the pool's offset and size. A split never changes a
+ * pool's purpose and may only happen before the region's TTM manager is
+ * initialized.
+ *
+ * The device aggregate described below is the only region type that has no
+ * manager and no partitions.
+ *
+ * The id shown below is the VRAM region instance id. For a tile region it
+ * is the id of the tile, which the uAPI relies on. The pair (binding, id)
+ * must uniquely identify a region.
+ *
+ * Partitioned region:
+ * A tile's VRAM region can be split so that a pool dedicated to some purpose,
+ * e.g. kernel-only, gets a range of its own and the default pool keeps the
+ * rest. The dedicated partition is carved out at the start of the region, at
+ * the lowest addresses, and takes the next free index. The default partition
+ * keeps index 0 and is moved above the dedicated range. A tile without such
+ * a reservation keeps one partition spanning the whole usable range::
+ *
+ *         xe_vram_region "tile0" (VRAM region id 0, binding TILE)
+ *         ,-------------------------------------------------------------.
+ *         | ttm: struct xe_ttm_vram_mgr (one manager, shared)           |
+ *         | .---------------------------------------------------------. |
+ *         | |  partitions[1]            |  partitions[0]              | |
+ *         | |  offset 0                 |  offset pool_size           | |
+ *         | |  size   pool_size         |  size   usable - pool_size  | |
+ *         | `---------------------------------------------------------' |
+ *         `-------------------------------------------------------------'
+ *                  ^                               ^
+ *                  |                               |
+ *             dedicated pool                  general-purpose pool
+ *
+ *         xe_vram_region "tile1" (VRAM region id 1, binding TILE)
+ *         ,-------------------------------------------------------------.
+ *         | ttm: struct xe_ttm_vram_mgr (one manager)                   |
+ *         | .---------------------------------------------------------. |
+ *         | |  partitions[0]                                          | |
+ *         | |  offset 0                                               | |
+ *         | |  size   whole usable range                              | |
+ *         | `---------------------------------------------------------' |
+ *         `-------------------------------------------------------------'
+ *                                     ^
+ *                                     |
+ *                            general-purpose pool
+ *
+ * Device aggregate:
+ * A device-level aggregate region is unrelated to the tile regions. It is
+ * never backed by a resource manager and has no partitions. It only
+ * aggregates the sizes and DPA ranges of every tile for reporting purposes.
+ * Nothing is ever allocated from it::
+ *
+ *         xe_vram_region "device" (VRAM region id 0, binding DEVICE)
+ *         ,-------------------------------------------------------------.
+ *         | ttm:        unused, not backed by any resource manager      |
+ *         | partitions: none, this region is never allocated from       |
+ *         | size:       total VRAM summed across all tiles              |
+ *         `-------------------------------------------------------------'
+ */
+
+/**
+ * struct xe_vram_pool - VRAM range used for a given allocation purpose
+ *
+ * VRAM allocations are placed through this frontend. It identifies an
+ * allocation purpose and resolves it to a TTM placement and the address
+ * range serving it. Whether that range is a whole region of its own - and
+ * thus has its own placement, mapping and address range - or one of several
+ * partitions of a region is a backend detail the allocation paths do not
+ * need to know, see xe_vram_pool_place().
+ *
+ * A pool stays valid for the lifetime of its region and its purpose is fixed
+ * once published.
+ */
+struct xe_vram_pool {
+	/** @region: region this pool belongs to */
+	struct xe_vram_region *region;
+	/**
+	 * @part: TTM partition backing this pool, or NULL until the manager
+	 * is initialized
+	 */
+	struct xe_ttm_vram_mgr_part *part;
+	/** @offset: byte offset of the pool from the start of @region */
+	u64 offset;
+	/** @size: size of the pool in bytes */
+	u64 size;
+	/** @purpose: allocation purpose served by this pool */
+	enum xe_vram_pool_purpose purpose;
+};
+
 /**
  * struct xe_vram_region - memory region structure
  * This is used to describe a memory region in xe
@@ -26,9 +162,11 @@ struct xe_vram_region {
 	/**
 	 * @id: VRAM region instance id
 	 *
-	 * The value should be unique for VRAM region.
+	 * The pair (@binding, @id) must uniquely identify a VRAM region.
 	 */
 	u8 id;
+	/** @binding: VRAM region instance binding */
+	enum xe_vram_binding binding;
 	/** @io_start: IO start address of this VRAM instance */
 	resource_size_t io_start;
 	/**
@@ -57,6 +195,25 @@ struct xe_vram_region {
 	 * (e.g stolen mem)
 	 */
 	resource_size_t actual_physical_size;
+	/**
+	 * @partitions: partitions this region is split into
+	 *
+	 * A non-aggregate region initially has @partitions[0] spanning its
+	 * whole usable range. It is the region's default, general-purpose
+	 * pool. An optional split may adjust its range and create another
+	 * partition before the TTM resource manager is initialized.
+	 *
+	 * A device aggregate region has no partitions. Allocation paths do
+	 * not take a region pointer, they take a &xe_vram_pool pointing into
+	 * this array, see the DOC above.
+	 */
+	struct xe_vram_pool partitions[XE_VRAM_MAX_PARTITIONS];
+	/**
+	 * @num_partitions: number of valid entries in @partitions
+	 *
+	 * Zero for a device aggregate region.
+	 */
+	unsigned int num_partitions;
 	/** @mapping: pointer to VRAM mappable space */
 	void __iomem *mapping;
 	/** @ttm: VRAM TTM manager */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v1 3/7] drm/xe/vram: Make VRAM pools the allocation handle
  2026-10-02 10:40 [PATCH v1 0/7] Introduce purpose-specific VRAM pools Piórkowski, Piotr
  2026-10-02 10:40 ` [PATCH v1 1/7] drm/xe: Define partitioned VRAM manager types Piórkowski, Piotr
  2026-10-02 10:40 ` [PATCH v1 2/7] drm/xe: Define VRAM regions and pools Piórkowski, Piotr
@ 2026-10-02 10:40 ` Piórkowski, Piotr
  2026-10-02 10:53   ` sashiko-bot
  2026-10-02 10:40 ` [PATCH v1 4/7] drm/xe/ttm: Back each VRAM pool with its own buddy allocator Piórkowski, Piotr
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 11+ messages in thread
From: Piórkowski, Piotr @ 2026-10-02 10:40 UTC (permalink / raw)
  To: intel-xe; +Cc: Piotr Piórkowski

From: Piotr Piórkowski <piotr.piorkowski@intel.com>

Allocation paths take a struct xe_vram_pool instead of a struct
xe_vram_region, so that a region can later be split into several pools
without touching every consumer again.

A pool resolves to a TTM placement through xe_vram_pool_place(), which
only ever narrows the page range of the placement, so that it composes
with a caller supplied range such as the CPU visible window of a small
BAR. Fixed placements apply it as well and fail if the requested range
does not intersect the pool.

BO creation and BO migration both resolve the pool serving the purpose
of an allocation through the pools the tile publishes, so they cannot
disagree on where an allocation of a given purpose goes. The PF queries
the free VRAM of the pool backing VF LMEM.

Every region still has exactly one pool spanning its whole usable range,
and the kernel pool of a tile is its general-purpose pool, so there is no
functional change.

Assisted-by: Claude Opus 5.5
Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
---
 drivers/gpu/drm/xe/display/xe_fb_pin.c        |   2 +-
 drivers/gpu/drm/xe/display/xe_initial_plane.c |   2 +-
 drivers/gpu/drm/xe/display/xe_panic.c         |   4 +-
 .../xe/tests/xe_gt_sriov_pf_config_kunit.c    |   8 +-
 drivers/gpu/drm/xe/xe_assert.h                |   3 +-
 drivers/gpu/drm/xe/xe_bo.c                    |  86 +++++---
 drivers/gpu/drm/xe/xe_bo.h                    |   2 +-
 drivers/gpu/drm/xe/xe_debugfs.c               |   2 +-
 drivers/gpu/drm/xe/xe_device.c                |   2 +-
 drivers/gpu/drm/xe/xe_device_types.h          |   2 +-
 drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c    |   7 +-
 drivers/gpu/drm/xe/xe_migrate.c               |   2 +-
 drivers/gpu/drm/xe/xe_pagefault.c             |   2 +-
 drivers/gpu/drm/xe/xe_query.c                 |   6 +-
 drivers/gpu/drm/xe/xe_svm.c                   |   2 +-
 drivers/gpu/drm/xe/xe_tile.c                  |  22 +--
 drivers/gpu/drm/xe/xe_tile.h                  |   6 +-
 drivers/gpu/drm/xe/xe_tile_debugfs.c          |   4 +-
 drivers/gpu/drm/xe/xe_tile_types.h            |   8 +-
 drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c        |   2 +-
 drivers/gpu/drm/xe/xe_ttm_vram_mgr.c          |  32 ++-
 drivers/gpu/drm/xe/xe_ttm_vram_mgr.h          |   3 +-
 drivers/gpu/drm/xe/xe_vram.c                  | 185 ++++++++++++++++--
 drivers/gpu/drm/xe/xe_vram.h                  |  13 +-
 24 files changed, 306 insertions(+), 101 deletions(-)

diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c
index 15fbd3fe6cbb7..9a3f14d358d24 100644
--- a/drivers/gpu/drm/xe/display/xe_fb_pin.c
+++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c
@@ -322,7 +322,7 @@ static struct i915_vma *__xe_pin_fb_vma(struct drm_gem_object *obj, bool is_dpt,
 	if (IS_DGFX(to_xe_device(bo->ttm.base.dev)) &&
 	    pin_params->needs_cpu_lmem_access &&
 	    !(bo->flags & XE_BO_FLAG_NEEDS_CPU_ACCESS)) {
-		struct xe_vram_region *vram = xe_device_get_root_tile(xe)->mem.vram;
+		struct xe_vram_region *vram = xe_device_get_root_tile(xe)->mem.vram->region;
 
 		/*
 		 * If we need to able to access the clear-color value stored in
diff --git a/drivers/gpu/drm/xe/display/xe_initial_plane.c b/drivers/gpu/drm/xe/display/xe_initial_plane.c
index 0f86b73036d03..971d9c78dd089 100644
--- a/drivers/gpu/drm/xe/display/xe_initial_plane.c
+++ b/drivers/gpu/drm/xe/display/xe_initial_plane.c
@@ -73,7 +73,7 @@ initial_plane_bo(struct xe_device *xe,
 		 * We don't currently expect this to ever be placed in the
 		 * stolen portion.
 		 */
-		if (phys_base >= xe_vram_region_usable_size(tile0->mem.vram)) {
+		if (phys_base >= xe_vram_region_usable_size(tile0->mem.vram->region)) {
 			drm_err(&xe->drm,
 				"Initial plane programming using invalid range, phys_base=%pa\n",
 				&phys_base);
diff --git a/drivers/gpu/drm/xe/display/xe_panic.c b/drivers/gpu/drm/xe/display/xe_panic.c
index 1a6cee25e9d76..b223ae8fc0209 100644
--- a/drivers/gpu/drm/xe/display/xe_panic.c
+++ b/drivers/gpu/drm/xe/display/xe_panic.c
@@ -52,7 +52,7 @@ static void xe_panic_page_set_pixel(struct drm_scanout_buffer *sb, unsigned int
 	if (new_page != panic->page) {
 		if (xe_bo_is_vram(bo)) {
 			/* Display is always mapped on root tile */
-			struct xe_vram_region *vram =
+			struct xe_vram_pool *vram =
 				xe_device_get_root_tile(xe_bo_device(bo))->mem.vram;
 
 			if (panic->page < 0 || new_page < panic->page) {
@@ -62,7 +62,7 @@ static void xe_panic_page_set_pixel(struct drm_scanout_buffer *sb, unsigned int
 				xe_res_next(&panic->res, PAGE_SIZE * (new_page - panic->page));
 			}
 			iosys_map_set_vaddr_iomem(&panic->vmap,
-						  vram->mapping + panic->res.start);
+						  vram->region->mapping + panic->res.start);
 		} else {
 			xe_panic_kunmap(panic);
 			iosys_map_set_vaddr(&panic->vmap,
diff --git a/drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_config_kunit.c b/drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_config_kunit.c
index e6eaa94d4d30f..2c67413b6acd4 100644
--- a/drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_config_kunit.c
+++ b/drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_config_kunit.c
@@ -44,8 +44,8 @@ static void pf_set_usable_vram(struct xe_device *xe, u64 usable)
 
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, tile);
 	xe->mem.vram->usable_size = usable;
-	tile->mem.vram->usable_size = usable;
-	KUNIT_ASSERT_EQ(test, usable, xe_vram_region_usable_size(tile->mem.vram));
+	tile->mem.vram->size = usable;
+	KUNIT_ASSERT_EQ(test, usable, xe_vram_pool_usable_size(tile->mem.vram));
 }
 
 static const void *num_vfs_gen_param(struct kunit *test, const void *prev, char *desc)
@@ -86,8 +86,10 @@ static int pf_gt_config_test_init(struct kunit *test)
 	vram = kunit_kzalloc(test, sizeof(*vram), GFP_KERNEL);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vram);
 	vram->usable_size = TEST_VRAM;
+	vram->partitions[0] = (struct xe_vram_pool) { .region = vram, .size = TEST_VRAM };
+	vram->num_partitions = 1;
 	xe->mem.vram = vram;
-	xe->tiles[0].mem.vram = vram;
+	xe->tiles[0].mem.vram = &vram->partitions[0];
 
 	/* pretend we have a valid LMTT */
 	KUNIT_ASSERT_TRUE(test, xe_device_has_lmtt(xe));
diff --git a/drivers/gpu/drm/xe/xe_assert.h b/drivers/gpu/drm/xe/xe_assert.h
index a818eaa05b7dc..010778c9ad1f1 100644
--- a/drivers/gpu/drm/xe/xe_assert.h
+++ b/drivers/gpu/drm/xe/xe_assert.h
@@ -147,7 +147,8 @@
 	char __buf[10] __maybe_unused;								\
 	xe_assert_msg(tile_to_xe(__tile), condition, "tile: %u VRAM %s\n" msg,			\
 		      __tile->id, ({ string_get_size(						\
-				     xe_vram_region_actual_physical_size(__tile->mem.vram), 1,	\
+				     xe_vram_region_actual_physical_size(			\
+					__tile->mem.vram->region), 1,				\
 				     STRING_UNITS_2, __buf, sizeof(__buf)); __buf; }), ## arg);	\
 })
 
diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index 6921b6967330d..b8a371a74e2d8 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -224,33 +224,53 @@ static u8 vram_bo_flag_to_tile_id(struct xe_device *xe, u32 vram_bo_flag)
 	return __ffs(vram_bo_flag >> (__ffs(XE_BO_FLAG_VRAM0) - 1)) - 1;
 }
 
-static u32 bo_vram_flags_to_vram_placement(struct xe_device *xe, u32 bo_flags, u32 vram_flag,
-					   enum ttm_bo_type type)
+static enum xe_vram_pool_purpose bo_vram_purpose(u32 bo_flags, enum ttm_bo_type type)
 {
-	u8 tile_id = vram_bo_flag_to_tile_id(xe, vram_flag);
+	return type == ttm_bo_type_kernel && !(bo_flags & XE_BO_FLAG_FORCE_USER_VRAM) ?
+		XE_VRAM_POOL_KERNEL : XE_VRAM_POOL_GENERAL;
+}
 
-	xe_assert(xe, tile_id < xe->info.tile_count);
+/* BO creation and migration both resolve the pool of a purpose through here */
+static struct xe_vram_pool *tile_vram_pool(struct xe_tile *tile,
+					   enum xe_vram_pool_purpose purpose)
+{
+	return purpose == XE_VRAM_POOL_KERNEL ? tile->mem.kernel_vram : tile->mem.vram;
+}
 
-	if (type == ttm_bo_type_kernel && !(bo_flags & XE_BO_FLAG_FORCE_USER_VRAM))
-		return xe->tiles[tile_id].mem.kernel_vram->placement;
-	else
-		return xe->tiles[tile_id].mem.vram->placement;
+static struct xe_vram_pool *bo_vram_pool(struct xe_device *xe, u32 bo_flags,
+					 u32 vram_flag, enum ttm_bo_type type)
+{
+	struct xe_tile *tile = &xe->tiles[vram_bo_flag_to_tile_id(xe, vram_flag)];
+
+	return tile_vram_pool(tile, bo_vram_purpose(bo_flags, type));
 }
 
-static void add_vram(struct xe_device *xe, struct xe_bo *bo,
-		     struct ttm_place *places, u32 bo_flags, u32 mem_type, u32 *c)
+static struct xe_vram_region *ttm_manager_to_vram_region(struct ttm_resource_manager *man)
 {
-	struct ttm_place place = { .mem_type = mem_type };
-	struct ttm_resource_manager *mgr = ttm_manager_type(&xe->ttm, mem_type);
-	struct xe_ttm_vram_mgr *vram_mgr = to_xe_ttm_vram_mgr(mgr);
+	return container_of(to_xe_ttm_vram_mgr(man), struct xe_vram_region, ttm);
+}
 
-	struct xe_vram_region *vram;
+static struct xe_vram_pool *region_vram_pool(struct xe_vram_region *vram,
+					     enum xe_vram_pool_purpose purpose)
+{
+	struct xe_vram_pool *pool = tile_vram_pool(&vram->xe->tiles[vram->id], purpose);
+
+	xe_assert(vram->xe, pool->region == vram);
+
+	return pool;
+}
+
+static void add_vram(struct xe_device *xe, struct xe_bo *bo,
+		     struct ttm_place *places, u32 bo_flags,
+		     struct xe_vram_pool *pool, u32 *c)
+{
+	struct xe_vram_region *vram = pool->region;
+	struct ttm_place place = {};
 	u64 io_size;
 
 	xe_assert(xe, *c < ARRAY_SIZE(bo->placements));
 
-	vram = container_of(vram_mgr, struct xe_vram_region, ttm);
-	xe_assert(xe, vram && vram->usable_size);
+	xe_assert(xe, vram->usable_size);
 	io_size = vram->io_size;
 
 	if (force_contiguous(bo_flags))
@@ -264,20 +284,31 @@ static void add_vram(struct xe_device *xe, struct xe_bo *bo,
 			place.flags |= TTM_PL_FLAG_TOPDOWN;
 		}
 	}
+
+	xe_vram_pool_place(pool, &place);
 	places[*c] = place;
 	*c += 1;
 }
 
+static void xe_bo_set_vram_place(struct xe_device *xe, struct xe_bo *bo,
+				 struct ttm_place *place, u32 mem_type)
+{
+	struct ttm_resource_manager *man = ttm_manager_type(&xe->ttm, mem_type);
+	struct xe_vram_region *vram = ttm_manager_to_vram_region(man);
+	enum xe_vram_pool_purpose purpose = bo_vram_purpose(bo->flags, bo->ttm.type);
+	u32 c = 0;
+
+	add_vram(xe, bo, place, bo->flags, region_vram_pool(vram, purpose), &c);
+}
+
 static void try_add_vram(struct xe_device *xe, struct xe_bo *bo,
 			 u32 bo_flags, enum ttm_bo_type type, u32 *c)
 {
 	u32 vram_flag;
 
-	for_each_set_bo_vram_flag(vram_flag, bo_flags) {
-		u32 pl = bo_vram_flags_to_vram_placement(xe, bo_flags, vram_flag, type);
-
-		add_vram(xe, bo, bo->placements, bo_flags, pl, c);
-	}
+	for_each_set_bo_vram_flag(vram_flag, bo_flags)
+		add_vram(xe, bo, bo->placements, bo_flags,
+			 bo_vram_pool(xe, bo_flags, vram_flag, type), c);
 }
 
 static void try_add_stolen(struct xe_device *xe, struct xe_bo *bo,
@@ -2519,10 +2550,13 @@ static int __xe_bo_fixed_placement(struct xe_device *xe,
 	place->fpfn = start >> PAGE_SHIFT;
 	place->lpfn = end >> PAGE_SHIFT;
 
-	if (flags & XE_BO_FLAG_STOLEN)
+	if (flags & XE_BO_FLAG_STOLEN) {
 		place->mem_type = XE_PL_STOLEN;
-	else
-		place->mem_type = bo_vram_flags_to_vram_placement(xe, flags, vram_flag, type);
+	} else {
+		xe_vram_pool_place(bo_vram_pool(xe, flags, vram_flag, type), place);
+		if (place->lpfn && place->fpfn >= place->lpfn)
+			return -EINVAL;
+	}
 
 	bo->placement = (struct ttm_placement) {
 		.num_placement = 1,
@@ -3915,9 +3949,7 @@ int xe_bo_migrate(struct xe_bo *bo, u32 mem_type, struct ttm_operation_ctx *tctx
 	drm_WARN_ON(&xe->drm, mem_type == XE_PL_STOLEN);
 
 	if (mem_type_is_vram(mem_type)) {
-		u32 c = 0;
-
-		add_vram(xe, bo, &requested, bo->flags, mem_type, &c);
+		xe_bo_set_vram_place(xe, bo, &requested, mem_type);
 	}
 
 	if (!tctx->no_wait_gpu)
diff --git a/drivers/gpu/drm/xe/xe_bo.h b/drivers/gpu/drm/xe/xe_bo.h
index 861b1be231ded..f93e22573985e 100644
--- a/drivers/gpu/drm/xe/xe_bo.h
+++ b/drivers/gpu/drm/xe/xe_bo.h
@@ -31,7 +31,7 @@
 #define XE_BO_FLAG_STOLEN		BIT(4)
 #define XE_BO_FLAG_VRAM(vram)		(XE_BO_FLAG_VRAM0 << ((vram)->id))
 #define XE_BO_FLAG_VRAM_IF_DGFX(tile)	(IS_DGFX(tile_to_xe(tile)) ? \
-					 XE_BO_FLAG_VRAM((tile)->mem.vram) : \
+					 XE_BO_FLAG_VRAM((tile)->mem.vram->region) : \
 					 XE_BO_FLAG_SYSTEM)
 #define XE_BO_FLAG_GGTT			BIT(5)
 #define XE_BO_FLAG_IGNORE_MIN_PAGE_SIZE BIT(6)
diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c
index 80f62634fae50..42c250bbea8d5 100644
--- a/drivers/gpu/drm/xe/xe_debugfs.c
+++ b/drivers/gpu/drm/xe/xe_debugfs.c
@@ -99,7 +99,7 @@ static ssize_t inject_mempage_offline_trigger(struct file *f,
 {
 	struct xe_device *xe = file_inode(f)->i_private;
 	struct xe_tile *tile = xe_device_get_root_tile(xe);
-	struct xe_vram_region *vr = tile->mem.vram;
+	struct xe_vram_region *vr = tile->mem.vram->region;
 	u64 pfn;
 	int ret;
 
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 8392c9fad3c48..2be96d86f4bee 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -689,7 +689,7 @@ static int xe_device_vram_alloc(struct xe_device *xe)
 	if (!IS_DGFX(xe))
 		return 0;
 
-	vram = drmm_kzalloc(&xe->drm, sizeof(*vram), GFP_KERNEL);
+	vram = xe_vram_region_alloc_device(xe);
 	if (!vram)
 		return -ENOMEM;
 
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 41f703a879169..bc6e9c30cf9f6 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -303,7 +303,7 @@ struct xe_device {
 
 	/** @mem: memory info for device */
 	struct {
-		/** @mem.vram: VRAM info for device */
+		/** @mem.vram: device level VRAM region aggregating all tiles */
 		struct xe_vram_region *vram;
 		/** @mem.sys_mgr: system TTM manager */
 		struct ttm_resource_manager sys_mgr;
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
index 6947aeed458ed..95d3e0e3357df 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
@@ -1715,7 +1715,7 @@ static int pf_provision_vf_lmem(struct xe_gt *gt, unsigned int vfid, u64 size)
 	bo = xe_bo_create_pin_range_novm(xe, tile,
 					 ALIGN(size, PAGE_SIZE), 0, ~0ull,
 					 ttm_bo_type_kernel,
-					 XE_BO_FLAG_VRAM(tile->mem.vram) |
+					 XE_BO_FLAG_VRAM(tile->mem.vram->region) |
 					 (alignment == SZ_2M ? XE_BO_FLAG_NEEDS_2M : 0) |
 					 XE_BO_FLAG_PINNED |
 					 XE_BO_FLAG_PINNED_LATE_RESTORE |
@@ -1926,7 +1926,8 @@ static u64 pf_query_free_lmem(struct xe_gt *gt)
 {
 	struct xe_tile *tile = gt->tile;
 
-	return xe_ttm_vram_get_avail(&tile->mem.vram->ttm.manager);
+	/* Only the general-purpose pool can back VF LMEM, see pf_provision_vf_lmem() */
+	return xe_ttm_vram_get_pool_avail(tile->mem.vram);
 }
 
 static u64 pf_query_max_lmem(struct xe_gt *gt)
@@ -1967,7 +1968,7 @@ static u64 pf_profile_fair_lmem(struct xe_gt *gt, unsigned int num_vfs)
 {
 	struct xe_tile *tile = gt_to_tile(gt);
 	bool admin_only_pf = xe_sriov_pf_admin_only(tile->xe);
-	u64 usable = xe_vram_region_usable_size(tile->mem.vram);
+	u64 usable = xe_vram_pool_usable_size(tile->mem.vram);
 	u64 spare = pf_get_min_spare_lmem(gt);
 	u64 available = usable > spare ? usable - spare : 0;
 	u64 shareable = ALIGN_DOWN(available, SZ_1G);
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index fffb3eb6c76eb..6000c1f6dc765 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -2596,7 +2596,7 @@ int xe_migrate_debug_ccs_overlap(struct xe_migrate *m,
 	if (!xe_device_has_flat_ccs(xe))
 		return -EINVAL;
 
-	first_page_dpa = xe_vram_region_dpa_base(m->tile->mem.vram);
+	first_page_dpa = xe_vram_region_dpa_base(m->tile->mem.vram->region);
 	clear_L0_ofs = xe_migrate_vram_ofs(xe, first_page_dpa, true);
 
 	scratch_dpa = xe_bo_addr(scratch_bo, 0, XE_PAGE_SIZE);
diff --git a/drivers/gpu/drm/xe/xe_pagefault.c b/drivers/gpu/drm/xe/xe_pagefault.c
index 5247321c805ec..2daaf3182204c 100644
--- a/drivers/gpu/drm/xe/xe_pagefault.c
+++ b/drivers/gpu/drm/xe/xe_pagefault.c
@@ -201,7 +201,7 @@ static int xe_pagefault_handle_vma(struct xe_gt *gt, struct xe_vma *vma,
 		xe_validation_ctx_init(&ctx, &vm->xe->val, &exec,
 				       (struct xe_val_flags) {});
 		drm_exec_until_all_locked(&exec) {
-			err = xe_pagefault_begin(&exec, vma, tile->mem.vram,
+			err = xe_pagefault_begin(&exec, vma, tile->mem.vram->region,
 						 needs_vram == 1);
 			drm_exec_retry_on_contention(&exec);
 			xe_validation_retry_on_oom(&ctx, &err);
diff --git a/drivers/gpu/drm/xe/xe_query.c b/drivers/gpu/drm/xe/xe_query.c
index dc975f5953683..0692ec93f55d2 100644
--- a/drivers/gpu/drm/xe/xe_query.c
+++ b/drivers/gpu/drm/xe/xe_query.c
@@ -414,12 +414,16 @@ static int query_gt_list(struct xe_device *xe, struct drm_xe_device_query *query
 		 * However the uAPI is generic and it's userspace's
 		 * responsibility to check the mem_class, without any
 		 * assumption.
+		 *
+		 * Only the general-purpose VRAM region of a tile is ever
+		 * exposed, and there is exactly one of them per tile, so its
+		 * region id doubles as the tile index here.
 		 */
 		if (!IS_DGFX(xe))
 			gt_list->gt_list[iter].near_mem_regions = 0x1;
 		else
 			gt_list->gt_list[iter].near_mem_regions =
-				BIT(gt_to_tile(gt)->mem.vram->id) << 1;
+				BIT(gt_to_tile(gt)->mem.vram->region->id) << 1;
 		gt_list->gt_list[iter].far_mem_regions = xe->info.mem_region_mask ^
 			gt_list->gt_list[iter].near_mem_regions;
 
diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
index 909a602d091ea..7f58240b0b5b4 100644
--- a/drivers/gpu/drm/xe/xe_svm.c
+++ b/drivers/gpu/drm/xe/xe_svm.c
@@ -2112,7 +2112,7 @@ int xe_pagemap_cache_create(struct xe_tile *tile)
 		if (IS_ERR(cache))
 			return PTR_ERR(cache);
 
-		tile->mem.vram->dpagemap_cache = cache;
+		tile->mem.vram->region->dpagemap_cache = cache;
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/xe/xe_tile.c b/drivers/gpu/drm/xe/xe_tile.c
index 74d925a337b76..a916121177ba7 100644
--- a/drivers/gpu/drm/xe/xe_tile.c
+++ b/drivers/gpu/drm/xe/xe_tile.c
@@ -119,20 +119,12 @@ int xe_tile_alloc_vram(struct xe_tile *tile)
 	if (!IS_DGFX(xe))
 		return 0;
 
-	vram = xe_vram_region_alloc(xe, tile->id, XE_PL_VRAM0 + tile->id);
+	vram = xe_vram_region_alloc_tile(xe, tile->id);
 	if (!vram)
 		return -ENOMEM;
-	tile->mem.vram = vram;
+	tile->mem.vram = xe_vram_region_default_pool(vram);
 
-	/*
-	 * If the kernel_vram is not already allocated,
-	 * it means that tile has common VRAM region for
-	 * kernel and user space.
-	 */
-	if (!tile->mem.kernel_vram)
-		tile->mem.kernel_vram = tile->mem.vram;
-
-	return 0;
+	return xe_vram_tile_alloc_kernel(tile);
 }
 
 /**
@@ -190,12 +182,14 @@ int xe_tile_init_noalloc(struct xe_tile *tile)
 	if (err)
 		return err;
 
-	if (IS_DGFX(xe) && !ttm_resource_manager_used(&tile->mem.vram->ttm.manager)) {
-		err = xe_ttm_vram_mgr_init(xe, tile->mem.vram);
+	if (IS_DGFX(xe) && !ttm_resource_manager_used(&tile->mem.vram->region->ttm.manager)) {
+		err = xe_ttm_vram_mgr_init(xe, tile->mem.vram->region);
 		if (err)
 			return err;
 
-		xe->info.mem_region_mask |= BIT(tile->mem.vram->id) << 1;
+		/* The uAPI indexes the general-purpose region of a tile by tile id */
+		xe_assert(xe, tile->mem.vram->region->id == tile->id);
+		xe->info.mem_region_mask |= BIT(tile->mem.vram->region->id) << 1;
 	}
 
 	return xe_tile_sysfs_init(tile);
diff --git a/drivers/gpu/drm/xe/xe_tile.h b/drivers/gpu/drm/xe/xe_tile.h
index a2a2c0e936b8e..63c92372bfc80 100644
--- a/drivers/gpu/drm/xe/xe_tile.h
+++ b/drivers/gpu/drm/xe/xe_tile.h
@@ -7,6 +7,7 @@
 #define _XE_TILE_H_
 
 #include "xe_tile_types.h"
+#include "xe_vram_types.h"
 
 struct xe_device;
 struct xe_pagemap;
@@ -29,11 +30,12 @@ static inline bool xe_tile_is_root(struct xe_tile *tile)
  * struct xe_tile pointer
  * @tile: Pointer to the struct xe_tile.
  *
- * Return: Pointer to the struct xe_vram_region embedded in *@tile.
+ * Return: Pointer to the struct xe_vram_region backing *@tile's general
+ * purpose VRAM pool.
  */
 static inline struct xe_vram_region *xe_tile_to_vr(struct xe_tile *tile)
 {
-	return tile->mem.vram;
+	return tile->mem.vram->region;
 }
 
 #if IS_ENABLED(CONFIG_DRM_XE_PAGEMAP)
diff --git a/drivers/gpu/drm/xe/xe_tile_debugfs.c b/drivers/gpu/drm/xe/xe_tile_debugfs.c
index 5df2f461b7b7a..b69f4521eed35 100644
--- a/drivers/gpu/drm/xe/xe_tile_debugfs.c
+++ b/drivers/gpu/drm/xe/xe_tile_debugfs.c
@@ -109,8 +109,8 @@ static const struct drm_info_list vf_safe_debugfs_list[] = {
 static void tile_debugfs_create_vram_mm(struct xe_tile *tile)
 {
 	if (tile->mem.vram)
-		ttm_resource_manager_create_debugfs(&tile->mem.vram->ttm.manager, tile->debugfs,
-						    "vram_mm");
+		ttm_resource_manager_create_debugfs(&tile->mem.vram->region->ttm.manager,
+						    tile->debugfs, "vram_mm");
 }
 
 /**
diff --git a/drivers/gpu/drm/xe/xe_tile_types.h b/drivers/gpu/drm/xe/xe_tile_types.h
index e1368c04846ae..f2497828c4aae 100644
--- a/drivers/gpu/drm/xe/xe_tile_types.h
+++ b/drivers/gpu/drm/xe/xe_tile_types.h
@@ -66,20 +66,20 @@ struct xe_tile {
 	/** @mem: memory management info for tile */
 	struct {
 		/**
-		 * @mem.kernel_vram: kernel-dedicated VRAM info for tile.
+		 * @mem.kernel_vram: kernel-dedicated VRAM pool for tile.
 		 *
 		 * Although VRAM is associated with a specific tile, it can
 		 * still be accessed by all tiles' GTs.
 		 */
-		struct xe_vram_region *kernel_vram;
+		struct xe_vram_pool *kernel_vram;
 
 		/**
-		 * @mem.vram: general purpose VRAM info for tile.
+		 * @mem.vram: general purpose VRAM pool for tile.
 		 *
 		 * Although VRAM is associated with a specific tile, it can
 		 * still be accessed by all tiles' GTs.
 		 */
-		struct xe_vram_region *vram;
+		struct xe_vram_pool *vram;
 
 		/** @mem.ggtt: Global graphics translation table */
 		struct xe_ggtt *ggtt;
diff --git a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c
index 60f39efb02d05..38a20307f49d6 100644
--- a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c
+++ b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c
@@ -63,7 +63,7 @@ static u32 get_wopcm_size(struct xe_device *xe)
 
 static u64 detect_lmembar_dgfx(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr)
 {
-	struct xe_vram_region *tile_vram = xe_device_get_root_tile(xe)->mem.vram;
+	struct xe_vram_region *tile_vram = xe_device_get_root_tile(xe)->mem.vram->region;
 	resource_size_t tile_io_start = xe_vram_region_io_start(tile_vram);
 	struct xe_mmio *mmio = xe_root_tile_mmio(xe);
 	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
index 9a514d983e90b..c9a28fad7c069 100644
--- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
+++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
@@ -27,6 +27,7 @@
 #include "xe_res_cursor.h"
 #include "xe_ttm_stolen_mgr.h"
 #include "xe_ttm_vram_mgr.h"
+#include "xe_vram.h"
 #include "xe_vram_types.h"
 
 static inline struct gpu_buddy_block *
@@ -507,7 +508,7 @@ int xe_ttm_vram_mgr_alloc_sgt(struct xe_device *xe,
 			      enum dma_data_direction dir,
 			      struct sg_table **sgt)
 {
-	struct xe_tile *tile = &xe->tiles[res->mem_type - XE_PL_VRAM0];
+	struct xe_vram_region *vram = xe_map_resource_to_region(res);
 	struct xe_ttm_vram_mgr_resource *vres = to_xe_ttm_vram_mgr_resource(res);
 	struct xe_res_cursor cursor;
 	struct scatterlist *sg;
@@ -545,7 +546,7 @@ int xe_ttm_vram_mgr_alloc_sgt(struct xe_device *xe,
 	 */
 	xe_res_first(res, offset, length, &cursor);
 	for_each_sgtable_sg((*sgt), sg, i) {
-		phys_addr_t phys = cursor.start + xe_vram_region_io_start(tile->mem.vram);
+		phys_addr_t phys = cursor.start + xe_vram_region_io_start(vram);
 		size_t size = min_t(u64, cursor.size, SZ_2G);
 		dma_addr_t addr;
 
@@ -612,13 +613,20 @@ void xe_ttm_vram_get_used(struct ttm_resource_manager *man,
 	mutex_unlock(&mgr->lock);
 }
 
-u64 xe_ttm_vram_get_avail(struct ttm_resource_manager *man)
+/**
+ * xe_ttm_vram_get_pool_avail - Free memory of a VRAM pool
+ * @pool: The VRAM pool, its region's TTM manager must be initialized
+ *
+ * Return: the number of bytes still available for allocation from @pool.
+ */
+u64 xe_ttm_vram_get_pool_avail(struct xe_vram_pool *pool)
 {
-	struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
+	struct xe_ttm_vram_mgr *mgr = &pool->region->ttm;
 	u64 avail;
 
+	/* A pool still spans the whole region of its manager */
 	mutex_lock(&mgr->lock);
-	avail =  mgr->mm.avail;
+	avail = mgr->mm.avail;
 	mutex_unlock(&mgr->lock);
 
 	return avail;
@@ -864,11 +872,13 @@ static struct xe_vram_region *xe_ttm_vram_addr_to_region(struct xe_device *xe, u
 	u8 id;
 
 	for_each_tile(tile, xe, id) {
-		struct xe_vram_region *vr = tile->mem.vram;
+		struct xe_vram_region *vr;
 
-		if (!vr)
+		if (!tile->mem.vram)
 			continue;
 
+		vr = tile->mem.vram->region;
+
 		if (addr >= vr->dpa_base && addr < (vr->dpa_base + vr->usable_size))
 			return vr;
 
@@ -963,7 +973,7 @@ EXPORT_SYMBOL(xe_ttm_vram_handle_addr_fault);
 int xe_ttm_vram_inject_fault(struct xe_device *xe)
 {
 	struct xe_tile *tile = xe_device_get_root_tile(xe);
-	struct xe_vram_region *vr = tile->mem.vram;
+	struct xe_vram_region *vr = tile->mem.vram->region;
 	struct xe_ttm_vram_mgr *vram_mgr = &vr->ttm;
 	struct gpu_buddy *mm = &vram_mgr->mm;
 	u64 addr;
@@ -1018,11 +1028,13 @@ static int vram_bad_pages_show(struct seq_file *m, void *unused)
 			   to_xe_ttm_vram_mgr(man)->max_pages);
 
 	for_each_tile(tile, xe, id) {
-		struct xe_vram_region *vr = tile->mem.vram;
+		struct xe_vram_region *vr;
 
 		man = ttm_manager_type(&xe->ttm, XE_PL_VRAM0 + id);
-		if (!man || !vr)
+		if (!man || !tile->mem.vram)
 			continue;
+
+		vr = tile->mem.vram->region;
 		mgr = to_xe_ttm_vram_mgr(man);
 
 		rcu_read_lock();
diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.h b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.h
index d77f067d197b2..6cf8217ec46b5 100644
--- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.h
+++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.h
@@ -7,6 +7,7 @@
 #define _XE_TTM_VRAM_MGR_H_
 
 #include "xe_ttm_vram_mgr_types.h"
+#include "xe_vram_types.h"
 
 enum dma_data_direction;
 struct xe_device;
@@ -27,7 +28,7 @@ int xe_ttm_vram_mgr_alloc_sgt(struct xe_device *xe,
 void xe_ttm_vram_mgr_free_sgt(struct device *dev, enum dma_data_direction dir,
 			      struct sg_table *sgt);
 
-u64 xe_ttm_vram_get_avail(struct ttm_resource_manager *man);
+u64 xe_ttm_vram_get_pool_avail(struct xe_vram_pool *pool);
 u64 xe_ttm_vram_get_cpu_visible_size(struct ttm_resource_manager *man);
 void xe_ttm_vram_get_used(struct ttm_resource_manager *man,
 			  u64 *used, u64 *used_visible);
diff --git a/drivers/gpu/drm/xe/xe_vram.c b/drivers/gpu/drm/xe/xe_vram.c
index dcedd8cfd731e..ec95b53bc53b1 100644
--- a/drivers/gpu/drm/xe/xe_vram.c
+++ b/drivers/gpu/drm/xe/xe_vram.c
@@ -27,6 +27,20 @@
 #include "xe_vram.h"
 #include "xe_vram_types.h"
 
+static const char *stringify_vram_binding(enum xe_vram_binding binding)
+{
+	switch (binding) {
+	case XE_VRAM_BINDING_NONE:
+		return "None";
+	case XE_VRAM_BINDING_DEVICE:
+		return "Device";
+	case XE_VRAM_BINDING_TILE:
+		return "Tile";
+	}
+
+	return "Unknown";
+}
+
 static bool resource_is_valid(struct pci_dev *pdev, int bar)
 {
 	if (!pci_resource_flags(pdev, bar))
@@ -198,19 +212,21 @@ static void vram_fini(void *arg)
 
 	xe_assert(xe, !xe->mem.vram->mapping);
 
-	for_each_tile(tile, xe, id) {
-		tile->mem.vram->mapping = NULL;
-		if (tile->mem.kernel_vram)
-			tile->mem.kernel_vram->mapping = NULL;
-	}
+	for_each_tile(tile, xe, id)
+		tile->mem.vram->region->mapping = NULL;
 }
 
-struct xe_vram_region *xe_vram_region_alloc(struct xe_device *xe, u8 id, u32 placement)
+static struct xe_vram_region *vram_region_alloc(struct xe_device *xe,
+						enum xe_vram_binding binding,
+						u8 id, u32 placement)
 {
 	struct xe_vram_region *vram;
 	struct drm_device *drm = &xe->drm;
+	bool tile_bound = binding != XE_VRAM_BINDING_DEVICE;
 
-	xe_assert(xe, id < xe->info.tile_count);
+	xe_assert(xe, binding != XE_VRAM_BINDING_NONE);
+	xe_assert(xe, !tile_bound || id < xe->info.tile_count);
+	xe_assert(xe, !tile_bound || placement >= XE_PL_VRAM0);
 
 	vram = drmm_kzalloc(drm, sizeof(*vram), GFP_KERNEL);
 	if (!vram)
@@ -219,12 +235,82 @@ struct xe_vram_region *xe_vram_region_alloc(struct xe_device *xe, u8 id, u32 pla
 	vram->xe = xe;
 	vram->id = id;
 	vram->placement = placement;
+	vram->binding = binding;
 #if defined(CONFIG_DRM_XE_PAGEMAP)
-	vram->migrate = xe->tiles[id].migrate;
+	if (tile_bound)
+		vram->migrate = xe->tiles[id].migrate;
 #endif
+	if (!tile_bound)
+		return vram;
+
+	/*
+	 * partitions[0] always exists, so its address is a stable handle even
+	 * before vram_region_init() sizes it to span the whole region.
+	 */
+	vram->partitions[0] = (struct xe_vram_pool) {
+		.region = vram,
+		.purpose = XE_VRAM_POOL_GENERAL,
+	};
 	return vram;
 }
 
+/**
+ * xe_vram_region_alloc_device - Allocate the device level VRAM region
+ * @xe: the &xe_device
+ *
+ * The device level region only aggregates the sizes and ranges of all tile
+ * VRAM regions, it is not backed by any TTM resource manager.
+ *
+ * Return: the allocated region, or NULL on failure.
+ */
+struct xe_vram_region *xe_vram_region_alloc_device(struct xe_device *xe)
+{
+	return vram_region_alloc(xe, XE_VRAM_BINDING_DEVICE, 0, 0);
+}
+
+/**
+ * xe_vram_region_alloc_tile - Allocate a general-purpose tile VRAM region
+ * @xe: the &xe_device
+ * @id: tile id
+ *
+ * Return: the allocated region, or NULL on failure.
+ */
+struct xe_vram_region *xe_vram_region_alloc_tile(struct xe_device *xe, u8 id)
+{
+	return vram_region_alloc(xe, XE_VRAM_BINDING_TILE, id, XE_PL_VRAM0 + id);
+}
+
+/**
+ * xe_vram_region_default_pool - Get the default pool of a VRAM region
+ * @vram: the VRAM region, which must not be a device aggregate
+ *
+ * Return: the default pool of @vram.
+ */
+struct xe_vram_pool *xe_vram_region_default_pool(struct xe_vram_region *vram)
+{
+	xe_assert(vram->xe, vram->binding != XE_VRAM_BINDING_DEVICE);
+
+	return &vram->partitions[0];
+}
+
+/**
+ * xe_vram_tile_alloc_kernel - Initialize the kernel VRAM pool of a tile
+ * @tile: the &xe_tile, with its general purpose VRAM pool already allocated
+ *
+ * Kernel allocations use the general-purpose pool by default.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int xe_vram_tile_alloc_kernel(struct xe_tile *tile)
+{
+	if (tile->mem.kernel_vram)
+		return 0;
+
+	tile->mem.kernel_vram = tile->mem.vram;
+
+	return 0;
+}
+
 static void print_vram_region_info(struct xe_device *xe, struct xe_vram_region *vram)
 {
 	struct drm_device *drm = &xe->drm;
@@ -233,17 +319,21 @@ static void print_vram_region_info(struct xe_device *xe, struct xe_vram_region *
 		drm_info(drm, "Small BAR device\n");
 
 	drm_info(drm,
-		 "VRAM[%u]: Actual physical size %pa, usable size exclude stolen %pa, CPU accessible size %pa\n",
-		 vram->id, &vram->actual_physical_size, &vram->usable_size, &vram->io_size);
-	drm_info(drm, "VRAM[%u]: DPA range: [%pa-%llx], io range: [%pa-%llx]\n",
-		 vram->id, &vram->dpa_base, vram->dpa_base + (u64)vram->actual_physical_size,
-		 &vram->io_start, vram->io_start + (u64)vram->io_size);
+		 "%s[%u] VRAM region: Actual physical size %pa, usable size exclude stolen %pa, CPU accessible size %pa\n",
+		 stringify_vram_binding(vram->binding), vram->id, &vram->actual_physical_size,
+		 &vram->usable_size, &vram->io_size);
+	drm_info(drm, "%s[%u] VRAM region: DPA range: [%pa-%llx], io range: [%pa-%llx]\n",
+		 stringify_vram_binding(vram->binding), vram->id, &vram->dpa_base,
+		 vram->dpa_base + (u64)vram->actual_physical_size, &vram->io_start,
+		 vram->io_start + (u64)vram->io_size);
 }
 
 static int vram_region_init(struct xe_device *xe, struct xe_vram_region *vram,
 			    struct xe_vram_region *lmem_bar, u64 offset, u64 usable_size,
 			    u64 region_size, resource_size_t remain_io_size)
 {
+	xe_assert(xe, vram->binding != XE_VRAM_BINDING_NONE);
+
 	/* Check if VRAM region is already initialized */
 	if (vram->mapping)
 		return 0;
@@ -253,7 +343,7 @@ static int vram_region_init(struct xe_device *xe, struct xe_vram_region *vram,
 	vram->io_size = min_t(u64, usable_size, remain_io_size);
 
 	if (!vram->io_size) {
-		drm_err(&xe->drm, "Tile without any CPU visible VRAM. Aborting.\n");
+		drm_err(&xe->drm, "VRAM region without any CPU visible memory\n");
 		return -ENODEV;
 	}
 
@@ -268,11 +358,65 @@ static int vram_region_init(struct xe_device *xe, struct xe_vram_region *vram,
 	vram->dpa_base = lmem_bar->dpa_base + offset;
 	vram->usable_size = usable_size;
 
+	/* The device aggregate only reports sizes, nothing is allocated from it */
+	if (vram->binding != XE_VRAM_BINDING_DEVICE) {
+		/* Until split, partitions[0] spans the whole usable range */
+		vram->partitions[0].offset = 0;
+		vram->partitions[0].size = usable_size;
+		vram->num_partitions = 1;
+	}
+
 	print_vram_region_info(xe, vram);
 
 	return 0;
 }
 
+/**
+ * xe_vram_pool_place - Fill in the TTM placement of a pool
+ * @pool: the VRAM pool to place in
+ * @place: the placement to narrow down to @pool
+ *
+ * Resolve @pool to the placement of the region backing it and, when the pool
+ * does not span that region, to the page range it covers. Callers do not have
+ * to care which of the two backs the pool.
+ *
+ * The range is only ever narrowed, so this composes with a caller supplied
+ * one, e.g. the CPU visible range of a small BAR.
+ */
+void xe_vram_pool_place(const struct xe_vram_pool *pool, struct ttm_place *place)
+{
+	u64 fpfn, lpfn;
+
+	place->mem_type = pool->region->placement;
+
+	if (pool->offset == 0 && pool->size == pool->region->usable_size)
+		return;
+
+	xe_assert(pool->region->xe, IS_ALIGNED(pool->offset, PAGE_SIZE));
+	xe_assert(pool->region->xe, IS_ALIGNED(pool->size, PAGE_SIZE));
+
+	fpfn = pool->offset >> PAGE_SHIFT;
+	lpfn = (pool->offset + pool->size) >> PAGE_SHIFT;
+
+	place->fpfn = max_t(u64, place->fpfn, fpfn);
+	place->lpfn = place->lpfn ? min_t(u64, place->lpfn, lpfn) : lpfn;
+}
+
+/**
+ * xe_vram_pool_usable_size - Usable size of a pool
+ * @pool: the VRAM pool
+ *
+ * Unlike xe_vram_region_usable_size(), which reports the whole region a pool
+ * may share with others, this reports only the range reserved for @pool's
+ * own purpose, e.g. what is actually available to hand out to userspace.
+ *
+ * Return: the usable size of @pool.
+ */
+resource_size_t xe_vram_pool_usable_size(const struct xe_vram_pool *pool)
+{
+	return pool->size;
+}
+
 /**
  * xe_map_resource_to_region - Map ttm resource to vram memory region
  * @res: The ttm resource
@@ -323,6 +467,7 @@ int xe_vram_probe(struct xe_device *xe)
 	remain_io_size = lmem_bar.io_size;
 
 	for_each_tile(tile, xe, id) {
+		struct xe_vram_region *tile_region;
 		u64 region_size;
 		u64 usable_size;
 		u64 tile_offset;
@@ -334,7 +479,8 @@ int xe_vram_probe(struct xe_device *xe)
 		total_size += region_size;
 		available_size += usable_size;
 
-		err = vram_region_init(xe, tile->mem.vram, &lmem_bar, tile_offset, usable_size,
+		tile_region = tile->mem.vram->region;
+		err = vram_region_init(xe, tile_region, &lmem_bar, tile_offset, usable_size,
 				       region_size, remain_io_size);
 		if (err)
 			return err;
@@ -344,7 +490,7 @@ int xe_vram_probe(struct xe_device *xe)
 				 &total_size, &lmem_bar.io_size);
 		}
 
-		remain_io_size -= min_t(u64, tile->mem.vram->actual_physical_size, remain_io_size);
+		remain_io_size -= min_t(u64, tile_region->actual_physical_size, remain_io_size);
 	}
 
 	err = vram_region_init(xe, xe->mem.vram, &lmem_bar, 0, available_size, total_size,
@@ -433,19 +579,20 @@ int xe_vram_reserve_memtest_bo(struct xe_device *xe)
 		if (!tile->mem.vram)
 			continue;
 
-		if (tile->mem.vram->io_size < tile->mem.vram->usable_size) {
+		if (tile->mem.vram->region->io_size < tile->mem.vram->region->usable_size) {
 			drm_info(&xe->drm,
 				 "Tile %d: Small-BAR system detected, skipping VRAM memtest\n",
 				 id);
 			continue;
 		}
 
-		vram_size = tile->mem.vram->usable_size;
+		vram_size = tile->mem.vram->region->usable_size;
 
 		tile->mem.memtest_bo = xe_bo_create_pin_map_at_novm(xe, tile, SZ_64K,
 								    vram_size - SZ_64K,
 								    ttm_bo_type_kernel,
-								    XE_BO_FLAG_VRAM_IF_DGFX(tile),
+								    XE_BO_FLAG_VRAM_IF_DGFX(tile) |
+								    XE_BO_FLAG_FORCE_USER_VRAM,
 								    0, false);
 		if (IS_ERR(tile->mem.memtest_bo)) {
 			drm_warn(&xe->drm, "Tile %d: Failed to reserve memtest BO\n", id);
diff --git a/drivers/gpu/drm/xe/xe_vram.h b/drivers/gpu/drm/xe/xe_vram.h
index 38425d81f777f..184850f4ed188 100644
--- a/drivers/gpu/drm/xe/xe_vram.h
+++ b/drivers/gpu/drm/xe/xe_vram.h
@@ -8,14 +8,23 @@
 
 #include <linux/types.h>
 
+#include "xe_vram_types.h"
+
 struct xe_device;
-struct xe_vram_region;
+struct xe_tile;
 struct ttm_resource;
+struct ttm_place;
 
 struct xe_vram_region *xe_map_resource_to_region(struct ttm_resource *res);
 int xe_vram_probe(struct xe_device *xe);
 
-struct xe_vram_region *xe_vram_region_alloc(struct xe_device *xe, u8 id, u32 placement);
+struct xe_vram_region *xe_vram_region_alloc_device(struct xe_device *xe);
+struct xe_vram_region *xe_vram_region_alloc_tile(struct xe_device *xe, u8 id);
+struct xe_vram_pool *xe_vram_region_default_pool(struct xe_vram_region *vram);
+int xe_vram_tile_alloc_kernel(struct xe_tile *tile);
+
+void xe_vram_pool_place(const struct xe_vram_pool *pool, struct ttm_place *place);
+resource_size_t xe_vram_pool_usable_size(const struct xe_vram_pool *pool);
 
 resource_size_t xe_vram_region_io_start(const struct xe_vram_region *vram);
 resource_size_t xe_vram_region_io_size(const struct xe_vram_region *vram);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v1 4/7] drm/xe/ttm: Back each VRAM pool with its own buddy allocator
  2026-10-02 10:40 [PATCH v1 0/7] Introduce purpose-specific VRAM pools Piórkowski, Piotr
                   ` (2 preceding siblings ...)
  2026-10-02 10:40 ` [PATCH v1 3/7] drm/xe/vram: Make VRAM pools the allocation handle Piórkowski, Piotr
@ 2026-10-02 10:40 ` Piórkowski, Piotr
  2026-10-02 10:40 ` [PATCH v1 5/7] drm/xe/vram: Allow splitting a region into pools Piórkowski, Piotr
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Piórkowski, Piotr @ 2026-10-02 10:40 UTC (permalink / raw)
  To: intel-xe; +Cc: Piotr Piórkowski, Matthew Brost

From: Piotr Piórkowski <piotr.piorkowski@intel.com>

Give every pool of a VRAM region a buddy allocator of its own, so that an
allocation can be confined to a pool without resorting to
%GPU_BUDDY_RANGE_ALLOCATION, which constrains the buddy algorithm.

Buddy offsets become partition relative, so resources and the resource
cursor now carry the partition their blocks were allocated from.

A placement range narrowed down to a pool may end up empty, e.g. a small
BAR CPU visible window not reaching the pool, so such a range is rejected
up front instead of underflowing the size check and the partition
relative offsets.

Usage reporting follows the pools: the memory region query reports the
size, usage and CPU visible usage of the general-purpose pools only, with
CPU visible usage now tracked per partition, and the free VRAM of a pool
is that of its own partition.

While at it, make xe_ttm_vram_mgr_intersects() and
xe_ttm_vram_mgr_compatible() treat a zero lpfn as no upper limit, as TTM
defines it, rather than as an empty range when fpfn is non-zero.

Regions still have a single pool spanning their whole usable range, so
apart from the above lpfn handling there is no functional change.

Suggested-by: Matthew Brost <matthew.brost@intel.com>
Assisted-by: Claude Opus 5.5
Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
---
 drivers/gpu/drm/xe/xe_query.c              |  21 +-
 drivers/gpu/drm/xe/xe_res_cursor.h         |  45 +--
 drivers/gpu/drm/xe/xe_svm.c                |  16 +-
 drivers/gpu/drm/xe/xe_ttm_vram_mgr.c       | 366 ++++++++++++++++-----
 drivers/gpu/drm/xe/xe_ttm_vram_mgr.h       |  51 ++-
 drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h |   2 -
 6 files changed, 370 insertions(+), 131 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_query.c b/drivers/gpu/drm/xe/xe_query.c
index 0692ec93f55d2..b65540348b053 100644
--- a/drivers/gpu/drm/xe/xe_query.c
+++ b/drivers/gpu/drm/xe/xe_query.c
@@ -284,6 +284,14 @@ static int query_mem_regions(struct xe_device *xe,
 	for (i = XE_PL_VRAM0; i <= XE_PL_VRAM1; ++i) {
 		man = ttm_manager_type(&xe->ttm, i);
 		if (man) {
+			u64 total_size;
+			u64 visible_size;
+			u64 used_visible;
+			u64 used;
+
+			xe_ttm_vram_get_general_pool_sizes(man, &total_size, &visible_size);
+			xe_ttm_vram_get_general_pool_used(man, &used, &used_visible);
+
 			mem_regions->mem_regions[mem_regions->num_mem_regions].mem_class =
 				DRM_XE_MEM_REGION_CLASS_VRAM;
 			mem_regions->mem_regions[mem_regions->num_mem_regions].instance =
@@ -292,16 +300,13 @@ static int query_mem_regions(struct xe_device *xe,
 				xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K ?
 				SZ_64K : PAGE_SIZE;
 			mem_regions->mem_regions[mem_regions->num_mem_regions].total_size =
-				man->size;
-
-			xe_ttm_vram_get_used(man,
-					     &mem_regions->mem_regions
-					     [mem_regions->num_mem_regions].used,
-					     &mem_regions->mem_regions
-					     [mem_regions->num_mem_regions].cpu_visible_used);
+				total_size;
 
+			mem_regions->mem_regions[mem_regions->num_mem_regions].used = used;
+			mem_regions->mem_regions[mem_regions->num_mem_regions].cpu_visible_used =
+				used_visible;
 			mem_regions->mem_regions[mem_regions->num_mem_regions].cpu_visible_size =
-				xe_ttm_vram_get_cpu_visible_size(man);
+				visible_size;
 			mem_regions->num_mem_regions++;
 		}
 	}
diff --git a/drivers/gpu/drm/xe/xe_res_cursor.h b/drivers/gpu/drm/xe/xe_res_cursor.h
index c3a037e5f34e2..586d572a02729 100644
--- a/drivers/gpu/drm/xe/xe_res_cursor.h
+++ b/drivers/gpu/drm/xe/xe_res_cursor.h
@@ -57,8 +57,14 @@ struct xe_res_cursor {
 	struct scatterlist *sgl;
 	/** @dma_addr: Current element in a struct drm_pagemap_addr array */
 	const struct drm_pagemap_addr *dma_addr;
-	/** @mm: Buddy allocator for VRAM cursor */
-	struct gpu_buddy *mm;
+	/**
+	 * @part: VRAM partition @node was allocated from
+	 *
+	 * Needed to resolve a VRAM region relative offset and a size from a
+	 * buddy block, see xe_ttm_vram_mgr_block_offset(). Only valid for the
+	 * VRAM memory types.
+	 */
+	struct xe_ttm_vram_mgr_part *part;
 	/**
 	 * @dma_start: DMA start address for the current segment.
 	 * This may be different to @dma_addr.addr since elements in
@@ -69,14 +75,6 @@ struct xe_res_cursor {
 	u64 dma_seg_size;
 };
 
-static struct gpu_buddy *xe_res_get_buddy(struct ttm_resource *res)
-{
-	struct ttm_resource_manager *mgr;
-
-	mgr = ttm_manager_type(res->bo->bdev, res->mem_type);
-	return &to_xe_ttm_vram_mgr(mgr)->mm;
-}
-
 /**
  * xe_res_first - initialize a xe_res_cursor
  *
@@ -107,16 +105,18 @@ static inline void xe_res_first(struct ttm_resource *res,
 		cur->size = size;
 		cur->remaining = size;
 		cur->node = NULL;
-		cur->mm = NULL;
+		cur->part = NULL;
 		break;
 	}
 	case XE_PL_VRAM0:
 	case XE_PL_VRAM1: {
+		struct xe_ttm_vram_mgr_resource *vres =
+			to_xe_ttm_vram_mgr_resource(res);
+		struct xe_ttm_vram_mgr_part *part = vres->part;
 		struct gpu_buddy_block *block;
 		struct list_head *head, *next;
-		struct gpu_buddy *mm = xe_res_get_buddy(res);
 
-		head = &to_xe_ttm_vram_mgr_resource(res)->blocks;
+		head = &vres->blocks;
 
 		block = list_first_entry_or_null(head,
 						 struct gpu_buddy_block,
@@ -124,8 +124,8 @@ static inline void xe_res_first(struct ttm_resource *res,
 		if (!block)
 			goto fallback;
 
-		while (start >= gpu_buddy_block_size(mm, block)) {
-			start -= gpu_buddy_block_size(mm, block);
+		while (start >= xe_ttm_vram_mgr_block_size(part, block)) {
+			start -= xe_ttm_vram_mgr_block_size(part, block);
 
 			next = block->link.next;
 			if (next != head)
@@ -133,9 +133,9 @@ static inline void xe_res_first(struct ttm_resource *res,
 						   link);
 		}
 
-		cur->mm = mm;
-		cur->start = gpu_buddy_block_offset(block) + start;
-		cur->size = min(gpu_buddy_block_size(mm, block) - start,
+		cur->part = part;
+		cur->start = xe_ttm_vram_mgr_block_offset(part, block) + start;
+		cur->size = min(xe_ttm_vram_mgr_block_size(part, block) - start,
 				size);
 		cur->remaining = size;
 		cur->node = block;
@@ -152,6 +152,7 @@ static inline void xe_res_first(struct ttm_resource *res,
 	cur->size = size;
 	cur->remaining = size;
 	cur->node = NULL;
+	cur->part = NULL;
 	cur->mem_type = XE_PL_TT;
 	XE_WARN_ON(res && start + size > res->size);
 }
@@ -311,15 +312,15 @@ static inline void xe_res_next(struct xe_res_cursor *cur, u64 size)
 		block = list_entry(next, struct gpu_buddy_block, link);
 
 
-		while (start >= gpu_buddy_block_size(cur->mm, block)) {
-			start -= gpu_buddy_block_size(cur->mm, block);
+		while (start >= xe_ttm_vram_mgr_block_size(cur->part, block)) {
+			start -= xe_ttm_vram_mgr_block_size(cur->part, block);
 
 			next = block->link.next;
 			block = list_entry(next, struct gpu_buddy_block, link);
 		}
 
-		cur->start = gpu_buddy_block_offset(block) + start;
-		cur->size = min(gpu_buddy_block_size(cur->mm, block) - start,
+		cur->start = xe_ttm_vram_mgr_block_offset(cur->part, block) + start;
+		cur->size = min(xe_ttm_vram_mgr_block_size(cur->part, block) - start,
 				cur->remaining);
 		cur->node = block;
 		break;
diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
index 7f58240b0b5b4..13e5bf0fd6cf4 100644
--- a/drivers/gpu/drm/xe/xe_svm.c
+++ b/drivers/gpu/drm/xe/xe_svm.c
@@ -803,28 +803,22 @@ static u64 block_offset_to_pfn(struct drm_pagemap *dpagemap, u64 offset)
 	return PHYS_PFN(offset + xpagemap->hpa_base);
 }
 
-static struct gpu_buddy *vram_to_buddy(struct xe_vram_region *vram)
-{
-	return &vram->ttm.mm;
-}
-
 static int xe_svm_populate_devmem_pfn(struct drm_pagemap_devmem *devmem_allocation,
 				      unsigned long npages, unsigned long *pfn)
 {
 	struct xe_bo *bo = to_xe_bo(devmem_allocation);
 	struct ttm_resource *res = bo->ttm.resource;
-	struct list_head *blocks = &to_xe_ttm_vram_mgr_resource(res)->blocks;
-	struct xe_vram_region *vr = xe_map_resource_to_region(res);
-	struct gpu_buddy *buddy = vram_to_buddy(vr);
+	struct xe_ttm_vram_mgr_resource *vres = to_xe_ttm_vram_mgr_resource(res);
 	struct gpu_buddy_block *block;
 	int j = 0;
 
-	list_for_each_entry(block, blocks, link) {
+	list_for_each_entry(block, &vres->blocks, link) {
+		u64 offset = xe_ttm_vram_mgr_block_offset(vres->part, block);
 		u64 block_pfn = block_offset_to_pfn(devmem_allocation->dpagemap,
-						    gpu_buddy_block_offset(block));
+						    offset);
 		int i;
 
-		for (i = 0; i < gpu_buddy_block_size(buddy, block) >> PAGE_SHIFT; ++i)
+		for (i = 0; i < xe_ttm_vram_mgr_block_size(vres->part, block) >> PAGE_SHIFT; ++i)
 			pfn[j++] = block_pfn + i;
 	}
 
diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
index c9a28fad7c069..d4665851f727b 100644
--- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
+++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
@@ -36,8 +36,9 @@ xe_ttm_vram_mgr_first_block(struct list_head *list)
 	return list_first_entry_or_null(list, struct gpu_buddy_block, link);
 }
 
-static inline bool xe_is_vram_mgr_blocks_contiguous(struct gpu_buddy *mm,
-						    struct list_head *head)
+static inline bool
+xe_is_vram_mgr_blocks_contiguous(struct xe_ttm_vram_mgr_part *part,
+				 struct list_head *head)
 {
 	struct gpu_buddy_block *block;
 	u64 start, size;
@@ -47,28 +48,94 @@ static inline bool xe_is_vram_mgr_blocks_contiguous(struct gpu_buddy *mm,
 		return false;
 
 	while (head != block->link.next) {
-		start = gpu_buddy_block_offset(block);
-		size = gpu_buddy_block_size(mm, block);
+		start = xe_ttm_vram_mgr_block_offset(part, block);
+		size = xe_ttm_vram_mgr_block_size(part, block);
 
 		block = list_entry(block->link.next, struct gpu_buddy_block,
 				   link);
-		if (start + size != gpu_buddy_block_offset(block))
+		if (start + size != xe_ttm_vram_mgr_block_offset(part, block))
 			return false;
 	}
 
 	return true;
 }
 
-static int xe_ttm_vram_buddy_alloc(struct xe_ttm_vram_mgr *mgr, u64 start,
+/*
+ * Find the partition able to satisfy the VRAM region relative range
+ * [@start, @end). @exact is set if the range covers the whole partition, in
+ * which case the caller can skip %GPU_BUDDY_RANGE_ALLOCATION as every block
+ * of the partition trivially satisfies the range.
+ *
+ * Partitions are a hard split, so a range straddling a partition boundary
+ * cannot be satisfied and NULL is returned.
+ */
+static struct xe_ttm_vram_mgr_part *
+xe_ttm_vram_mgr_select_part(struct xe_ttm_vram_mgr *mgr, u64 start, u64 end,
+			    bool *exact)
+{
+	unsigned int i;
+
+	for (i = 0; i < mgr->num_parts; ++i) {
+		struct xe_ttm_vram_mgr_part *part = &mgr->parts[i];
+
+		if (start == part->pool->offset &&
+		    end == part->pool->offset + part->pool->size) {
+			*exact = true;
+			return part;
+		}
+	}
+
+	for (i = 0; i < mgr->num_parts; ++i) {
+		struct xe_ttm_vram_mgr_part *part = &mgr->parts[i];
+
+		if (start >= part->pool->offset &&
+		    end <= part->pool->offset + part->pool->size) {
+			*exact = false;
+			return part;
+		}
+	}
+
+	return NULL;
+}
+
+/*
+ * Find the partition containing the VRAM region relative offset @addr, or
+ * NULL if @addr is outside the region.
+ */
+static struct xe_ttm_vram_mgr_part *
+xe_ttm_vram_mgr_addr_to_part(struct xe_ttm_vram_mgr *mgr, u64 addr)
+{
+	unsigned int i;
+
+	for (i = 0; i < mgr->num_parts; ++i) {
+		struct xe_ttm_vram_mgr_part *part = &mgr->parts[i];
+
+		if (addr >= part->pool->offset &&
+		    addr < part->pool->offset + part->pool->size)
+			return part;
+	}
+
+	return NULL;
+}
+
+/*
+ * Allocate the VRAM region relative range [@start, @end) from @part. The
+ * range must be contained within @part and is translated to the partition
+ * relative offsets tracked by its buddy allocator.
+ */
+static int xe_ttm_vram_buddy_alloc(struct xe_ttm_vram_mgr *mgr,
+				   struct xe_ttm_vram_mgr_part *part, u64 start,
 				   u64 end, u64 size, u64 min_page_size,
 				   struct list_head *blocks, unsigned long flags,
 				   struct ttm_resource *res, u64 *used_visible)
 {
-	struct gpu_buddy *mm = &mgr->mm;
 	struct gpu_buddy_block *block;
 	int err;
 
-	err = gpu_buddy_alloc_blocks(mm, start, end, size, min_page_size, blocks, flags);
+	err = gpu_buddy_alloc_blocks(&part->mm,
+				     start - part->pool->offset,
+				     end - part->pool->offset,
+				     size, min_page_size, blocks, flags);
 	if (err)
 		return err;
 
@@ -87,10 +154,11 @@ static int xe_ttm_vram_buddy_alloc(struct xe_ttm_vram_mgr *mgr, u64 start,
 		*used_visible = size;
 	} else {
 		list_for_each_entry(block, blocks, link) {
-			u64 blk_start = gpu_buddy_block_offset(block);
+			u64 blk_start = xe_ttm_vram_mgr_block_offset(part, block);
 
 			if (blk_start < mgr->visible_size) {
-				u64 blk_end = blk_start + gpu_buddy_block_size(mm, block);
+				u64 blk_end = blk_start +
+					xe_ttm_vram_mgr_block_size(part, block);
 
 				*used_visible += min(blk_end, mgr->visible_size) - blk_start;
 			}
@@ -98,6 +166,7 @@ static int xe_ttm_vram_buddy_alloc(struct xe_ttm_vram_mgr *mgr, u64 start,
 	}
 
 	mgr->visible_avail -= *used_visible;
+	part->used_visible += *used_visible;
 	return 0;
 }
 
@@ -108,17 +177,20 @@ static int xe_ttm_vram_mgr_new(struct ttm_resource_manager *man,
 {
 	struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
 	struct xe_ttm_vram_mgr_resource *vres;
-	struct gpu_buddy *mm = &mgr->mm;
+	struct xe_ttm_vram_mgr_part *part;
 	u64 size, min_page_size;
 	unsigned long lpfn;
+	bool exact;
 	int err;
 
 	lpfn = place->lpfn;
 	if (!lpfn || lpfn > man->size >> PAGE_SHIFT)
 		lpfn = man->size >> PAGE_SHIFT;
 
-	if (tbo->base.size >> PAGE_SHIFT > (lpfn - place->fpfn))
-		return -E2BIG; /* don't trigger eviction for the impossible */
+	/* don't trigger eviction for the impossible */
+	if (place->fpfn >= lpfn ||
+	    tbo->base.size >> PAGE_SHIFT > (lpfn - place->fpfn))
+		return -E2BIG;
 
 	vres = kzalloc_obj(*vres);
 	if (!vres)
@@ -134,13 +206,21 @@ static int xe_ttm_vram_mgr_new(struct ttm_resource_manager *man,
 
 	INIT_LIST_HEAD(&vres->blocks);
 
+	part = xe_ttm_vram_mgr_select_part(mgr, (u64)place->fpfn << PAGE_SHIFT,
+					   (u64)lpfn << PAGE_SHIFT, &exact);
+	if (!part) {
+		err = -ENOSPC;
+		goto error_fini;
+	}
+	vres->part = part;
+
 	if (place->flags & TTM_PL_FLAG_TOPDOWN)
 		vres->flags |= GPU_BUDDY_TOPDOWN_ALLOCATION;
 
 	if (place->flags & TTM_PL_FLAG_CONTIGUOUS)
 		vres->flags |= GPU_BUDDY_CONTIGUOUS_ALLOCATION;
 
-	if (place->fpfn || lpfn != man->size >> PAGE_SHIFT)
+	if (!exact)
 		vres->flags |= GPU_BUDDY_RANGE_ALLOCATION;
 
 	if (WARN_ON(!vres->base.size)) {
@@ -153,11 +233,20 @@ static int xe_ttm_vram_mgr_new(struct ttm_resource_manager *man,
 	if (tbo->page_alignment)
 		min_page_size = (u64)tbo->page_alignment << PAGE_SHIFT;
 
-	if (WARN_ON(min_page_size < mm->chunk_size)) {
+	if (WARN_ON(min_page_size < part->mm.chunk_size)) {
 		err = -EINVAL;
 		goto error_fini;
 	}
 
+	/*
+	 * Buddy offsets are partition relative, so an allocation aligned within
+	 * the partition is only aligned in the region if the base is too.
+	 */
+	if (!IS_ALIGNED(part->pool->offset, min_page_size)) {
+		err = -ENOSPC;
+		goto error_fini;
+	}
+
 	if (WARN_ON(!IS_ALIGNED(size, min_page_size))) {
 		err = -EINVAL;
 		goto error_fini;
@@ -169,7 +258,7 @@ static int xe_ttm_vram_mgr_new(struct ttm_resource_manager *man,
 		goto error_unlock;
 	}
 
-	err = xe_ttm_vram_buddy_alloc(mgr, (u64)place->fpfn << PAGE_SHIFT,
+	err = xe_ttm_vram_buddy_alloc(mgr, part, (u64)place->fpfn << PAGE_SHIFT,
 				      (u64)lpfn << PAGE_SHIFT, size,
 				      min_page_size, &vres->blocks, vres->flags,
 				      &vres->base, &vres->used_visible_size);
@@ -178,7 +267,7 @@ static int xe_ttm_vram_mgr_new(struct ttm_resource_manager *man,
 	mutex_unlock(&mgr->lock);
 
 	if (!(vres->base.placement & TTM_PL_FLAG_CONTIGUOUS) &&
-	    xe_is_vram_mgr_blocks_contiguous(mm, &vres->blocks))
+	    xe_is_vram_mgr_blocks_contiguous(part, &vres->blocks))
 		vres->base.placement |= TTM_PL_FLAG_CONTIGUOUS;
 
 	/*
@@ -190,7 +279,8 @@ static int xe_ttm_vram_mgr_new(struct ttm_resource_manager *man,
 								 typeof(*block),
 								 link);
 
-		vres->base.start = gpu_buddy_block_offset(block) >> PAGE_SHIFT;
+		vres->base.start =
+			xe_ttm_vram_mgr_block_offset(part, block) >> PAGE_SHIFT;
 	} else {
 		vres->base.start = XE_BO_INVALID_OFFSET;
 	}
@@ -207,6 +297,7 @@ static int xe_ttm_vram_mgr_new(struct ttm_resource_manager *man,
 }
 
 static void xe_ttm_vram_buddy_free(struct xe_ttm_vram_mgr *mgr,
+				   struct xe_ttm_vram_mgr_part *part,
 				   struct list_head *blocks,
 				   u64 used_visible)
 {
@@ -214,8 +305,9 @@ static void xe_ttm_vram_buddy_free(struct xe_ttm_vram_mgr *mgr,
 
 	list_for_each_entry(block, blocks, link)
 		block->private = NULL;
-	gpu_buddy_free_list(&mgr->mm, blocks, 0);
+	gpu_buddy_free_list(&part->mm, blocks, 0);
 	mgr->visible_avail += used_visible;
+	part->used_visible -= used_visible;
 }
 
 /*
@@ -236,7 +328,8 @@ static void xe_ttm_vram_retry_queued_pages(struct xe_ttm_vram_mgr *mgr)
 	lockdep_assert_held(&mgr->lock);
 
 	list_for_each_entry_safe(pos, n, &mgr->queued_pages, queued_link) {
-		if (xe_ttm_vram_buddy_alloc(mgr, pos->addr, pos->addr + PAGE_SIZE,
+		if (xe_ttm_vram_buddy_alloc(mgr, pos->part, pos->addr,
+					    pos->addr + PAGE_SIZE,
 					    PAGE_SIZE, PAGE_SIZE, &pos->blocks,
 					    GPU_BUDDY_RANGE_ALLOCATION, NULL,
 					    &pos->used_visible_size)) {
@@ -258,7 +351,8 @@ static void xe_ttm_vram_mgr_del(struct ttm_resource_manager *man,
 	struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
 
 	mutex_lock(&mgr->lock);
-	xe_ttm_vram_buddy_free(mgr, &vres->blocks, vres->used_visible_size);
+	xe_ttm_vram_buddy_free(mgr, vres->part, &vres->blocks,
+			       vres->used_visible_size);
 	if (unlikely(!list_empty(&mgr->queued_pages)))
 		xe_ttm_vram_retry_queued_pages(mgr);
 	mutex_unlock(&mgr->lock);
@@ -272,7 +366,7 @@ static void xe_ttm_vram_mgr_debug(struct ttm_resource_manager *man,
 				  struct drm_printer *printer)
 {
 	struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
-	struct gpu_buddy *mm = &mgr->mm;
+	unsigned int i;
 
 	mutex_lock(&mgr->lock);
 	drm_printf(printer, "default_page_size: %lluKiB\n",
@@ -282,7 +376,15 @@ static void xe_ttm_vram_mgr_debug(struct ttm_resource_manager *man,
 	drm_printf(printer, "visible_size: %lluMiB\n",
 		   (u64)mgr->visible_size >> 20);
 
-	drm_buddy_print(mm, printer);
+	for (i = 0; i < mgr->num_parts; ++i) {
+		struct xe_ttm_vram_mgr_part *part = &mgr->parts[i];
+
+		drm_printf(printer, "partition %u: base %lluMiB size %lluMiB%s\n",
+			   i, part->pool->offset >> 20, part->pool->size >> 20,
+			   part->pool->purpose == XE_VRAM_POOL_KERNEL ?
+			   " (kernel only)" : "");
+		drm_buddy_print(&part->mm, printer);
+	}
 	mutex_unlock(&mgr->lock);
 	drm_printf(printer, "man size:%llu\n", man->size);
 }
@@ -295,8 +397,8 @@ static bool xe_ttm_vram_mgr_intersects(struct ttm_resource_manager *man,
 	struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
 	struct xe_ttm_vram_mgr_resource *vres =
 		to_xe_ttm_vram_mgr_resource(res);
-	struct gpu_buddy *mm = &mgr->mm;
 	struct gpu_buddy_block *block;
+	unsigned long place_lpfn;
 
 	if (!place->fpfn && !place->lpfn)
 		return true;
@@ -304,13 +406,16 @@ static bool xe_ttm_vram_mgr_intersects(struct ttm_resource_manager *man,
 	if (!place->fpfn && place->lpfn == mgr->visible_size >> PAGE_SHIFT)
 		return vres->used_visible_size > 0;
 
+	/* A zero lpfn means no upper limit */
+	place_lpfn = place->lpfn ? place->lpfn : man->size >> PAGE_SHIFT;
+
 	list_for_each_entry(block, &vres->blocks, link) {
 		unsigned long fpfn =
-			gpu_buddy_block_offset(block) >> PAGE_SHIFT;
+			xe_ttm_vram_mgr_block_offset(vres->part, block) >> PAGE_SHIFT;
 		unsigned long lpfn = fpfn +
-			(gpu_buddy_block_size(mm, block) >> PAGE_SHIFT);
+			(xe_ttm_vram_mgr_block_size(vres->part, block) >> PAGE_SHIFT);
 
-		if (place->fpfn < lpfn && place->lpfn > fpfn)
+		if (place->fpfn < lpfn && place_lpfn > fpfn)
 			return true;
 	}
 
@@ -325,8 +430,8 @@ static bool xe_ttm_vram_mgr_compatible(struct ttm_resource_manager *man,
 	struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
 	struct xe_ttm_vram_mgr_resource *vres =
 		to_xe_ttm_vram_mgr_resource(res);
-	struct gpu_buddy *mm = &mgr->mm;
 	struct gpu_buddy_block *block;
+	unsigned long place_lpfn;
 
 	if (!place->fpfn && !place->lpfn)
 		return true;
@@ -334,13 +439,16 @@ static bool xe_ttm_vram_mgr_compatible(struct ttm_resource_manager *man,
 	if (!place->fpfn && place->lpfn == mgr->visible_size >> PAGE_SHIFT)
 		return vres->used_visible_size == size;
 
+	/* A zero lpfn means no upper limit */
+	place_lpfn = place->lpfn ? place->lpfn : man->size >> PAGE_SHIFT;
+
 	list_for_each_entry(block, &vres->blocks, link) {
 		unsigned long fpfn =
-			gpu_buddy_block_offset(block) >> PAGE_SHIFT;
+			xe_ttm_vram_mgr_block_offset(vres->part, block) >> PAGE_SHIFT;
 		unsigned long lpfn = fpfn +
-			(gpu_buddy_block_size(mm, block) >> PAGE_SHIFT);
+			(xe_ttm_vram_mgr_block_size(vres->part, block) >> PAGE_SHIFT);
 
-		if (fpfn < place->fpfn || lpfn > place->lpfn)
+		if (fpfn < place->fpfn || lpfn > place_lpfn)
 			return false;
 	}
 
@@ -396,19 +504,33 @@ static void xe_ttm_vram_free_bad_pages(struct xe_ttm_vram_mgr *mgr)
 
 	list_for_each_entry_safe(pos, n, &mgr->offlined_pages, offlined_link) {
 		list_del_rcu(&pos->offlined_link);
-		xe_ttm_vram_buddy_free(mgr, &pos->blocks, pos->used_visible_size);
+		xe_ttm_vram_buddy_free(mgr, pos->part, &pos->blocks,
+				       pos->used_visible_size);
 		--mgr->n_offlined_pages;
 		kfree_rcu(pos, rcu);
 	}
 	list_for_each_entry_safe(pos, n, &mgr->queued_pages, queued_link) {
 		list_del_rcu(&pos->queued_link);
 		/* queued entries have no buddy reservation yet */
-		xe_ttm_vram_buddy_free(mgr, &pos->blocks, 0);
+		xe_ttm_vram_buddy_free(mgr, pos->part, &pos->blocks, 0);
 		--mgr->n_queued_pages;
 		kfree_rcu(pos, rcu);
 	}
 }
 
+/* Tear down every initialized partition and unpublish it from its pool */
+static void xe_ttm_vram_mgr_fini_parts(struct xe_ttm_vram_mgr *mgr)
+{
+	unsigned int i;
+
+	for (i = 0; i < mgr->num_parts; ++i) {
+		mgr->parts[i].pool->part = NULL;
+		gpu_buddy_fini(&mgr->parts[i].mm);
+	}
+
+	mgr->num_parts = 0;
+}
+
 static void xe_ttm_vram_mgr_fini(struct drm_device *dev, void *arg)
 {
 	struct xe_device *xe = to_xe_device(dev);
@@ -424,40 +546,86 @@ static void xe_ttm_vram_mgr_fini(struct drm_device *dev, void *arg)
 
 	WARN_ON_ONCE(mgr->visible_avail != mgr->visible_size);
 
-	gpu_buddy_fini(&mgr->mm);
+	xe_ttm_vram_mgr_fini_parts(mgr);
 
 	ttm_resource_manager_cleanup(&mgr->manager);
 
 	ttm_set_driver_manager(&xe->ttm, mgr->mem_type, NULL);
 }
 
-int __xe_ttm_vram_mgr_init(struct xe_device *xe, struct xe_ttm_vram_mgr *mgr,
-			   u32 mem_type, u64 size, u64 io_size,
-			   u64 default_page_size)
+/*
+ * Back every pool of the region with a buddy allocator of its own.
+ *
+ * Buddy offsets are partition relative, so a partition base has to be aligned
+ * to %XE_TTM_VRAM_MGR_PART_ALIGN, otherwise an aligned buddy allocation is not
+ * aligned in the region. Allocations needing a larger alignment are rejected
+ * by xe_ttm_vram_mgr_new() if the partition base does not honour it.
+ */
+static int xe_ttm_vram_mgr_init_parts(struct xe_device *xe, struct xe_ttm_vram_mgr *mgr,
+				      struct xe_vram_region *vram)
 {
+	unsigned int i;
+	int err;
+
+	for (i = 0; i < vram->num_partitions; ++i) {
+		struct xe_ttm_vram_mgr_part *part = &mgr->parts[i];
+		struct xe_vram_pool *pool = &vram->partitions[i];
+
+		xe_assert(xe, IS_ALIGNED(pool->offset, XE_TTM_VRAM_MGR_PART_ALIGN));
+		xe_assert(xe, pool->offset + pool->size <= vram->usable_size);
+
+		err = gpu_buddy_init(&part->mm, pool->size, mgr->default_page_size);
+		if (err) {
+			xe_ttm_vram_mgr_fini_parts(mgr);
+			return err;
+		}
+
+		gpu_buddy_driver_set_lock(&part->mm, &mgr->lock);
+
+		part->pool = pool;
+		pool->part = part;
+		mgr->num_parts = i + 1;
+	}
+
+	return 0;
+}
+
+/**
+ * xe_ttm_vram_mgr_init - initialize TTM VRAM region
+ * @xe: pointer to Xe device
+ * @vram: pointer to xe_vram_region that contains the memory region attributes
+ *
+ * Initialize the Xe TTM manager of @vram, with one buddy allocator per pool
+ * of the region.
+ *
+ * Returns 0 for success, negative error code otherwise.
+ */
+int xe_ttm_vram_mgr_init(struct xe_device *xe, struct xe_vram_region *vram)
+{
+	struct xe_ttm_vram_mgr *mgr = &vram->ttm;
 	struct ttm_resource_manager *man = &mgr->manager;
+	u64 io_size = xe_vram_region_io_size(vram);
 	struct dmem_cgroup_region *cg;
-	const char *name;
 	int err;
 
 	man->func = &xe_ttm_vram_mgr_func;
-	mgr->mem_type = mem_type;
+	mgr->mem_type = vram->placement;
 	err = drmm_mutex_init(&xe->drm, &mgr->lock);
 	if (err)
 		return err;
 	INIT_LIST_HEAD(&mgr->offlined_pages);
 	INIT_LIST_HEAD(&mgr->queued_pages);
-	mgr->default_page_size = default_page_size;
+	mgr->default_page_size = PAGE_SIZE;
 	mgr->visible_size = io_size;
 	mgr->visible_avail = io_size;
 
-	ttm_resource_manager_init(man, &xe->ttm, size);
-	err = gpu_buddy_init(&mgr->mm, man->size, default_page_size);
+	ttm_resource_manager_init(man, &xe->ttm, xe_vram_region_usable_size(vram));
+
+	err = xe_ttm_vram_mgr_init_parts(xe, mgr, vram);
 	if (err)
 		return err;
 
-	gpu_buddy_driver_set_lock(&mgr->mm, &mgr->lock);
-	ttm_set_driver_manager(&xe->ttm, mem_type, &mgr->manager);
+	ttm_set_driver_manager(&xe->ttm, mgr->mem_type, man);
 
 	/*
 	 * Register the fini action before the cgroup region so that devres
@@ -468,10 +636,9 @@ int __xe_ttm_vram_mgr_init(struct xe_device *xe, struct xe_ttm_vram_mgr *mgr,
 	if (err)
 		return err;
 
-	name = mem_type == XE_PL_VRAM0 ? "vram0" : "vram1";
-	cg = drmm_cgroup_register_region(&xe->drm, name,
+	cg = drmm_cgroup_register_region(&xe->drm, xe_mem_type_to_name[mgr->mem_type],
 					 &(struct dmem_cgroup_init){
-						.size = size,
+						.size = man->size,
 						.ops = &xe_ttm_vram_mgr_dmem_ops,
 						.reclaim_priv = man,
 					 });
@@ -484,23 +651,6 @@ int __xe_ttm_vram_mgr_init(struct xe_device *xe, struct xe_ttm_vram_mgr *mgr,
 	return drmm_add_action_or_reset(&xe->drm, xe_ttm_vram_mgr_set_unused, man);
 }
 
-/**
- * xe_ttm_vram_mgr_init - initialize TTM VRAM region
- * @xe: pointer to Xe device
- * @vram: pointer to xe_vram_region that contains the memory region attributes
- *
- * Initialize the Xe TTM for given @vram region using the given parameters.
- *
- * Returns 0 for success, negative error code otherwise.
- */
-int xe_ttm_vram_mgr_init(struct xe_device *xe, struct xe_vram_region *vram)
-{
-	return __xe_ttm_vram_mgr_init(xe, &vram->ttm, vram->placement,
-				      xe_vram_region_usable_size(vram),
-				      xe_vram_region_io_size(vram),
-				      PAGE_SIZE);
-}
-
 int xe_ttm_vram_mgr_alloc_sgt(struct xe_device *xe,
 			      struct ttm_resource *res,
 			      u64 offset, u64 length,
@@ -595,21 +745,64 @@ void xe_ttm_vram_mgr_free_sgt(struct device *dev, enum dma_data_direction dir,
 	kfree(sgt);
 }
 
-u64 xe_ttm_vram_get_cpu_visible_size(struct ttm_resource_manager *man)
+/**
+ * xe_ttm_vram_get_general_pool_sizes - Sizes of the general-purpose pools
+ * @man: The TTM resource manager of the VRAM region
+ * @size: total size of the general-purpose pools
+ * @cpu_visible_size: CPU-visible size of the general-purpose pools
+ *
+ * Report only VRAM available to userspace. The visible size is clipped to
+ * the manager's CPU-visible range, which starts at the region base.
+ */
+void xe_ttm_vram_get_general_pool_sizes(struct ttm_resource_manager *man,
+					u64 *size, u64 *cpu_visible_size)
 {
 	struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
+	unsigned int i;
+
+	*size = 0;
+	*cpu_visible_size = 0;
+	for (i = 0; i < mgr->num_parts; ++i) {
+		struct xe_vram_pool *pool = mgr->parts[i].pool;
+		u64 end = pool->offset + pool->size;
 
-	return mgr->visible_size;
+		if (pool->purpose != XE_VRAM_POOL_GENERAL)
+			continue;
+
+		*size += pool->size;
+		if (pool->offset < mgr->visible_size)
+			*cpu_visible_size += min(end, mgr->visible_size) - pool->offset;
+	}
 }
 
-void xe_ttm_vram_get_used(struct ttm_resource_manager *man,
-			  u64 *used, u64 *used_visible)
+/**
+ * xe_ttm_vram_get_general_pool_used - Usage of the general-purpose pools
+ * @man: The TTM resource manager of the VRAM region
+ * @used: bytes allocated from the general-purpose pools
+ * @used_visible: CPU-visible bytes allocated from the general-purpose pools
+ *
+ * Counterpart of xe_ttm_vram_get_general_pool_sizes(), memory allocated from
+ * pools serving another purpose, e.g. kernel-only, is not accounted.
+ */
+void xe_ttm_vram_get_general_pool_used(struct ttm_resource_manager *man,
+				       u64 *used, u64 *used_visible)
 {
 	struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
+	unsigned int i;
+
+	*used = 0;
+	*used_visible = 0;
 
 	mutex_lock(&mgr->lock);
-	*used = mgr->mm.size - mgr->mm.avail;
-	*used_visible = mgr->visible_size - mgr->visible_avail;
+	for (i = 0; i < mgr->num_parts; ++i) {
+		struct xe_ttm_vram_mgr_part *part = &mgr->parts[i];
+
+		if (part->pool->purpose != XE_VRAM_POOL_GENERAL)
+			continue;
+
+		*used += part->mm.size - part->mm.avail;
+		*used_visible += part->used_visible;
+	}
 	mutex_unlock(&mgr->lock);
 }
 
@@ -624,9 +817,8 @@ u64 xe_ttm_vram_get_pool_avail(struct xe_vram_pool *pool)
 	struct xe_ttm_vram_mgr *mgr = &pool->region->ttm;
 	u64 avail;
 
-	/* A pool still spans the whole region of its manager */
 	mutex_lock(&mgr->lock);
-	avail = mgr->mm.avail;
+	avail = pool->part ? pool->part->mm.avail : 0;
 	mutex_unlock(&mgr->lock);
 
 	return avail;
@@ -776,9 +968,10 @@ static struct xe_bo *xe_ttm_vram_block_owner_get(struct xe_device *xe,
 }
 
 static int xe_ttm_vram_reserve_page_at_addr(struct xe_device *xe, u64 addr,
-					    struct xe_ttm_vram_mgr *vram_mgr, struct gpu_buddy *mm)
+					    struct xe_ttm_vram_mgr *vram_mgr)
 {
 	struct xe_ttm_vram_offline_resource *nentry;
+	struct xe_ttm_vram_mgr_part *part;
 	struct xe_bo *pbo_to_put = NULL;
 	struct xe_bo *pbo = NULL;
 	struct gpu_buddy_block *block;
@@ -788,7 +981,11 @@ static int xe_ttm_vram_reserve_page_at_addr(struct xe_device *xe, u64 addr,
 	scoped_guard(mutex, &vram_mgr->lock) {
 		if (xe_ttm_vram_page_already_processed(vram_mgr, addr))
 			return -EEXIST;
-		block = gpu_buddy_allocated_addr_to_block(mm, addr);
+		part = xe_ttm_vram_mgr_addr_to_part(vram_mgr, addr);
+		if (WARN_ON(!part))
+			return -ENXIO;
+		block = gpu_buddy_allocated_addr_to_block(&part->mm,
+							  addr - part->pool->offset);
 		if (WARN_ON(IS_ERR(block)))
 			return PTR_ERR(block);
 
@@ -798,6 +995,7 @@ static int xe_ttm_vram_reserve_page_at_addr(struct xe_device *xe, u64 addr,
 		INIT_LIST_HEAD(&nentry->blocks);
 		nentry->status = XE_PAGE_RESERVE_PENDING;
 		nentry->addr = addr;
+		nentry->part = part;
 
 		if (block) {
 			pbo = xe_ttm_vram_block_owner_get(xe, block);
@@ -822,7 +1020,8 @@ static int xe_ttm_vram_reserve_page_at_addr(struct xe_device *xe, u64 addr,
 		} else {
 			/* Immediately offline unoccupied pages */
 			/* Queue free(to-be-reserved) pages */
-			ret = xe_ttm_vram_buddy_alloc(vram_mgr, addr, addr + size,
+			ret = xe_ttm_vram_buddy_alloc(vram_mgr, part, addr,
+						      addr + size,
 						      size, size, &nentry->blocks,
 						      GPU_BUDDY_RANGE_ALLOCATION,
 						      NULL, &nentry->used_visible_size);
@@ -917,7 +1116,6 @@ int xe_ttm_vram_handle_addr_fault(struct xe_device *xe, u64 addr)
 {
 	struct xe_ttm_vram_mgr *vram_mgr;
 	struct xe_vram_region *vr;
-	struct gpu_buddy *mm;
 
 	/* Assert that the address is PAGE_SIZE aligned */
 	if (WARN_ON_ONCE(!IS_ALIGNED(addr, PAGE_SIZE))) {
@@ -941,7 +1139,6 @@ int xe_ttm_vram_handle_addr_fault(struct xe_device *xe, u64 addr)
 		return -EIO;
 	}
 	vram_mgr = &vr->ttm;
-	mm = &vram_mgr->mm;
 
 	if (xe->ras.disable_vram_page_offline) {
 		xe_err(xe, "0x%llx is reported as corrupted address by HW\n",
@@ -950,7 +1147,7 @@ int xe_ttm_vram_handle_addr_fault(struct xe_device *xe, u64 addr)
 	}
 
 	/* Reserve page at address */
-	return xe_ttm_vram_reserve_page_at_addr(xe, addr - vr->dpa_base, vram_mgr, mm);
+	return xe_ttm_vram_reserve_page_at_addr(xe, addr - vr->dpa_base, vram_mgr);
 }
 EXPORT_SYMBOL(xe_ttm_vram_handle_addr_fault);
 
@@ -975,7 +1172,6 @@ int xe_ttm_vram_inject_fault(struct xe_device *xe)
 	struct xe_tile *tile = xe_device_get_root_tile(xe);
 	struct xe_vram_region *vr = tile->mem.vram->region;
 	struct xe_ttm_vram_mgr *vram_mgr = &vr->ttm;
-	struct gpu_buddy *mm = &vram_mgr->mm;
 	u64 addr;
 
 	if (vr->actual_physical_size < PAGE_SIZE)
@@ -983,13 +1179,19 @@ int xe_ttm_vram_inject_fault(struct xe_device *xe)
 
 	addr = vr->actual_physical_size - PAGE_SIZE;
 	while (addr < vr->actual_physical_size) {
+		struct xe_ttm_vram_mgr_part *part;
 		struct gpu_buddy_block *block;
 		bool found = false;
 
 		scoped_guard(mutex, &vram_mgr->lock) {
-			block = gpu_buddy_allocated_addr_to_block(mm, addr);
-			if (!block)
-				found = true;
+			part = xe_ttm_vram_mgr_addr_to_part(vram_mgr, addr);
+			if (part) {
+				u64 offset = addr - part->pool->offset;
+
+				block = gpu_buddy_allocated_addr_to_block(&part->mm, offset);
+				if (!block)
+					found = true;
+			}
 		}
 
 		/*
diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.h b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.h
index 6cf8217ec46b5..4c625a05c80d1 100644
--- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.h
+++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.h
@@ -14,9 +14,6 @@ struct xe_device;
 struct xe_tile;
 struct xe_vram_region;
 
-int __xe_ttm_vram_mgr_init(struct xe_device *xe, struct xe_ttm_vram_mgr *mgr,
-			   u32 mem_type, u64 size, u64 io_size,
-			   u64 default_page_size);
 int xe_ttm_vram_mgr_init(struct xe_device *xe, struct xe_vram_region *vram);
 void xe_ttm_vram_debugfs_init(struct xe_device *xe, struct dentry *root);
 int xe_ttm_vram_mgr_alloc_sgt(struct xe_device *xe,
@@ -29,9 +26,10 @@ void xe_ttm_vram_mgr_free_sgt(struct device *dev, enum dma_data_direction dir,
 			      struct sg_table *sgt);
 
 u64 xe_ttm_vram_get_pool_avail(struct xe_vram_pool *pool);
-u64 xe_ttm_vram_get_cpu_visible_size(struct ttm_resource_manager *man);
-void xe_ttm_vram_get_used(struct ttm_resource_manager *man,
-			  u64 *used, u64 *used_visible);
+void xe_ttm_vram_get_general_pool_sizes(struct ttm_resource_manager *man,
+					u64 *size, u64 *cpu_visible_size);
+void xe_ttm_vram_get_general_pool_used(struct ttm_resource_manager *man,
+				       u64 *used, u64 *used_visible);
 int xe_ttm_vram_handle_addr_fault(struct xe_device *xe, u64 addr);
 int xe_ttm_vram_inject_fault(struct xe_device *xe);
 
@@ -47,4 +45,45 @@ to_xe_ttm_vram_mgr(struct ttm_resource_manager *man)
 	return container_of(man, struct xe_ttm_vram_mgr, manager);
 }
 
+/**
+ * xe_ttm_vram_mgr_block_offset() - VRAM region relative offset of a block
+ * @part: Partition @block was allocated from
+ * @block: The buddy block
+ *
+ * A VRAM region may be split across several buddy allocators, and the offset
+ * tracked by a partition's buddy allocator is relative to the start of that
+ * partition. A raw &gpu_buddy_block is therefore not enough on its own to
+ * locate the memory it describes, so the owning partition has to be supplied
+ * by the caller. Every block reachable outside this layer hangs off a
+ * &xe_ttm_vram_mgr_resource, so use its @part.
+ *
+ * Use this rather than gpu_buddy_block_offset() anywhere an offset within the
+ * VRAM region (i.e. a DPA relative to the region base) is needed.
+ *
+ * Return: Offset of @block relative to the start of the VRAM region.
+ */
+static inline u64
+xe_ttm_vram_mgr_block_offset(const struct xe_ttm_vram_mgr_part *part,
+			     const struct gpu_buddy_block *block)
+{
+	return part->pool->offset + gpu_buddy_block_offset(block);
+}
+
+/**
+ * xe_ttm_vram_mgr_block_size() - Size of a buddy block
+ * @part: Partition @block was allocated from
+ * @block: The buddy block
+ *
+ * Wrapper around gpu_buddy_block_size() taking the partition @block was
+ * allocated from, see xe_ttm_vram_mgr_block_offset().
+ *
+ * Return: Size of @block in bytes.
+ */
+static inline u64
+xe_ttm_vram_mgr_block_size(struct xe_ttm_vram_mgr_part *part,
+			   struct gpu_buddy_block *block)
+{
+	return gpu_buddy_block_size(&part->mm, block);
+}
+
 #endif
diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h b/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h
index 6af179b2b95b5..01f21b9b5dcf2 100644
--- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h
+++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h
@@ -55,8 +55,6 @@ struct xe_ttm_vram_mgr_part {
 struct xe_ttm_vram_mgr {
 	/** @manager: Base TTM resource manager */
 	struct ttm_resource_manager manager;
-	/** @mm: DRM buddy allocator which manages the VRAM */
-	struct gpu_buddy mm;
 	/** @parts: Partitions this VRAM region is split into */
 	struct xe_ttm_vram_mgr_part parts[XE_TTM_VRAM_MGR_MAX_PARTS];
 	/** @num_parts: Number of initialized entries in @parts */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v1 5/7] drm/xe/vram: Allow splitting a region into pools
  2026-10-02 10:40 [PATCH v1 0/7] Introduce purpose-specific VRAM pools Piórkowski, Piotr
                   ` (3 preceding siblings ...)
  2026-10-02 10:40 ` [PATCH v1 4/7] drm/xe/ttm: Back each VRAM pool with its own buddy allocator Piórkowski, Piotr
@ 2026-10-02 10:40 ` Piórkowski, Piotr
  2026-10-02 10:40 ` [PATCH v1 6/7] drm/xe/kunit: Test partitioned VRAM manager Piórkowski, Piotr
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Piórkowski, Piotr @ 2026-10-02 10:40 UTC (permalink / raw)
  To: intel-xe; +Cc: Piotr Piórkowski

From: Piotr Piórkowski <piotr.piorkowski@intel.com>

Add xe_vram_pool_create(), which carves a pool with a dedicated purpose
out of the low addresses of a region and shrinks the default pool
accordingly. This is the building block for reserving a range of a
tile's VRAM exclusively for a given purpose, e.g. the lowest chunk for
kernel allocations. Placement of such a pool is narrowed to the page
range it covers, and the VRAM manager backs it with a buddy allocator
of its own.

BO placement resolves pools through the tile, so creating a pool does not
by itself redirect any allocation, the caller has to publish the new pool
in the tile.

Nothing creates a second pool yet, so there is still no functional
change.

Assisted-by: Claude Opus 5.5
Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
---
 drivers/gpu/drm/xe/xe_vram.c | 88 ++++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/xe/xe_vram.h |  2 +
 2 files changed, 87 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_vram.c b/drivers/gpu/drm/xe/xe_vram.c
index ec95b53bc53b1..1df4f2514afc0 100644
--- a/drivers/gpu/drm/xe/xe_vram.c
+++ b/drivers/gpu/drm/xe/xe_vram.c
@@ -41,6 +41,18 @@ static const char *stringify_vram_binding(enum xe_vram_binding binding)
 	return "Unknown";
 }
 
+static const char *stringify_vram_pool_purpose(enum xe_vram_pool_purpose purpose)
+{
+	switch (purpose) {
+	case XE_VRAM_POOL_GENERAL:
+		return "General";
+	case XE_VRAM_POOL_KERNEL:
+		return "Kernel";
+	}
+
+	return "Unknown";
+}
+
 static bool resource_is_valid(struct pci_dev *pdev, int bar)
 {
 	if (!pci_resource_flags(pdev, bar))
@@ -297,7 +309,8 @@ struct xe_vram_pool *xe_vram_region_default_pool(struct xe_vram_region *vram)
  * xe_vram_tile_alloc_kernel - Initialize the kernel VRAM pool of a tile
  * @tile: the &xe_tile, with its general purpose VRAM pool already allocated
  *
- * Kernel allocations use the general-purpose pool by default.
+ * Kernel allocations use the general-purpose pool by default. A separate
+ * kernel-only pool can be created explicitly with xe_vram_pool_create().
  *
  * Return: 0 on success, negative error code on failure.
  */
@@ -358,19 +371,88 @@ static int vram_region_init(struct xe_device *xe, struct xe_vram_region *vram,
 	vram->dpa_base = lmem_bar->dpa_base + offset;
 	vram->usable_size = usable_size;
 
+	print_vram_region_info(xe, vram);
+
 	/* The device aggregate only reports sizes, nothing is allocated from it */
 	if (vram->binding != XE_VRAM_BINDING_DEVICE) {
 		/* Until split, partitions[0] spans the whole usable range */
 		vram->partitions[0].offset = 0;
 		vram->partitions[0].size = usable_size;
 		vram->num_partitions = 1;
+		drm_info(&xe->drm,
+			 "Created %s[%u] VRAM pool[%u]: purpose=%s offset=0x%llx size=0x%llx\n",
+			 stringify_vram_binding(vram->binding), vram->id, 0,
+			 stringify_vram_pool_purpose(vram->partitions[0].purpose),
+			 vram->partitions[0].offset, vram->partitions[0].size);
 	}
 
-	print_vram_region_info(xe, vram);
-
 	return 0;
 }
 
+/**
+ * xe_vram_pool_create - Add a pool to a VRAM region
+ * @vram: the VRAM region
+ * @purpose: the purpose served by the new pool
+ * @size: the size of the new pool
+ *
+ * Add a pool at the bottom of @vram and shrink the default pool accordingly.
+ * Existing non-default pools stay at the bottom in creation order. All pools
+ * share the region, the TTM manager and the placement, while the VRAM manager
+ * backs each of them with a buddy allocator of its own.
+ *
+ * The bottom of a region is also where its CPU visible window starts, so on
+ * a small BAR device the new pool takes CPU visible memory away from the
+ * default pool.
+ *
+ * Creating a pool does not make allocations use it. BO placement resolves
+ * pools through the tile, so the caller has to publish the new pool there,
+ * e.g. in &xe_tile.mem.kernel_vram for a kernel-only pool.
+ *
+ * Return: the new pool, or NULL if the pool cannot be created, in particular
+ * once the TTM manager of @vram is initialized.
+ */
+struct xe_vram_pool *xe_vram_pool_create(struct xe_vram_region *vram,
+					 enum xe_vram_pool_purpose purpose, u64 size)
+{
+	struct xe_device *xe = vram->xe;
+	struct xe_vram_pool *pool;
+	u64 offset;
+
+	/* Splitting is only safe while no memory has been handed out yet */
+	if (ttm_resource_manager_used(&vram->ttm.manager))
+		return NULL;
+
+	/* A region without partitions, e.g. the device aggregate, cannot split */
+	if (!vram->num_partitions ||
+	    vram->num_partitions >= XE_VRAM_MAX_PARTITIONS)
+		return NULL;
+
+	if (!size || !IS_ALIGNED(size, XE_TTM_VRAM_MGR_PART_ALIGN))
+		return NULL;
+
+	if (size >= vram->partitions[0].size)
+		return NULL;
+
+	offset = vram->partitions[0].offset;
+	pool = &vram->partitions[vram->num_partitions];
+	*pool = (struct xe_vram_pool) {
+		.region = vram,
+		.offset = offset,
+		.size = size,
+		.purpose = purpose,
+	};
+	vram->partitions[0].offset += size;
+	vram->partitions[0].size -= size;
+	vram->num_partitions++;
+	drm_info(&xe->drm,
+		 "Created %s[%u] VRAM pool[%u]: purpose=%s offset=0x%llx size=0x%llx\n",
+		 stringify_vram_binding(vram->binding), vram->id,
+		 vram->num_partitions - 1,
+		 stringify_vram_pool_purpose(pool->purpose), pool->offset, pool->size);
+
+	return pool;
+}
+
 /**
  * xe_vram_pool_place - Fill in the TTM placement of a pool
  * @pool: the VRAM pool to place in
diff --git a/drivers/gpu/drm/xe/xe_vram.h b/drivers/gpu/drm/xe/xe_vram.h
index 184850f4ed188..c45e4934a90c6 100644
--- a/drivers/gpu/drm/xe/xe_vram.h
+++ b/drivers/gpu/drm/xe/xe_vram.h
@@ -21,6 +21,8 @@ int xe_vram_probe(struct xe_device *xe);
 struct xe_vram_region *xe_vram_region_alloc_device(struct xe_device *xe);
 struct xe_vram_region *xe_vram_region_alloc_tile(struct xe_device *xe, u8 id);
 struct xe_vram_pool *xe_vram_region_default_pool(struct xe_vram_region *vram);
+struct xe_vram_pool *xe_vram_pool_create(struct xe_vram_region *vram,
+					 enum xe_vram_pool_purpose purpose, u64 size);
 int xe_vram_tile_alloc_kernel(struct xe_tile *tile);
 
 void xe_vram_pool_place(const struct xe_vram_pool *pool, struct ttm_place *place);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v1 6/7] drm/xe/kunit: Test partitioned VRAM manager
  2026-10-02 10:40 [PATCH v1 0/7] Introduce purpose-specific VRAM pools Piórkowski, Piotr
                   ` (4 preceding siblings ...)
  2026-10-02 10:40 ` [PATCH v1 5/7] drm/xe/vram: Allow splitting a region into pools Piórkowski, Piotr
@ 2026-10-02 10:40 ` Piórkowski, Piotr
  2026-10-02 10:40 ` [PATCH v1 7/7] drm/xe/kunit: Test VRAM pool allocation Piórkowski, Piotr
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Piórkowski, Piotr @ 2026-10-02 10:40 UTC (permalink / raw)
  To: intel-xe; +Cc: Piotr Piórkowski

From: Piotr Piórkowski <piotr.piorkowski@intel.com>

Exercise partition selection and address lookup, plus pool usage and
CPU-visible memory accounting across partitions.

Assisted-by: Claude Opus 5.5
Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
---
 drivers/gpu/drm/xe/tests/xe_ttm_vram_mgr.c | 147 +++++++++++++++++++++
 drivers/gpu/drm/xe/xe_ttm_vram_mgr.c       |   4 +
 2 files changed, 151 insertions(+)
 create mode 100644 drivers/gpu/drm/xe/tests/xe_ttm_vram_mgr.c

diff --git a/drivers/gpu/drm/xe/tests/xe_ttm_vram_mgr.c b/drivers/gpu/drm/xe/tests/xe_ttm_vram_mgr.c
new file mode 100644
index 0000000000000..1ad3186e6d5be
--- /dev/null
+++ b/drivers/gpu/drm/xe/tests/xe_ttm_vram_mgr.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0 AND MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#include <kunit/test.h>
+
+#include "xe_vram_types.h"
+
+/* The layout xe_ttm_vram_mgr_init() derives from the pools of a region */
+static struct xe_ttm_vram_mgr *split_mgr(struct kunit *test, u64 kernel_size, u64 size)
+{
+	struct xe_ttm_vram_mgr *mgr;
+	struct xe_vram_pool *pools;
+
+	mgr = kunit_kzalloc(test, sizeof(*mgr), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, mgr);
+	pools = kunit_kcalloc(test, 2, sizeof(*pools), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, pools);
+
+	pools[0].offset = 0;
+	pools[0].size = kernel_size;
+	pools[0].purpose = XE_VRAM_POOL_KERNEL;
+	pools[1].offset = kernel_size;
+	pools[1].size = size - kernel_size;
+	pools[1].purpose = XE_VRAM_POOL_GENERAL;
+	mgr->parts[0].pool = &pools[0];
+	mgr->parts[1].pool = &pools[1];
+	mgr->num_parts = 2;
+
+	return mgr;
+}
+
+static void select_part(struct kunit *test)
+{
+	struct xe_ttm_vram_mgr *mgr = split_mgr(test, SZ_128M, SZ_1G);
+	struct xe_ttm_vram_mgr_part *part;
+	bool exact = false;
+
+	/* The ranges a pool resolves to cover a whole partition */
+	part = xe_ttm_vram_mgr_select_part(mgr, 0, SZ_128M, &exact);
+	KUNIT_EXPECT_PTR_EQ(test, part, &mgr->parts[0]);
+	KUNIT_EXPECT_TRUE(test, exact);
+
+	part = xe_ttm_vram_mgr_select_part(mgr, SZ_128M, SZ_1G, &exact);
+	KUNIT_EXPECT_PTR_EQ(test, part, &mgr->parts[1]);
+	KUNIT_EXPECT_TRUE(test, exact);
+
+	/* A narrower range still resolves, but needs a range allocation */
+	part = xe_ttm_vram_mgr_select_part(mgr, SZ_256M, SZ_512M, &exact);
+	KUNIT_EXPECT_PTR_EQ(test, part, &mgr->parts[1]);
+	KUNIT_EXPECT_FALSE(test, exact);
+
+	/* Partitions are a hard split */
+	part = xe_ttm_vram_mgr_select_part(mgr, 0, SZ_256M, &exact);
+	KUNIT_EXPECT_NULL(test, part);
+	part = xe_ttm_vram_mgr_select_part(mgr, 0, SZ_2G, &exact);
+	KUNIT_EXPECT_NULL(test, part);
+}
+
+static void addr_to_part(struct kunit *test)
+{
+	struct xe_ttm_vram_mgr *mgr = split_mgr(test, SZ_128M, SZ_1G);
+
+	KUNIT_EXPECT_PTR_EQ(test, xe_ttm_vram_mgr_addr_to_part(mgr, 0), &mgr->parts[0]);
+	KUNIT_EXPECT_PTR_EQ(test, xe_ttm_vram_mgr_addr_to_part(mgr, SZ_128M - PAGE_SIZE),
+			    &mgr->parts[0]);
+	KUNIT_EXPECT_PTR_EQ(test, xe_ttm_vram_mgr_addr_to_part(mgr, SZ_128M), &mgr->parts[1]);
+	KUNIT_EXPECT_PTR_EQ(test, xe_ttm_vram_mgr_addr_to_part(mgr, SZ_1G - PAGE_SIZE),
+			    &mgr->parts[1]);
+	KUNIT_EXPECT_NULL(test, xe_ttm_vram_mgr_addr_to_part(mgr, SZ_1G));
+}
+
+static void general_pool_usage(struct kunit *test)
+{
+	struct xe_ttm_vram_mgr *mgr = split_mgr(test, SZ_128M, SZ_1G);
+	LIST_HEAD(kernel_blocks);
+	LIST_HEAD(general_blocks);
+	u64 kernel_visible = 0;
+	u64 general_visible = 0;
+	u64 used, used_visible;
+	unsigned int i;
+	int err;
+
+	mutex_init(&mgr->lock);
+	/* Only the bottom 256M are CPU visible */
+	mgr->visible_size = SZ_256M;
+	mgr->visible_avail = SZ_256M;
+	for (i = 0; i < mgr->num_parts; ++i) {
+		KUNIT_ASSERT_EQ(test, gpu_buddy_init(&mgr->parts[i].mm,
+						     mgr->parts[i].pool->size,
+						     PAGE_SIZE), 0);
+		gpu_buddy_driver_set_lock(&mgr->parts[i].mm, &mgr->lock);
+	}
+
+	mutex_lock(&mgr->lock);
+	err = xe_ttm_vram_buddy_alloc(mgr, &mgr->parts[0], 0, SZ_128M, SZ_8M,
+				      PAGE_SIZE, &kernel_blocks,
+				      GPU_BUDDY_RANGE_ALLOCATION, NULL,
+				      &kernel_visible);
+	KUNIT_EXPECT_EQ(test, err, 0);
+	/* Straddles the end of the CPU visible window */
+	err = xe_ttm_vram_buddy_alloc(mgr, &mgr->parts[1], SZ_256M - SZ_4M,
+				      SZ_256M + SZ_4M, SZ_8M, PAGE_SIZE,
+				      &general_blocks,
+				      GPU_BUDDY_RANGE_ALLOCATION, NULL,
+				      &general_visible);
+	KUNIT_EXPECT_EQ(test, err, 0);
+	mutex_unlock(&mgr->lock);
+
+	KUNIT_EXPECT_EQ(test, kernel_visible, (u64)SZ_8M);
+	KUNIT_EXPECT_EQ(test, general_visible, (u64)SZ_4M);
+	KUNIT_EXPECT_EQ(test, mgr->visible_avail, (u64)(SZ_256M - SZ_8M - SZ_4M));
+
+	/* Memory taken from the kernel-only pool is not reported */
+	xe_ttm_vram_get_general_pool_used(&mgr->manager, &used, &used_visible);
+	KUNIT_EXPECT_EQ(test, used, (u64)SZ_8M);
+	KUNIT_EXPECT_EQ(test, used_visible, (u64)SZ_4M);
+
+	mutex_lock(&mgr->lock);
+	xe_ttm_vram_buddy_free(mgr, &mgr->parts[0], &kernel_blocks, kernel_visible);
+	xe_ttm_vram_buddy_free(mgr, &mgr->parts[1], &general_blocks, general_visible);
+	mutex_unlock(&mgr->lock);
+
+	xe_ttm_vram_get_general_pool_used(&mgr->manager, &used, &used_visible);
+	KUNIT_EXPECT_EQ(test, used, 0ull);
+	KUNIT_EXPECT_EQ(test, used_visible, 0ull);
+	KUNIT_EXPECT_EQ(test, mgr->visible_avail, (u64)SZ_256M);
+
+	for (i = 0; i < mgr->num_parts; ++i)
+		gpu_buddy_fini(&mgr->parts[i].mm);
+	mutex_destroy(&mgr->lock);
+}
+
+static struct kunit_case xe_ttm_vram_mgr_tests[] = {
+	KUNIT_CASE(select_part),
+	KUNIT_CASE(addr_to_part),
+	KUNIT_CASE(general_pool_usage),
+	{}
+};
+
+static struct kunit_suite xe_ttm_vram_mgr_test_suite = {
+	.name = "xe_ttm_vram_mgr",
+	.test_cases = xe_ttm_vram_mgr_tests,
+};
+
+kunit_test_suite(xe_ttm_vram_mgr_test_suite);
diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
index d4665851f727b..4cc720c9f9caa 100644
--- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
+++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
@@ -1285,3 +1285,7 @@ void xe_ttm_vram_debugfs_init(struct xe_device *xe, struct dentry *root)
 		return;
 	debugfs_create_file("vram_bad_pages", 0444, root, xe, &vram_bad_pages_fops);
 }
+
+#if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST)
+#include "tests/xe_ttm_vram_mgr.c"
+#endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v1 7/7] drm/xe/kunit: Test VRAM pool allocation
  2026-10-02 10:40 [PATCH v1 0/7] Introduce purpose-specific VRAM pools Piórkowski, Piotr
                   ` (5 preceding siblings ...)
  2026-10-02 10:40 ` [PATCH v1 6/7] drm/xe/kunit: Test partitioned VRAM manager Piórkowski, Piotr
@ 2026-10-02 10:40 ` Piórkowski, Piotr
  2026-10-02 10:47 ` ✗ CI.checkpatch: warning for Introduce purpose-specific VRAM pools Patchwork
  2026-10-02 10:49 ` ✓ CI.KUnit: success " Patchwork
  8 siblings, 0 replies; 11+ messages in thread
From: Piórkowski, Piotr @ 2026-10-02 10:40 UTC (permalink / raw)
  To: intel-xe; +Cc: Piotr Piórkowski

From: Piotr Piórkowski <piotr.piorkowski@intel.com>

Exercise default pool setup, pool splitting and partition limits, and
TTM placement range narrowing.

Assisted-by: Claude Opus 5.5
Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
---
 drivers/gpu/drm/xe/tests/xe_vram.c | 155 +++++++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_vram.c       |   4 +
 2 files changed, 159 insertions(+)
 create mode 100644 drivers/gpu/drm/xe/tests/xe_vram.c

diff --git a/drivers/gpu/drm/xe/tests/xe_vram.c b/drivers/gpu/drm/xe/tests/xe_vram.c
new file mode 100644
index 0000000000000..043c40b6bb0a9
--- /dev/null
+++ b/drivers/gpu/drm/xe/tests/xe_vram.c
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: GPL-2.0 AND MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#include <kunit/test.h>
+
+#include "xe_kunit_helpers.h"
+#include "xe_pci_test.h"
+
+static int xe_vram_test_init(struct kunit *test)
+{
+	struct xe_pci_fake_data fake = {
+		.platform = XE_BATTLEMAGE,
+		.graphics_verx100 = 2001,
+	};
+
+	test->priv = &fake;
+	xe_kunit_helper_xe_device_test_init(test);
+
+	return 0;
+}
+
+static struct xe_vram_pool *tile_pool(struct kunit *test, struct xe_device *xe)
+{
+	struct xe_vram_region *vram = xe_vram_region_alloc_tile(xe, 0);
+	struct xe_vram_pool *pool;
+
+	KUNIT_ASSERT_NOT_NULL(test, vram);
+	vram->usable_size = SZ_64M;
+	vram->io_size = SZ_64M;
+	pool = xe_vram_region_default_pool(vram);
+	pool->size = SZ_64M;
+	pool->purpose = XE_VRAM_POOL_GENERAL;
+	vram->num_partitions = 1;
+
+	return pool;
+}
+
+static void kernel_pool_defaults_to_general(struct kunit *test)
+{
+	struct xe_device *xe = test->priv;
+	struct xe_vram_pool *general = tile_pool(test, xe);
+	struct xe_tile *tile = &xe->tiles[0];
+
+	tile->mem.vram = general;
+	tile->mem.kernel_vram = NULL;
+
+	KUNIT_ASSERT_EQ(test, xe_vram_tile_alloc_kernel(tile), 0);
+	KUNIT_EXPECT_PTR_EQ(test, tile->mem.kernel_vram, tile->mem.vram);
+}
+
+static void partition_carve(struct kunit *test)
+{
+	struct xe_device *xe = test->priv;
+	struct xe_vram_pool *general = tile_pool(test, xe);
+	struct xe_vram_region *vram = general->region;
+	struct xe_vram_pool *kernel0 = &vram->partitions[1];
+
+	KUNIT_EXPECT_PTR_EQ(test, xe_vram_pool_create(vram, XE_VRAM_POOL_KERNEL, 0), NULL);
+	KUNIT_EXPECT_PTR_EQ(test, xe_vram_pool_create(vram, XE_VRAM_POOL_KERNEL, SZ_1M), NULL);
+	KUNIT_EXPECT_PTR_EQ(test, xe_vram_pool_create(vram, XE_VRAM_POOL_KERNEL, SZ_64M), NULL);
+	KUNIT_EXPECT_EQ(test, vram->num_partitions, 1u);
+
+	KUNIT_ASSERT_NOT_NULL(test, xe_vram_pool_create(vram, XE_VRAM_POOL_KERNEL, SZ_8M));
+	KUNIT_ASSERT_EQ(test, vram->num_partitions, 2u);
+	KUNIT_EXPECT_EQ(test, kernel0->purpose, XE_VRAM_POOL_KERNEL);
+	KUNIT_EXPECT_EQ(test, kernel0->offset, 0ull);
+	KUNIT_EXPECT_EQ(test, kernel0->size, (u64)SZ_8M);
+	KUNIT_EXPECT_EQ(test, general->purpose, XE_VRAM_POOL_GENERAL);
+	KUNIT_EXPECT_EQ(test, general->offset, (u64)SZ_8M);
+	KUNIT_EXPECT_EQ(test, general->size, (u64)(SZ_64M - SZ_8M));
+
+	/* Both partitions keep sharing the region, its manager and its placement */
+	KUNIT_EXPECT_PTR_EQ(test, kernel0->region, vram);
+	KUNIT_EXPECT_PTR_EQ(test, general->region, vram);
+	KUNIT_EXPECT_EQ(test, vram->placement, (u32)XE_PL_VRAM0);
+
+	KUNIT_EXPECT_EQ(test, xe_vram_pool_usable_size(kernel0), (resource_size_t)SZ_8M);
+	KUNIT_EXPECT_EQ(test, xe_vram_pool_usable_size(general),
+			(resource_size_t)(SZ_64M - SZ_8M));
+}
+
+static void partition_limit(struct kunit *test)
+{
+	struct xe_device *xe = test->priv;
+	struct xe_vram_pool *general = tile_pool(test, xe);
+	struct xe_vram_region *vram = general->region;
+	struct xe_vram_pool *pool;
+	unsigned int i;
+
+	for (i = 1; i < XE_VRAM_MAX_PARTITIONS; i++) {
+		pool = xe_vram_pool_create(vram, XE_VRAM_POOL_KERNEL, SZ_2M);
+		KUNIT_ASSERT_NOT_NULL(test, pool);
+	}
+
+	KUNIT_EXPECT_EQ(test, vram->num_partitions, XE_VRAM_MAX_PARTITIONS);
+	KUNIT_EXPECT_PTR_EQ(test,
+			    xe_vram_pool_create(vram, XE_VRAM_POOL_KERNEL, SZ_2M),
+			    NULL);
+}
+
+static void pool_place(struct kunit *test)
+{
+	struct xe_device *xe = test->priv;
+	struct xe_vram_pool *general = tile_pool(test, xe);
+	struct xe_vram_region *vram = general->region;
+	struct xe_vram_pool *kernel = &vram->partitions[1];
+	struct ttm_place place = {};
+
+	/* A pool spanning the region only resolves to its placement */
+	xe_vram_pool_place(general, &place);
+	KUNIT_EXPECT_EQ(test, place.mem_type, (u32)XE_PL_VRAM0);
+	KUNIT_EXPECT_EQ(test, place.fpfn, 0u);
+	KUNIT_EXPECT_EQ(test, place.lpfn, 0u);
+
+	KUNIT_ASSERT_NOT_NULL(test, xe_vram_pool_create(vram, XE_VRAM_POOL_KERNEL, SZ_8M));
+
+	place = (struct ttm_place) {};
+	xe_vram_pool_place(kernel, &place);
+	KUNIT_EXPECT_EQ(test, place.fpfn, 0u);
+	KUNIT_EXPECT_EQ(test, place.lpfn, SZ_8M >> PAGE_SHIFT);
+
+	place = (struct ttm_place) {};
+	xe_vram_pool_place(general, &place);
+	KUNIT_EXPECT_EQ(test, place.fpfn, SZ_8M >> PAGE_SHIFT);
+	KUNIT_EXPECT_EQ(test, place.lpfn, SZ_64M >> PAGE_SHIFT);
+
+	/* A caller supplied range, e.g. the CPU visible one, is only narrowed */
+	place = (struct ttm_place) { .lpfn = SZ_4M >> PAGE_SHIFT };
+	xe_vram_pool_place(kernel, &place);
+	KUNIT_EXPECT_EQ(test, place.fpfn, 0u);
+	KUNIT_EXPECT_EQ(test, place.lpfn, SZ_4M >> PAGE_SHIFT);
+
+	place = (struct ttm_place) { .lpfn = SZ_32M >> PAGE_SHIFT };
+	xe_vram_pool_place(general, &place);
+	KUNIT_EXPECT_EQ(test, place.fpfn, SZ_8M >> PAGE_SHIFT);
+	KUNIT_EXPECT_EQ(test, place.lpfn, SZ_32M >> PAGE_SHIFT);
+}
+
+static struct kunit_case xe_vram_tests[] = {
+	KUNIT_CASE(kernel_pool_defaults_to_general),
+	KUNIT_CASE(partition_carve),
+	KUNIT_CASE(partition_limit),
+	KUNIT_CASE(pool_place),
+	{}
+};
+
+static struct kunit_suite xe_vram_test_suite = {
+	.name = "xe_vram",
+	.test_cases = xe_vram_tests,
+	.init = xe_vram_test_init,
+};
+
+kunit_test_suite(xe_vram_test_suite);
diff --git a/drivers/gpu/drm/xe/xe_vram.c b/drivers/gpu/drm/xe/xe_vram.c
index 1df4f2514afc0..cfc1dc77b2cb4 100644
--- a/drivers/gpu/drm/xe/xe_vram.c
+++ b/drivers/gpu/drm/xe/xe_vram.c
@@ -639,6 +639,10 @@ resource_size_t xe_vram_region_actual_physical_size(const struct xe_vram_region
 }
 EXPORT_SYMBOL_IF_KUNIT(xe_vram_region_actual_physical_size);
 
+#if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST)
+#include "tests/xe_vram.c"
+#endif
+
 #if IS_ENABLED(CONFIG_DRM_XE_DEBUG_MEM)
 static void memtest_bo_cleanup(void *arg)
 {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* ✗ CI.checkpatch: warning for Introduce purpose-specific VRAM pools
  2026-10-02 10:40 [PATCH v1 0/7] Introduce purpose-specific VRAM pools Piórkowski, Piotr
                   ` (6 preceding siblings ...)
  2026-10-02 10:40 ` [PATCH v1 7/7] drm/xe/kunit: Test VRAM pool allocation Piórkowski, Piotr
@ 2026-10-02 10:47 ` Patchwork
  2026-10-02 10:49 ` ✓ CI.KUnit: success " Patchwork
  8 siblings, 0 replies; 11+ messages in thread
From: Patchwork @ 2026-10-02 10:47 UTC (permalink / raw)
  To: Piórkowski, Piotr; +Cc: intel-xe

== Series Details ==

Series: Introduce purpose-specific VRAM pools
URL   : https://patchwork.freedesktop.org/series/175411/
State : warning

== Summary ==

+ KERNEL=/kernel
+ git clone https://gitlab.freedesktop.org/drm/maintainer-tools mt
Cloning into 'mt'...
warning: redirecting to https://gitlab.freedesktop.org/drm/maintainer-tools.git/
+ git -C mt rev-list -n1 origin/master
6bef5ce5c74dc76b4ee69ab2832c0d1fd63c91c7
+ cd /kernel
+ git config --global --add safe.directory /kernel
+ git log -n1
commit 05303bf785e248bace09283bc017f7f694fde2ef
Author: Piotr Piórkowski <piotr.piorkowski@intel.com>
Date:   Fri Oct 2 12:40:18 2026 +0200

    drm/xe/kunit: Test VRAM pool allocation
    
    Exercise default pool setup, pool splitting and partition limits, and
    TTM placement range narrowing.
    
    Assisted-by: Claude Opus 5.5
    Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
+ /mt/dim checkpatch e38a977a5512cc72c297eeb5b048a24201622900 drm-intel
88be58c8e8a4 drm/xe: Define partitioned VRAM manager types
397361c6572f drm/xe: Define VRAM regions and pools
1eb4a7ff10d7 drm/xe/vram: Make VRAM pools the allocation handle
9e799ed9f63c drm/xe/ttm: Back each VRAM pool with its own buddy allocator
5d645ffb8b3d drm/xe/vram: Allow splitting a region into pools
e2c93f9f25ef drm/xe/kunit: Test partitioned VRAM manager
-:16: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#16: 
new file mode 100644

total: 0 errors, 1 warnings, 0 checks, 154 lines checked
05303bf785e2 drm/xe/kunit: Test VRAM pool allocation
-:16: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#16: 
new file mode 100644

total: 0 errors, 1 warnings, 0 checks, 165 lines checked



^ permalink raw reply	[flat|nested] 11+ messages in thread

* ✓ CI.KUnit: success for Introduce purpose-specific VRAM pools
  2026-10-02 10:40 [PATCH v1 0/7] Introduce purpose-specific VRAM pools Piórkowski, Piotr
                   ` (7 preceding siblings ...)
  2026-10-02 10:47 ` ✗ CI.checkpatch: warning for Introduce purpose-specific VRAM pools Patchwork
@ 2026-10-02 10:49 ` Patchwork
  8 siblings, 0 replies; 11+ messages in thread
From: Patchwork @ 2026-10-02 10:49 UTC (permalink / raw)
  To: Piórkowski, Piotr; +Cc: intel-xe

== Series Details ==

Series: Introduce purpose-specific VRAM pools
URL   : https://patchwork.freedesktop.org/series/175411/
State : success

== Summary ==

+ trap cleanup EXIT
+ kunitconfigs=('/kernel/drivers/gpu/tests/.kunitconfig' '/kernel/drivers/gpu/drm/xe/.kunitconfig' '/kernel/drivers/gpu/drm/tests/.kunitconfig' '/kernel/drivers/gpu/drm/ttm/tests/.kunitconfig' '/kernel/drivers/dma-buf/.kunitconfig')
+ for kcfg in "${kunitconfigs[@]}"
+ [[ ! -f /kernel/drivers/gpu/tests/.kunitconfig ]]
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/tests/.kunitconfig
[10:47:54] Configuring KUnit Kernel ...
Generating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[10:47:58] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[10:48:19] Starting KUnit Kernel (1/1)...
[10:48:19] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[10:48:19] ============= refcount_interrupt (4 subtests) ==============
[10:48:19] [PASSED] test_single_irq_change
[10:48:19] [PASSED] test_nested_irq_change
[10:48:19] [PASSED] test_multiple_irq_change
[10:48:19] [PASSED] test_irq_save
[10:48:19] =============== [PASSED] refcount_interrupt ================
[10:48:19] ================= gpu_buddy (14 subtests) ==================
[10:48:19] [PASSED] gpu_test_buddy_alloc_limit
[10:48:19] [PASSED] gpu_test_buddy_alloc_optimistic
[10:48:19] [PASSED] gpu_test_buddy_alloc_pessimistic
[10:48:19] [PASSED] gpu_test_buddy_alloc_pathological
[10:48:19] [PASSED] gpu_test_buddy_alloc_contiguous
[10:48:19] [PASSED] gpu_test_buddy_alloc_clear
[10:48:19] [PASSED] gpu_test_buddy_alloc_range
[10:48:19] [PASSED] gpu_test_buddy_alloc_range_bias
[10:48:20] [PASSED] gpu_test_buddy_fragmentation_performance
[10:48:21] [PASSED] gpu_test_buddy_dirty_tracker_performance
[10:48:21] [PASSED] gpu_test_buddy_alloc_exceeds_max_order
[10:48:21] [PASSED] gpu_test_buddy_offset_aligned_allocation
[10:48:21] [PASSED] gpu_test_buddy_subtree_offset_alignment_stress
[10:48:21] [PASSED] gpu_test_buddy_addr_to_block
[10:48:21] ==================== [PASSED] gpu_buddy ====================
[10:48:21] ============================================================
[10:48:21] Testing complete. Ran 18 tests: passed: 18
[10:48:21] Elapsed time: 27.083s total, 4.448s configuring, 20.718s building, 1.838s running

+ for kcfg in "${kunitconfigs[@]}"
+ [[ ! -f /kernel/drivers/gpu/drm/xe/.kunitconfig ]]
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/xe/.kunitconfig
[10:48:21] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[10:48:23] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[10:48:58] Starting KUnit Kernel (1/1)...
[10:48:58] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[10:48:58] ============= refcount_interrupt (4 subtests) ==============
[10:48:58] [PASSED] test_single_irq_change
[10:48:58] [PASSED] test_nested_irq_change
[10:48:58] [PASSED] test_multiple_irq_change
[10:48:58] [PASSED] test_irq_save
[10:48:58] =============== [PASSED] refcount_interrupt ================
[10:48:58] ================== guc_buf (11 subtests) ===================
[10:48:58] [PASSED] test_smallest
[10:48:58] [PASSED] test_largest
[10:48:58] [PASSED] test_granular
[10:48:58] [PASSED] test_unique
[10:48:58] [PASSED] test_overlap
[10:48:58] [PASSED] test_reusable
[10:48:58] [PASSED] test_too_big
[10:48:58] [PASSED] test_flush
[10:48:58] [PASSED] test_lookup
[10:48:58] [PASSED] test_data
[10:48:58] [PASSED] test_class
[10:48:58] ===================== [PASSED] guc_buf =====================
[10:48:58] =================== guc_dbm (7 subtests) ===================
[10:48:58] [PASSED] test_empty
[10:48:58] [PASSED] test_default
[10:48:58] ======================== test_size  ========================
[10:48:58] [PASSED] 4
[10:48:58] [PASSED] 8
[10:48:58] [PASSED] 32
[10:48:58] [PASSED] 256
[10:48:58] ==================== [PASSED] test_size ====================
[10:48:58] ======================= test_reuse  ========================
[10:48:58] [PASSED] 4
[10:48:58] [PASSED] 8
[10:48:58] [PASSED] 32
[10:48:58] [PASSED] 256
[10:48:58] =================== [PASSED] test_reuse ====================
[10:48:58] =================== test_range_overlap  ====================
[10:48:58] [PASSED] 4
[10:48:58] [PASSED] 8
[10:48:58] [PASSED] 32
[10:48:58] [PASSED] 256
[10:48:58] =============== [PASSED] test_range_overlap ================
[10:48:58] =================== test_range_compact  ====================
[10:48:58] [PASSED] 4
[10:48:58] [PASSED] 8
[10:48:58] [PASSED] 32
[10:48:58] [PASSED] 256
[10:48:58] =============== [PASSED] test_range_compact ================
[10:48:58] ==================== test_range_spare  =====================
[10:48:58] [PASSED] 4
[10:48:58] [PASSED] 8
[10:48:58] [PASSED] 32
[10:48:58] [PASSED] 256
[10:48:58] ================ [PASSED] test_range_spare =================
[10:48:58] ===================== [PASSED] guc_dbm =====================
[10:48:58] =================== guc_idm (6 subtests) ===================
[10:48:58] [PASSED] bad_init
[10:48:58] [PASSED] no_init
[10:48:58] [PASSED] init_fini
[10:48:58] [PASSED] check_used
[10:48:58] [PASSED] check_quota
[10:48:58] [PASSED] check_all
[10:48:58] ===================== [PASSED] guc_idm =====================
[10:48:58] ============== guc_klv_helpers (13 subtests) ===============
[10:48:58] [PASSED] test_count
[10:48:58] [PASSED] test_encode_u32
[10:48:58] [PASSED] test_encode_u64
[10:48:58] [PASSED] test_encode_string
[10:48:58] [PASSED] test_encode_object_raw
[10:48:58] [PASSED] test_encode_object_klv
[10:48:58] [PASSED] test_encode_object_nested
[10:48:58] [PASSED] test_encode_object_basic
[10:48:58] ===================== test_decode_u16  =====================
[10:48:58] [PASSED] empty
[10:48:58] [PASSED] valid
[10:48:58] [PASSED] max
[10:48:58] [PASSED] big
[10:48:58] [PASSED] long
[10:48:58] ================= [PASSED] test_decode_u16 =================
[10:48:58] ===================== test_decode_u32  =====================
[10:48:58] [PASSED] empty
[10:48:58] [PASSED] valid
[10:48:58] [PASSED] max
[10:48:58] [PASSED] long
[10:48:58] ================= [PASSED] test_decode_u32 =================
[10:48:58] ===================== test_decode_u64  =====================
[10:48:58] [PASSED] empty
[10:48:58] [PASSED] short
[10:48:58] [PASSED] valid
[10:48:58] [PASSED] max
[10:48:58] [PASSED] long
[10:48:58] ================= [PASSED] test_decode_u64 =================
[10:48:58] ===================== test_decode_str  =====================
[10:48:58] [PASSED] empty
[10:48:58] [PASSED] one
[10:48:58] [PASSED] one_trash
[10:48:58] [PASSED] two
[10:48:58] [PASSED] two_trash
[10:48:58] [PASSED] three
[10:48:58] [PASSED] dword
[10:48:58] [PASSED] four
[10:48:58] [PASSED] five
[10:48:58] [PASSED] six
[10:48:58] [PASSED] seven
[10:48:58] [PASSED] qword
[10:48:58] ================= [PASSED] test_decode_str =================
[10:48:58] [PASSED] test_print
[10:48:58] ================= [PASSED] guc_klv_helpers =================
[10:48:58] =================== xe_log (4 subtests) ====================
[10:48:58] [PASSED] demo_cper
[10:48:58] [PASSED] demo_dmesg
[10:48:58] ======================= test_dmesg  ========================
[10:48:58] [PASSED] test_fatal
[10:48:58] [PASSED] test_fatal_tile
[10:48:58] [PASSED] test_fatal_gt
[10:48:58] [PASSED] test_fatal_comp
[10:48:58] [PASSED] test_fatal_comp_tile
[10:48:58] [PASSED] test_fatal_comp_gt
[10:48:58] [PASSED] test_fatal_all
[10:48:58] [PASSED] test_recoverable
[10:48:58] [PASSED] test_recoverable_tile
[10:48:58] [PASSED] test_recoverable_gt
[10:48:58] [PASSED] test_recoverable_comp
[10:48:58] [PASSED] test_recoverable_comp_tile
[10:48:58] [PASSED] test_recoverable_comp_gt
[10:48:58] [PASSED] test_recoverable_all
[10:48:58] [PASSED] test_info
[10:48:58] [PASSED] test_info_tile
[10:48:58] [PASSED] test_info_gt
[10:48:58] [PASSED] test_info_err
[10:48:58] [PASSED] test_info_comp
[10:48:58] [PASSED] test_info_comp_tile
[10:48:58] [PASSED] test_info_comp_gt
[10:48:58] [PASSED] test_info_all
[10:48:58] [PASSED] test_hw_fatal
[10:48:58] [PASSED] test_hw_recoverable
[10:48:58] [PASSED] test_hw_corrected
[10:48:58] [PASSED] test_hw_informational
[10:48:58] =================== [PASSED] test_dmesg ====================
[10:48:58] ====================== test_invalid  =======================
[10:48:58] [SKIPPED] no-component no-location no-warn (requires CONFIG_DRM_XE_DEBUG)
[10:48:58] [SKIPPED] reserved location (requires CONFIG_DRM_XE_DEBUG)
[10:48:58] [SKIPPED] unknown location (requires CONFIG_DRM_XE_DEBUG)
[10:48:58] [SKIPPED] nonzero-device-id location (requires CONFIG_DRM_XE_DEBUG)
[10:48:58] [SKIPPED] invalid-tile-id location (requires CONFIG_DRM_XE_DEBUG)
[10:48:58] [SKIPPED] invalid-gt-id location (requires CONFIG_DRM_XE_DEBUG)
[10:48:58] [SKIPPED] unknown component class (requires CONFIG_DRM_XE_DEBUG)
[10:48:58] [SKIPPED] unknown system component (requires CONFIG_DRM_XE_DEBUG)
[10:48:58] [SKIPPED] unknown hardware component (requires CONFIG_DRM_XE_DEBUG)
[10:48:58] [SKIPPED] unknown component and location (requires CONFIG_DRM_XE_DEBUG)
[10:48:58] ================== [SKIPPED] test_invalid ==================
[10:48:58] ===================== [PASSED] xe_log ======================
[10:48:58] =============== xe_ttm_vram_mgr (3 subtests) ===============
[10:48:58] [PASSED] select_part
[10:48:58] [PASSED] addr_to_part
[10:48:58] [PASSED] general_pool_usage
[10:48:58] ================= [PASSED] xe_ttm_vram_mgr =================
[10:48:58] =================== xe_vram (4 subtests) ===================
[10:48:58] [PASSED] kernel_pool_defaults_to_general
[10:48:58] [PASSED] partition_carve
[10:48:58] [PASSED] partition_limit
[10:48:58] [PASSED] pool_place
[10:48:58] ===================== [PASSED] xe_vram =====================
[10:48:58] ================== no_relay (3 subtests) ===================
[10:48:58] [PASSED] xe_drops_guc2pf_if_not_ready
[10:48:58] [PASSED] xe_drops_guc2vf_if_not_ready
[10:48:58] [PASSED] xe_rejects_send_if_not_ready
[10:48:58] ==================== [PASSED] no_relay =====================
[10:48:58] ================== pf_relay (14 subtests) ==================
[10:48:58] [PASSED] pf_rejects_guc2pf_too_short
[10:48:58] [PASSED] pf_rejects_guc2pf_too_long
[10:48:58] [PASSED] pf_rejects_guc2pf_no_payload
[10:48:58] [PASSED] pf_fails_no_payload
[10:48:58] [PASSED] pf_fails_bad_origin
[10:48:58] [PASSED] pf_fails_bad_type
[10:48:58] [PASSED] pf_txn_reports_error
[10:48:58] [PASSED] pf_txn_sends_pf2guc
[10:48:58] [PASSED] pf_sends_pf2guc
[10:48:58] [SKIPPED] pf_loopback_nop (requires CONFIG_DRM_XE_DEBUG_SRIOV)
[10:48:58] [SKIPPED] pf_loopback_echo (requires CONFIG_DRM_XE_DEBUG_SRIOV)
[10:48:58] [SKIPPED] pf_loopback_fail (requires CONFIG_DRM_XE_DEBUG_SRIOV)
[10:48:58] [SKIPPED] pf_loopback_busy (requires CONFIG_DRM_XE_DEBUG_SRIOV)
[10:48:58] [SKIPPED] pf_loopback_retry (requires CONFIG_DRM_XE_DEBUG_SRIOV)
[10:48:58] ==================== [PASSED] pf_relay =====================
[10:48:58] ================== vf_relay (3 subtests) ===================
[10:48:58] [PASSED] vf_rejects_guc2vf_too_short
[10:48:58] [PASSED] vf_rejects_guc2vf_too_long
[10:48:58] [PASSED] vf_rejects_guc2vf_no_payload
[10:48:58] ==================== [PASSED] vf_relay =====================
[10:48:58] ================ pf_gt_config (9 subtests) =================
[10:48:58] [PASSED] fair_contexts_1vf
[10:48:58] [PASSED] fair_doorbells_1vf
[10:48:58] [PASSED] fair_ggtt_1vf
[10:48:58] ====================== fair_vram_1vf  ======================
[10:48:58] [PASSED] 3.50 GiB
[10:48:58] [PASSED] 11.5 GiB
[10:48:58] [PASSED] 15.5 GiB
[10:48:58] [PASSED] 31.5 GiB
[10:48:58] [PASSED] 63.5 GiB
[10:48:58] [PASSED] 1.91 GiB
[10:48:58] ================== [PASSED] fair_vram_1vf ==================
[10:48:58] ================ fair_vram_1vf_admin_only  =================
[10:48:58] [PASSED] 3.50 GiB
[10:48:58] [PASSED] 11.5 GiB
[10:48:58] [PASSED] 15.5 GiB
[10:48:58] [PASSED] 31.5 GiB
[10:48:58] [PASSED] 63.5 GiB
[10:48:58] [PASSED] 1.91 GiB
[10:48:58] ============ [PASSED] fair_vram_1vf_admin_only =============
[10:48:58] ====================== fair_contexts  ======================
[10:48:58] [PASSED] 1 VF
[10:48:58] [PASSED] 2 VFs
[10:48:58] [PASSED] 3 VFs
[10:48:58] [PASSED] 4 VFs
[10:48:58] [PASSED] 5 VFs
[10:48:58] [PASSED] 6 VFs
[10:48:58] [PASSED] 7 VFs
[10:48:58] [PASSED] 8 VFs
[10:48:58] [PASSED] 9 VFs
[10:48:58] [PASSED] 10 VFs
[10:48:58] [PASSED] 11 VFs
[10:48:58] [PASSED] 12 VFs
[10:48:58] [PASSED] 13 VFs
[10:48:58] [PASSED] 14 VFs
[10:48:58] [PASSED] 15 VFs
[10:48:58] [PASSED] 16 VFs
[10:48:58] [PASSED] 17 VFs
[10:48:58] [PASSED] 18 VFs
[10:48:58] [PASSED] 19 VFs
[10:48:58] [PASSED] 20 VFs
[10:48:58] [PASSED] 21 VFs
[10:48:58] [PASSED] 22 VFs
[10:48:58] [PASSED] 23 VFs
[10:48:58] [PASSED] 24 VFs
[10:48:58] [PASSED] 25 VFs
[10:48:58] [PASSED] 26 VFs
[10:48:58] [PASSED] 27 VFs
[10:48:58] [PASSED] 28 VFs
[10:48:58] [PASSED] 29 VFs
[10:48:58] [PASSED] 30 VFs
[10:48:58] [PASSED] 31 VFs
[10:48:58] [PASSED] 32 VFs
[10:48:58] [PASSED] 33 VFs
[10:48:58] [PASSED] 34 VFs
[10:48:58] [PASSED] 35 VFs
[10:48:58] [PASSED] 36 VFs
[10:48:58] [PASSED] 37 VFs
[10:48:58] [PASSED] 38 VFs
[10:48:58] [PASSED] 39 VFs
[10:48:58] [PASSED] 40 VFs
[10:48:58] [PASSED] 41 VFs
[10:48:58] [PASSED] 42 VFs
[10:48:58] [PASSED] 43 VFs
[10:48:58] [PASSED] 44 VFs
[10:48:58] [PASSED] 45 VFs
[10:48:58] [PASSED] 46 VFs
[10:48:58] [PASSED] 47 VFs
[10:48:58] [PASSED] 48 VFs
[10:48:58] [PASSED] 49 VFs
[10:48:58] [PASSED] 50 VFs
[10:48:58] [PASSED] 51 VFs
[10:48:58] [PASSED] 52 VFs
[10:48:58] [PASSED] 53 VFs
[10:48:58] [PASSED] 54 VFs
[10:48:58] [PASSED] 55 VFs
[10:48:58] [PASSED] 56 VFs
[10:48:58] [PASSED] 57 VFs
[10:48:58] [PASSED] 58 VFs
[10:48:58] [PASSED] 59 VFs
[10:48:58] [PASSED] 60 VFs
[10:48:58] [PASSED] 61 VFs
[10:48:58] [PASSED] 62 VFs
[10:48:58] [PASSED] 63 VFs
[10:48:58] ================== [PASSED] fair_contexts ==================
[10:48:58] ===================== fair_doorbells  ======================
[10:48:58] [PASSED] 1 VF
[10:48:58] [PASSED] 2 VFs
[10:48:58] [PASSED] 3 VFs
[10:48:58] [PASSED] 4 VFs
[10:48:58] [PASSED] 5 VFs
[10:48:58] [PASSED] 6 VFs
[10:48:58] [PASSED] 7 VFs
[10:48:58] [PASSED] 8 VFs
[10:48:58] [PASSED] 9 VFs
[10:48:58] [PASSED] 10 VFs
[10:48:58] [PASSED] 11 VFs
[10:48:58] [PASSED] 12 VFs
[10:48:58] [PASSED] 13 VFs
[10:48:58] [PASSED] 14 VFs
[10:48:58] [PASSED] 15 VFs
[10:48:58] [PASSED] 16 VFs
[10:48:58] [PASSED] 17 VFs
[10:48:58] [PASSED] 18 VFs
[10:48:58] [PASSED] 19 VFs
[10:48:58] [PASSED] 20 VFs
[10:48:58] [PASSED] 21 VFs
[10:48:58] [PASSED] 22 VFs
[10:48:58] [PASSED] 23 VFs
[10:48:58] [PASSED] 24 VFs
[10:48:58] [PASSED] 25 VFs
[10:48:58] [PASSED] 26 VFs
[10:48:58] [PASSED] 27 VFs
[10:48:58] [PASSED] 28 VFs
[10:48:58] [PASSED] 29 VFs
[10:48:58] [PASSED] 30 VFs
[10:48:58] [PASSED] 31 VFs
[10:48:58] [PASSED] 32 VFs
[10:48:58] [PASSED] 33 VFs
[10:48:58] [PASSED] 34 VFs
[10:48:58] [PASSED] 35 VFs
[10:48:58] [PASSED] 36 VFs
[10:48:58] [PASSED] 37 VFs
[10:48:58] [PASSED] 38 VFs
[10:48:58] [PASSED] 39 VFs
[10:48:58] [PASSED] 40 VFs
[10:48:58] [PASSED] 41 VFs
[10:48:58] [PASSED] 42 VFs
[10:48:58] [PASSED] 43 VFs
[10:48:58] [PASSED] 44 VFs
[10:48:58] [PASSED] 45 VFs
[10:48:58] [PASSED] 46 VFs
[10:48:58] [PASSED] 47 VFs
[10:48:58] [PASSED] 48 VFs
[10:48:58] [PASSED] 49 VFs
[10:48:58] [PASSED] 50 VFs
[10:48:58] [PASSED] 51 VFs
[10:48:58] [PASSED] 52 VFs
[10:48:58] [PASSED] 53 VFs
[10:48:58] [PASSED] 54 VFs
[10:48:58] [PASSED] 55 VFs
[10:48:58] [PASSED] 56 VFs
[10:48:58] [PASSED] 57 VFs
[10:48:58] [PASSED] 58 VFs
[10:48:58] [PASSED] 59 VFs
[10:48:58] [PASSED] 60 VFs
[10:48:58] [PASSED] 61 VFs
[10:48:58] [PASSED] 62 VFs
[10:48:58] [PASSED] 63 VFs
[10:48:58] ================= [PASSED] fair_doorbells ==================
[10:48:58] ======================== fair_ggtt  ========================
[10:48:58] [PASSED] 1 VF
[10:48:58] [PASSED] 2 VFs
[10:48:58] [PASSED] 3 VFs
[10:48:58] [PASSED] 4 VFs
[10:48:58] [PASSED] 5 VFs
[10:48:58] [PASSED] 6 VFs
[10:48:58] [PASSED] 7 VFs
[10:48:58] [PASSED] 8 VFs
[10:48:58] [PASSED] 9 VFs
[10:48:58] [PASSED] 10 VFs
[10:48:58] [PASSED] 11 VFs
[10:48:58] [PASSED] 12 VFs
[10:48:58] [PASSED] 13 VFs
[10:48:58] [PASSED] 14 VFs
[10:48:58] [PASSED] 15 VFs
[10:48:58] [PASSED] 16 VFs
[10:48:58] [PASSED] 17 VFs
[10:48:58] [PASSED] 18 VFs
[10:48:58] [PASSED] 19 VFs
[10:48:58] [PASSED] 20 VFs
[10:48:58] [PASSED] 21 VFs
[10:48:58] [PASSED] 22 VFs
[10:48:58] [PASSED] 23 VFs
[10:48:58] [PASSED] 24 VFs
[10:48:58] [PASSED] 25 VFs
[10:48:58] [PASSED] 26 VFs
[10:48:58] [PASSED] 27 VFs
[10:48:58] [PASSED] 28 VFs
[10:48:58] [PASSED] 29 VFs
[10:48:58] [PASSED] 30 VFs
[10:48:58] [PASSED] 31 VFs
[10:48:58] [PASSED] 32 VFs
[10:48:58] [PASSED] 33 VFs
[10:48:58] [PASSED] 34 VFs
[10:48:58] [PASSED] 35 VFs
[10:48:58] [PASSED] 36 VFs
[10:48:58] [PASSED] 37 VFs
[10:48:58] [PASSED] 38 VFs
[10:48:58] [PASSED] 39 VFs
[10:48:58] [PASSED] 40 VFs
[10:48:58] [PASSED] 41 VFs
[10:48:58] [PASSED] 42 VFs
[10:48:58] [PASSED] 43 VFs
[10:48:58] [PASSED] 44 VFs
[10:48:58] [PASSED] 45 VFs
[10:48:58] [PASSED] 46 VFs
[10:48:58] [PASSED] 47 VFs
[10:48:58] [PASSED] 48 VFs
[10:48:58] [PASSED] 49 VFs
[10:48:58] [PASSED] 50 VFs
[10:48:58] [PASSED] 51 VFs
[10:48:58] [PASSED] 52 VFs
[10:48:58] [PASSED] 53 VFs
[10:48:58] [PASSED] 54 VFs
[10:48:58] [PASSED] 55 VFs
[10:48:58] [PASSED] 56 VFs
[10:48:58] [PASSED] 57 VFs
[10:48:58] [PASSED] 58 VFs
[10:48:58] [PASSED] 59 VFs
[10:48:58] [PASSED] 60 VFs
[10:48:58] [PASSED] 61 VFs
[10:48:58] [PASSED] 62 VFs
[10:48:58] [PASSED] 63 VFs
[10:48:58] ==================== [PASSED] fair_ggtt ====================
[10:48:58] ======================== fair_vram  ========================
[10:48:58] [PASSED] 1 VF
[10:48:58] [PASSED] 2 VFs
[10:48:58] [PASSED] 3 VFs
[10:48:58] [PASSED] 4 VFs
[10:48:58] [PASSED] 5 VFs
[10:48:58] [PASSED] 6 VFs
[10:48:58] [PASSED] 7 VFs
[10:48:58] [PASSED] 8 VFs
[10:48:58] [PASSED] 9 VFs
[10:48:58] [PASSED] 10 VFs
[10:48:58] [PASSED] 11 VFs
[10:48:58] [PASSED] 12 VFs
[10:48:58] [PASSED] 13 VFs
[10:48:58] [PASSED] 14 VFs
[10:48:58] [PASSED] 15 VFs
[10:48:58] [PASSED] 16 VFs
[10:48:58] [PASSED] 17 VFs
[10:48:58] [PASSED] 18 VFs
[10:48:58] [PASSED] 19 VFs
[10:48:58] [PASSED] 20 VFs
[10:48:58] [PASSED] 21 VFs
[10:48:58] [PASSED] 22 VFs
[10:48:58] [PASSED] 23 VFs
[10:48:58] [PASSED] 24 VFs
[10:48:58] [PASSED] 25 VFs
[10:48:58] [PASSED] 26 VFs
[10:48:58] [PASSED] 27 VFs
[10:48:58] [PASSED] 28 VFs
[10:48:58] [PASSED] 29 VFs
[10:48:58] [PASSED] 30 VFs
[10:48:58] [PASSED] 31 VFs
[10:48:58] [PASSED] 32 VFs
[10:48:58] [PASSED] 33 VFs
[10:48:58] [PASSED] 34 VFs
[10:48:58] [PASSED] 35 VFs
[10:48:58] [PASSED] 36 VFs
[10:48:58] [PASSED] 37 VFs
[10:48:58] [PASSED] 38 VFs
[10:48:58] [PASSED] 39 VFs
[10:48:58] [PASSED] 40 VFs
[10:48:58] [PASSED] 41 VFs
[10:48:58] [PASSED] 42 VFs
[10:48:58] [PASSED] 43 VFs
[10:48:58] [PASSED] 44 VFs
[10:48:58] [PASSED] 45 VFs
[10:48:58] [PASSED] 46 VFs
[10:48:58] [PASSED] 47 VFs
[10:48:58] [PASSED] 48 VFs
[10:48:58] [PASSED] 49 VFs
[10:48:58] [PASSED] 50 VFs
[10:48:58] [PASSED] 51 VFs
[10:48:58] [PASSED] 52 VFs
[10:48:58] [PASSED] 53 VFs
[10:48:58] [PASSED] 54 VFs
[10:48:58] [PASSED] 55 VFs
[10:48:58] [PASSED] 56 VFs
[10:48:58] [PASSED] 57 VFs
[10:48:58] [PASSED] 58 VFs
[10:48:58] [PASSED] 59 VFs
[10:48:58] [PASSED] 60 VFs
[10:48:58] [PASSED] 61 VFs
[10:48:58] [PASSED] 62 VFs
[10:48:58] [PASSED] 63 VFs
[10:48:58] ==================== [PASSED] fair_vram ====================
[10:48:58] ================== [PASSED] pf_gt_config ===================
[10:48:58] ===================== lmtt (1 subtest) =====================
[10:48:58] ======================== test_ops  =========================
[10:48:58] [PASSED] 2-level
[10:48:58] [PASSED] multi-level
[10:48:58] ==================== [PASSED] test_ops =====================
[10:48:58] ====================== [PASSED] lmtt =======================
[10:48:58] ================= sriov_packet (1 subtest) =================
[10:48:58] [PASSED] test_descriptor_init
[10:48:58] ================== [PASSED] sriov_packet ===================
[10:48:58] ================= pf_service (11 subtests) =================
[10:48:58] [PASSED] pf_negotiate_any
[10:48:58] [PASSED] pf_negotiate_base_match
[10:48:58] [PASSED] pf_negotiate_base_newer
[10:48:58] [PASSED] pf_negotiate_base_next
[10:48:58] [SKIPPED] pf_negotiate_base_older (no older minor)
[10:48:58] [PASSED] pf_negotiate_base_prev
[10:48:58] [PASSED] pf_negotiate_latest_match
[10:48:58] [PASSED] pf_negotiate_latest_newer
[10:48:58] [PASSED] pf_negotiate_latest_next
[10:48:58] [SKIPPED] pf_negotiate_latest_older (no older minor)
[10:48:58] [SKIPPED] pf_negotiate_latest_prev (no prev major)
[10:48:58] =================== [PASSED] pf_service ====================
[10:48:58] ================= xe_guc_g2g (2 subtests) ==================
[10:48:58] ============== xe_live_guc_g2g_kunit_default  ==============
[10:48:58] ========= [SKIPPED] xe_live_guc_g2g_kunit_default ==========
[10:48:58] ============== xe_live_guc_g2g_kunit_allmem  ===============
[10:48:58] ========== [SKIPPED] xe_live_guc_g2g_kunit_allmem ==========
[10:48:58] =================== [SKIPPED] xe_guc_g2g ===================
[10:48:58] =================== xe_mocs (2 subtests) ===================
[10:48:58] ================ xe_live_mocs_kernel_kunit  ================
[10:48:58] =========== [SKIPPED] xe_live_mocs_kernel_kunit ============
[10:48:58] ================ xe_live_mocs_reset_kunit  =================
[10:48:58] ============ [SKIPPED] xe_live_mocs_reset_kunit ============
[10:48:58] ==================== [SKIPPED] xe_mocs =====================
[10:48:58] ================= xe_migrate (2 subtests) ==================
[10:48:58] ================= xe_migrate_sanity_kunit  =================
[10:48:58] ============ [SKIPPED] xe_migrate_sanity_kunit =============
[10:48:58] ================== xe_validate_ccs_kunit  ==================
[10:48:58] ============= [SKIPPED] xe_validate_ccs_kunit ==============
[10:48:58] =================== [SKIPPED] xe_migrate ===================
[10:48:58] ================== xe_dma_buf (1 subtest) ==================
[10:48:58] ==================== xe_dma_buf_kunit  =====================
[10:48:58] ================ [SKIPPED] xe_dma_buf_kunit ================
[10:48:58] =================== [SKIPPED] xe_dma_buf ===================
[10:48:58] ================= xe_bo_shrink (1 subtest) =================
[10:48:58] =================== xe_bo_shrink_kunit  ====================
[10:48:58] =============== [SKIPPED] xe_bo_shrink_kunit ===============
[10:48:58] ================== [SKIPPED] xe_bo_shrink ==================
[10:48:58] ==================== xe_bo (2 subtests) ====================
[10:48:58] ================== xe_ccs_migrate_kunit  ===================
[10:48:58] ============== [SKIPPED] xe_ccs_migrate_kunit ==============
[10:48:58] ==================== xe_bo_evict_kunit  ====================
[10:48:58] =============== [SKIPPED] xe_bo_evict_kunit ================
[10:48:58] ===================== [SKIPPED] xe_bo ======================
[10:48:58] =================== xe_any (9 subtests) ====================
[10:48:58] [PASSED] test_to_xe
[10:48:58] [PASSED] test_to_dev
[10:48:58] [PASSED] test_to_pdev
[10:48:58] [PASSED] test_to_drm
[10:48:58] [PASSED] test_if_pdev
[10:48:58] [PASSED] test_if_xe
[10:48:58] [PASSED] test_if_tile
[10:48:58] [PASSED] test_if_gt
[10:48:58] [PASSED] test_to_id
[10:48:58] ===================== [PASSED] xe_any ======================
[10:48:58] ==================== args (13 subtests) ====================
[10:48:58] [PASSED] count_args_test
[10:48:58] [PASSED] call_args_example
[10:48:58] [PASSED] call_args_test
[10:48:58] [PASSED] drop_first_arg_example
[10:48:58] [PASSED] drop_first_arg_test
[10:48:58] [PASSED] first_arg_example
[10:48:58] [PASSED] first_arg_test
[10:48:58] [PASSED] last_arg_example
[10:48:58] [PASSED] last_arg_test
[10:48:58] [PASSED] pick_arg_example
[10:48:58] [PASSED] if_args_example
[10:48:58] [PASSED] if_args_test
[10:48:58] [PASSED] sep_comma_example
[10:48:58] ====================== [PASSED] args =======================
[10:48:58] =================== xe_pci (3 subtests) ====================
[10:48:58] ==================== check_graphics_ip  ====================
[10:48:58] [PASSED] 12.00 Xe_LP
[10:48:58] [PASSED] 12.10 Xe_LP+
[10:48:58] [PASSED] 12.55 Xe_HPG
[10:48:58] [PASSED] 12.60 Xe_HPC
[10:48:58] [PASSED] 12.70 Xe_LPG
[10:48:58] [PASSED] 12.71 Xe_LPG
[10:48:58] [PASSED] 12.74 Xe_LPG+
[10:48:58] [PASSED] 20.01 Xe2_HPG
[10:48:58] [PASSED] 20.02 Xe2_HPG
[10:48:58] [PASSED] 20.04 Xe2_LPG
[10:48:58] [PASSED] 30.00 Xe3_LPG
[10:48:58] [PASSED] 30.01 Xe3_LPG
[10:48:58] [PASSED] 30.03 Xe3_LPG
[10:48:58] [PASSED] 30.04 Xe3_LPG
[10:48:58] [PASSED] 30.05 Xe3_LPG
[10:48:58] [PASSED] 35.10 Xe3p_LPG
[10:48:58] [PASSED] 35.11 Xe3p_XPC
[10:48:58] ================ [PASSED] check_graphics_ip ================
[10:48:58] ===================== check_media_ip  ======================
[10:48:58] [PASSED] 12.00 Xe_M
[10:48:58] [PASSED] 12.55 Xe_HPM
[10:48:58] [PASSED] 13.00 Xe_LPM+
[10:48:58] [PASSED] 13.01 Xe2_HPM
[10:48:58] [PASSED] 20.00 Xe2_LPM
[10:48:58] [PASSED] 30.00 Xe3_LPM
[10:48:58] [PASSED] 30.02 Xe3_LPM
[10:48:58] [PASSED] 35.00 Xe3p_LPM
[10:48:58] [PASSED] 35.03 Xe3p_HPM
[10:48:58] ================= [PASSED] check_media_ip ==================
[10:48:58] =================== check_platform_desc  ===================
[10:48:58] [PASSED] 0x9A60 (TIGERLAKE)
[10:48:58] [PASSED] 0x9A68 (TIGERLAKE)
[10:48:58] [PASSED] 0x9A70 (TIGERLAKE)
[10:48:58] [PASSED] 0x9A40 (TIGERLAKE)
[10:48:58] [PASSED] 0x9A49 (TIGERLAKE)
[10:48:58] [PASSED] 0x9A59 (TIGERLAKE)
[10:48:58] [PASSED] 0x9A78 (TIGERLAKE)
[10:48:58] [PASSED] 0x9AC0 (TIGERLAKE)
[10:48:58] [PASSED] 0x9AC9 (TIGERLAKE)
[10:48:58] [PASSED] 0x9AD9 (TIGERLAKE)
[10:48:58] [PASSED] 0x9AF8 (TIGERLAKE)
[10:48:58] [PASSED] 0x4C80 (ROCKETLAKE)
[10:48:58] [PASSED] 0x4C8A (ROCKETLAKE)
[10:48:58] [PASSED] 0x4C8B (ROCKETLAKE)
[10:48:58] [PASSED] 0x4C8C (ROCKETLAKE)
[10:48:58] [PASSED] 0x4C90 (ROCKETLAKE)
[10:48:58] [PASSED] 0x4C9A (ROCKETLAKE)
[10:48:58] [PASSED] 0x4680 (ALDERLAKE_S)
[10:48:58] [PASSED] 0x4682 (ALDERLAKE_S)
[10:48:58] [PASSED] 0x4688 (ALDERLAKE_S)
[10:48:58] [PASSED] 0x468A (ALDERLAKE_S)
[10:48:58] [PASSED] 0x468B (ALDERLAKE_S)
[10:48:58] [PASSED] 0x4690 (ALDERLAKE_S)
[10:48:58] [PASSED] 0x4692 (ALDERLAKE_S)
[10:48:58] [PASSED] 0x4693 (ALDERLAKE_S)
[10:48:58] [PASSED] 0x46A0 (ALDERLAKE_P)
[10:48:58] [PASSED] 0x46A1 (ALDERLAKE_P)
[10:48:58] [PASSED] 0x46A2 (ALDERLAKE_P)
[10:48:58] [PASSED] 0x46A3 (ALDERLAKE_P)
[10:48:58] [PASSED] 0x46A6 (ALDERLAKE_P)
[10:48:58] [PASSED] 0x46A8 (ALDERLAKE_P)
[10:48:58] [PASSED] 0x46AA (ALDERLAKE_P)
[10:48:58] [PASSED] 0x462A (ALDERLAKE_P)
[10:48:58] [PASSED] 0x4626 (ALDERLAKE_P)
[10:48:58] [PASSED] 0x4628 (ALDERLAKE_P)
[10:48:58] [PASSED] 0x46B0 (ALDERLAKE_P)
[10:48:58] [PASSED] 0x46B1 (ALDERLAKE_P)
[10:48:58] [PASSED] 0x46B2 (ALDERLAKE_P)
[10:48:58] [PASSED] 0x46B3 (ALDERLAKE_P)
[10:48:58] [PASSED] 0x46C0 (ALDERLAKE_P)
[10:48:58] [PASSED] 0x46C1 (ALDERLAKE_P)
[10:48:58] [PASSED] 0x46C2 (ALDERLAKE_P)
[10:48:58] [PASSED] 0x46C3 (ALDERLAKE_P)
[10:48:58] [PASSED] 0x46D0 (ALDERLAKE_N)
[10:48:58] [PASSED] 0x46D1 (ALDERLAKE_N)
[10:48:58] [PASSED] 0x46D2 (ALDERLAKE_N)
[10:48:58] [PASSED] 0x46D3 (ALDERLAKE_N)
[10:48:58] [PASSED] 0x46D4 (ALDERLAKE_N)
[10:48:58] [PASSED] 0xA721 (ALDERLAKE_P)
[10:48:58] [PASSED] 0xA7A1 (ALDERLAKE_P)
[10:48:58] [PASSED] 0xA7A9 (ALDERLAKE_P)
[10:48:58] [PASSED] 0xA7AC (ALDERLAKE_P)
[10:48:58] [PASSED] 0xA7AD (ALDERLAKE_P)
[10:48:58] [PASSED] 0xA720 (ALDERLAKE_P)
[10:48:58] [PASSED] 0xA7A0 (ALDERLAKE_P)
[10:48:58] [PASSED] 0xA7A8 (ALDERLAKE_P)
[10:48:58] [PASSED] 0xA7AA (ALDERLAKE_P)
[10:48:58] [PASSED] 0xA7AB (ALDERLAKE_P)
[10:48:58] [PASSED] 0xA780 (ALDERLAKE_S)
[10:48:58] [PASSED] 0xA781 (ALDERLAKE_S)
[10:48:58] [PASSED] 0xA782 (ALDERLAKE_S)
[10:48:58] [PASSED] 0xA783 (ALDERLAKE_S)
[10:48:58] [PASSED] 0xA788 (ALDERLAKE_S)
[10:48:58] [PASSED] 0xA789 (ALDERLAKE_S)
[10:48:58] [PASSED] 0xA78A (ALDERLAKE_S)
[10:48:58] [PASSED] 0xA78B (ALDERLAKE_S)
[10:48:58] [PASSED] 0x4905 (DG1)
[10:48:58] [PASSED] 0x4906 (DG1)
[10:48:58] [PASSED] 0x4907 (DG1)
[10:48:58] [PASSED] 0x4908 (DG1)
[10:48:58] [PASSED] 0x4909 (DG1)
[10:48:58] [PASSED] 0x56C0 (DG2)
[10:48:58] [PASSED] 0x56C2 (DG2)
[10:48:58] [PASSED] 0x56C1 (DG2)
[10:48:58] [PASSED] 0x7D51 (METEORLAKE)
[10:48:58] [PASSED] 0x7DD1 (METEORLAKE)
[10:48:58] [PASSED] 0x7D41 (METEORLAKE)
[10:48:58] [PASSED] 0x7D67 (METEORLAKE)
[10:48:58] [PASSED] 0xB640 (METEORLAKE)
[10:48:58] [PASSED] 0x56A0 (DG2)
[10:48:58] [PASSED] 0x56A1 (DG2)
[10:48:58] [PASSED] 0x56A2 (DG2)
[10:48:58] [PASSED] 0x56BE (DG2)
[10:48:58] [PASSED] 0x56BF (DG2)
[10:48:58] [PASSED] 0x5690 (DG2)
[10:48:58] [PASSED] 0x5691 (DG2)
[10:48:58] [PASSED] 0x5692 (DG2)
[10:48:58] [PASSED] 0x56A5 (DG2)
[10:48:58] [PASSED] 0x56A6 (DG2)
[10:48:58] [PASSED] 0x56B0 (DG2)
[10:48:58] [PASSED] 0x56B1 (DG2)
[10:48:58] [PASSED] 0x56BA (DG2)
[10:48:58] [PASSED] 0x56BB (DG2)
[10:48:58] [PASSED] 0x56BC (DG2)
[10:48:58] [PASSED] 0x56BD (DG2)
[10:48:58] [PASSED] 0x5693 (DG2)
[10:48:58] [PASSED] 0x5694 (DG2)
[10:48:58] [PASSED] 0x5695 (DG2)
[10:48:58] [PASSED] 0x56A3 (DG2)
[10:48:58] [PASSED] 0x56A4 (DG2)
[10:48:58] [PASSED] 0x56B2 (DG2)
[10:48:58] [PASSED] 0x56B3 (DG2)
[10:48:58] [PASSED] 0x5696 (DG2)
[10:48:58] [PASSED] 0x5697 (DG2)
[10:48:58] [PASSED] 0xB69 (PVC)
[10:48:58] [PASSED] 0xB6E (PVC)
[10:48:58] [PASSED] 0xBD4 (PVC)
[10:48:58] [PASSED] 0xBD5 (PVC)
[10:48:58] [PASSED] 0xBD6 (PVC)
[10:48:58] [PASSED] 0xBD7 (PVC)
[10:48:58] [PASSED] 0xBD8 (PVC)
[10:48:58] [PASSED] 0xBD9 (PVC)
[10:48:58] [PASSED] 0xBDA (PVC)
[10:48:58] [PASSED] 0xBDB (PVC)
[10:48:58] [PASSED] 0xBE0 (PVC)
[10:48:58] [PASSED] 0xBE1 (PVC)
[10:48:58] [PASSED] 0xBE5 (PVC)
[10:48:58] [PASSED] 0x7D40 (METEORLAKE)
[10:48:58] [PASSED] 0x7D45 (METEORLAKE)
[10:48:58] [PASSED] 0x7D55 (METEORLAKE)
[10:48:58] [PASSED] 0x7D60 (METEORLAKE)
[10:48:58] [PASSED] 0x7DD5 (METEORLAKE)
[10:48:58] [PASSED] 0x6420 (LUNARLAKE)
[10:48:58] [PASSED] 0x64A0 (LUNARLAKE)
[10:48:58] [PASSED] 0x64B0 (LUNARLAKE)
[10:48:58] [PASSED] 0xE202 (BATTLEMAGE)
[10:48:58] [PASSED] 0xE209 (BATTLEMAGE)
[10:48:58] [PASSED] 0xE20B (BATTLEMAGE)
[10:48:58] [PASSED] 0xE20C (BATTLEMAGE)
[10:48:58] [PASSED] 0xE20D (BATTLEMAGE)
[10:48:58] [PASSED] 0xE210 (BATTLEMAGE)
[10:48:58] [PASSED] 0xE211 (BATTLEMAGE)
[10:48:58] [PASSED] 0xE212 (BATTLEMAGE)
[10:48:58] [PASSED] 0xE216 (BATTLEMAGE)
[10:48:58] [PASSED] 0xE220 (BATTLEMAGE)
[10:48:58] [PASSED] 0xE221 (BATTLEMAGE)
[10:48:58] [PASSED] 0xE222 (BATTLEMAGE)
[10:48:58] [PASSED] 0xE223 (BATTLEMAGE)
[10:48:58] [PASSED] 0xB080 (PANTHERLAKE)
[10:48:58] [PASSED] 0xB081 (PANTHERLAKE)
[10:48:58] [PASSED] 0xB082 (PANTHERLAKE)
[10:48:58] [PASSED] 0xB083 (PANTHERLAKE)
[10:48:58] [PASSED] 0xB084 (PANTHERLAKE)
[10:48:58] [PASSED] 0xB085 (PANTHERLAKE)
[10:48:58] [PASSED] 0xB086 (PANTHERLAKE)
[10:48:58] [PASSED] 0xB087 (PANTHERLAKE)
[10:48:58] [PASSED] 0xB08F (PANTHERLAKE)
[10:48:58] [PASSED] 0xB090 (PANTHERLAKE)
[10:48:58] [PASSED] 0xB0A0 (PANTHERLAKE)
[10:48:58] [PASSED] 0xB0A1 (PANTHERLAKE)
[10:48:58] [PASSED] 0xB0B0 (PANTHERLAKE)
[10:48:58] [PASSED] 0xFD80 (PANTHERLAKE)
[10:48:58] [PASSED] 0xFD81 (PANTHERLAKE)
[10:48:58] [PASSED] 0xD740 (NOVALAKE_S)
[10:48:58] [PASSED] 0xD741 (NOVALAKE_S)
[10:48:58] [PASSED] 0xD742 (NOVALAKE_S)
[10:48:58] [PASSED] 0xD743 (NOVALAKE_S)
[10:48:58] [PASSED] 0xD745 (NOVALAKE_S)
[10:48:58] [PASSED] 0xD74A (NOVALAKE_S)
[10:48:58] [PASSED] 0xD74B (NOVALAKE_S)
[10:48:58] [PASSED] 0x674C (CRESCENTISLAND)
[10:48:58] [PASSED] 0x674D (CRESCENTISLAND)
[10:48:58] [PASSED] 0x674E (CRESCENTISLAND)
[10:48:58] [PASSED] 0x674F (CRESCENTISLAND)
[10:48:58] [PASSED] 0x6750 (CRESCENTISLAND)
[10:48:58] [PASSED] 0x6751 (CRESCENTISLAND)
[10:48:58] [PASSED] 0xD750 (NOVALAKE_P)
[10:48:58] [PASSED] 0xD751 (NOVALAKE_P)
[10:48:58] [PASSED] 0xD752 (NOVALAKE_P)
[10:48:58] [PASSED] 0xD753 (NOVALAKE_P)
[10:48:58] [PASSED] 0xD754 (NOVALAKE_P)
[10:48:58] [PASSED] 0xD755 (NOVALAKE_P)
[10:48:58] [PASSED] 0xD756 (NOVALAKE_P)
[10:48:58] [PASSED] 0xD757 (NOVALAKE_P)
[10:48:58] [PASSED] 0xD75F (NOVALAKE_P)
[10:48:58] =============== [PASSED] check_platform_desc ===============
[10:48:58] ===================== [PASSED] xe_pci ======================
[10:48:58] ============= xe_rtp_tables_test (5 subtests) ==============
[10:48:58] ================== xe_rtp_table_gt_test  ===================
[10:48:58] [PASSED] gt_was/14011060649
[10:48:58] [PASSED] gt_was/14011059788
[10:48:58] [PASSED] gt_was/14015795083
[10:48:58] [PASSED] gt_was/16021867713
[10:48:58] [PASSED] gt_was/14019449301
[10:48:58] [PASSED] gt_was/16028005424
[10:48:58] [PASSED] gt_was/14026578760
[10:48:58] [PASSED] gt_was/1409420604
[10:48:58] [PASSED] gt_was/1408615072
[10:48:58] [PASSED] gt_was/22010523718
[10:48:58] [PASSED] gt_was/14011006942
[10:48:58] [PASSED] gt_was/14014830051
[10:48:58] [PASSED] gt_was/18018781329
[10:48:58] [PASSED] gt_was/1509235366
[10:48:58] [PASSED] gt_was/18018781329
[10:48:58] [PASSED] gt_was/16016694945
[10:48:58] [PASSED] gt_was/14018575942
[10:48:58] [PASSED] gt_was/22016670082
[10:48:58] [PASSED] gt_was/22016670082
[10:48:58] [PASSED] gt_was/14017421178
[10:48:58] [PASSED] gt_was/16025250150
[10:48:58] [PASSED] gt_was/14021871409
[10:48:58] [PASSED] gt_was/16021865536
[10:48:58] [PASSED] gt_was/14021486841
[10:48:58] [PASSED] gt_was/14025160223
[10:48:58] [PASSED] gt_was/14026144927, 16029437861, 14026127056
[10:48:58] [PASSED] gt_was/14025635424
[10:48:58] [PASSED] gt_was/16028005424
[10:48:58] ============== [PASSED] xe_rtp_table_gt_test ===============
[10:48:58] ================== xe_rtp_table_gt_test  ===================
[10:48:58] [PASSED] gt_tunings/Tuning: Blend Fill Caching Optimization Disable
[10:48:58] [PASSED] gt_tunings/Tuning: 32B Access Enable
[10:48:58] [PASSED] gt_tunings/Tuning: L3 cache
[10:48:58] [PASSED] gt_tunings/Tuning: L3 cache - media
[10:48:58] [PASSED] gt_tunings/Tuning: Compression Overfetch
[10:48:58] [PASSED] gt_tunings/Tuning: Compression Overfetch - media
[10:48:58] [PASSED] gt_tunings/Tuning: Enable compressible partial write overfetch in L3
[10:48:58] [PASSED] gt_tunings/Tuning: Enable compressible partial write overfetch in L3 - media
[10:48:58] [PASSED] gt_tunings/Tuning: L2 Overfetch Compressible Only
[10:48:58] [PASSED] gt_tunings/Tuning: L2 Overfetch Compressible Only - media
[10:48:58] [PASSED] gt_tunings/Tuning: Stateless compression control
[10:48:58] [PASSED] gt_tunings/Tuning: Stateless compression control - media
[10:48:58] [PASSED] gt_tunings/Tuning: L3 RW flush all Cache
[10:48:58] [PASSED] gt_tunings/Tuning: L3 RW flush all cache - media
[10:48:58] [PASSED] gt_tunings/Tuning: Set STLB Bank Hash Mode to 4KB
[10:48:58] [PASSED] gt_tunings/Tuning: Force All Non-Compressible Memory Reads to be 256B Overfetches
[10:48:58] ============== [PASSED] xe_rtp_table_gt_test ===============
[10:48:58] ================== xe_rtp_table_oob_test  ==================
[10:48:58] [PASSED] oob_was/1607983814
[10:48:58] [PASSED] oob_was/16010904313
[10:48:58] [PASSED] oob_was/18022495364
[10:48:58] [PASSED] oob_was/22012773006
[10:48:58] [PASSED] oob_was/14014475959
[10:48:58] [PASSED] oob_was/22011391025
[10:48:58] [PASSED] oob_was/22012727170
[10:48:58] [PASSED] oob_was/22012727685
[10:48:58] [PASSED] oob_was/22016596838
[10:48:58] [PASSED] oob_was/18020744125
[10:48:58] [PASSED] oob_was/1409600907
[10:48:58] [PASSED] oob_was/22014953428
[10:48:58] [PASSED] oob_was/16017236439
[10:48:58] [PASSED] oob_was/14019821291
[10:48:58] [PASSED] oob_was/14015076503
[10:48:58] [PASSED] oob_was/22016122933
[10:48:58] [PASSED] oob_was/14018913170
[10:48:58] [PASSED] oob_was/14018094691
[10:48:58] [PASSED] oob_was/18024947630
[10:48:58] [PASSED] oob_was/16022287689
[10:48:58] [PASSED] oob_was/13011645652
[10:48:58] [PASSED] oob_was/14022293748
[10:48:58] [PASSED] oob_was/22019794406
[10:48:58] [PASSED] oob_was/22019338487
[10:48:58] [PASSED] oob_was/16023588340
[10:48:58] [PASSED] oob_was/14019789679
[10:48:58] [PASSED] oob_was/14022866841
[10:48:58] [PASSED] oob_was/16021333562
[10:48:58] [PASSED] oob_was/14016712196
[10:48:58] [PASSED] oob_was/14015568240
[10:48:58] [PASSED] oob_was/18013179988
[10:48:58] [PASSED] oob_was/1508761755
[10:48:58] [PASSED] oob_was/16023105232
[10:48:58] [PASSED] oob_was/16026508708
[10:48:58] [PASSED] oob_was/14020001231
[10:48:58] [PASSED] oob_was/16023683509
[10:48:58] [PASSED] oob_was/14025515070
[10:48:58] [PASSED] oob_was/15015404425_disable
[10:48:58] [PASSED] oob_was/16026007364
[10:48:58] [PASSED] oob_was/14020316580
[10:48:58] [PASSED] oob_was/14025883347
[10:48:58] [PASSED] oob_was/16029380221
[10:48:58] [PASSED] oob_was/22022079272
[10:48:58] [PASSED] oob_was/16029897822
[10:48:58] [PASSED] oob_was/14027054324
[10:48:58] [PASSED] oob_was/14025941587
[10:48:58] [PASSED] oob_was/16030224309
[10:48:58] ============== [PASSED] xe_rtp_table_oob_test ==============
[10:48:58] ================ xe_rtp_table_dev_oob_test  ================
[10:48:58] [PASSED] device_oob_was/22010954014
[10:48:58] [PASSED] device_oob_was/15015404425
[10:48:58] [PASSED] device_oob_was/22019338487_display
[10:48:58] [PASSED] device_oob_was/14022085890
[10:48:58] [PASSED] device_oob_was/14026539277
[10:48:58] [PASSED] device_oob_was/14026633728
[10:48:58] [PASSED] device_oob_was/14026746987
[10:48:58] [PASSED] device_oob_was/14026779378
[10:48:58] ============ [PASSED] xe_rtp_table_dev_oob_test ============
[10:48:58] ========== xe_rtp_table_missing_upper_bound_test  ==========
[10:48:58] [PASSED] register_whitelist/WaAllowPMDepthAndInvocationCountAccessFromUMD, 1408556865
[10:48:58] [PASSED] register_whitelist/1508744258, 14012131227, 1808121037
[10:48:58] [PASSED] register_whitelist/1806527549
[10:48:58] [PASSED] register_whitelist/allow_read_ctx_timestamp
[10:48:58] [PASSED] register_whitelist/allow_read_queue_timestamp
[10:48:58] [PASSED] register_whitelist/16014440446
[10:48:58] [PASSED] register_whitelist/16017236439
[10:48:58] [PASSED] register_whitelist/16020183090
[10:48:58] [PASSED] register_whitelist/14024997852
[10:48:58] [PASSED] register_whitelist/14024997852
[10:48:58] ====== [PASSED] xe_rtp_table_missing_upper_bound_test ======
[10:48:58] =============== [PASSED] xe_rtp_tables_test ================
[10:48:58] =================== xe_rtp (3 subtests) ====================
[10:48:58] =================== xe_rtp_rules_tests  ====================
[10:48:58] [PASSED] no
[10:48:58] [PASSED] yes
[10:48:58] [PASSED] no-and-no
[10:48:58] [PASSED] no-and-yes
[10:48:58] [PASSED] yes-and-no
[10:48:58] [PASSED] yes-and-yes
[10:48:58] [PASSED] no-or-no
[10:48:58] [PASSED] no-or-yes
[10:48:58] [PASSED] yes-or-no
[10:48:58] [PASSED] yes-or-yes
[10:48:58] [PASSED] no-yes-or-yes-no
[10:48:58] [PASSED] no-yes-or-yes-yes
[10:48:58] [PASSED] yes-yes-or-no-yes
[10:48:58] [PASSED] yes-yes-or-yes-yes
[10:48:58] [PASSED] no-no-or-yes-or-no
[10:48:58] [PASSED] or
[10:48:58] [PASSED] or-yes
[10:48:58] [PASSED] or-no
[10:48:58] [PASSED] yes-or
[10:48:58] [PASSED] no-or
[10:48:58] [PASSED] no-or-or-yes
[10:48:58] [PASSED] yes-or-or-no
[10:48:58] [PASSED] no-or-or-no
[10:48:58] [PASSED] missing-context-engine-class
[10:48:58] [PASSED] missing-context-engine-class-or-yes
[10:48:58] [PASSED] missing-context-engine-class-or-or-yes
[10:48:58] =============== [PASSED] xe_rtp_rules_tests ================
[10:48:58] =============== xe_rtp_process_to_sr_tests  ================
[10:48:58] [PASSED] coalesce-same-reg
[10:48:58] [PASSED] coalesce-same-reg-literal-and-func
[10:48:58] [PASSED] no-match-no-add
[10:48:58] [PASSED] two-regs-two-entries
[10:48:58] [PASSED] clr-one-set-other
[10:48:58] [PASSED] set-field
[10:48:58] [PASSED] conflict-duplicate
[10:48:58] [PASSED] conflict-not-disjoint
[10:48:58] [PASSED] conflict-not-disjoint-literal-and-func
[10:48:58] [PASSED] conflict-reg-type
[10:48:58] [PASSED] bad-mcr-reg-forced-to-regular
[10:48:58] [PASSED] bad-regular-reg-forced-to-mcr
[10:48:58] =========== [PASSED] xe_rtp_process_to_sr_tests ============
[10:48:58] ================== xe_rtp_process_tests  ===================
[10:48:58] [PASSED] active1
[10:48:58] [PASSED] active2
[10:48:58] [PASSED] active-inactive
[10:48:58] [PASSED] inactive-active
[10:48:58] [PASSED] inactive-active-inactive
[10:48:58] [PASSED] inactive-inactive-inactive
[10:48:58] ============== [PASSED] xe_rtp_process_tests ===============
[10:48:58] ===================== [PASSED] xe_rtp ======================
[10:48:58] ==================== xe_wa (1 subtest) =====================
[10:48:58] ======================== xe_wa_gt  =========================
[10:48:58] [PASSED] TIGERLAKE B0
[10:48:58] [PASSED] DG1 A0
[10:48:58] [PASSED] DG1 B0
[10:48:58] [PASSED] ALDERLAKE_S A0
[10:48:58] [PASSED] ALDERLAKE_S B0
[10:48:58] [PASSED] ALDERLAKE_S C0
[10:48:58] [PASSED] ALDERLAKE_S D0
[10:48:58] [PASSED] ALDERLAKE_P A0
[10:48:58] [PASSED] ALDERLAKE_P B0
[10:48:58] [PASSED] ALDERLAKE_P C0
[10:48:58] [PASSED] ALDERLAKE_S RPLS D0
[10:48:58] [PASSED] ALDERLAKE_P RPLU E0
[10:48:58] [PASSED] DG2 G10 C0
[10:48:58] [PASSED] DG2 G11 B1
[10:48:58] [PASSED] DG2 G12 A1
[10:48:58] [PASSED] METEORLAKE 12.70(Xe_LPG) A0 13.00(Xe_LPM+) A0
[10:48:58] [PASSED] METEORLAKE 12.71(Xe_LPG) A0 13.00(Xe_LPM+) A0
[10:48:58] [PASSED] METEORLAKE 12.74(Xe_LPG+) A0 13.00(Xe_LPM+) A0
[10:48:58] [PASSED] LUNARLAKE 20.04(Xe2_LPG) A0 20.00(Xe2_LPM) A0
[10:48:58] [PASSED] LUNARLAKE 20.04(Xe2_LPG) B0 20.00(Xe2_LPM) A0
[10:48:58] [PASSED] BATTLEMAGE 20.01(Xe2_HPG) A0 13.01(Xe2_HPM) A1
[10:48:58] [PASSED] PANTHERLAKE 30.00(Xe3_LPG) A0 30.00(Xe3_LPM) A0
[10:48:58] ==================== [PASSED] xe_wa_gt =====================
[10:48:58] ====================== [PASSED] xe_wa ======================
[10:48:58] ============================================================
[10:48:58] Testing complete. Ran 832 tests: passed: 804, skipped: 28
[10:48:58] Elapsed time: 37.311s total, 1.813s configuring, 34.731s building, 0.716s running

+ for kcfg in "${kunitconfigs[@]}"
+ [[ ! -f /kernel/drivers/gpu/drm/tests/.kunitconfig ]]
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/tests/.kunitconfig
[10:48:58] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[10:49:00] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[10:49:26] Starting KUnit Kernel (1/1)...
[10:49:26] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[10:49:26] ============= refcount_interrupt (4 subtests) ==============
[10:49:26] [PASSED] test_single_irq_change
[10:49:26] [PASSED] test_nested_irq_change
[10:49:26] [PASSED] test_multiple_irq_change
[10:49:26] [PASSED] test_irq_save
[10:49:26] =============== [PASSED] refcount_interrupt ================
[10:49:26] ============ drm_test_pick_cmdline (2 subtests) ============
[10:49:26] [PASSED] drm_test_pick_cmdline_res_1920_1080_60
[10:49:26] =============== drm_test_pick_cmdline_named  ===============
[10:49:26] [PASSED] NTSC
[10:49:26] [PASSED] NTSC-J
[10:49:26] [PASSED] PAL
[10:49:26] [PASSED] PAL-M
[10:49:26] =========== [PASSED] drm_test_pick_cmdline_named ===========
[10:49:26] ============== [PASSED] drm_test_pick_cmdline ==============
[10:49:26] == drm_test_atomic_get_connector_for_encoder (1 subtest) ===
[10:49:26] [PASSED] drm_test_drm_atomic_get_connector_for_encoder
[10:49:26] ==== [PASSED] drm_test_atomic_get_connector_for_encoder ====
[10:49:26] =========== drm_validate_clone_mode (2 subtests) ===========
[10:49:26] ============== drm_test_check_in_clone_mode  ===============
[10:49:26] [PASSED] in_clone_mode
[10:49:26] [PASSED] not_in_clone_mode
[10:49:26] ========== [PASSED] drm_test_check_in_clone_mode ===========
[10:49:26] =============== drm_test_check_valid_clones  ===============
[10:49:26] [PASSED] not_in_clone_mode
[10:49:26] [PASSED] valid_clone
[10:49:26] [PASSED] invalid_clone
[10:49:26] =========== [PASSED] drm_test_check_valid_clones ===========
[10:49:26] ============= [PASSED] drm_validate_clone_mode =============
[10:49:26] ============= drm_validate_modeset (1 subtest) =============
[10:49:26] [PASSED] drm_test_check_connector_changed_modeset
[10:49:26] ============== [PASSED] drm_validate_modeset ===============
[10:49:26] ====== drm_test_bridge_get_current_state (1 subtest) =======
[10:49:26] [PASSED] drm_test_drm_bridge_get_current_state_atomic
[10:49:26] ======== [PASSED] drm_test_bridge_get_current_state ========
[10:49:26] ====== drm_test_bridge_helper_reset_crtc (3 subtests) ======
[10:49:26] [PASSED] drm_test_drm_bridge_helper_reset_crtc_atomic
[10:49:26] [PASSED] drm_test_drm_bridge_helper_reset_crtc_atomic_disabled
[10:49:26] [PASSED] drm_test_drm_bridge_helper_hdmi_output_bus_fmts
[10:49:26] ======== [PASSED] drm_test_bridge_helper_reset_crtc ========
[10:49:26] ============== drm_bridge_alloc (2 subtests) ===============
[10:49:26] [PASSED] drm_test_drm_bridge_alloc_basic
[10:49:26] [PASSED] drm_test_drm_bridge_alloc_get_put
[10:49:26] ================ [PASSED] drm_bridge_alloc =================
[10:49:26] ============= drm_bridge_bus_fmt (5 subtests) ==============
[10:49:26] [PASSED] drm_test_bridge_rgb_yuv_rgb
[10:49:26] [PASSED] drm_test_bridge_must_convert_to_yuv444
[10:49:26] [PASSED] drm_test_bridge_hdmi_auto_rgb
[10:49:26] [PASSED] drm_test_bridge_auto_first
[10:49:26] [PASSED] drm_test_bridge_rgb_yuv_no_path
[10:49:26] =============== [PASSED] drm_bridge_bus_fmt ================
[10:49:26] ============= drm_cmdline_parser (40 subtests) =============
[10:49:26] [PASSED] drm_test_cmdline_force_d_only
[10:49:26] [PASSED] drm_test_cmdline_force_D_only_dvi
[10:49:26] [PASSED] drm_test_cmdline_force_D_only_hdmi
[10:49:26] [PASSED] drm_test_cmdline_force_D_only_not_digital
[10:49:26] [PASSED] drm_test_cmdline_force_e_only
[10:49:26] [PASSED] drm_test_cmdline_res
[10:49:26] [PASSED] drm_test_cmdline_res_vesa
[10:49:26] [PASSED] drm_test_cmdline_res_vesa_rblank
[10:49:26] [PASSED] drm_test_cmdline_res_rblank
[10:49:26] [PASSED] drm_test_cmdline_res_bpp
[10:49:26] [PASSED] drm_test_cmdline_res_refresh
[10:49:26] [PASSED] drm_test_cmdline_res_bpp_refresh
[10:49:26] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced
[10:49:26] [PASSED] drm_test_cmdline_res_bpp_refresh_margins
[10:49:26] [PASSED] drm_test_cmdline_res_bpp_refresh_force_off
[10:49:26] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on
[10:49:26] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_analog
[10:49:26] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_digital
[10:49:26] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced_margins_force_on
[10:49:26] [PASSED] drm_test_cmdline_res_margins_force_on
[10:49:26] [PASSED] drm_test_cmdline_res_vesa_margins
[10:49:26] [PASSED] drm_test_cmdline_name
[10:49:26] [PASSED] drm_test_cmdline_name_bpp
[10:49:26] [PASSED] drm_test_cmdline_name_option
[10:49:26] [PASSED] drm_test_cmdline_name_bpp_option
[10:49:26] [PASSED] drm_test_cmdline_rotate_0
[10:49:26] [PASSED] drm_test_cmdline_rotate_90
[10:49:26] [PASSED] drm_test_cmdline_rotate_180
[10:49:26] [PASSED] drm_test_cmdline_rotate_270
[10:49:26] [PASSED] drm_test_cmdline_hmirror
[10:49:26] [PASSED] drm_test_cmdline_vmirror
[10:49:26] [PASSED] drm_test_cmdline_margin_options
[10:49:26] [PASSED] drm_test_cmdline_multiple_options
[10:49:26] [PASSED] drm_test_cmdline_bpp_extra_and_option
[10:49:26] [PASSED] drm_test_cmdline_extra_and_option
[10:49:26] [PASSED] drm_test_cmdline_freestanding_options
[10:49:26] [PASSED] drm_test_cmdline_freestanding_force_e_and_options
[10:49:26] [PASSED] drm_test_cmdline_panel_orientation
[10:49:26] ================ drm_test_cmdline_invalid  =================
[10:49:26] [PASSED] margin_only
[10:49:26] [PASSED] interlace_only
[10:49:26] [PASSED] res_missing_x
[10:49:26] [PASSED] res_missing_y
[10:49:26] [PASSED] res_bad_y
[10:49:26] [PASSED] res_missing_y_bpp
[10:49:26] [PASSED] res_bad_bpp
[10:49:26] [PASSED] res_bad_refresh
[10:49:26] [PASSED] res_bpp_refresh_force_on_off
[10:49:26] [PASSED] res_invalid_mode
[10:49:26] [PASSED] res_bpp_wrong_place_mode
[10:49:26] [PASSED] name_bpp_refresh
[10:49:26] [PASSED] name_refresh
[10:49:26] [PASSED] name_refresh_wrong_mode
[10:49:26] [PASSED] name_refresh_invalid_mode
[10:49:26] [PASSED] rotate_multiple
[10:49:26] [PASSED] rotate_invalid_val
[10:49:26] [PASSED] rotate_truncated
[10:49:26] [PASSED] invalid_option
[10:49:26] [PASSED] invalid_tv_option
[10:49:26] [PASSED] truncated_tv_option
[10:49:26] ============ [PASSED] drm_test_cmdline_invalid =============
[10:49:26] =============== drm_test_cmdline_tv_options  ===============
[10:49:26] [PASSED] NTSC
[10:49:26] [PASSED] NTSC_443
[10:49:26] [PASSED] NTSC_J
[10:49:26] [PASSED] PAL
[10:49:26] [PASSED] PAL_M
[10:49:26] [PASSED] PAL_N
[10:49:26] [PASSED] SECAM
[10:49:26] [PASSED] MONO_525
[10:49:26] [PASSED] MONO_625
[10:49:26] =========== [PASSED] drm_test_cmdline_tv_options ===========
[10:49:26] =============== [PASSED] drm_cmdline_parser ================
[10:49:26] ========== drmm_connector_hdmi_init (20 subtests) ==========
[10:49:26] [PASSED] drm_test_connector_hdmi_init_valid
[10:49:26] [PASSED] drm_test_connector_hdmi_init_bpc_8
[10:49:26] [PASSED] drm_test_connector_hdmi_init_bpc_10
[10:49:26] [PASSED] drm_test_connector_hdmi_init_bpc_12
[10:49:26] [PASSED] drm_test_connector_hdmi_init_bpc_invalid
[10:49:26] [PASSED] drm_test_connector_hdmi_init_bpc_null
[10:49:26] [PASSED] drm_test_connector_hdmi_init_formats_empty
[10:49:26] [PASSED] drm_test_connector_hdmi_init_formats_no_rgb
[10:49:26] === drm_test_connector_hdmi_init_formats_yuv420_allowed  ===
[10:49:26] [PASSED] supported_formats=0x9 yuv420_allowed=1
[10:49:26] [PASSED] supported_formats=0x9 yuv420_allowed=0
[10:49:26] [PASSED] supported_formats=0x5 yuv420_allowed=1
[10:49:26] [PASSED] supported_formats=0x5 yuv420_allowed=0
[10:49:26] === [PASSED] drm_test_connector_hdmi_init_formats_yuv420_allowed ===
[10:49:26] [PASSED] drm_test_connector_hdmi_init_null_ddc
[10:49:26] [PASSED] drm_test_connector_hdmi_init_null_product
[10:49:26] [PASSED] drm_test_connector_hdmi_init_null_vendor
[10:49:26] [PASSED] drm_test_connector_hdmi_init_product_length_exact
[10:49:26] [PASSED] drm_test_connector_hdmi_init_product_length_too_long
[10:49:26] [PASSED] drm_test_connector_hdmi_init_product_valid
[10:49:26] [PASSED] drm_test_connector_hdmi_init_vendor_length_exact
[10:49:26] [PASSED] drm_test_connector_hdmi_init_vendor_length_too_long
[10:49:26] [PASSED] drm_test_connector_hdmi_init_vendor_valid
[10:49:26] ========= drm_test_connector_hdmi_init_type_valid  =========
[10:49:26] [PASSED] HDMI-A
[10:49:26] [PASSED] HDMI-B
[10:49:26] ===== [PASSED] drm_test_connector_hdmi_init_type_valid =====
[10:49:26] ======== drm_test_connector_hdmi_init_type_invalid  ========
[10:49:26] [PASSED] Unknown
[10:49:26] [PASSED] VGA
[10:49:26] [PASSED] DVI-I
[10:49:26] [PASSED] DVI-D
[10:49:26] [PASSED] DVI-A
[10:49:26] [PASSED] Composite
[10:49:26] [PASSED] SVIDEO
[10:49:26] [PASSED] LVDS
[10:49:26] [PASSED] Component
[10:49:26] [PASSED] DIN
[10:49:26] [PASSED] DP
[10:49:26] [PASSED] TV
[10:49:26] [PASSED] eDP
[10:49:26] [PASSED] Virtual
[10:49:26] [PASSED] DSI
[10:49:26] [PASSED] DPI
[10:49:26] [PASSED] Writeback
[10:49:26] [PASSED] SPI
[10:49:26] [PASSED] USB
[10:49:26] ==== [PASSED] drm_test_connector_hdmi_init_type_invalid ====
[10:49:26] ============ [PASSED] drmm_connector_hdmi_init =============
[10:49:26] ============= drmm_connector_init (3 subtests) =============
[10:49:26] [PASSED] drm_test_drmm_connector_init
[10:49:26] [PASSED] drm_test_drmm_connector_init_null_ddc
[10:49:26] ========= drm_test_drmm_connector_init_type_valid  =========
[10:49:26] [PASSED] Unknown
[10:49:26] [PASSED] VGA
[10:49:26] [PASSED] DVI-I
[10:49:26] [PASSED] DVI-D
[10:49:26] [PASSED] DVI-A
[10:49:26] [PASSED] Composite
[10:49:26] [PASSED] SVIDEO
[10:49:26] [PASSED] LVDS
[10:49:26] [PASSED] Component
[10:49:26] [PASSED] DIN
[10:49:26] [PASSED] DP
[10:49:26] [PASSED] HDMI-A
[10:49:26] [PASSED] HDMI-B
[10:49:26] [PASSED] TV
[10:49:26] [PASSED] eDP
[10:49:26] [PASSED] Virtual
[10:49:26] [PASSED] DSI
[10:49:26] [PASSED] DPI
[10:49:26] [PASSED] Writeback
[10:49:26] [PASSED] SPI
[10:49:26] [PASSED] USB
[10:49:26] ===== [PASSED] drm_test_drmm_connector_init_type_valid =====
[10:49:26] =============== [PASSED] drmm_connector_init ===============
[10:49:26] ========= drm_connector_dynamic_init (6 subtests) ==========
[10:49:26] [PASSED] drm_test_drm_connector_dynamic_init
[10:49:26] [PASSED] drm_test_drm_connector_dynamic_init_null_ddc
[10:49:26] [PASSED] drm_test_drm_connector_dynamic_init_not_added
[10:49:26] [PASSED] drm_test_drm_connector_dynamic_init_properties
[10:49:26] ===== drm_test_drm_connector_dynamic_init_type_valid  ======
[10:49:26] [PASSED] Unknown
[10:49:26] [PASSED] VGA
[10:49:26] [PASSED] DVI-I
[10:49:26] [PASSED] DVI-D
[10:49:26] [PASSED] DVI-A
[10:49:26] [PASSED] Composite
[10:49:26] [PASSED] SVIDEO
[10:49:26] [PASSED] LVDS
[10:49:26] [PASSED] Component
[10:49:26] [PASSED] DIN
[10:49:26] [PASSED] DP
[10:49:26] [PASSED] HDMI-A
[10:49:26] [PASSED] HDMI-B
[10:49:26] [PASSED] TV
[10:49:26] [PASSED] eDP
[10:49:26] [PASSED] Virtual
[10:49:26] [PASSED] DSI
[10:49:26] [PASSED] DPI
[10:49:26] [PASSED] Writeback
[10:49:26] [PASSED] SPI
[10:49:26] [PASSED] USB
[10:49:26] = [PASSED] drm_test_drm_connector_dynamic_init_type_valid ==
[10:49:26] ======== drm_test_drm_connector_dynamic_init_name  =========
[10:49:26] [PASSED] Unknown
[10:49:26] [PASSED] VGA
[10:49:26] [PASSED] DVI-I
[10:49:26] [PASSED] DVI-D
[10:49:26] [PASSED] DVI-A
[10:49:26] [PASSED] Composite
[10:49:26] [PASSED] SVIDEO
[10:49:26] [PASSED] LVDS
[10:49:26] [PASSED] Component
[10:49:26] [PASSED] DIN
[10:49:26] [PASSED] DP
[10:49:26] [PASSED] HDMI-A
[10:49:26] [PASSED] HDMI-B
[10:49:26] [PASSED] TV
[10:49:26] [PASSED] eDP
[10:49:26] [PASSED] Virtual
[10:49:26] [PASSED] DSI
[10:49:26] [PASSED] DPI
[10:49:26] [PASSED] Writeback
[10:49:26] [PASSED] SPI
[10:49:26] [PASSED] USB
[10:49:26] ==== [PASSED] drm_test_drm_connector_dynamic_init_name =====
[10:49:26] =========== [PASSED] drm_connector_dynamic_init ============
[10:49:26] ==== drm_connector_dynamic_register_early (4 subtests) =====
[10:49:26] [PASSED] drm_test_drm_connector_dynamic_register_early_on_list
[10:49:26] [PASSED] drm_test_drm_connector_dynamic_register_early_defer
[10:49:26] [PASSED] drm_test_drm_connector_dynamic_register_early_no_init
[10:49:26] [PASSED] drm_test_drm_connector_dynamic_register_early_no_mode_object
[10:49:26] ====== [PASSED] drm_connector_dynamic_register_early =======
[10:49:26] ======= drm_connector_dynamic_register (7 subtests) ========
[10:49:26] [PASSED] drm_test_drm_connector_dynamic_register_on_list
[10:49:26] [PASSED] drm_test_drm_connector_dynamic_register_no_defer
[10:49:26] [PASSED] drm_test_drm_connector_dynamic_register_no_init
[10:49:26] [PASSED] drm_test_drm_connector_dynamic_register_mode_object
[10:49:26] [PASSED] drm_test_drm_connector_dynamic_register_sysfs
[10:49:26] [PASSED] drm_test_drm_connector_dynamic_register_sysfs_name
[10:49:26] [PASSED] drm_test_drm_connector_dynamic_register_debugfs
[10:49:26] ========= [PASSED] drm_connector_dynamic_register ==========
[10:49:26] = drm_connector_attach_broadcast_rgb_property (2 subtests) =
[10:49:26] [PASSED] drm_test_drm_connector_attach_broadcast_rgb_property
[10:49:26] [PASSED] drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector
[10:49:26] === [PASSED] drm_connector_attach_broadcast_rgb_property ===
[10:49:26] ========== drm_get_tv_mode_from_name (2 subtests) ==========
[10:49:26] ========== drm_test_get_tv_mode_from_name_valid  ===========
[10:49:26] [PASSED] NTSC
[10:49:26] [PASSED] NTSC-443
[10:49:26] [PASSED] NTSC-J
[10:49:26] [PASSED] PAL
[10:49:26] [PASSED] PAL-M
[10:49:26] [PASSED] PAL-N
[10:49:26] [PASSED] SECAM
[10:49:26] [PASSED] Mono
[10:49:26] ====== [PASSED] drm_test_get_tv_mode_from_name_valid =======
[10:49:26] [PASSED] drm_test_get_tv_mode_from_name_truncated
[10:49:26] ============ [PASSED] drm_get_tv_mode_from_name ============
[10:49:26] = drm_test_connector_hdmi_compute_mode_clock (12 subtests) =
[10:49:26] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb
[10:49:26] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc
[10:49:26] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1
[10:49:26] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc
[10:49:26] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1
[10:49:26] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_double
[10:49:26] = drm_test_connector_hdmi_compute_mode_clock_yuv420_valid  =
[10:49:26] [PASSED] VIC 96
[10:49:26] [PASSED] VIC 97
[10:49:26] [PASSED] VIC 101
[10:49:26] [PASSED] VIC 102
[10:49:26] [PASSED] VIC 106
[10:49:26] [PASSED] VIC 107
[10:49:26] === [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_valid ===
[10:49:26] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc
[10:49:26] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc
[10:49:26] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc
[10:49:26] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc
[10:49:26] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc
[10:49:26] === [PASSED] drm_test_connector_hdmi_compute_mode_clock ====
[10:49:26] == drm_hdmi_connector_get_broadcast_rgb_name (2 subtests) ==
[10:49:26] === drm_test_drm_hdmi_connector_get_broadcast_rgb_name  ====
[10:49:26] [PASSED] Automatic
[10:49:26] [PASSED] Full
[10:49:26] [PASSED] Limited 16:235
[10:49:26] === [PASSED] drm_test_drm_hdmi_connector_get_broadcast_rgb_name ===
[10:49:26] [PASSED] drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid
[10:49:26] ==== [PASSED] drm_hdmi_connector_get_broadcast_rgb_name ====
[10:49:26] == drm_hdmi_connector_get_output_format_name (2 subtests) ==
[10:49:26] === drm_test_drm_hdmi_connector_get_output_format_name  ====
[10:49:26] [PASSED] RGB
[10:49:26] [PASSED] YUV 4:2:0
[10:49:26] [PASSED] YUV 4:2:2
[10:49:26] [PASSED] YUV 4:4:4
[10:49:26] === [PASSED] drm_test_drm_hdmi_connector_get_output_format_name ===
[10:49:26] [PASSED] drm_test_drm_hdmi_connector_get_output_format_name_invalid
[10:49:26] ==== [PASSED] drm_hdmi_connector_get_output_format_name ====
[10:49:26] ============= drm_damage_helper (21 subtests) ==============
[10:49:26] [PASSED] drm_test_damage_iter_no_damage
[10:49:26] [PASSED] drm_test_damage_iter_no_damage_fractional_src
[10:49:26] [PASSED] drm_test_damage_iter_no_damage_src_moved
[10:49:26] [PASSED] drm_test_damage_iter_no_damage_fractional_src_moved
[10:49:26] [PASSED] drm_test_damage_iter_no_damage_not_visible
[10:49:26] [PASSED] drm_test_damage_iter_no_damage_no_crtc
[10:49:26] [PASSED] drm_test_damage_iter_no_damage_no_fb
[10:49:26] [PASSED] drm_test_damage_iter_simple_damage
[10:49:26] [PASSED] drm_test_damage_iter_single_damage
[10:49:26] [PASSED] drm_test_damage_iter_single_damage_intersect_src
[10:49:26] [PASSED] drm_test_damage_iter_single_damage_outside_src
[10:49:26] [PASSED] drm_test_damage_iter_single_damage_fractional_src
[10:49:26] [PASSED] drm_test_damage_iter_single_damage_intersect_fractional_src
[10:49:26] [PASSED] drm_test_damage_iter_single_damage_outside_fractional_src
[10:49:26] [PASSED] drm_test_damage_iter_single_damage_src_moved
[10:49:26] [PASSED] drm_test_damage_iter_single_damage_fractional_src_moved
[10:49:26] [PASSED] drm_test_damage_iter_damage
[10:49:26] [PASSED] drm_test_damage_iter_damage_one_intersect
[10:49:26] [PASSED] drm_test_damage_iter_damage_one_outside
[10:49:26] [PASSED] drm_test_damage_iter_damage_src_moved
[10:49:26] [PASSED] drm_test_damage_iter_damage_not_visible
[10:49:26] ================ [PASSED] drm_damage_helper ================
[10:49:26] ============== drm_dp_mst_helper (3 subtests) ==============
[10:49:26] ============== drm_test_dp_mst_calc_pbn_mode  ==============
[10:49:26] [PASSED] Clock 154000 BPP 30 DSC disabled
[10:49:26] [PASSED] Clock 234000 BPP 30 DSC disabled
[10:49:26] [PASSED] Clock 297000 BPP 24 DSC disabled
[10:49:26] [PASSED] Clock 332880 BPP 24 DSC enabled
[10:49:26] [PASSED] Clock 324540 BPP 24 DSC enabled
[10:49:26] ========== [PASSED] drm_test_dp_mst_calc_pbn_mode ==========
[10:49:26] ============== drm_test_dp_mst_calc_pbn_div  ===============
[10:49:26] [PASSED] Link rate 2000000 lane count 4
[10:49:26] [PASSED] Link rate 2000000 lane count 2
[10:49:26] [PASSED] Link rate 2000000 lane count 1
[10:49:26] [PASSED] Link rate 1350000 lane count 4
[10:49:26] [PASSED] Link rate 1350000 lane count 2
[10:49:26] [PASSED] Link rate 1350000 lane count 1
[10:49:26] [PASSED] Link rate 1000000 lane count 4
[10:49:26] [PASSED] Link rate 1000000 lane count 2
[10:49:26] [PASSED] Link rate 1000000 lane count 1
[10:49:26] [PASSED] Link rate 810000 lane count 4
[10:49:26] [PASSED] Link rate 810000 lane count 2
[10:49:26] [PASSED] Link rate 810000 lane count 1
[10:49:26] [PASSED] Link rate 540000 lane count 4
[10:49:26] [PASSED] Link rate 540000 lane count 2
[10:49:26] [PASSED] Link rate 540000 lane count 1
[10:49:26] [PASSED] Link rate 270000 lane count 4
[10:49:26] [PASSED] Link rate 270000 lane count 2
[10:49:26] [PASSED] Link rate 270000 lane count 1
[10:49:26] [PASSED] Link rate 162000 lane count 4
[10:49:26] [PASSED] Link rate 162000 lane count 2
[10:49:26] [PASSED] Link rate 162000 lane count 1
[10:49:26] ========== [PASSED] drm_test_dp_mst_calc_pbn_div ===========
[10:49:26] ========= drm_test_dp_mst_sideband_msg_req_decode  =========
[10:49:26] [PASSED] DP_ENUM_PATH_RESOURCES with port number
[10:49:26] [PASSED] DP_POWER_UP_PHY with port number
[10:49:26] [PASSED] DP_POWER_DOWN_PHY with port number
[10:49:26] [PASSED] DP_ALLOCATE_PAYLOAD with SDP stream sinks
[10:49:26] [PASSED] DP_ALLOCATE_PAYLOAD with port number
[10:49:26] [PASSED] DP_ALLOCATE_PAYLOAD with VCPI
[10:49:26] [PASSED] DP_ALLOCATE_PAYLOAD with PBN
[10:49:26] [PASSED] DP_QUERY_PAYLOAD with port number
[10:49:26] [PASSED] DP_QUERY_PAYLOAD with VCPI
[10:49:26] [PASSED] DP_REMOTE_DPCD_READ with port number
[10:49:26] [PASSED] DP_REMOTE_DPCD_READ with DPCD address
[10:49:26] [PASSED] DP_REMOTE_DPCD_READ with max number of bytes
[10:49:26] [PASSED] DP_REMOTE_DPCD_WRITE with port number
[10:49:26] [PASSED] DP_REMOTE_DPCD_WRITE with DPCD address
[10:49:26] [PASSED] DP_REMOTE_DPCD_WRITE with data array
[10:49:26] [PASSED] DP_REMOTE_I2C_READ with port number
[10:49:26] [PASSED] DP_REMOTE_I2C_READ with I2C device ID
[10:49:26] [PASSED] DP_REMOTE_I2C_READ with transactions array
[10:49:26] [PASSED] DP_REMOTE_I2C_WRITE with port number
[10:49:26] [PASSED] DP_REMOTE_I2C_WRITE with I2C device ID
[10:49:26] [PASSED] DP_REMOTE_I2C_WRITE with data array
[10:49:26] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream ID
[10:49:26] [PASSED] DP_QUERY_STREAM_ENC_STATUS with client ID
[10:49:26] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream event
[10:49:26] [PASSED] DP_QUERY_STREAM_ENC_STATUS with valid stream event
[10:49:26] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream behavior
[10:49:26] [PASSED] DP_QUERY_STREAM_ENC_STATUS with a valid stream behavior
[10:49:26] ===== [PASSED] drm_test_dp_mst_sideband_msg_req_decode =====
[10:49:26] ================ [PASSED] drm_dp_mst_helper ================
[10:49:26] ================== drm_exec (7 subtests) ===================
[10:49:26] [PASSED] sanitycheck
[10:49:26] [PASSED] test_lock
[10:49:26] [PASSED] test_lock_unlock
[10:49:26] [PASSED] test_duplicates
[10:49:26] [PASSED] test_prepare
[10:49:26] [PASSED] test_prepare_array
[10:49:26] [PASSED] test_multiple_loops
[10:49:26] ==================== [PASSED] drm_exec =====================
[10:49:26] =========== drm_format_helper_test (17 subtests) ===========
[10:49:26] ============== drm_test_fb_xrgb8888_to_gray8  ==============
[10:49:26] [PASSED] single_pixel_source_buffer
[10:49:26] [PASSED] single_pixel_clip_rectangle
[10:49:26] [PASSED] well_known_colors
[10:49:26] [PASSED] destination_pitch
[10:49:26] ========== [PASSED] drm_test_fb_xrgb8888_to_gray8 ==========
[10:49:26] ============= drm_test_fb_xrgb8888_to_rgb332  ==============
[10:49:26] [PASSED] single_pixel_source_buffer
[10:49:26] [PASSED] single_pixel_clip_rectangle
[10:49:26] [PASSED] well_known_colors
[10:49:26] [PASSED] destination_pitch
[10:49:26] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb332 ==========
[10:49:26] ============= drm_test_fb_xrgb8888_to_rgb565  ==============
[10:49:26] [PASSED] single_pixel_source_buffer
[10:49:26] [PASSED] single_pixel_clip_rectangle
[10:49:26] [PASSED] well_known_colors
[10:49:26] [PASSED] destination_pitch
[10:49:26] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb565 ==========
[10:49:26] ============ drm_test_fb_xrgb8888_to_xrgb1555  =============
[10:49:26] [PASSED] single_pixel_source_buffer
[10:49:26] [PASSED] single_pixel_clip_rectangle
[10:49:26] [PASSED] well_known_colors
[10:49:26] [PASSED] destination_pitch
[10:49:26] ======== [PASSED] drm_test_fb_xrgb8888_to_xrgb1555 =========
[10:49:26] ============ drm_test_fb_xrgb8888_to_argb1555  =============
[10:49:26] [PASSED] single_pixel_source_buffer
[10:49:26] [PASSED] single_pixel_clip_rectangle
[10:49:26] [PASSED] well_known_colors
[10:49:26] [PASSED] destination_pitch
[10:49:26] ======== [PASSED] drm_test_fb_xrgb8888_to_argb1555 =========
[10:49:26] ============ drm_test_fb_xrgb8888_to_rgba5551  =============
[10:49:26] [PASSED] single_pixel_source_buffer
[10:49:26] [PASSED] single_pixel_clip_rectangle
[10:49:26] [PASSED] well_known_colors
[10:49:26] [PASSED] destination_pitch
[10:49:26] ======== [PASSED] drm_test_fb_xrgb8888_to_rgba5551 =========
[10:49:26] ============= drm_test_fb_xrgb8888_to_rgb888  ==============
[10:49:26] [PASSED] single_pixel_source_buffer
[10:49:26] [PASSED] single_pixel_clip_rectangle
[10:49:26] [PASSED] well_known_colors
[10:49:26] [PASSED] destination_pitch
[10:49:26] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb888 ==========
[10:49:26] ============= drm_test_fb_xrgb8888_to_bgr888  ==============
[10:49:26] [PASSED] single_pixel_source_buffer
[10:49:26] [PASSED] single_pixel_clip_rectangle
[10:49:26] [PASSED] well_known_colors
[10:49:26] [PASSED] destination_pitch
[10:49:26] ========= [PASSED] drm_test_fb_xrgb8888_to_bgr888 ==========
[10:49:26] ============ drm_test_fb_xrgb8888_to_argb8888  =============
[10:49:26] [PASSED] single_pixel_source_buffer
[10:49:26] [PASSED] single_pixel_clip_rectangle
[10:49:26] [PASSED] well_known_colors
[10:49:26] [PASSED] destination_pitch
[10:49:26] ======== [PASSED] drm_test_fb_xrgb8888_to_argb8888 =========
[10:49:26] =========== drm_test_fb_xrgb8888_to_xrgb2101010  ===========
[10:49:26] [PASSED] single_pixel_source_buffer
[10:49:26] [PASSED] single_pixel_clip_rectangle
[10:49:26] [PASSED] well_known_colors
[10:49:26] [PASSED] destination_pitch
[10:49:26] ======= [PASSED] drm_test_fb_xrgb8888_to_xrgb2101010 =======
[10:49:26] =========== drm_test_fb_xrgb8888_to_argb2101010  ===========
[10:49:26] [PASSED] single_pixel_source_buffer
[10:49:26] [PASSED] single_pixel_clip_rectangle
[10:49:26] [PASSED] well_known_colors
[10:49:26] [PASSED] destination_pitch
[10:49:26] ======= [PASSED] drm_test_fb_xrgb8888_to_argb2101010 =======
[10:49:26] ============== drm_test_fb_xrgb8888_to_mono  ===============
[10:49:26] [PASSED] single_pixel_source_buffer
[10:49:26] [PASSED] single_pixel_clip_rectangle
[10:49:26] [PASSED] well_known_colors
[10:49:26] [PASSED] destination_pitch
[10:49:26] ========== [PASSED] drm_test_fb_xrgb8888_to_mono ===========
[10:49:26] ==================== drm_test_fb_swab  =====================
[10:49:26] [PASSED] single_pixel_source_buffer
[10:49:26] [PASSED] single_pixel_clip_rectangle
[10:49:26] [PASSED] well_known_colors
[10:49:26] [PASSED] destination_pitch
[10:49:26] ================ [PASSED] drm_test_fb_swab =================
[10:49:26] ============ drm_test_fb_xrgb8888_to_xbgr8888  =============
[10:49:26] [PASSED] single_pixel_source_buffer
[10:49:26] [PASSED] single_pixel_clip_rectangle
[10:49:26] [PASSED] well_known_colors
[10:49:26] [PASSED] destination_pitch
[10:49:26] ======== [PASSED] drm_test_fb_xrgb8888_to_xbgr8888 =========
[10:49:26] ============ drm_test_fb_xrgb8888_to_abgr8888  =============
[10:49:26] [PASSED] single_pixel_source_buffer
[10:49:26] [PASSED] single_pixel_clip_rectangle
[10:49:26] [PASSED] well_known_colors
[10:49:26] [PASSED] destination_pitch
[10:49:26] ======== [PASSED] drm_test_fb_xrgb8888_to_abgr8888 =========
[10:49:26] ================= drm_test_fb_clip_offset  =================
[10:49:26] [PASSED] pass through
[10:49:26] [PASSED] horizontal offset
[10:49:26] [PASSED] vertical offset
[10:49:26] [PASSED] horizontal and vertical offset
[10:49:26] [PASSED] horizontal offset (custom pitch)
[10:49:26] [PASSED] vertical offset (custom pitch)
[10:49:26] [PASSED] horizontal and vertical offset (custom pitch)
[10:49:26] ============= [PASSED] drm_test_fb_clip_offset =============
[10:49:26] =================== drm_test_fb_memcpy  ====================
[10:49:26] [PASSED] single_pixel_source_buffer: XR24 little-endian (0x34325258)
[10:49:26] [PASSED] single_pixel_source_buffer: XRA8 little-endian (0x38415258)
[10:49:26] [PASSED] single_pixel_source_buffer: YU24 little-endian (0x34325559)
[10:49:26] [PASSED] single_pixel_clip_rectangle: XB24 little-endian (0x34324258)
[10:49:26] [PASSED] single_pixel_clip_rectangle: XRA8 little-endian (0x38415258)
[10:49:26] [PASSED] single_pixel_clip_rectangle: YU24 little-endian (0x34325559)
[10:49:26] [PASSED] well_known_colors: XB24 little-endian (0x34324258)
[10:49:26] [PASSED] well_known_colors: XRA8 little-endian (0x38415258)
[10:49:26] [PASSED] well_known_colors: YU24 little-endian (0x34325559)
[10:49:26] [PASSED] destination_pitch: XB24 little-endian (0x34324258)
[10:49:26] [PASSED] destination_pitch: XRA8 little-endian (0x38415258)
[10:49:26] [PASSED] destination_pitch: YU24 little-endian (0x34325559)
[10:49:26] =============== [PASSED] drm_test_fb_memcpy ================
[10:49:26] ============= [PASSED] drm_format_helper_test ==============
[10:49:26] ================= drm_format (18 subtests) =================
[10:49:26] [PASSED] drm_test_format_block_width_invalid
[10:49:26] [PASSED] drm_test_format_block_width_one_plane
[10:49:26] [PASSED] drm_test_format_block_width_two_plane
[10:49:26] [PASSED] drm_test_format_block_width_three_plane
[10:49:26] [PASSED] drm_test_format_block_width_tiled
[10:49:26] [PASSED] drm_test_format_block_height_invalid
[10:49:26] [PASSED] drm_test_format_block_height_one_plane
[10:49:26] [PASSED] drm_test_format_block_height_two_plane
[10:49:26] [PASSED] drm_test_format_block_height_three_plane
[10:49:26] [PASSED] drm_test_format_block_height_tiled
[10:49:26] [PASSED] drm_test_format_min_pitch_invalid
[10:49:26] [PASSED] drm_test_format_min_pitch_one_plane_8bpp
[10:49:26] [PASSED] drm_test_format_min_pitch_one_plane_16bpp
[10:49:26] [PASSED] drm_test_format_min_pitch_one_plane_24bpp
[10:49:26] [PASSED] drm_test_format_min_pitch_one_plane_32bpp
[10:49:26] [PASSED] drm_test_format_min_pitch_two_plane
[10:49:26] [PASSED] drm_test_format_min_pitch_three_plane_8bpp
[10:49:26] [PASSED] drm_test_format_min_pitch_tiled
[10:49:26] =================== [PASSED] drm_format ====================
[10:49:26] ============== drm_framebuffer (10 subtests) ===============
[10:49:26] ========== drm_test_framebuffer_check_src_coords  ==========
[10:49:26] [PASSED] Success: source fits into fb
[10:49:26] [PASSED] Fail: overflowing fb with x-axis coordinate
[10:49:26] [PASSED] Fail: overflowing fb with y-axis coordinate
[10:49:26] [PASSED] Fail: overflowing fb with source width
[10:49:26] [PASSED] Fail: overflowing fb with source height
[10:49:26] ====== [PASSED] drm_test_framebuffer_check_src_coords ======
[10:49:26] [PASSED] drm_test_framebuffer_cleanup
[10:49:26] =============== drm_test_framebuffer_create  ===============
[10:49:26] [PASSED] ABGR8888 normal sizes
[10:49:26] [PASSED] ABGR8888 max sizes
[10:49:26] [PASSED] ABGR8888 pitch greater than min required
[10:49:26] [PASSED] ABGR8888 pitch less than min required
[10:49:26] [PASSED] ABGR8888 Invalid width
[10:49:26] [PASSED] ABGR8888 Invalid buffer handle
[10:49:26] [PASSED] No pixel format
[10:49:26] [PASSED] ABGR8888 Width 0
[10:49:26] [PASSED] ABGR8888 Height 0
[10:49:26] [PASSED] ABGR8888 Out of bound height * pitch combination
[10:49:26] [PASSED] ABGR8888 Large buffer offset
[10:49:26] [PASSED] ABGR8888 Buffer offset for inexistent plane
[10:49:26] [PASSED] ABGR8888 Invalid flag
[10:49:26] [PASSED] ABGR8888 Set DRM_MODE_FB_MODIFIERS without modifiers
[10:49:26] [PASSED] ABGR8888 Valid buffer modifier
[10:49:26] [PASSED] ABGR8888 Invalid buffer modifier(DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
[10:49:26] [PASSED] ABGR8888 Extra pitches without DRM_MODE_FB_MODIFIERS
[10:49:26] [PASSED] ABGR8888 Extra pitches with DRM_MODE_FB_MODIFIERS
[10:49:26] [PASSED] NV12 Normal sizes
[10:49:26] [PASSED] NV12 Max sizes
[10:49:26] [PASSED] NV12 Invalid pitch
[10:49:26] [PASSED] NV12 Invalid modifier/missing DRM_MODE_FB_MODIFIERS flag
[10:49:26] [PASSED] NV12 different  modifier per-plane
[10:49:26] [PASSED] NV12 with DRM_FORMAT_MOD_SAMSUNG_64_32_TILE
[10:49:26] [PASSED] NV12 Valid modifiers without DRM_MODE_FB_MODIFIERS
[10:49:26] [PASSED] NV12 Modifier for inexistent plane
[10:49:26] [PASSED] NV12 Handle for inexistent plane
[10:49:26] [PASSED] NV12 Handle for inexistent plane without DRM_MODE_FB_MODIFIERS
[10:49:26] [PASSED] YVU420 DRM_MODE_FB_MODIFIERS set without modifier
[10:49:26] [PASSED] YVU420 Normal sizes
[10:49:26] [PASSED] YVU420 Max sizes
[10:49:26] [PASSED] YVU420 Invalid pitch
[10:49:26] [PASSED] YVU420 Different pitches
[10:49:26] [PASSED] YVU420 Different buffer offsets/pitches
[10:49:26] [PASSED] YVU420 Modifier set just for plane 0, without DRM_MODE_FB_MODIFIERS
[10:49:26] [PASSED] YVU420 Modifier set just for planes 0, 1, without DRM_MODE_FB_MODIFIERS
[10:49:26] [PASSED] YVU420 Modifier set just for plane 0, 1, with DRM_MODE_FB_MODIFIERS
[10:49:26] [PASSED] YVU420 Valid modifier
[10:49:26] [PASSED] YVU420 Different modifiers per plane
[10:49:26] [PASSED] YVU420 Modifier for inexistent plane
[10:49:26] [PASSED] YUV420_10BIT Invalid modifier(DRM_FORMAT_MOD_LINEAR)
[10:49:26] [PASSED] X0L2 Normal sizes
[10:49:26] [PASSED] X0L2 Max sizes
[10:49:26] [PASSED] X0L2 Invalid pitch
[10:49:26] [PASSED] X0L2 Pitch greater than minimum required
[10:49:26] [PASSED] X0L2 Handle for inexistent plane
[10:49:26] [PASSED] X0L2 Offset for inexistent plane, without DRM_MODE_FB_MODIFIERS set
[10:49:26] [PASSED] X0L2 Modifier without DRM_MODE_FB_MODIFIERS set
[10:49:26] [PASSED] X0L2 Valid modifier
[10:49:26] [PASSED] X0L2 Modifier for inexistent plane
[10:49:26] =========== [PASSED] drm_test_framebuffer_create ===========
[10:49:26] [PASSED] drm_test_framebuffer_free
[10:49:26] [PASSED] drm_test_framebuffer_init
[10:49:26] [PASSED] drm_test_framebuffer_init_bad_format
[10:49:26] [PASSED] drm_test_framebuffer_init_dev_mismatch
[10:49:26] [PASSED] drm_test_framebuffer_lookup
[10:49:26] [PASSED] drm_test_framebuffer_lookup_inexistent
[10:49:26] [PASSED] drm_test_framebuffer_modifiers_not_supported
[10:49:26] ================= [PASSED] drm_framebuffer =================
[10:49:26] ================ drm_gem_shmem (8 subtests) ================
[10:49:26] [PASSED] drm_gem_shmem_test_obj_create
[10:49:26] [PASSED] drm_gem_shmem_test_obj_create_private
[10:49:26] [PASSED] drm_gem_shmem_test_pin_pages
[10:49:26] [PASSED] drm_gem_shmem_test_vmap
[10:49:26] [PASSED] drm_gem_shmem_test_get_sg_table
[10:49:26] [PASSED] drm_gem_shmem_test_get_pages_sgt
[10:49:26] [PASSED] drm_gem_shmem_test_madvise
[10:49:26] [PASSED] drm_gem_shmem_test_purge
[10:49:26] ================== [PASSED] drm_gem_shmem ==================
[10:49:26] === drm_atomic_helper_connector_hdmi_check (29 subtests) ===
[10:49:26] [PASSED] drm_test_check_broadcast_rgb_auto_cea_mode
[10:49:26] [PASSED] drm_test_check_broadcast_rgb_auto_cea_mode_vic_1
[10:49:26] [PASSED] drm_test_check_broadcast_rgb_full_cea_mode
[10:49:26] [PASSED] drm_test_check_broadcast_rgb_full_cea_mode_vic_1
[10:49:26] [PASSED] drm_test_check_broadcast_rgb_limited_cea_mode
[10:49:26] [PASSED] drm_test_check_broadcast_rgb_limited_cea_mode_vic_1
[10:49:26] ====== drm_test_check_broadcast_rgb_cea_mode_yuv420  =======
[10:49:26] [PASSED] Automatic
[10:49:26] [PASSED] Full
[10:49:26] [PASSED] Limited 16:235
[10:49:26] == [PASSED] drm_test_check_broadcast_rgb_cea_mode_yuv420 ===
[10:49:26] [PASSED] drm_test_check_broadcast_rgb_crtc_mode_changed
[10:49:26] [PASSED] drm_test_check_broadcast_rgb_crtc_mode_not_changed
[10:49:26] [PASSED] drm_test_check_disable_connector
[10:49:26] [PASSED] drm_test_check_hdmi_funcs_reject_rate
[10:49:26] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_rgb
[10:49:26] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_yuv420
[10:49:26] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422
[10:49:26] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420
[10:49:26] [PASSED] drm_test_check_driver_unsupported_fallback_yuv420
[10:49:26] [PASSED] drm_test_check_output_bpc_crtc_mode_changed
[10:49:26] [PASSED] drm_test_check_output_bpc_crtc_mode_not_changed
[10:49:26] [PASSED] drm_test_check_output_bpc_dvi
[10:49:26] [PASSED] drm_test_check_output_bpc_format_vic_1
[10:49:26] [PASSED] drm_test_check_output_bpc_format_display_8bpc_only
[10:49:26] [PASSED] drm_test_check_output_bpc_format_display_rgb_only
[10:49:26] [PASSED] drm_test_check_output_bpc_format_driver_8bpc_only
[10:49:26] [PASSED] drm_test_check_output_bpc_format_driver_rgb_only
[10:49:26] [PASSED] drm_test_check_tmds_char_rate_rgb_8bpc
[10:49:26] [PASSED] drm_test_check_tmds_char_rate_rgb_10bpc
[10:49:26] [PASSED] drm_test_check_tmds_char_rate_rgb_12bpc
[10:49:26] ============ drm_test_check_hdmi_color_format  =============
[10:49:26] [PASSED] AUTO -> RGB
[10:49:26] [PASSED] YCBCR422 -> YUV422
[10:49:26] [PASSED] YCBCR420 -> YUV420
[10:49:26] [PASSED] YCBCR444 -> YUV444
[10:49:26] [PASSED] RGB -> RGB
[10:49:26] ======== [PASSED] drm_test_check_hdmi_color_format =========
[10:49:26] ======== drm_test_check_hdmi_color_format_420_only  ========
[10:49:26] [PASSED] RGB should fail
[10:49:26] [PASSED] YUV444 should fail
[10:49:26] [PASSED] YUV422 should fail
[10:49:26] [PASSED] YUV420 should work
[10:49:26] ==== [PASSED] drm_test_check_hdmi_color_format_420_only ====
[10:49:26] ===== [PASSED] drm_atomic_helper_connector_hdmi_check ======
[10:49:26] === drm_atomic_helper_connector_hdmi_reset (6 subtests) ====
[10:49:26] [PASSED] drm_test_check_broadcast_rgb_value
[10:49:26] [PASSED] drm_test_check_bpc_8_value
[10:49:26] [PASSED] drm_test_check_bpc_10_value
[10:49:26] [PASSED] drm_test_check_bpc_12_value
[10:49:26] [PASSED] drm_test_check_format_value
[10:49:26] [PASSED] drm_test_check_tmds_char_value
[10:49:26] ===== [PASSED] drm_atomic_helper_connector_hdmi_reset ======
[10:49:26] = drm_atomic_helper_connector_hdmi_mode_valid (7 subtests) =
[10:49:26] [PASSED] drm_test_check_mode_valid
[10:49:26] [PASSED] drm_test_check_mode_valid_reject
[10:49:26] [PASSED] drm_test_check_mode_valid_reject_rate
[10:49:26] [PASSED] drm_test_check_mode_valid_reject_max_clock
[10:49:26] [PASSED] drm_test_check_mode_valid_yuv420_only_max_clock
[10:49:26] [PASSED] drm_test_check_mode_valid_reject_yuv420_only_connector
[10:49:26] [PASSED] drm_test_check_mode_valid_accept_yuv420_also_connector_rgb
[10:49:26] === [PASSED] drm_atomic_helper_connector_hdmi_mode_valid ===
[10:49:26] = drm_atomic_helper_connector_hdmi_infoframes (5 subtests) =
[10:49:26] [PASSED] drm_test_check_infoframes
[10:49:26] [PASSED] drm_test_check_reject_avi_infoframe
[10:49:26] [PASSED] drm_test_check_reject_hdr_infoframe_bpc_8
[10:49:26] [PASSED] drm_test_check_reject_hdr_infoframe_bpc_10
[10:49:26] [PASSED] drm_test_check_reject_audio_infoframe
[10:49:26] === [PASSED] drm_atomic_helper_connector_hdmi_infoframes ===
[10:49:26] ================= drm_managed (2 subtests) =================
[10:49:26] [PASSED] drm_test_managed_release_action
[10:49:26] [PASSED] drm_test_managed_run_action
[10:49:26] =================== [PASSED] drm_managed ===================
[10:49:26] =================== drm_mm (6 subtests) ====================
[10:49:26] [PASSED] drm_test_mm_init
[10:49:26] [PASSED] drm_test_mm_debug
[10:49:26] [PASSED] drm_test_mm_align32
[10:49:26] [PASSED] drm_test_mm_align64
[10:49:26] [PASSED] drm_test_mm_lowest
[10:49:26] [PASSED] drm_test_mm_highest
[10:49:26] ===================== [PASSED] drm_mm ======================
[10:49:26] ============= drm_modes_analog_tv (5 subtests) =============
[10:49:26] [PASSED] drm_test_modes_analog_tv_mono_576i
[10:49:26] [PASSED] drm_test_modes_analog_tv_ntsc_480i
[10:49:26] [PASSED] drm_test_modes_analog_tv_ntsc_480i_inlined
[10:49:26] [PASSED] drm_test_modes_analog_tv_pal_576i
[10:49:26] [PASSED] drm_test_modes_analog_tv_pal_576i_inlined
[10:49:26] =============== [PASSED] drm_modes_analog_tv ===============
[10:49:26] ============== drm_panic_helper (3 subtests) ===============
[10:49:26] ============= drm_test_panic_screen_user_map  ==============
[10:49:26] [PASSED] Panic screen user, mode: 1024 x 768 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen user, mode: 494 x 494 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen user, mode: 1920 x 1080 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen user, mode: 1024 x 768 	RG16 little-endian (0x36314752)
[10:49:26] [PASSED] Panic screen user, mode: 1024 x 768 	RG24 little-endian (0x34324752)
[10:49:26] [PASSED] Panic screen kmsg, mode: 1024 x 768 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen kmsg, mode: 494 x 494 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen kmsg, mode: 1920 x 1080 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen kmsg, mode: 1024 x 768 	RG16 little-endian (0x36314752)
[10:49:26] [PASSED] Panic screen kmsg, mode: 1024 x 768 	RG24 little-endian (0x34324752)
[10:49:26] ========= [PASSED] drm_test_panic_screen_user_map ==========
[10:49:26] ============= drm_test_panic_screen_user_page  =============
[10:49:26] [PASSED] Panic screen user, mode: 1024 x 768 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen user, mode: 494 x 494 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen user, mode: 1920 x 1080 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen user, mode: 1024 x 768 	RG16 little-endian (0x36314752)
[10:49:26] [PASSED] Panic screen user, mode: 1024 x 768 	RG24 little-endian (0x34324752)
[10:49:26] [PASSED] Panic screen kmsg, mode: 1024 x 768 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen kmsg, mode: 494 x 494 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen kmsg, mode: 1920 x 1080 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen kmsg, mode: 1024 x 768 	RG16 little-endian (0x36314752)
[10:49:26] [PASSED] Panic screen kmsg, mode: 1024 x 768 	RG24 little-endian (0x34324752)
[10:49:26] ========= [PASSED] drm_test_panic_screen_user_page =========
[10:49:26] ========== drm_test_panic_screen_user_set_pixel  ===========
[10:49:26] [PASSED] Panic screen user, mode: 1024 x 768 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen user, mode: 494 x 494 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen user, mode: 1920 x 1080 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen user, mode: 1024 x 768 	RG16 little-endian (0x36314752)
[10:49:26] [PASSED] Panic screen user, mode: 1024 x 768 	RG24 little-endian (0x34324752)
[10:49:26] [PASSED] Panic screen kmsg, mode: 1024 x 768 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen kmsg, mode: 494 x 494 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen kmsg, mode: 1920 x 1080 	XR24 little-endian (0x34325258)
[10:49:26] [PASSED] Panic screen kmsg, mode: 1024 x 768 	RG16 little-endian (0x36314752)
[10:49:26] [PASSED] Panic screen kmsg, mode: 1024 x 768 	RG24 little-endian (0x34324752)
[10:49:26] ====== [PASSED] drm_test_panic_screen_user_set_pixel =======
[10:49:26] ================ [PASSED] drm_panic_helper =================
[10:49:26] ============== drm_plane_helper (2 subtests) ===============
[10:49:26] =============== drm_test_check_plane_state  ================
[10:49:26] [PASSED] clipping_simple
[10:49:26] [PASSED] clipping_rotate_reflect
[10:49:26] [PASSED] positioning_simple
[10:49:26] [PASSED] upscaling
[10:49:26] [PASSED] downscaling
[10:49:26] [PASSED] rounding1
[10:49:26] [PASSED] rounding2
[10:49:26] [PASSED] rounding3
[10:49:26] [PASSED] rounding4
[10:49:26] =========== [PASSED] drm_test_check_plane_state ============
[10:49:26] =========== drm_test_check_invalid_plane_state  ============
[10:49:26] [PASSED] positioning_invalid
[10:49:26] [PASSED] upscaling_invalid
[10:49:26] [PASSED] downscaling_invalid
[10:49:26] ======= [PASSED] drm_test_check_invalid_plane_state ========
[10:49:26] ================ [PASSED] drm_plane_helper =================
[10:49:26] ====== drm_connector_helper_tv_get_modes (1 subtest) =======
[10:49:26] ====== drm_test_connector_helper_tv_get_modes_check  =======
[10:49:26] [PASSED] None
[10:49:26] [PASSED] PAL
[10:49:26] [PASSED] NTSC
[10:49:26] [PASSED] Both, NTSC Default
[10:49:26] [PASSED] Both, PAL Default
[10:49:26] [PASSED] Both, NTSC Default, with PAL on command-line
[10:49:26] [PASSED] Both, PAL Default, with NTSC on command-line
[10:49:26] == [PASSED] drm_test_connector_helper_tv_get_modes_check ===
[10:49:26] ======== [PASSED] drm_connector_helper_tv_get_modes ========
[10:49:26] ================== drm_rect (9 subtests) ===================
[10:49:26] [PASSED] drm_test_rect_clip_scaled_div_by_zero
[10:49:26] [PASSED] drm_test_rect_clip_scaled_not_clipped
[10:49:26] [PASSED] drm_test_rect_clip_scaled_clipped
[10:49:26] [PASSED] drm_test_rect_clip_scaled_signed_vs_unsigned
[10:49:26] ================= drm_test_rect_intersect  =================
[10:49:26] [PASSED] top-left x bottom-right: 2x2+1+1 x 2x2+0+0
[10:49:26] [PASSED] top-right x bottom-left: 2x2+0+0 x 2x2+1-1
[10:49:26] [PASSED] bottom-left x top-right: 2x2+1-1 x 2x2+0+0
[10:49:26] [PASSED] bottom-right x top-left: 2x2+0+0 x 2x2+1+1
[10:49:26] [PASSED] right x left: 2x1+0+0 x 3x1+1+0
[10:49:26] [PASSED] left x right: 3x1+1+0 x 2x1+0+0
[10:49:26] [PASSED] up x bottom: 1x2+0+0 x 1x3+0-1
[10:49:26] [PASSED] bottom x up: 1x3+0-1 x 1x2+0+0
[10:49:26] [PASSED] touching corner: 1x1+0+0 x 2x2+1+1
[10:49:26] [PASSED] touching side: 1x1+0+0 x 1x1+1+0
[10:49:26] [PASSED] equal rects: 2x2+0+0 x 2x2+0+0
[10:49:26] [PASSED] inside another: 2x2+0+0 x 1x1+1+1
[10:49:26] [PASSED] far away: 1x1+0+0 x 1x1+3+6
[10:49:26] [PASSED] points intersecting: 0x0+5+10 x 0x0+5+10
[10:49:26] [PASSED] points not intersecting: 0x0+0+0 x 0x0+5+10
[10:49:26] ============= [PASSED] drm_test_rect_intersect =============
[10:49:26] ================ drm_test_rect_calc_hscale  ================
[10:49:26] [PASSED] normal use
[10:49:26] [PASSED] out of max range
[10:49:26] [PASSED] out of min range
[10:49:26] [PASSED] zero dst
[10:49:26] [PASSED] negative src
[10:49:26] [PASSED] negative dst
[10:49:26] ============ [PASSED] drm_test_rect_calc_hscale ============
[10:49:26] ================ drm_test_rect_calc_vscale  ================
[10:49:26] [PASSED] normal use
[10:49:26] [PASSED] out of max range
[10:49:26] [PASSED] out of min range
[10:49:26] [PASSED] zero dst
[10:49:26] [PASSED] negative src
[10:49:26] [PASSED] negative dst
[10:49:26] ============ [PASSED] drm_test_rect_calc_vscale ============
[10:49:26] ================== drm_test_rect_rotate  ===================
[10:49:26] [PASSED] reflect-x
[10:49:26] [PASSED] reflect-y
[10:49:26] [PASSED] rotate-0
[10:49:26] [PASSED] rotate-90
[10:49:26] [PASSED] rotate-180
[10:49:26] [PASSED] rotate-270
[10:49:26] ============== [PASSED] drm_test_rect_rotate ===============
[10:49:26] ================ drm_test_rect_rotate_inv  =================
[10:49:26] [PASSED] reflect-x
[10:49:26] [PASSED] reflect-y
[10:49:26] [PASSED] rotate-0
[10:49:26] [PASSED] rotate-90
[10:49:26] [PASSED] rotate-180
[10:49:26] [PASSED] rotate-270
[10:49:26] ============ [PASSED] drm_test_rect_rotate_inv =============
[10:49:26] ==================== [PASSED] drm_rect =====================
[10:49:26] ============ drm_sysfb_modeset_test (1 subtest) ============
[10:49:26] ============ drm_test_sysfb_build_fourcc_list  =============
[10:49:26] [PASSED] no native formats
[10:49:26] [PASSED] XRGB8888 as native format
[10:49:26] [PASSED] remove duplicates
[10:49:26] [PASSED] convert alpha formats
[10:49:26] [PASSED] random formats
[10:49:26] ======== [PASSED] drm_test_sysfb_build_fourcc_list =========
[10:49:26] ============= [PASSED] drm_sysfb_modeset_test ==============
[10:49:26] ================== drm_fixp (2 subtests) ===================
[10:49:26] [PASSED] drm_test_int2fixp
[10:49:26] [PASSED] drm_test_sm2fixp
[10:49:26] ==================== [PASSED] drm_fixp =====================
[10:49:26] ============================================================
[10:49:26] Testing complete. Ran 671 tests: passed: 671
[10:49:26] Elapsed time: 27.698s total, 1.805s configuring, 25.427s building, 0.414s running

+ for kcfg in "${kunitconfigs[@]}"
+ [[ ! -f /kernel/drivers/gpu/drm/ttm/tests/.kunitconfig ]]
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/ttm/tests/.kunitconfig
[10:49:26] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[10:49:28] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[10:49:39] Starting KUnit Kernel (1/1)...
[10:49:39] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[10:49:39] ============= refcount_interrupt (4 subtests) ==============
[10:49:39] [PASSED] test_single_irq_change
[10:49:39] [PASSED] test_nested_irq_change
[10:49:39] [PASSED] test_multiple_irq_change
[10:49:39] [PASSED] test_irq_save
[10:49:39] =============== [PASSED] refcount_interrupt ================
[10:49:39] ================= ttm_device (5 subtests) ==================
[10:49:39] [PASSED] ttm_device_init_basic
[10:49:39] [PASSED] ttm_device_init_multiple
[10:49:39] [PASSED] ttm_device_fini_basic
[10:49:39] [PASSED] ttm_device_init_no_vma_man
[10:49:39] ================== ttm_device_init_pools  ==================
[10:49:39] [PASSED] No DMA allocations, no DMA32 required
[10:49:39] [PASSED] DMA allocations, DMA32 required
[10:49:39] [PASSED] No DMA allocations, DMA32 required
[10:49:39] [PASSED] DMA allocations, no DMA32 required
[10:49:39] ============== [PASSED] ttm_device_init_pools ==============
[10:49:39] =================== [PASSED] ttm_device ====================
[10:49:39] ================== ttm_pool (8 subtests) ===================
[10:49:39] ================== ttm_pool_alloc_basic  ===================
[10:49:39] [PASSED] One page
[10:49:39] [PASSED] More than one page
[10:49:39] [PASSED] Above the allocation limit
[10:49:39] [PASSED] One page, with coherent DMA mappings enabled
[10:49:39] [PASSED] Above the allocation limit, with coherent DMA mappings enabled
[10:49:39] ============== [PASSED] ttm_pool_alloc_basic ===============
[10:49:39] ============== ttm_pool_alloc_basic_dma_addr  ==============
[10:49:39] [PASSED] One page
[10:49:39] [PASSED] More than one page
[10:49:39] [PASSED] Above the allocation limit
[10:49:39] [PASSED] One page, with coherent DMA mappings enabled
[10:49:39] [PASSED] Above the allocation limit, with coherent DMA mappings enabled
[10:49:39] ========== [PASSED] ttm_pool_alloc_basic_dma_addr ==========
[10:49:39] [PASSED] ttm_pool_alloc_order_caching_match
[10:49:39] [PASSED] ttm_pool_alloc_caching_mismatch
[10:49:39] [PASSED] ttm_pool_alloc_order_mismatch
[10:49:39] [PASSED] ttm_pool_free_dma_alloc
[10:49:39] [PASSED] ttm_pool_free_no_dma_alloc
[10:49:39] [PASSED] ttm_pool_fini_basic
[10:49:39] ==================== [PASSED] ttm_pool =====================
[10:49:39] ================ ttm_resource (8 subtests) =================
[10:49:39] ================= ttm_resource_init_basic  =================
[10:49:39] [PASSED] Init resource in TTM_PL_SYSTEM
[10:49:39] [PASSED] Init resource in TTM_PL_VRAM
[10:49:39] [PASSED] Init resource in a private placement
[10:49:39] [PASSED] Init resource in TTM_PL_SYSTEM, set placement flags
[10:49:39] ============= [PASSED] ttm_resource_init_basic =============
[10:49:39] [PASSED] ttm_resource_init_pinned
[10:49:39] [PASSED] ttm_resource_fini_basic
[10:49:39] [PASSED] ttm_resource_manager_init_basic
[10:49:39] [PASSED] ttm_resource_manager_usage_basic
[10:49:39] [PASSED] ttm_resource_manager_set_used_basic
[10:49:39] [PASSED] ttm_sys_man_alloc_basic
[10:49:39] [PASSED] ttm_sys_man_free_basic
[10:49:39] ================== [PASSED] ttm_resource ===================
[10:49:39] =================== ttm_tt (15 subtests) ===================
[10:49:39] ==================== ttm_tt_init_basic  ====================
[10:49:39] [PASSED] Page-aligned size
[10:49:39] [PASSED] Extra pages requested
[10:49:39] ================ [PASSED] ttm_tt_init_basic ================
[10:49:39] [PASSED] ttm_tt_init_misaligned
[10:49:39] [PASSED] ttm_tt_fini_basic
[10:49:39] [PASSED] ttm_tt_fini_sg
[10:49:39] [PASSED] ttm_tt_fini_shmem
[10:49:39] [PASSED] ttm_tt_create_basic
[10:49:39] [PASSED] ttm_tt_create_invalid_bo_type
[10:49:39] [PASSED] ttm_tt_create_ttm_exists
[10:49:39] [PASSED] ttm_tt_create_failed
[10:49:39] [PASSED] ttm_tt_destroy_basic
[10:49:39] [PASSED] ttm_tt_populate_null_ttm
[10:49:39] [PASSED] ttm_tt_populate_populated_ttm
[10:49:39] [PASSED] ttm_tt_unpopulate_basic
[10:49:39] [PASSED] ttm_tt_unpopulate_empty_ttm
[10:49:39] [PASSED] ttm_tt_swapin_basic
[10:49:39] ===================== [PASSED] ttm_tt ======================
[10:49:39] =================== ttm_bo (14 subtests) ===================
[10:49:39] =========== ttm_bo_reserve_optimistic_no_ticket  ===========
[10:49:39] [PASSED] Cannot be interrupted and sleeps
[10:49:39] [PASSED] Cannot be interrupted, locks straight away
[10:49:39] [PASSED] Can be interrupted, sleeps
[10:49:39] ======= [PASSED] ttm_bo_reserve_optimistic_no_ticket =======
[10:49:39] [PASSED] ttm_bo_reserve_locked_no_sleep
[10:49:39] [PASSED] ttm_bo_reserve_no_wait_ticket
[10:49:39] [PASSED] ttm_bo_reserve_double_resv
[10:49:39] [PASSED] ttm_bo_reserve_interrupted
[10:49:39] [PASSED] ttm_bo_reserve_deadlock
[10:49:39] [PASSED] ttm_bo_unreserve_basic
[10:49:39] [PASSED] ttm_bo_unreserve_pinned
[10:49:39] [PASSED] ttm_bo_unreserve_bulk
[10:49:39] [PASSED] ttm_bo_fini_basic
[10:49:39] [PASSED] ttm_bo_fini_shared_resv
[10:49:39] [PASSED] ttm_bo_pin_basic
[10:49:39] [PASSED] ttm_bo_pin_unpin_resource
[10:49:39] [PASSED] ttm_bo_multiple_pin_one_unpin
[10:49:39] ===================== [PASSED] ttm_bo ======================
[10:49:39] ============== ttm_bo_validate (22 subtests) ===============
[10:49:39] ============== ttm_bo_init_reserved_sys_man  ===============
[10:49:39] [PASSED] Buffer object for userspace
[10:49:39] [PASSED] Kernel buffer object
[10:49:39] [PASSED] Shared buffer object
[10:49:39] ========== [PASSED] ttm_bo_init_reserved_sys_man ===========
[10:49:39] ============== ttm_bo_init_reserved_mock_man  ==============
[10:49:39] [PASSED] Buffer object for userspace
[10:49:39] [PASSED] Kernel buffer object
[10:49:39] [PASSED] Shared buffer object
[10:49:39] ========== [PASSED] ttm_bo_init_reserved_mock_man ==========
[10:49:39] [PASSED] ttm_bo_init_reserved_resv
[10:49:39] ================== ttm_bo_validate_basic  ==================
[10:49:39] [PASSED] Buffer object for userspace
[10:49:39] [PASSED] Kernel buffer object
[10:49:39] [PASSED] Shared buffer object
[10:49:39] ============== [PASSED] ttm_bo_validate_basic ==============
[10:49:39] [PASSED] ttm_bo_validate_invalid_placement
[10:49:39] ============= ttm_bo_validate_same_placement  ==============
[10:49:39] [PASSED] System manager
[10:49:39] [PASSED] VRAM manager
[10:49:39] ========= [PASSED] ttm_bo_validate_same_placement ==========
[10:49:39] [PASSED] ttm_bo_validate_failed_alloc
[10:49:39] [PASSED] ttm_bo_validate_pinned
[10:49:39] [PASSED] ttm_bo_validate_busy_placement
[10:49:39] ================ ttm_bo_validate_multihop  =================
[10:49:39] [PASSED] Buffer object for userspace
[10:49:39] [PASSED] Kernel buffer object
[10:49:39] [PASSED] Shared buffer object
[10:49:39] ============ [PASSED] ttm_bo_validate_multihop =============
[10:49:39] ========== ttm_bo_validate_no_placement_signaled  ==========
[10:49:39] [PASSED] Buffer object in system domain, no page vector
[10:49:39] [PASSED] Buffer object in system domain with an existing page vector
[10:49:39] ====== [PASSED] ttm_bo_validate_no_placement_signaled ======
[10:49:39] ======== ttm_bo_validate_no_placement_not_signaled  ========
[10:49:39] [PASSED] Buffer object for userspace
[10:49:39] [PASSED] Kernel buffer object
[10:49:39] [PASSED] Shared buffer object
[10:49:39] ==== [PASSED] ttm_bo_validate_no_placement_not_signaled ====
[10:49:39] [PASSED] ttm_bo_validate_move_fence_signaled
[10:49:39] ========= ttm_bo_validate_move_fence_not_signaled  =========
[10:49:39] [PASSED] Waits for GPU
[10:49:39] [PASSED] Tries to lock straight away
[10:49:39] ===== [PASSED] ttm_bo_validate_move_fence_not_signaled =====
[10:49:39] [PASSED] ttm_bo_validate_swapout
[10:49:39] [PASSED] ttm_bo_validate_happy_evict
[10:49:39] [PASSED] ttm_bo_validate_all_pinned_evict
[10:49:39] [PASSED] ttm_bo_validate_allowed_only_evict
[10:49:39] [PASSED] ttm_bo_validate_deleted_evict
[10:49:39] [PASSED] ttm_bo_validate_busy_domain_evict
[10:49:39] [PASSED] ttm_bo_validate_evict_gutting
[10:49:39] [PASSED] ttm_bo_validate_recrusive_evict
[10:49:39] ================= [PASSED] ttm_bo_validate =================
[10:49:39] ============================================================
[10:49:39] Testing complete. Ran 106 tests: passed: 106
[10:49:39] Elapsed time: 12.431s total, 1.797s configuring, 10.419s building, 0.180s running

+ for kcfg in "${kunitconfigs[@]}"
+ [[ ! -f /kernel/drivers/dma-buf/.kunitconfig ]]
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/dma-buf/.kunitconfig
[10:49:39] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[10:49:41] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[10:49:50] Starting KUnit Kernel (1/1)...
[10:49:50] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[10:49:50] ============= refcount_interrupt (4 subtests) ==============
[10:49:50] [PASSED] test_single_irq_change
[10:49:50] [PASSED] test_nested_irq_change
[10:49:50] [PASSED] test_multiple_irq_change
[10:49:50] [PASSED] test_irq_save
[10:49:50] =============== [PASSED] refcount_interrupt ================
[10:49:50] =============== dma-buf-fence (12 subtests) ================
[10:49:50] [PASSED] test_sanitycheck
[10:49:50] [PASSED] test_signaling
[10:49:50] [PASSED] test_add_callback
[10:49:50] [PASSED] test_late_add_callback
[10:49:50] [PASSED] test_rm_callback
[10:49:50] [PASSED] test_late_rm_callback
[10:49:50] [PASSED] test_status
[10:49:50] [PASSED] test_error
[10:49:50] [PASSED] test_wait
[10:49:50] [PASSED] test_wait_timeout
[10:49:50] [PASSED] test_stub
[10:49:50] [SKIPPED] test_race_signal_callback (requires at least 2 CPUs)
[10:49:50] ================== [PASSED] dma-buf-fence ==================
[10:49:50] ============ dma-buf-fence-chain (11 subtests) =============
[10:49:50] [PASSED] test_sanitycheck
[10:49:50] [PASSED] test_find_seqno
[10:49:50] [PASSED] test_find_signaled
[10:49:50] [PASSED] test_find_out_of_order
[10:49:55] [PASSED] test_find_gap
[10:49:55] [PASSED] test_find_race
[10:49:55] [PASSED] test_signal_forward
[10:49:55] [PASSED] test_signal_backward
[10:49:55] [PASSED] test_wait_forward
[10:49:55] [PASSED] test_wait_backward
[10:49:55] [PASSED] test_wait_random
[10:49:55] =============== [PASSED] dma-buf-fence-chain ===============
[10:49:55] ============ dma-buf-fence-unwrap (10 subtests) ============
[10:49:55] [PASSED] test_sanitycheck
[10:49:55] [PASSED] test_unwrap_array
[10:49:55] [PASSED] test_unwrap_chain
[10:49:55] [PASSED] test_unwrap_chain_array
[10:49:55] [PASSED] test_unwrap_merge
[10:49:55] [PASSED] test_unwrap_merge_duplicate
[10:49:55] [PASSED] test_unwrap_merge_seqno
[10:49:55] [PASSED] test_unwrap_merge_order
[10:49:55] [PASSED] test_unwrap_merge_complex
[10:49:55] [PASSED] test_unwrap_merge_complex_seqno
[10:49:55] ============== [PASSED] dma-buf-fence-unwrap ===============
[10:49:55] ================ dma-buf-resv (5 subtests) =================
[10:49:55] [PASSED] test_sanitycheck
[10:49:55] ===================== test_signaling  ======================
[10:49:55] [PASSED] kernel
[10:49:55] [PASSED] write
[10:49:55] [PASSED] read
[10:49:55] [PASSED] bookkeep
[10:49:55] ================= [PASSED] test_signaling ==================
[10:49:55] ====================== test_for_each  ======================
[10:49:55] [PASSED] kernel
[10:49:55] [PASSED] write
[10:49:55] [PASSED] read
[10:49:55] [PASSED] bookkeep
[10:49:55] ================== [PASSED] test_for_each ==================
[10:49:55] ================= test_for_each_unlocked  ==================
[10:49:55] [PASSED] kernel
[10:49:55] [PASSED] write
[10:49:55] [PASSED] read
[10:49:55] [PASSED] bookkeep
[10:49:55] ============= [PASSED] test_for_each_unlocked ==============
[10:49:55] ===================== test_get_fences  =====================
[10:49:55] [PASSED] kernel
[10:49:55] [PASSED] write
[10:49:55] [PASSED] read
[10:49:55] [PASSED] bookkeep
[10:49:55] ================= [PASSED] test_get_fences =================
[10:49:55] ================== [PASSED] dma-buf-resv ===================
[10:49:55] ============================================================
[10:49:55] Testing complete. Ran 54 tests: passed: 53, skipped: 1
[10:49:55] Elapsed time: 16.050s total, 1.761s configuring, 9.017s building, 5.260s running

+ cleanup
++ stat -c %u:%g /kernel
+ chown -R 1003:1003 /kernel



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v1 3/7] drm/xe/vram: Make VRAM pools the allocation handle
  2026-10-02 10:40 ` [PATCH v1 3/7] drm/xe/vram: Make VRAM pools the allocation handle Piórkowski, Piotr
@ 2026-10-02 10:53   ` sashiko-bot
  0 siblings, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-10-02 10:53 UTC (permalink / raw)
  To: Piórkowski, Piotr; +Cc: intel-xe

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] xe: NULL pointer dereference of tile->mem.vram on integrated graphics
--

commit c154aad6efc21416255e0f4ca071bf1270bc02d1
Author: Piotr Piórkowski <piotr.piorkowski@intel.com>
drm/xe/vram: Make VRAM pools the allocation handle

This commit changes allocation paths to use a struct xe_vram_pool rather
than a struct xe_vram_region. This allows regions to be split into several
pools without affecting every consumer. BO creation, migration, and page
fault paths are updated to interact with the new pool abstractions.

> diff --git a/drivers/gpu/drm/xe/xe_assert.h b/drivers/gpu/drm/xe/xe_assert.h
> --- a/drivers/gpu/drm/xe/xe_assert.h
> +++ b/drivers/gpu/drm/xe/xe_assert.h
[ ... ]
> @@ -147,7 +147,8 @@
>  	char __buf[10] __maybe_unused;								\
>  	xe_assert_msg(tile_to_xe(__tile), condition, "tile: %u VRAM %s\n" msg,			\
>  		      __tile->id, ({ string_get_size(						\
> -				     xe_vram_region_actual_physical_size(__tile->mem.vram), 1,	\
> +				     xe_vram_region_actual_physical_size(			\
> +					__tile->mem.vram->region), 1,				\
>  				     STRING_UNITS_2, __buf, sizeof(__buf)); __buf; }), ## arg);	\
>  })

[Severity: High]
Is it possible for __tile->mem.vram to be NULL here on integrated graphics?

On systems without dedicated graphics, xe_tile_alloc_vram() leaves 
tile->mem.vram as NULL. If an assertion triggers, evaluating 
__tile->mem.vram->region while formatting the message might cause a kernel
panic.

> diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c
> --- a/drivers/gpu/drm/xe/xe_debugfs.c
> +++ b/drivers/gpu/drm/xe/xe_debugfs.c
[ ... ]
> @@ -99,7 +99,7 @@ static ssize_t inject_mempage_offline_trigger(struct file *f,
>  {
>  	struct xe_device *xe = file_inode(f)->i_private;
>  	struct xe_tile *tile = xe_device_get_root_tile(xe);
> -	struct xe_vram_region *vr = tile->mem.vram;
> +	struct xe_vram_region *vr = tile->mem.vram->region;
>  	u64 pfn;
>  	int ret;

[Severity: High]
Could this early dereference cause a panic on integrated graphics?

If tile->mem.vram is NULL, evaluating tile->mem.vram->region before the
subsequent !vr check below will fault when accessing this debugfs node.

> diff --git a/drivers/gpu/drm/xe/xe_pagefault.c b/drivers/gpu/drm/xe/xe_pagefault.c
> --- a/drivers/gpu/drm/xe/xe_pagefault.c
> +++ b/drivers/gpu/drm/xe/xe_pagefault.c
[ ... ]
> @@ -201,7 +201,7 @@ static int xe_pagefault_handle_vma(struct xe_gt *gt, struct xe_vma *vma,
>  		xe_validation_ctx_init(&ctx, &vm->xe->val, &exec,
>  				       (struct xe_val_flags) {});
>  		drm_exec_until_all_locked(&exec) {
> -			err = xe_pagefault_begin(&exec, vma, tile->mem.vram,
> +			err = xe_pagefault_begin(&exec, vma, tile->mem.vram->region,
>  						 needs_vram == 1);
>  			drm_exec_retry_on_contention(&exec);
>  			xe_validation_retry_on_oom(&ctx, &err);

[Severity: High]
Does tile->mem.vram need a NULL check before being dereferenced?

During a GPU page fault on an integrated graphics system, tile->mem.vram is
expected to be NULL. Evaluating tile->mem.vram->region directly here to pass
into xe_pagefault_begin() could lead to a NULL pointer dereference.

> diff --git a/drivers/gpu/drm/xe/xe_tile.h b/drivers/gpu/drm/xe/xe_tile.h
> --- a/drivers/gpu/drm/xe/xe_tile.h
> +++ b/drivers/gpu/drm/xe/xe_tile.h
[ ... ]
> @@ -29,11 +30,12 @@ static inline bool xe_tile_is_root(struct xe_tile *tile)
>   * struct xe_tile pointer
>   * @tile: Pointer to the struct xe_tile.
>   *
> - * Return: Pointer to the struct xe_vram_region embedded in *@tile.
> + * Return: Pointer to the struct xe_vram_region backing *@tile's general
> + * purpose VRAM pool.
>   */
>  static inline struct xe_vram_region *xe_tile_to_vr(struct xe_tile *tile)
>  {
> -	return tile->mem.vram;
> +	return tile->mem.vram->region;
>  }

[Severity: High]
Will this unconditionally dereference tile->mem.vram?

Previously this function just returned the pointer, which could safely be
NULL if the device had no VRAM pool. Extracting the region from it might now
panic on integrated graphics if called.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261002104018.3648425-1-piotr.piorkowski@intel.com?part=3

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2026-10-02 10:53 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-02 10:40 [PATCH v1 0/7] Introduce purpose-specific VRAM pools Piórkowski, Piotr
2026-10-02 10:40 ` [PATCH v1 1/7] drm/xe: Define partitioned VRAM manager types Piórkowski, Piotr
2026-10-02 10:40 ` [PATCH v1 2/7] drm/xe: Define VRAM regions and pools Piórkowski, Piotr
2026-10-02 10:40 ` [PATCH v1 3/7] drm/xe/vram: Make VRAM pools the allocation handle Piórkowski, Piotr
2026-10-02 10:53   ` sashiko-bot
2026-10-02 10:40 ` [PATCH v1 4/7] drm/xe/ttm: Back each VRAM pool with its own buddy allocator Piórkowski, Piotr
2026-10-02 10:40 ` [PATCH v1 5/7] drm/xe/vram: Allow splitting a region into pools Piórkowski, Piotr
2026-10-02 10:40 ` [PATCH v1 6/7] drm/xe/kunit: Test partitioned VRAM manager Piórkowski, Piotr
2026-10-02 10:40 ` [PATCH v1 7/7] drm/xe/kunit: Test VRAM pool allocation Piórkowski, Piotr
2026-10-02 10:47 ` ✗ CI.checkpatch: warning for Introduce purpose-specific VRAM pools Patchwork
2026-10-02 10:49 ` ✓ CI.KUnit: success " Patchwork

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox