]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/xe: Add initial support for separate kernel VRAM region on the tile
authorPiotr Piórkowski <piotr.piorkowski@intel.com>
Fri, 3 Oct 2025 16:26:15 +0000 (18:26 +0200)
committerMichal Wajdeczko <michal.wajdeczko@intel.com>
Mon, 6 Oct 2025 06:33:46 +0000 (08:33 +0200)
So far, kernel and userspace allocations have shared the same VRAM region.
However, in some scenarios, it may be necessary to reserve a separate
VRAM area exclusively for kernel allocations.
Let's add preliminary support for such a configuration.

v2:
- replaced for_each_bo_flag_vram with the improved
  for_each_set_bo_vram_flag helper (Matthew)
- moved the VRAM flag iteration macro definition into xe_bo.c (Matthew)
- drop unused bo_flgas from bo_vram_flags_to_vram_placement (Matthew)
- use hweight32 helper in __xe_bo_fixed_placement for readability
  (Matthew)
v3: remove unnecessary VRAM fixup id

Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Link: https://lore.kernel.org/r/20251003162619.1984236-2-piotr.piorkowski@intel.com
drivers/gpu/drm/xe/xe_bo.c
drivers/gpu/drm/xe/xe_bo.h
drivers/gpu/drm/xe/xe_device_types.h
drivers/gpu/drm/xe/xe_tile.c
drivers/gpu/drm/xe/xe_vram.c

index 4410e28dee54bec46da90b4ff4b89d826133860b..ce20f58ee80e599d5dad8cf029328f6d80bf32c9 100644 (file)
@@ -34,6 +34,7 @@
 #include "xe_res_cursor.h"
 #include "xe_shrinker.h"
 #include "xe_sriov_vf_ccs.h"
+#include "xe_tile.h"
 #include "xe_trace_bo.h"
 #include "xe_ttm_stolen_mgr.h"
 #include "xe_vm.h"
@@ -81,6 +82,10 @@ static struct ttm_placement tt_placement = {
        .placement = tt_placement_flags,
 };
 
+#define for_each_set_bo_vram_flag(bit__, bo_flags__) \
+       for (unsigned int __bit_tmp = BIT(0); __bit_tmp <= XE_BO_FLAG_VRAM_MASK; __bit_tmp <<= 1) \
+               for_each_if(((bit__) = __bit_tmp) & (bo_flags__) & XE_BO_FLAG_VRAM_MASK)
+
 bool mem_type_is_vram(u32 mem_type)
 {
        return mem_type >= XE_PL_VRAM0 && mem_type != XE_PL_STOLEN;
@@ -213,6 +218,27 @@ static bool force_contiguous(u32 bo_flags)
               bo_flags & XE_BO_FLAG_PINNED;
 }
 
