[PATCH i-g-t] tests/intel/xe_multi_tile: Multi-Tile support in IGT
nishit.sharma at intel.com
nishit.sharma at intel.com
Fri Feb 28 09:22:51 UTC 2025
From: Nishit Sharma <nishit.sharma at intel.com>
Added functionality to check Multi-Tile available in platform or not. GT%d exposed
related to each Tile%d. Functionality added to check if any tile%d not provided by
driver or missed E.g.tile available in platforms in order tile0, tile1...tileX in
serial order, If tile1 tile2 tile4...tileX populated than will get Warning tile3 not available.
Signed-off-by: Nishit Sharma <nishit.sharma at intel.com>
---
include/drm-uapi/xe_drm.h | 88 ++++++++
lib/igt_sysfs.c | 3 +-
lib/xe/xe_query.h | 38 +++-
tests/intel/xe_multi_tile.c | 423 ++++++++++++++++++++++++++++++++++++
tests/meson.build | 1 +
5 files changed, 551 insertions(+), 2 deletions(-)
create mode 100644 tests/intel/xe_multi_tile.c
diff --git a/include/drm-uapi/xe_drm.h b/include/drm-uapi/xe_drm.h
index 08e263b3b..5e2a54353 100644
--- a/include/drm-uapi/xe_drm.h
+++ b/include/drm-uapi/xe_drm.h
@@ -188,6 +188,94 @@ struct drm_xe_user_extension {
__u32 pad;
};
+enum xe_gt_type {
+ XE_GT_TYPE_UNINITIALIZED,
+ XE_GT_TYPE_MAIN,
+ XE_GT_TYPE_MEDIA,
+};
+
+/**
+ * struct xe_gt - A "Graphics Technology" unit of the GPU
+ *
+ * A GT ("Graphics Technology") is the subset of a GPU primarily responsible
+ * for implementing the graphics, compute, and/or media IP.
+ *
+ */
+struct xe_gt {
+ /** @tile: Backpointer to GT's tile */
+ struct drm_xe_tile *tile;
+
+ /** @info: GT info */
+ struct {
+ /** @info.type: type of GT */
+ enum xe_gt_type type;
+
+ /** @info.id: Unique ID of this GT within the PCI Device */
+
+ __u8 id;
+
+ /**
+ * @gt_count: Number of GT/s available in tile
+ *
+ * */
+ __u8 gt_count;
+ } info;
+};
+
+/**
+ * struct drm_xe_tile - hardware tile structure
+ *
+ * Tile structure contains info like tile ID, vram id, flag to check any tile
+ * missing or out of order, gt count per tile
+ *
+ */
+struct drm_xe_tile {
+ /** @xe: Backpointer to tile's PCI device */
+ struct xe_device *xe;
+
+ /** @id: ID of the tile */
+ __u8 id;
+
+ /**
+ * @vram_id: ID of associated TTM VRAM region
+ *
+ * For multi-tile platforms not using unified vram, this is same
+ * as @id. Otherwise this is always 0 to denote a single unified
+ * vram region is in use.
+ */
+ __u8 vram_id;
+
+ /**
+ * @mis_tile: Flasg to check if tile ID missing or out of order
+ *
+ */
+ __u8 mis_tile:1;
+
+ /**
+ * @gt_count: Number of GT/s available in tile
+ *
+ * */
+ __u8 gt_count;
+
+ /**
+ * @primary_gt: Primary GT
+ */
+ struct xe_gt *primary_gt;
+
+ /**
+ * @media_gt: Media GT
+ *
+ * Only present on devices with media version >= 13.
+ */
+ struct xe_gt *media_gt;
+
+ /**
+ * @gt_list: List of GT descriptors from driver
+ *
+ */
+ struct drm_xe_query_gt_list *gt_list;
+};
+
/**
* struct drm_xe_ext_set_property - Generic set property extension
*
diff --git a/lib/igt_sysfs.c b/lib/igt_sysfs.c
index 2e4c2ee63..6fb70ccc9 100644
--- a/lib/igt_sysfs.c
+++ b/lib/igt_sysfs.c
@@ -235,7 +235,8 @@ char *xe_sysfs_gt_path(int xe_device, int gt, char *path, int pathlen)
if (IS_PONTEVECCHIO(intel_get_drm_devid(xe_device)))
snprintf(path, pathlen, "/sys/dev/char/%d:%d/device/tile%d/gt%d",
- major(st.st_rdev), minor(st.st_rdev), gt, gt);
+ major(st.st_rdev), minor(st.st_rdev),
+ xe_gt_get_tile_id(xe_device, gt), gt);
else
snprintf(path, pathlen, "/sys/dev/char/%d:%d/device/tile0/gt%d",
major(st.st_rdev), minor(st.st_rdev), gt);
diff --git a/lib/xe/xe_query.h b/lib/xe/xe_query.h
index a84a6bfa5..34fea94d1 100644
--- a/lib/xe/xe_query.h
+++ b/lib/xe/xe_query.h
@@ -21,6 +21,7 @@
#define XE_DEFAULT_ALIGNMENT_64K SZ_64K
struct xe_device {
+#define XE_MAX_TILES_PER_DEVICE 4
/** @fd: xe fd */
int fd;
@@ -36,6 +37,27 @@ struct xe_device {
/** @gt_list: gt info */
struct drm_xe_query_gt_list *gt_list;
+ /** @tiles: device tiles */
+ struct drm_xe_tile tiles[XE_MAX_TILES_PER_DEVICE];
+
+ /** @info: device info */
+ struct drm_xe_tile_info {
+ /** @info.tile_count: Number of tiles */
+ uint8_t tile_count;
+ /** @info.gt_count: Total number of GTs for entire device */
+ uint8_t gt_count;
+ /** @tile_unvailable: Flag to check if tile is missing or out of order */
+ uint8_t tile_unavailable:1;
+ /** @mis_tile: Tile ID missing or out of order */
+ uint8_t mis_tile_id[XE_MAX_TILES_PER_DEVICE];
+ /** @mis_tile_count: missing TIle ID **/
+ uint8_t mis_tile_count;
+ /** @info.graphics_verx100: graphics IP version */
+ __u32 graphics_verx100;
+ /** @info.media_verx100: media IP version */
+ __u32 media_verx100;
+ } info;
+
/** @gt_list: bitmask of all memory regions */
uint64_t memory_regions;
@@ -75,13 +97,22 @@ struct xe_device {
++__class)
#define xe_for_each_gt(__fd, __gt) \
for (__gt = 0; __gt < xe_number_gt(__fd); ++__gt)
-
+#define xe_for_each_tile(tile__, xe__, id__) \
+ for ((id__) = 0; (id__) < (xe__)->info.tile_count; (id__)++) \
+ for_each_if((tile__) = &(xe__)->tiles[(id__)])
+#define xe_for_each_remote_tile(tile__, xe__, id__) \
+ for ((id__) = 0; (id__) < (xe__)->info.tile_count; (id__)++) \
+ for_each_if((tile__) = &(xe__)->tiles[(id__)])
+#define xe_for_each_device_gt(gt__, xe__, id__) \
+ for ((id__) = 0; (id__) < (xe__)->info.gt_count; (id__)++) \
+ for_each_if((gt__) = xe_device_get_gt((xe__), (id__)))
#define xe_for_each_mem_region(__fd, __memreg, __r) \
for (uint64_t igt_unique(__i) = 0; igt_unique(__i) < igt_fls(__memreg); igt_unique(__i)++) \
for_if(__r = (__memreg & (1ull << igt_unique(__i))))
#define XE_IS_CLASS_SYSMEM(__region) ((__region)->mem_class == DRM_XE_MEM_REGION_CLASS_SYSMEM)
#define XE_IS_CLASS_VRAM(__region) ((__region)->mem_class == DRM_XE_MEM_REGION_CLASS_VRAM)
+#define MEDIA_VER(xe) ((xe)->info.media_verx100 / 100)
/*
* Max possible engine instance in drm_xe_engine_class_instance::engine_instance. Only
@@ -89,6 +120,11 @@ struct xe_device {
*/
#define XE_MAX_ENGINE_INSTANCE 9
+/*
+ * Max possible GT per Tile
+ */
+#define XE_MAX_GT_PER_TILE 2
+
unsigned int xe_number_gt(int fd);
uint64_t all_memory_regions(int fd);
uint64_t system_memory(int fd);
diff --git a/tests/intel/xe_multi_tile.c b/tests/intel/xe_multi_tile.c
new file mode 100644
index 000000000..c5b2e0472
--- /dev/null
+++ b/tests/intel/xe_multi_tile.c
@@ -0,0 +1,423 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2025 Intel Corporation
+ *
+ * Authors:
+ * Nishit Sharma <nishit.sharma at intel.com>
+ */
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "igt.h"
+#include "igt_sysfs.h"
+
+#include "xe_drm.h"
+#include "xe/xe_ioctl.h"
+#include "xe/xe_query.h"
+
+/**
+ * TEST: Test to verify if multi-tile support available in platform
+ * Category: Core
+ * Mega feature: General Core features
+ * Sub-category: Tile/GT operations
+ * Functionality: multi-tile
+ * Test category: functionality test
+ */
+
+/**
+ * SUBTEST: multi-tile-info
+ * Description: Test gathers Tile_ID/s and GT_ID/s, update internal struct
+ */
+
+struct xe_gt *xe_gt_alloc(struct drm_xe_tile *tile);
+int xe_tile_init(struct drm_xe_tile *tile, struct xe_device *xe, uint8_t id);
+struct drm_xe_tile *xe_device_get_root_tile(struct xe_device *xe);
+struct xe_gt *xe_tile_get_gt(struct drm_xe_tile *tile, u8 gt_id);
+struct xe_gt *xe_device_get_gt(struct xe_device *xe_dev, uint8_t gt_id);
+
+/*
+ * xe_gt_list: Get the list of gt%d, tile%d and count from driver
+ * @fd: GPU device descriptor
+ *
+ * Function gets the count of gt available in device
+ * including other information such as gt count, graphics ip version
+ *
+ * Return: Returns drm_xe_query_gt_list pointer
+ */
+struct drm_xe_query_gt_list *xe_gt_list(int fd)
+{
+ struct drm_xe_query_gt_list *gt_list;
+ struct drm_xe_device_query query = {
+ .extensions = 0,
+ .query = DRM_XE_DEVICE_QUERY_GT_LIST,
+ .size = 0,
+ .data = 0,
+ };
+
+ igt_assert_eq(igt_ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query), 0);
+ igt_assert_neq(query.size, 0);
+
+ gt_list = malloc(query.size);
+ igt_assert(gt_list);
+
+ query.data = to_user_pointer(gt_list);
+ igt_assert_eq(igt_ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query), 0);
+
+ return gt_list;
+}
+/*
+ * xe_gt_alloc: Memory allocation for gt struct and initializing
+ * struct drm_xe_tile as per gt
+ * @tile *: Tile structure
+ *
+ * This allocates memory per GT available on tile and assigns corresponding tile address
+ * to corresponding gt
+ *
+ * Return: Returns gt structure pointer
+ */
+struct xe_gt *xe_gt_alloc(struct drm_xe_tile *tile)
+{
+ struct xe_gt *gt;
+
+ gt = malloc(sizeof(*gt));
+ igt_assert(gt);
+
+ gt->tile = tile;
+ return gt;
+}
+/**
+ * xe_tile_init - Initialize the tile structure and allocates memmory for primary GT
+ * @tile: Tile to initialize
+ * @xe: Parent Xe device
+ * @id: Tile ID
+ *
+ * Initializes per-tile resources.
+ *
+ * Returns: 0 on success, assert if no memory allocation.
+ */
+int xe_tile_init(struct drm_xe_tile *tile, struct xe_device *xe, uint8_t id)
+{
+ tile->xe = xe;
+ tile->id = id;
+
+ tile->primary_gt = xe_gt_alloc(tile);
+ igt_assert(tile->primary_gt);
+
+ return 0;
+}
+/**
+ * xe_device_get_root_tile: Returns address of root tile
+ * @xe: GPU Device structure which holds information about tile
+ * available in system
+ *
+ * Return: root tile address
+ */
+struct drm_xe_tile *xe_device_get_root_tile(struct xe_device *xe)
+{
+ return &xe->tiles[0];
+}
+/**
+ * xe_tile_get_gt: Return address gt struct
+ * @tile *: Tile associated with gt
+ * @gt_id: gt%d
+ *
+ * Returns: Based on gt_id passed xe_gt address returned which
+ * can be media_gt or primary gt
+ */
+struct xe_gt *xe_tile_get_gt(struct drm_xe_tile *tile, u8 gt_id)
+{
+ igt_assert_f(gt_id <= XE_MAX_GT_PER_TILE, "gt_id greater than defined XE_MAX_GT_PER_TILE");
+
+ return gt_id ? tile->media_gt : tile->primary_gt;
+}
+/**
+ * @xe_dev: GPU Device structure which holds information about tile
+ * @gt_id: gt%d
+ *
+ * Returns: gt struct address based on media version available in platform
+ */
+struct xe_gt *xe_device_get_gt(struct xe_device *xe_dev, uint8_t gt_id)
+{
+ struct drm_xe_tile *root_tile = xe_device_get_root_tile(xe_dev);
+ struct xe_gt *gt;
+
+ if (MEDIA_VER(xe_dev) >= 13)
+ gt = xe_tile_get_gt(root_tile, gt_id);
+ else
+ gt = xe_dev->tiles[gt_id].primary_gt;
+
+ igt_assert(gt);
+
+ return gt;
+}
+/**
+ * @xe_dev: GPU Device structure which holds information about tile
+ * @gt_id: gt%d
+ *
+ * Check gt%d passed available or not on tile%d
+ *
+ * Return: None
+ */
+static void igt_check_gt_per_tile(struct xe_device *xe_dev, uint8_t gt_id)
+{
+ uint8_t id;
+ struct drm_xe_tile *tile;
+ struct xe_gt *gt;
+
+ xe_for_each_device_gt(gt, xe_dev, id) {
+ tile = gt->tile;
+ if(gt_id == gt->info.id)
+ {
+ igt_info("GT ID :%d available in Tile :tile%d\n",
+ gt_id, tile->id);
+ }
+ }
+}
+/**
+ * @xe_dev: GPU Device structure which holds information about tile
+ * @gt_id: gt%d
+ *
+ * To query gt%d available in tile%d by iterating over list of tiles available
+ *
+ * Returns: None
+ */
+static void igt_query_gt_per_tile(struct xe_device *xe_dev, uint8_t gt_id)
+{
+ struct drm_xe_tile *tile;
+ struct xe_gt *gt;
+
+ xe_for_each_tile(tile, xe_dev, gt_id) {
+ gt = tile->primary_gt;
+
+ if(MEDIA_VER(xe_dev) >= 12)
+ gt = tile->media_gt;
+
+ igt_info("Inside GT Id :%d GT type :%d GT count :%d for Tile ID :%d GT count in Tile :%d\n",
+ gt->info.id, gt->info.type, gt->info.gt_count, tile->id, tile->gt_count);
+ }
+}
+/**
+ * igt_show_device_gt: To show gt availale on GPU device
+ * @xe_dev: GPU Device structure which holds information about tile
+ * @fd: GPU device descriptor
+ *
+ * Show GT%d available on device
+ *
+ * Return: None
+ */
+static void igt_show_device_gt(struct xe_device *xe_dev, int fd)
+{
+ struct drm_xe_tile *tile;
+ struct xe_gt *gt;
+
+ uint8_t id;
+
+ xe_for_each_device_gt(gt, xe_dev, id) {
+ tile = gt->tile;
+ igt_info("GT Id :%d GT type :%d Tile ID :%d\n",
+ gt->info.id, gt->info.type, tile->id);
+ }
+}
+/**
+ * igt_gt_init_per_tile: Initialize xe_gt structure per gt%d and per tile%d
+ * @xe_dev: GPU Device structure which holds information about tile
+ * @fd: GPU device descriptor
+ *
+ * Returns: 0 in case of success or assert
+ */
+static uint8_t igt_gt_init_per_tile(struct xe_device *xe_dev, int fd)
+{
+ uint8_t gt_id = 0;
+ struct drm_xe_tile *tile;
+ struct xe_gt *gt;
+ int ip_version, media_version;
+ char name[100];
+ FILE *file;
+
+ igt_info("per Tile initialization\n");
+
+ xe_for_each_tile(tile, xe_dev, gt_id) {
+ int err;
+ err = xe_tile_init(tile, xe_dev, gt_id);
+ igt_assert_eq(err, 0);
+ }
+
+ xe_for_each_tile(tile, xe_dev, gt_id) {
+ gt = tile->primary_gt;
+ //new_gt = gt;
+ gt->info.id = xe_dev->info.gt_count++;
+ gt->info.type= XE_GT_TYPE_MAIN;
+ gt->info.gt_count++;
+ tile->gt_count++;
+
+ file = fopen("/sys/kernel/debug/dri/0/info", "r");
+ igt_assert(file);
+
+ while (fscanf(file, "%s %d", name, &ip_version) == 1) {
+ ip_version = -1;
+ }
+ while (fscanf(file, "%s %d", name, &media_version) == 1) {
+ media_version = -1;
+ }
+
+ fclose(file);
+
+ xe_dev->info.graphics_verx100 = ip_version;
+ xe_dev->info.media_verx100 = media_version;
+
+ if (MEDIA_VER(xe_dev) < 13)
+ continue;
+
+ /*
+ * Allocate and setup media GT for platforms with standalone
+ * media.
+ *
+ */
+ tile->media_gt = xe_gt_alloc(tile);
+ igt_assert(tile->media_gt);
+ gt->info.type = XE_GT_TYPE_MEDIA;
+ gt->info.id = xe_dev->info.gt_count++;
+ gt->info.gt_count++;
+ tile->gt_count++;
+ }
+
+ return 0;
+}
+/**
+ * igt_check_missing_tile_sysfs: Checking if tile missing or out of order in system
+ * @xe_device: GPU Device structure which holds information about tile
+ * @fd: Device descriptor
+ *
+ * This opens the sysfs tile directory corresponding to device and tile for use
+ * The mis_tile_id[] contains tile%d which is checked with sysfs whether entry is present
+ * or not. E.g. After tile2 user get tile4, tile3 is missing which will be checked in sysfs path
+ *
+ * Returns: None
+ */
+static void igt_check_missing_tile_sysfs(struct xe_device *xe_dev,
+ int fd)
+{
+ char path[96];
+
+ igt_info("Checking missing tiles with sysfs\n");
+
+ for(int mis = 0; mis < xe_dev->info.mis_tile_count; mis++) {
+ xe_sysfs_tile_path(fd, xe_dev->info.mis_tile_id[mis], path, sizeof(path));
+ }
+
+ igt_assert_f(xe_dev->info.mis_tile_count < 0, "No Tile entry in sysfs found.");
+}
+/**
+ * igt_check_if_missingtile: Checking if tile missing by iterating over
+ * filled mis tile array
+ * @xe_dev: GPU Device structure which holds information about tile
+ * fd: GPU device descriptor
+ *
+ * Returns: None
+ */
+static void igt_check_if_missingtile(struct xe_device *xe_dev, int fd)
+{
+ igt_info("Checking missing/out of order tiles\n");
+
+ for(int i= 0; i < xe_dev->info.mis_tile_count; i++){
+ igt_warn("Tile :%d out of order/missing\n",
+ xe_dev->info.mis_tile_id[i]);
+ }
+}
+/**
+ * igt_get_tile_count: To get count of tile/s available in system,
+ * Getting missing tile and tle count if any
+ * @xe_dev: GPU Device structure which holds information about tile
+ * @fd: Device descriptor
+ * gt_list: list of gt%d and relavant information returned from Driver via IOCTL
+ *
+ * Return: Tile count
+ */
+static uint8_t igt_get_tile_count(struct xe_device *xe_dev, int fd,
+ struct drm_xe_query_gt_list *gt_list)
+{
+ int prev_tile = -1, tile_id;
+ uint8_t tile_mis_count = -1;
+
+ for(int index = 0; index < gt_list->num_gt; index++) {
+ tile_id = gt_list->gt_list[index].tile_id;
+ if(prev_tile != tile_id)
+ {
+ if(++tile_mis_count != tile_id) {
+ xe_dev->info.tile_unavailable = true;
+ xe_dev->info.mis_tile_id[xe_dev->info.mis_tile_count++] = tile_mis_count;
+ }
+ prev_tile = tile_id;
+ xe_dev->info.tile_count++;
+ }
+ xe_dev->info.tile_unavailable = false;
+ }
+
+ return xe_dev->info.tile_count;
+}
+
+igt_main
+{
+ int fd;
+ struct drm_xe_query_gt_list *gt_list;
+ struct xe_device *xe_dev;
+ struct drm_xe_tile *tile;
+ uint8_t gt_count;
+ uint8_t gt_arr[] = {0,1,2,3,4,5,6,7,8};
+
+ igt_fixture {
+ fd = drm_open_driver(DRIVER_XE);
+ xe_dev = xe_device_get(fd);
+ }
+
+ tile = malloc(sizeof(*tile));
+ igt_assert(tile);
+
+ igt_subtest("multi-tile-info") {
+ /** get gt information from driver using ioctl **/
+ gt_list = xe_gt_list(fd);
+ /** store pointer returned from driver which have gt information **/
+ tile->gt_list = gt_list;
+
+ /** Get tile count, initialize flag to check if any tile missing
+ * Fill internal struct
+ */
+ gt_count = igt_get_tile_count(xe_dev, fd, gt_list);
+ igt_assert_neq(gt_count, 0);
+ igt_info("Tiles :%d available in platform\n", gt_count);
+
+ /** check if multi-tile supported in platform */
+ igt_assert_f(xe_dev->info.tile_count > 1,
+ "Multi-Tile not supported in platform :%d\n",
+ xe_dev->info.tile_count);
+
+ /************* Per Tile Initilization ***********/
+ igt_assert_eq(igt_gt_init_per_tile(xe_dev, fd), 0);
+
+ /******** Condition to check if any tile missing/out of order *****/
+ if (xe_dev->info.tile_unavailable)
+ igt_check_if_missingtile(xe_dev, fd);
+
+ /******* Checking missing/out of order tile comparing with sysfs ***/
+ if (xe_dev->info.tile_unavailable)
+ igt_check_missing_tile_sysfs(xe_dev, fd);
+
+ /****** Display GT information on GPU Device *******/
+ igt_show_device_gt(xe_dev, fd);
+
+ /****** Query GT per Tile *****/
+ igt_query_gt_per_tile(xe_dev, fd);
+
+ /***** Checking GT exist, if exist on which tile or doesn't exist ******/
+ for(int gt_id = 0; gt_id < sizeof(gt_arr); gt_id++)
+ igt_check_gt_per_tile(xe_dev, gt_id);
+ }
+
+ igt_fixture {
+ drm_close_driver(fd);
+ }
+}
diff --git a/tests/meson.build b/tests/meson.build
index a0f984b34..9def89f38 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -294,6 +294,7 @@ intel_xe_progs = [
'xe_exec_reset',
'xe_exec_sip',
'xe_exec_store',
+ 'xe_multi_tile',
'xe_exec_threads',
'xe_exercise_blt',
'xe_fault_injection',
--
2.43.0
More information about the igt-dev
mailing list