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); > + } > +}
