Re: [PATCH i-g-t v5 01/10] tests/imagination: Add framework for Imagination tests

Kamil Konieczny <[email protected]> Tue, 28 Jul 2026 16:03:28 +0200
Newsgroups org.freedesktop.lists.igt-dev
Message-ID <[email protected]>
Hi Robert,
On 2026-07-28 at 09:18:56 +0200, Robert Mazur wrote:
> From: Matt Coster <[email protected]>
> 
> Add the initial IGT infrastructure for PowerVR (Imagination) GPUs and
> introduce the first GEM buffer object creation tests.
> 
> The tests verify valid BO creation and validate error handling for
> invalid ioctl parameters.
> 
> PowerVR DRM driver background:
> https://lore.kernel.org/dri-devel/[email protected]/
> Driver documentation:
> https://docs.kernel.org/gpu/imagination/index.html
> 
> Signed-off-by: Matt Coster <[email protected]>
> Signed-off-by: Robert Mazur <[email protected]>

LGTM
Reviewed-by: Kamil Konieczny <[email protected]>

Regards,
Kamil

> ---
>  docs/platforms.md             |  1 +
>  lib/drmtest.c                 | 11 +++++++
>  lib/drmtest.h                 |  3 ++
>  lib/igt_pvr.c                 | 75 +++++++++++++++++++++++++++++++++++++++++++
>  lib/igt_pvr.h                 | 16 +++++++++
>  lib/meson.build               |  1 +
>  meson.build                   |  8 +++++
>  tests/imagination/meson.build | 13 ++++++++
>  tests/imagination/pvr_gem.c   | 66 +++++++++++++++++++++++++++++++++++++
>  tests/meson.build             |  2 ++
>  10 files changed, 196 insertions(+)
> 
> diff --git a/docs/platforms.md b/docs/platforms.md
> index 214f53c1d..ea86a89c9 100644
> --- a/docs/platforms.md
> +++ b/docs/platforms.md
> @@ -25,6 +25,7 @@ Support exists for the following platforms:
>  - Panthor
>  - Virtual GPUs (e.g., virtio_gpu in QEMU/KVM/AVD or vmwgfx)
>  - Virtual display (vkms)
> +- Imagination (powervr)
>  
>  #### Intel
>  
> diff --git a/lib/drmtest.c b/lib/drmtest.c
> index b0be06a75..1e789d2af 100644
> --- a/lib/drmtest.c
> +++ b/lib/drmtest.c
> @@ -143,6 +143,11 @@ bool is_msm_device(int fd)
>  	return __is_device(fd, "msm");
>  }
>  
> +bool is_pvr_device(int fd)
> +{
> +	return __is_device(fd, "powervr");
> +}
> +
>  bool is_nouveau_device(int fd)
>  {
>  	/* Currently all nouveau-specific codepaths require libdrm */
> @@ -227,6 +232,7 @@ static const struct module {
>  	{ DRIVER_MSM, "msm" },
>  	{ DRIVER_PANFROST, "panfrost" },
>  	{ DRIVER_PANTHOR, "panthor" },
> +	{ DRIVER_POWERVR, "powervr" },
>  	{ DRIVER_V3D, "v3d" },
>  	{ DRIVER_VC4, "vc4" },
>  	{ DRIVER_VGEM, "vgem" },
> @@ -988,6 +994,11 @@ void igt_require_amdgpu(int fd)
>  	igt_require(is_amdgpu_device(fd));
>  }
>  
> +void igt_require_imagination(int fd)
> +{
> +	igt_require(is_pvr_device(fd));
> +}
> +
>  void igt_require_intel(int fd)
>  {
>  	igt_require(is_intel_device(fd));
> diff --git a/lib/drmtest.h b/lib/drmtest.h
> index 9d488b274..012de9dee 100644
> --- a/lib/drmtest.h
> +++ b/lib/drmtest.h
> @@ -59,6 +59,7 @@ int __get_drm_device_name(int fd, char *name, int name_size);
>  #define DRIVER_VIRTIO	(1 << 10)
>  #define DRIVER_PANTHOR	(1 << 11)
>  #define DRIVER_ASAHI	(1 << 12)
> +#define DRIVER_POWERVR	(1 << 13)
>  
>  /*
>   * Exclude DRIVER_VGEM and DRIVER_VIRTIO from DRIVER_ANY since if you run
> @@ -137,6 +138,7 @@ int drm_prepare_filtered_multigpu(int chipset);
>  int drm_open_filtered_card(int idx);
>  
>  void igt_require_amdgpu(int fd);
> +void igt_require_imagination(int fd);
>  void igt_require_intel(int fd);
>  void igt_require_i915(int fd);
>  void igt_require_nouveau(int fd);
> @@ -150,6 +152,7 @@ bool is_i915_device(int fd);
>  bool is_mtk_device(int fd);
>  bool is_msm_device(int fd);
>  bool is_nouveau_device(int fd);
> +bool is_pvr_device(int fd);
>  bool is_vc4_device(int fd);
>  bool is_xe_device(int fd);
>  bool is_intel_device(int fd);
> diff --git a/lib/igt_pvr.c b/lib/igt_pvr.c
> new file mode 100644
> index 000000000..048ccab31
> --- /dev/null
> +++ b/lib/igt_pvr.c
> @@ -0,0 +1,75 @@
> +// SPDX-License-Identifier: GPL-2.0 or MIT
> +/* Copyright (c) 2026 Imagination Technologies Ltd. All Rights Reserved */
> +
> +#include <limits.h>
> +#include <stddef.h>
> +#include <stdint.h>
> +#include <sys/types.h>
> +
> +#include "igt_pvr.h"
> +
> +#include "drmtest.h"
> +#include "ioctl_wrappers.h"
> +
> +#include "pvr_drm.h"
> +
> +/**
> + * SECTION:igt_pvr
> + * @short_description: PowerVR support library
> + * @title: pvr
> + * @include: igt.h
> + *
> + * This library provides various auxiliary helper functions for writing PowerVR
> + * tests.
> + */
> +
> +/**
> + * igt_pvr_ioctl_create_bo:
> + * @fd: The file descriptor of the DRM device.
> + * @size: On entry, the requested size of the buffer object. On return, the
> + *        actual size of the buffer object.
> + *
> + * Function to create a buffer object.
> + *
> + * Returns: The handle of the created buffer object.
> + */
> +uint32_t igt_pvr_ioctl_create_bo(int fd, size_t *size)
> +{
> +	struct drm_pvr_ioctl_create_bo_args arg = {
> +		.size = *size,
> +	};
> +
> +	do_ioctl(fd, DRM_IOCTL_PVR_CREATE_BO, &arg);
> +
> +	igt_assert(arg.size >= *size && arg.size <= SIZE_MAX);
> +	*size = (size_t)arg.size;
> +
> +	return arg.handle;
> +}
> +
> +
> +/**
> + * igt_pvr_ioctl_get_bo_mmap_offset:
> + * @fd: The file descriptor of the DRM device.
> + * @handle: The handle of the buffer object.
> + *
> + * Function to get the mmap offset of a buffer object.
> + *
> + * Returns: The mmap offset of the buffer object.
> + */
> +off_t igt_pvr_ioctl_get_bo_mmap_offset(int fd, uint32_t handle)
> +{
> +	struct drm_pvr_ioctl_get_bo_mmap_offset_args arg = {
> +		.handle = handle,
> +	};
> +
> +	do_ioctl(fd, DRM_IOCTL_PVR_GET_BO_MMAP_OFFSET, &arg);
> +
> +	/*
> +	 * There is no OFF_MAX equivalent to SIZE_MAX; use the identical (by
> +	 * definition) PTRDIFF_MAX instead.
> +	 */
> +	igt_assert(arg.offset <= PTRDIFF_MAX);
> +
> +	return (off_t)arg.offset;
> +}
> diff --git a/lib/igt_pvr.h b/lib/igt_pvr.h
> new file mode 100644
> index 000000000..e8b2d9026
> --- /dev/null
> +++ b/lib/igt_pvr.h
> @@ -0,0 +1,16 @@
> +/* SPDX-License-Identifier: GPL-2.0 or MIT */
> +/* Copyright (c) 2026 Imagination Technologies Ltd. All Rights Reserved */
> +
> +#ifndef IGT_PVR_H
> +#define IGT_PVR_H
> +
> +#include <stddef.h>
> +#include <stdint.h>
> +#include <sys/types.h>
> +
> +#include "pvr_drm.h"
> +
> +uint32_t igt_pvr_ioctl_create_bo(int fd, size_t *size);
> +off_t igt_pvr_ioctl_get_bo_mmap_offset(int fd, uint32_t handle);
> +
> +#endif /* IGT_PVR_H */
> diff --git a/lib/meson.build b/lib/meson.build
> index c45a96530..05632eede 100644
> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -110,6 +110,7 @@ lib_sources = [
>  	'igt_asahi.c',
>  	'igt_panfrost.c',
>  	'igt_panthor.c',
> +	'igt_pvr.c',
>  	'igt_v3d.c',
>  	'igt_vc4.c',
>  	'igt_vmwgfx.c',
> diff --git a/meson.build b/meson.build
> index e09122a09..b30438e31 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -289,6 +289,7 @@ asahidir = join_paths(libexecdir, 'asahi')
>  msmdir = join_paths(libexecdir, 'msm')
>  panfrostdir = join_paths(libexecdir, 'panfrost')
>  panthordir = join_paths(libexecdir, 'panthor')
> +pvrdir = join_paths(libexecdir, 'imagination')
>  unigrafdir = join_paths(libexecdir, 'unigraf')
>  v3ddir = join_paths(libexecdir, 'v3d')
>  vc4dir = join_paths(libexecdir, 'vc4')
> @@ -355,6 +356,12 @@ if get_option('use_rpath')
>  	endforeach
>  	panthor_rpathdir = join_paths(panthor_rpathdir, libdir)
>  
> +	pvrdir_rpathdir = '$ORIGIN'
> +	foreach p : pvrdir.split('/')
> +		pvrdir_rpathdir = join_paths(pvrdir_rpathdir, '..')
> +	endforeach
> +	pvrdir_rpathdir = join_paths(pvrdir_rpathdir, libdir)
> +
>  	v3d_rpathdir = '$ORIGIN'
>  	foreach p : v3ddir.split('/')
>  		v3d_rpathdir = join_paths(v3d_rpathdir, '..')
> @@ -392,6 +399,7 @@ else
>  	msm_rpathdir = ''
>  	panfrost_rpathdir = ''
>  	panthor_rpathdir = ''
> +	pvrdir_rpathdir = ''
>  	v3d_rpathdir = ''
>  	vc4_rpathdir = ''
>  	vkms_rpathdir = ''
> diff --git a/tests/imagination/meson.build b/tests/imagination/meson.build
> new file mode 100644
> index 000000000..65b90c39f
> --- /dev/null
> +++ b/tests/imagination/meson.build
> @@ -0,0 +1,13 @@
> +pvr_progs = [ 'pvr_gem',
> +	    ]
> +
> +pvr_deps = test_deps
> +
> +foreach prog : pvr_progs
> +	test_executables += executable(prog, prog + '.c',
> +				       dependencies : pvr_deps,
> +				       install_dir : pvrdir,
> +				       install_rpath : pvrdir_rpathdir,
> +				       install : true)
> +	test_list += join_paths('pvr', prog)
> +endforeach
> diff --git a/tests/imagination/pvr_gem.c b/tests/imagination/pvr_gem.c
> new file mode 100644
> index 000000000..273f4d56f
> --- /dev/null
> +++ b/tests/imagination/pvr_gem.c
> @@ -0,0 +1,66 @@
> +// SPDX-License-Identifier: GPL-2.0 or MIT
> +/* Copyright (c) 2026 Imagination Technologies Ltd. All Rights Reserved */
> +
> +#include <linux/errno.h>
> +#include <stddef.h>
> +#include <stdint.h>
> +
> +#include "igt.h"
> +#include "igt_pvr.h"
> +
> +#include "pvr_drm.h"
> +
> +int igt_main()
> +{
> +	int fd;
> +
> +	igt_fixture()
> +	{
> +		fd = drm_open_driver(DRIVER_POWERVR);
> +	}
> +
> +	igt_describe("Test valid buffer object creation");
> +	igt_subtest("create-bo-4096")
> +	{
> +		size_t size = 4096;
> +		uint32_t handle = igt_pvr_ioctl_create_bo(fd, &size);
> +
> +		gem_close(fd, handle);
> +	}
> +
> +	igt_describe("Test buffer object creation with 0 size");
> +	igt_subtest("create-bo-0")
> +	{
> +		struct drm_pvr_ioctl_create_bo_args arg = {
> +			.size = 0,
> +		};
> +
> +		do_ioctl_err(fd, DRM_IOCTL_PVR_CREATE_BO, &arg, EINVAL);
> +	}
> +
> +	igt_describe("Test buffer object creation with bad padding");
> +	igt_subtest("create-bo-bad-padding")
> +	{
> +		struct drm_pvr_ioctl_create_bo_args arg = {
> +			.size = 4096,
> +			._padding_c = 0xbad6bad6,
> +		};
> +
> +		do_ioctl_err(fd, DRM_IOCTL_PVR_CREATE_BO, &arg, EINVAL);
> +	}
> +
> +	igt_describe("Test buffer object creation with unaligned size");
> +	igt_subtest("create-bo-unaligned-fail")
> +	{
> +		struct drm_pvr_ioctl_create_bo_args arg = {
> +			.size = 4000,
> +		};
> +
> +		do_ioctl_err(fd, DRM_IOCTL_PVR_CREATE_BO, &arg, EINVAL);
> +	}
> +
> +	igt_fixture()
> +	{
> +		drm_close_driver(fd);
> +	}
> +}
> diff --git a/tests/meson.build b/tests/meson.build
> index 6d90627b9..63adc61b9 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -561,3 +561,5 @@ if not meson.is_cross_build()
>  endif
>  
>  subdir('intel-ci')
> +
> +subdir('imagination')
> 
> -- 
> 2.43.0
>