+static u8 vram_bo_flag_to_tile_id(struct xe_device *xe, u32 vram_bo_flag)
+{
+       xe_assert(xe, vram_bo_flag & XE_BO_FLAG_VRAM_MASK);
+       xe_assert(xe, (vram_bo_flag & (vram_bo_flag - 1)) == 0);
+
+       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 vram_flag,
+                                          enum ttm_bo_type type)
+{
+       u8 tile_id = vram_bo_flag_to_tile_id(xe, vram_flag);
+
+       xe_assert(xe, tile_id < xe->info.tile_count);
+
+       if (type == ttm_bo_type_kernel)
+               return xe->tiles[tile_id].mem.kernel_vram->placement;
+       else
+               return xe->tiles[tile_id].mem.vram->placement;
+}
+
 static void add_vram(struct xe_device *xe, struct xe_bo *bo,
                     struct ttm_place *places, u32 bo_flags, u32 mem_type, u32 *c)
 {
@@ -245,12 +271,15 @@ static void add_vram(struct xe_device *xe, struct xe_bo *bo,
 }
 
 static void try_add_vram(struct xe_device *xe, struct xe_bo *bo,
-                        u32 bo_flags, u32 *c)
+                        u32 bo_flags, enum ttm_bo_type type, u32 *c)
 {
-       if (bo_flags & XE_BO_FLAG_VRAM0)
-               add_vram(xe, bo, bo->placements, bo_flags, XE_PL_VRAM0, c);
-       if (bo_flags & XE_BO_FLAG_VRAM1)
-               add_vram(xe, bo, bo->placements, bo_flags, XE_PL_VRAM1, c);
+       u32 vram_flag;
+
+       for_each_set_bo_vram_flag(vram_flag, bo_flags) {
+               u32 pl = bo_vram_flags_to_vram_placement(xe, vram_flag, type);
+
+               add_vram(xe, bo, bo->placements, bo_flags, pl, c);
+       }
 }
 
 static void try_add_stolen(struct xe_device *xe, struct xe_bo *bo,
@@ -269,11 +298,11 @@ static void try_add_stolen(struct xe_device *xe, struct xe_bo *bo,
 }
 
 static int __xe_bo_placement_for_flags(struct xe_device *xe, struct xe_bo *bo,
-                                      u32 bo_flags)
+                                      u32 bo_flags, enum ttm_bo_type type)
 {
        u32 c = 0;
 
-       try_add_vram(xe, bo, bo_flags, &c);
+       try_add_vram(xe, bo, bo_flags, type, &c);
        try_add_system(xe, bo, bo_flags, &c);
        try_add_stolen(xe, bo, bo_flags, &c);
 
@@ -289,10 +318,10 @@ static int __xe_bo_placement_for_flags(struct xe_device *xe, struct xe_bo *bo,
 }
 
 int xe_bo_placement_for_flags(struct xe_device *xe, struct xe_bo *bo,
-                             u32 bo_flags)
+                             u32 bo_flags, enum ttm_bo_type type)
 {
        xe_bo_assert_held(bo);
-       return __xe_bo_placement_for_flags(xe, bo, bo_flags);
+       return __xe_bo_placement_for_flags(xe, bo, bo_flags, type);
 }
 
 static void xe_evict_flags(struct ttm_buffer_object *tbo,
@@ -2164,7 +2193,7 @@ struct xe_bo *xe_bo_init_locked(struct xe_device *xe, struct xe_bo *bo,
 
        xe_validation_assert_exec(xe, exec, &bo->ttm.base);
        if (!(flags & XE_BO_FLAG_FIXED_PLACEMENT)) {
-               err = __xe_bo_placement_for_flags(xe, bo, bo->flags);
+               err = __xe_bo_placement_for_flags(xe, bo, bo->flags, type);
                if (WARN_ON(err)) {
                        xe_ttm_bo_destroy(&bo->ttm);
                        return ERR_PTR(err);
@@ -2222,34 +2251,31 @@ struct xe_bo *xe_bo_init_locked(struct xe_device *xe, struct xe_bo *bo,
 }
 
 static int __xe_bo_fixed_placement(struct xe_device *xe,
-                                  struct xe_bo *bo,
+                                  struct xe_bo *bo, enum ttm_bo_type type,
                                   u32 flags,
                                   u64 start, u64 end, u64 size)
 {
        struct ttm_place *place = bo->placements;
+       u32 vram_flag, vram_stolen_flags;
 
        if (flags & (XE_BO_FLAG_USER | XE_BO_FLAG_SYSTEM))
                return -EINVAL;
 
+       vram_flag = flags & XE_BO_FLAG_VRAM_MASK;
+       vram_stolen_flags = (flags & (XE_BO_FLAG_STOLEN)) | vram_flag;
+
+       /* check if more than one VRAM/STOLEN flag is set */
+       if (hweight32(vram_stolen_flags) > 1)
+               return -EINVAL;
+
        place->flags = TTM_PL_FLAG_CONTIGUOUS;
        place->fpfn = start >> PAGE_SHIFT;
        place->lpfn = end >> PAGE_SHIFT;
 
-       switch (flags & (XE_BO_FLAG_STOLEN | XE_BO_FLAG_VRAM_MASK)) {
-       case XE_BO_FLAG_VRAM0:
-               place->mem_type = XE_PL_VRAM0;
-               break;
-       case XE_BO_FLAG_VRAM1:
-               place->mem_type = XE_PL_VRAM1;
-               break;
-       case XE_BO_FLAG_STOLEN:
+       if (flags & XE_BO_FLAG_STOLEN)
                place->mem_type = XE_PL_STOLEN;
-               break;
-
-       default:
-               /* 0 or multiple of the above set */
-               return -EINVAL;
-       }
+       else
+               place->mem_type = bo_vram_flags_to_vram_placement(xe, vram_flag, type);
 
        bo->placement = (struct ttm_placement) {
                .num_placement = 1,
@@ -2278,7 +2304,7 @@ __xe_bo_create_locked(struct xe_device *xe,
                        return bo;
 
                flags |= XE_BO_FLAG_FIXED_PLACEMENT;
-               err = __xe_bo_fixed_placement(xe, bo, flags, start, end, size);
+               err = __xe_bo_fixed_placement(xe, bo, type, flags, start, end, size);
                if (err) {
                        xe_bo_free(bo);
                        return ERR_PTR(err);
index a77af42b5f9ea10d73fa2d281e2eae004dd55e54..9a8401300b15ccd9a587cb0cdb82144b93c8d5e2 100644 (file)
@@ -122,7 +122,7 @@ struct xe_bo *xe_managed_bo_create_from_data(struct xe_device *xe, struct xe_til
 int xe_managed_bo_reinit_in_vram(struct xe_device *xe, struct xe_tile *tile, struct xe_bo **src);
 
 int xe_bo_placement_for_flags(struct xe_device *xe, struct xe_bo *bo,
-                             u32 bo_flags);
+                             u32 bo_flags, enum ttm_bo_type type);
 
 static inline struct xe_bo *ttm_to_xe_bo(const struct ttm_buffer_object *bo)
 {
index 74d7af830b85d8a7ab614d6e876567e4dc11c693..989244418950179e2d3445f6ceb3e0000b67e4a7 100644 (file)
@@ -158,7 +158,15 @@ struct xe_tile {
        /** @mem: memory management info for tile */
        struct {
                /**
-                * @mem.vram: VRAM info for tile.
+                * @mem.kernel_vram: kernel-dedicated VRAM info 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;
+
+               /**
+                * @mem.vram: general purpose VRAM info for tile.
                 *
                 * Although VRAM is associated with a specific tile, it can
                 * still be accessed by all tiles' GTs.
index d49ba34019635eb1dccd3b8a00c123d5a1c135aa..6edb5062c1da54b80fc8355a67f29096f34eea53 100644 (file)
@@ -124,6 +124,14 @@ int xe_tile_alloc_vram(struct xe_tile *tile)
                return -ENOMEM;
        tile->mem.vram = 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;
 }
 
index b44ebf50fedbbbe2f1ba2df1001931ef9b1e2e3a..7adfccf68e4c8a5fed8a3bd6b8ab0952def63131 100644 (file)
@@ -13,6 +13,7 @@
 #include "regs/xe_gt_regs.h"
 #include "regs/xe_regs.h"
 #include "xe_assert.h"
+#include "xe_bo.h"
 #include "xe_device.h"
 #include "xe_force_wake.h"
 #include "xe_gt_mcr.h"
@@ -283,8 +284,11 @@ static void vram_fini(void *arg)
 
        xe->mem.vram->mapping = NULL;
 
-       for_each_tile(tile, xe, id)
+       for_each_tile(tile, xe, id) {
                tile->mem.vram->mapping = NULL;
+               if (tile->mem.kernel_vram)
+                       tile->mem.kernel_vram->mapping = NULL;
+       }
 }
 
 struct xe_vram_region *xe_vram_region_alloc(struct xe_device *xe, u8 id, u32 placement)