On Tue,  4 Nov 2025 17:28:42 -0300
Daniel Almeida <[email protected]> wrote:

> Add the necessary code needed to compile panthor tests as well as the
> basic infrastructure that will be used by the Panthor tests themselves.
> 
> To make sure everything is in order, add a basic test in
> panthor_query.c.
> 
> Acked-by: Kamil Konieczny <[email protected]>
> Signed-off-by: Daniel Almeida <[email protected]>

Reviewed-by: Boris Brezillon <[email protected]>

> ---
>  lib/igt_panthor.c             |  41 ++++++++
>  lib/igt_panthor.h             | 193 ++++++++++++++++++++++++++++++++++
>  lib/meson.build               |   1 +
>  meson.build                   |   8 ++
>  tests/meson.build             |   2 +
>  tests/panthor/meson.build     |  12 +++
>  tests/panthor/panthor_query.c |  29 +++++
>  7 files changed, 286 insertions(+)
>  create mode 100644 lib/igt_panthor.c
>  create mode 100644 lib/igt_panthor.h
>  create mode 100644 tests/panthor/meson.build
>  create mode 100644 tests/panthor/panthor_query.c
> 
> diff --git a/lib/igt_panthor.c b/lib/igt_panthor.c
> new file mode 100644
> index 000000000..0b690f796
> --- /dev/null
> +++ b/lib/igt_panthor.c
> @@ -0,0 +1,41 @@
> +// SPDX-License-Identifier: MIT
> +// SPDX-FileCopyrightText: Copyright (C) 2025 Collabora Ltd.
> +
> +#include "drmtest.h"
> +#include "igt_panthor.h"
> +#include "ioctl_wrappers.h"
> +#include "panthor_drm.h"
> +
> +/**
> + * SECTION:igt_panthor
> + * @short_description: Panthor support library
> + * @title: Panthor
> + * @include: igt.h
> + *
> + * This library provides various auxiliary helper functions for writing 
> Panthor
> + * tests.
> + */
> +
> +/**
> + * igt_panthor_query:
> + * @fd: device file descriptor
> + * @type: query type (e.g., DRM_PANTHOR_DEV_QUERY_GPU_INFO)
> + * @data: pointer to a struct to store the query result
> + * @size: size of the result struct
> + * @err: expected error code, or 0 for success
> + *
> + * Query GPU information.
> + */
> +void igt_panthor_query(int fd, int32_t type, void *data, size_t size, int 
> err)
> +{
> +     struct drm_panthor_dev_query query = {
> +             .type = type,
> +             .pointer = (uintptr_t)data,
> +             .size = size,
> +     };
> +
> +     if (err)
> +             do_ioctl_err(fd, DRM_IOCTL_PANTHOR_DEV_QUERY, &query, err);
> +     else
> +             do_ioctl(fd, DRM_IOCTL_PANTHOR_DEV_QUERY, &query);
> +}
> diff --git a/lib/igt_panthor.h b/lib/igt_panthor.h
> new file mode 100644
> index 000000000..6f94b8f79
> --- /dev/null
> +++ b/lib/igt_panthor.h
> @@ -0,0 +1,193 @@
> +/* SPDX-License-Identifier: MIT */
> +/* SPDX-FileCopyrightText: Copyright (C) 2025 Collabora Ltd. */
> +
> +#ifndef IGT_PANTHOR_H
> +#define IGT_PANTHOR_H
> +
> +#include <stddef.h>
> +#include <stdint.h>
> +#include <stdbool.h>
> +
> +void igt_panthor_query(int fd, int32_t type, void *data, size_t size, int 
> err);
> +
> +enum cs_opcode {
> +     CS_OPCODE_NOP = 0,
> +     CS_OPCODE_MOVE48 = 1,
> +     CS_OPCODE_MOVE32 = 2,
> +     CS_OPCODE_WAIT = 3,
> +     CS_OPCODE_STM = 21,
> +     CS_OPCODE_FLUSH_CACHE = 36,
> +};
> +
> +enum cs_flush_mode {
> +     CS_FLUSH_MODE_NONE = 0,
> +     CS_FLUSH_MODE_CLEAN = 1,
> +     CS_FLUSH_MODE_INVALIDATE = 2,
> +     CS_FLUSH_MODE_CLEAN_AND_INVALIDATE = 3,
> +};
> +
> +/* There's no plan to support big endian in the UMD, so keep
> + * things simple and don't bother supporting it here either.
> + */
> +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
> +#error "big endian not supported"
> +#endif
> +
> +struct cs_instr {
> +     union {
> +             struct {
> +                     uint64_t data: 56;
> +                     uint64_t opcode: 8;
> +             } any;
> +             struct {
> +                     uint64_t unused: 56;
> +                     uint64_t opcode: 8;
> +             } nop;
> +             struct {
> +                     uint64_t immediate: 48;
> +                     uint64_t dest: 8;
> +                     uint64_t opcode: 8;
> +             } move48;
> +             struct {
> +                     uint64_t immediate: 32;
> +                     uint64_t unused: 16;
> +                     uint64_t dest: 8;
> +                     uint64_t opcode: 8;
> +             } move32;
> +             struct {
> +                     uint64_t unused0: 16;
> +                     uint64_t wait_mask: 16;
> +                     uint64_t progress_inc: 1;
> +                     uint64_t unused1: 23;
> +                     uint64_t opcode: 8;
> +             } wait;
> +             struct {
> +                     uint64_t offset: 16;
> +                     uint64_t mask: 16;
> +                     uint64_t unused: 8;
> +                     uint64_t address: 8;
> +                     uint64_t src: 8;
> +                     uint64_t opcode: 8;
> +             } stm;
> +             struct {
> +                     uint64_t l2_mode: 4;
> +                     uint64_t lsc_mode: 4;
> +                     uint64_t other_mode: 4;
> +                     uint64_t unused0: 4;
> +                     uint64_t wait_mask: 16;
> +                     uint64_t unused1: 8;
> +                     uint64_t flush_id: 8;
> +                     uint64_t signal_slot: 4;
> +                     uint64_t unused2: 4;
> +                     uint64_t opcode: 8;
> +             } flush;
> +             uint64_t raw;
> +     };
> +};
> +
> +static inline uint64_t
> +cs_nop(void)
> +{
> +     struct cs_instr instr = {
> +             .nop = {
> +                     .opcode = CS_OPCODE_NOP,
> +             },
> +     };
> +
> +     return instr.raw;
> +}
> +
> +static inline uint64_t
> +cs_mov48(uint8_t dst, uint64_t imm)
> +{
> +     struct cs_instr instr = {
> +             .move48 = {
> +                     .opcode = CS_OPCODE_MOVE48,
> +                     .dest = dst,
> +                     .immediate = (uint64_t)imm & 0xffffffffffffull,
> +             },
> +     };
> +
> +     return instr.raw;
> +}
> +
> +static inline uint64_t
> +cs_mov32(uint8_t dst, uint32_t imm)
> +{
> +     struct cs_instr instr = {
> +             .move32 = {
> +                     .opcode = CS_OPCODE_MOVE32,
> +                     .dest = dst,
> +                     .immediate = (uint32_t)imm,
> +             },
> +     };
> +
> +     return instr.raw;
> +}
> +
> +static inline uint64_t
> +cs_wait(uint16_t wait_mask, bool progress_inc)
> +{
> +     struct cs_instr instr = {
> +             .wait = {
> +                     .opcode = CS_OPCODE_WAIT,
> +                     .wait_mask = wait_mask,
> +                     .progress_inc = progress_inc,
> +             },
> +     };
> +
> +     return instr.raw;
> +}
> +
> +static inline uint64_t
> +cs_stm(uint8_t address, uint8_t src, uint16_t mask, int16_t offset)
> +{
> +     struct cs_instr instr = {
> +             .stm = {
> +                     .opcode = CS_OPCODE_STM,
> +                     .offset = (uint16_t)offset,
> +                     .mask = mask,
> +                     .src = src,
> +                     .address = address,
> +             },
> +     };
> +
> +     return instr.raw;
> +}
> +
> +static inline uint64_t
> +cs_stm32(uint8_t address, uint8_t src, int16_t offset)
> +{
> +     return cs_stm(address, src, 0x1, offset);
> +}
> +
> +static inline uint64_t
> +cs_stm64(uint8_t address, uint8_t src, int16_t offset)
> +{
> +     return cs_stm(address, src, 0x3, offset);
> +}
> +
> +static inline uint64_t
> +cs_flush(enum cs_flush_mode l2_mode,
> +      enum cs_flush_mode lsc_mode,
> +      enum cs_flush_mode other_mode,
> +      uint16_t wait_mask,
> +      uint8_t flush_id,
> +      uint8_t signal_slot)
> +{
> +     struct cs_instr instr = {
> +             .flush = {
> +                     .l2_mode = l2_mode,
> +                     .lsc_mode = lsc_mode,
> +                     .other_mode = other_mode,
> +                     .wait_mask = wait_mask,
> +                     .flush_id = flush_id,
> +                     .signal_slot = signal_slot,
> +                     .opcode = CS_OPCODE_FLUSH_CACHE,
> +             },
> +     };
> +
> +     return instr.raw;
> +}
> +
> +#endif /* IGT_PANTHOR_H */
> diff --git a/lib/meson.build b/lib/meson.build
> index 725a46e98..707ce6ff9 100644
> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -106,6 +106,7 @@ lib_sources = [
>       'igt_kmod.c',
>       'igt_ktap.c',
>       'igt_panfrost.c',
> +     'igt_panthor.c',
>       'igt_v3d.c',
>       'igt_vc4.c',
>       'igt_vmwgfx.c',
> diff --git a/meson.build b/meson.build
> index db6e09a94..bfcffbb9a 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -288,6 +288,7 @@ libexecdir = join_paths(get_option('libexecdir'), 
> 'igt-gpu-tools')
>  amdgpudir = join_paths(libexecdir, 'amdgpu')
>  msmdir = join_paths(libexecdir, 'msm')
>  panfrostdir = join_paths(libexecdir, 'panfrost')
> +panthordir = join_paths(libexecdir, 'panthor')
>  v3ddir = join_paths(libexecdir, 'v3d')
>  vc4dir = join_paths(libexecdir, 'vc4')
>  vkmsdir = join_paths(libexecdir, 'vkms')
> @@ -341,6 +342,12 @@ if get_option('use_rpath')
>       endforeach
>       panfrost_rpathdir = join_paths(panfrost_rpathdir, libdir)
>  
> +     panthor_rpathdir = '$ORIGIN'
> +     foreach p : panthordir.split('/')
> +             panthor_rpathdir = join_paths(panthor_rpathdir, '..')
> +     endforeach
> +     panthor_rpathdir = join_paths(panthor_rpathdir, libdir)
> +
>       v3d_rpathdir = '$ORIGIN'
>       foreach p : v3ddir.split('/')
>               v3d_rpathdir = join_paths(v3d_rpathdir, '..')
> @@ -370,6 +377,7 @@ else
>       amdgpudir_rpathdir = ''
>       msm_rpathdir = ''
>       panfrost_rpathdir = ''
> +     panthor_rpathdir = ''
>       v3d_rpathdir = ''
>       vc4_rpathdir = ''
>       vkms_rpathdir = ''
> diff --git a/tests/meson.build b/tests/meson.build
> index f2267bc09..e1fdac2cf 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -490,6 +490,8 @@ subdir('msm')
>  
>  subdir('panfrost')
>  
> +subdir('panthor')
> +
>  subdir('v3d')
>  
>  subdir('vc4')
> diff --git a/tests/panthor/meson.build b/tests/panthor/meson.build
> new file mode 100644
> index 000000000..ce13aebaa
> --- /dev/null
> +++ b/tests/panthor/meson.build
> @@ -0,0 +1,12 @@
> +panthor_progs = [
> +     'panthor_query'
> +]
> +
> +foreach prog : panthor_progs
> +     test_executables += executable(prog, prog + '.c',
> +                                    dependencies : test_deps,
> +                                    install_dir : panthordir,
> +                                    install_rpath : panthor_rpathdir,
> +                                    install : true)
> +     test_list += join_paths('panthor', prog)
> +endforeach
> diff --git a/tests/panthor/panthor_query.c b/tests/panthor/panthor_query.c
> new file mode 100644
> index 000000000..81c2ebd23
> --- /dev/null
> +++ b/tests/panthor/panthor_query.c
> @@ -0,0 +1,29 @@
> +// SPDX-License-Identifier: MIT
> +// SPDX-FileCopyrightText: Copyright (C) 2025 Collabora Ltd.
> +
> +#include "igt.h"
> +#include "igt_core.h"
> +#include "igt_panthor.h"
> +#include "panthor_drm.h"
> +#include <stdint.h>
> +
> +igt_main {
> +     int fd;
> +
> +     igt_fixture {
> +             fd = drm_open_driver(DRIVER_PANTHOR);
> +     }
> +
> +     igt_describe("Query GPU information from ROM.");
> +     igt_subtest("query") {
> +             struct drm_panthor_gpu_info gpu = {};
> +
> +             igt_panthor_query(fd, DRM_PANTHOR_DEV_QUERY_GPU_INFO, &gpu, 
> sizeof(gpu), 0);
> +
> +             igt_assert_neq(gpu.gpu_id, 0);
> +     }
> +
> +     igt_fixture {
> +             drm_close_driver(fd);
> +     }
> +}

Reply via email to