<div dir="ltr"><div>Hi Kamil,</div><div><br></div><div>Thank you very much for the reviews!</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">please use 'tests/' as a prefix in subject, also change test name,<br>
so instead of<br>
[PATCH] drm_virtgpu: Add functional coverage for core VirtIO-GPU ioctls<br>
<br>
better:<br>
[PATCH] tests/virtgpu: Add functional coverage for core VirtIO-GPU ioctls<span class="gmail-im"><br></span></blockquote><div>Ack, but I would rather prefer to use tests/drm_virtgpu instead considering that I'm testing DRM ioctls for the virtio-GPU driver and this matches other test patterns</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
I would name them without 'drm-virtgpu-' prefix. Up to you.<span class="gmail-im"><br></span></blockquote><div>I think the drm-virtgpu prefix looks better, I also figured it fits with the igt naming convention, like the drm_mm follows this format.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Could someone from your team help with review?</blockquote><div>Sure <a class="gmail_plusreply" id="plusReplyChip-0" href="mailto:aesteve@redhat.com" tabindex="-1">@Albert Esteve</a> <a class="gmail_plusreply" id="plusReplyChip-1" href="mailto:javierm@redhat.com" tabindex="-1">@Javier Martinez Canillas</a> could you help? <br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Please rename it into virtgpu.c: <br></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
s/drm_virtgpu.c/virtgpu.c/</blockquote><div>As per the first reply, I believe drm_virtgpu is better</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-im"></span> Please move igt headers after system ones.</blockquote><div>Ack</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Remove space from " Testing", so</blockquote><div>Yes, thanks for the catch!</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">At least try to open all cardN until you find virtio, there is<br>
sometimes simpleDRM driver loaded and then cards could start from 1,<br>
/dev/dri/card1<br>
<br>
What about checking with getversion? For idea see core_getversion test.</blockquote><div> Right! This makes sense - Thank you for the reference.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Please do not make initialization with asserts here, I would suggest<br>
to move this into a function, for example:<br>
int create_resource(int fd, ... other params...)<br>
<br>
and then calling this before each test. For example:<br>
<br>
bool create_res(struct drm_virtgpu_resource_create *res)<br>
{<br>
if(res->array_size == 1) /* already created */<br>
return true;<br>
<br>
... rest of creation ...<br>
}<br>
<br>
igt_subtest("virtgpu-map") {<br>
...vars here...<br>
<br>
igt_assert(create_res(&args));<br>
<br>
<br>
Or you could just create it in this fixture without asserts,<br>
place asserts in a function check_res() and call it in each<br>
subtests which needs them. For example:<br>
<br>
igt_subtest("virtgpu-map") {<br>
...vars here...<br>
<br>
check_res(&args);<br>
<br>
This also looks like a good candidate for a separate subtest?<span class="gmail-im"><br></span></blockquote><div>Yes, Initially I thought about making it a seperate subtest but considering that many subtests needed it, I put it in the igt_fixture().</div><div>I will put it in a separate function and create a `drm-virtgpu-resource-create` subtest to run it independently, this will also enable it to be used by other subtests.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-im"><br></span>
Please use C-style comments:<br>
/* Request mmap offset */<br>
<br>
Same applies for following code.</blockquote><div>Noted with thanks!</div><div><br></div><div>BR,</div><div>Dorinda Bassey. <br></div><div> </div></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Thu, May 22, 2025 at 6:20 PM Kamil Konieczny <<a href="mailto:kamil.konieczny@linux.intel.com">kamil.konieczny@linux.intel.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Dorinda,<br>
On 2025-05-14 at 12:28:00 +0200, Dorinda Bassey wrote:<br>
<br>
please use 'tests/' as a prefix in subject, also change test name,<br>
so instead of<br>
[PATCH] drm_virtgpu: Add functional coverage for core VirtIO-GPU ioctls<br>
<br>
better:<br>
[PATCH] tests/virtgpu: Add functional coverage for core VirtIO-GPU ioctls<br>
<br>
> This test suite adds coverage for multiple DRM ioctls specific<br>
> to the VirtIO-GPU driver, verifying functionality such as<br>
> resource creation, memory mapping, 3D transfers, context<br>
> initialization, and parameter querying.<br>
> Each test validates a key ioctl to ensure correct behavior from<br>
> user space and backend implementations. Each subtest is<br>
> self-contained and can be executed independently.<br>
> <br>
> Included subtests:<br>
> - drm-virtgpu-map<br>
> - drm-virtgpu-execbuffer<br>
> - drm-virtgpu-resource-info<br>
> - drm-virtgpu-3d-transfer-to-host<br>
> - drm-virtgpu-3d-transfer-from-host<br>
> - drm-virtgpu-3d-wait<br>
> - drm-virtgpu-resource-create-blob<br>
> - drm-virtgpu-get-caps<br>
> - drm-virtgpu-context-init<br>
> - drm-virtgpu-getparam<br>
<br>
I would name them without 'drm-virtgpu-' prefix. Up to you.<br>
<br>
> <br>
> How to Test with QEMU virtio-vga-gl or rustvmm vhost-device-gpu<br>
> <br>
> 1. Launch a QEMU guest with virtio-vga-gl<br>
> ./build/qemu-system-x86_64 \<br>
> -enable-kvm \<br>
> -cpu host \<br>
> -m 4096 \<br>
> -machine q35 \<br>
> -display gtk,gl=on \<br>
> -vga none \<br>
> -device virtio-vga-gl \<br>
> -drive file=image.qcow2,format=qcow2 \<br>
> -netdev user,id=n0,hostfwd=tcp::2222-:22 \<br>
> -device virtio-net-pci,netdev=n0<br>
> <br>
> ssh into the guest and run the tests.<br>
> <br>
> 2. Start the vhost-device-gpu backend and Launch a QEMU<br>
> guest with vhost-user-gpu-pci or vhost-user-vga, see guide on:<br>
> <a href="https://crates.io/crates/vhost-device-gpu" rel="noreferrer" target="_blank">https://crates.io/crates/vhost-device-gpu</a><br>
<br>
Could someone from your team help with review?<br>
<br>
> <br>
> Signed-off-by: Dorinda Bassey <<a href="mailto:dbassey@redhat.com" target="_blank">dbassey@redhat.com</a>><br>
> ---<br>
> tests/drm_virtgpu.c | 388 ++++++++++++++++++++++++++++++++++++++++++++<br>
<br>
Please rename it into virtgpu.c:<br>
<br>
s/drm_virtgpu.c/virtgpu.c/<br>
<br>
> tests/meson.build | 1 +<br>
> 2 files changed, 389 insertions(+)<br>
> create mode 100644 tests/drm_virtgpu.c<br>
> <br>
> diff --git a/tests/drm_virtgpu.c b/tests/drm_virtgpu.c<br>
> new file mode 100644<br>
> index 000000000..8de7880db<br>
> --- /dev/null<br>
> +++ b/tests/drm_virtgpu.c<br>
> @@ -0,0 +1,388 @@<br>
> +// SPDX-License-Identifier: MIT<br>
> +/*<br>
> + * Copyright © 2025 Red Hat Inc.<br>
> + *<br>
> + * Authors: Dorinda Bassey <<a href="mailto:dbassey@redhat.com" target="_blank">dbassey@redhat.com</a>><br>
> + */<br>
> +<br>
> +/**<br>
> + * TEST: drm virtgpu ioctls<br>
> + * Description: Testing of the virtIO-GPU driver DRM ioctls<br>
> + * Category: Core<br>
> + * Mega feature: General Core features<br>
> + * Sub-category: virtIO-GPU DRM ioctls<br>
> + * Functionality: drm_ioctls<br>
> + * Feature: Virtualization graphics support<br>
> + * Test category: functionality test<br>
> + */<br>
> +<br>
> +#include "igt.h"<br>
> +<br>
> +#include "drm.h"<br>
> +#include "virtgpu_drm.h"<br>
<br>
Please move igt headers after system ones.<br>
<br>
> +<br>
> +#include <fcntl.h><br>
> +#include <errno.h><br>
> +#include <string.h><br>
> +#include <sys/ioctl.h><br>
> +<br>
> +/**<br>
> + * SUBTEST: drm-virtgpu-map<br>
> + *<br>
> + * SUBTEST: drm-virtgpu-execbuffer<br>
> + *<br>
> + * SUBTEST: drm-virtgpu-resource-info<br>
> + *<br>
> + * SUBTEST: drm-virtgpu-3d-transfer-to-host<br>
> + *<br>
> + * SUBTEST: drm-virtgpu-3d-transfer-from-host<br>
> + *<br>
> + * SUBTEST: drm-virtgpu-3d-wait<br>
> + *<br>
> + * SUBTEST: drm-virtgpu-resource-create-blob<br>
> + *<br>
> + * SUBTEST: drm-virtgpu-get-caps<br>
> +<br>
> + * SUBTEST: drm-virtgpu-context-init<br>
> + *<br>
> + * SUBTEST: drm-virtgpu-getparam<br>
> + */<br>
> +<br>
> +IGT_TEST_DESCRIPTION(" Testing of the virtIO-GPU driver DRM ioctls");<br>
<br>
Remove space from " Testing", so<br>
IGT_TEST_DESCRIPTION("Testing of the virtIO-GPU driver DRM ioctls");<br>
<br>
> +<br>
> +#define VIRTGPU_DEVICE "/dev/dri/card0"<br>
<br>
At least try to open all cardN until you find virtio, there is<br>
sometimes simpleDRM driver loaded and then cards could start from 1,<br>
/dev/dri/card1<br>
<br>
What about checking with getversion? For idea see core_getversion test.<br>
<br>
> +<br>
> +#define CAPS_BUFFER_SIZE 4096<br>
> +<br>
> +static const struct {<br>
> + const char *name;<br>
> + uint64_t id;<br>
> +} params[] = {<br>
> + {"3D_FEATURES", VIRTGPU_PARAM_3D_FEATURES},<br>
> + {"CAPSET_QUERY_FIX", VIRTGPU_PARAM_CAPSET_QUERY_FIX},<br>
> + {"RESOURCE_BLOB", VIRTGPU_PARAM_RESOURCE_BLOB},<br>
> + {"HOST_VISIBLE", VIRTGPU_PARAM_HOST_VISIBLE},<br>
> + {"CROSS_DEVICE", VIRTGPU_PARAM_CROSS_DEVICE},<br>
> + {"CONTEXT_INIT", VIRTGPU_PARAM_CONTEXT_INIT},<br>
> + {"SUPPORTED_CAPSET_IDs", VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs},<br>
> + {"EXPLICIT_DEBUG_NAME", VIRTGPU_PARAM_EXPLICIT_DEBUG_NAME},<br>
> +};<br>
> +<br>
> +static void test_capset(int drm_fd, uint32_t capset_id)<br>
> +{<br>
> + uint8_t *caps_buf;<br>
> + struct drm_virtgpu_get_caps caps;<br>
> + int ret;<br>
> + int i;<br>
> +<br>
> + caps_buf = malloc(CAPS_BUFFER_SIZE);<br>
> + igt_require(caps_buf);<br>
> + memset(caps_buf, 0, CAPS_BUFFER_SIZE);<br>
> +<br>
> + memset(&caps, 0, sizeof(caps));<br>
> + caps.cap_set_id = capset_id;<br>
> + caps.size = CAPS_BUFFER_SIZE;<br>
> + caps.addr = (uintptr_t) caps_buf;<br>
> +<br>
> + ret = ioctl(drm_fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &caps);<br>
> + if (ret == 0) {<br>
> + igt_info("Capset ID %u: SUCCESS\n", capset_id);<br>
> + igt_info(" Reported size: %u\n", caps.size);<br>
> + igt_info(" First 16 bytes: ");<br>
> + for (i = 0; i < 16; i++)<br>
> + igt_info("%02x ", caps_buf[i]);<br>
> + igt_info("\n");<br>
> + } else {<br>
> + igt_info("Capset ID %u: FAILED - %s\n", capset_id,<br>
> + strerror(errno));<br>
> + }<br>
> +<br>
> + free(caps_buf);<br>
> +}<br>
> +<br>
> +igt_main {<br>
> + int drm_fd;<br>
> + void *caps_buf = NULL;<br>
> +<br>
> + struct drm_virtgpu_resource_create args;<br>
> + bool resource_created = false;<br>
> +<br>
> + igt_fixture {<br>
> + int ret;<br>
> +<br>
> + drm_fd = open(VIRTGPU_DEVICE, O_RDWR | O_CLOEXEC);<br>
> + igt_require(drm_fd >= 0);<br>
> +<br>
> + caps_buf = malloc(CAPS_BUFFER_SIZE);<br>
> + igt_require(caps_buf);<br>
> + memset(caps_buf, 0, CAPS_BUFFER_SIZE);<br>
> +<br>
> + // Create resource<br>
> + memset(&args, 0, sizeof(args));<br>
> + args.target = 2;<br>
> + args.format = 87;<br>
> + args.bind = (1 << 0);<br>
> + args.width = 64;<br>
> + args.height = 64;<br>
> + args.depth = 1;<br>
> + args.array_size = 1;<br>
> +<br>
> + ret = ioctl(drm_fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE, &args);<br>
> + igt_assert_f(ret == 0, "RESOURCE_CREATE failed: %s\n",<br>
> + strerror(errno));<br>
> + igt_assert_neq(args.res_handle, 0);<br>
> +<br>
> + resource_created = true;<br>
> + igt_info("Created resource: res_handle=%u, bo_handle=%u\n",<br>
> + args.res_handle, args.bo_handle);<br>
<br>
Please do not make initialization with asserts here, I would suggest<br>
to move this into a function, for example:<br>
int create_resource(int fd, ... other params...)<br>
<br>
and then calling this before each test. For example:<br>
<br>
bool create_res(struct drm_virtgpu_resource_create *res)<br>
{<br>
if(res->array_size == 1) /* already created */<br>
return true;<br>
<br>
... rest of creation ...<br>
}<br>
<br>
igt_subtest("virtgpu-map") {<br>
...vars here...<br>
<br>
igt_assert(create_res(&args));<br>
<br>
<br>
Or you could just create it in this fixture without asserts,<br>
place asserts in a function check_res() and call it in each<br>
subtests which needs them. For example:<br>
<br>
igt_subtest("virtgpu-map") {<br>
...vars here...<br>
<br>
check_res(&args);<br>
<br>
This also looks like a good candidate for a separate subtest?<br>
<br>
> + }<br>
> +<br>
> + igt_describe<br>
> + ("Maps a buffer object and tests read/write access via mmap.");<br>
> + igt_subtest("drm-virtgpu-map") {<br>
> + struct drm_virtgpu_map map = { };<br>
> + void *map_ptr;<br>
> + int ret;<br>
> +<br>
> + memset(&map, 0, sizeof(map));<br>
> + map.handle = args.bo_handle;<br>
> +<br>
> + // Request mmap offset<br>
<br>
Please use C-style comments:<br>
/* Request mmap offset */<br>
<br>
Same applies for following code.<br>
<br>
Regards,<br>
Kamil<br>
<br>
> + ret = ioctl(drm_fd, DRM_IOCTL_VIRTGPU_MAP, &map);<br>
> + igt_assert_f(ret == 0, "MAP ioctl failed: %s\n",<br>
> + strerror(errno));<br>
> + igt_assert(map.offset != 0);<br>
> +<br>
> + // Try mmap<br>
> + map_ptr =<br>
> + mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd,<br>
> + map.offset);<br>
> + igt_assert(map_ptr != MAP_FAILED);<br>
> +<br>
> + igt_info("Successfully mmap'ed BO: offset=0x%lx\n",<br>
> + (unsigned long)map.offset);<br>
> +<br>
> + // Simple test: write and read<br>
> + memset(map_ptr, 0xaa, 4096);<br>
> + igt_assert(((uint8_t *) map_ptr)[0] == 0xaa);<br>
> +<br>
> + munmap(map_ptr, 4096);<br>
> + }<br>
> +<br>
> + igt_describe("Submits a dummy execbuffer to the GPU.");<br>
> + igt_subtest("drm-virtgpu-execbuffer") {<br>
> + struct drm_virtgpu_execbuffer execbuf = { };<br>
> + uint32_t handles[1];<br>
> + int ret;<br>
> +<br>
> + handles[0] = args.bo_handle;<br>
> +<br>
> + // Submit dummy execbuffer<br>
> + execbuf.flags = 0;<br>
> + execbuf.size = 0; // No command<br>
> + execbuf.command = 0; // No command buffer<br>
> + execbuf.bo_handles = (uintptr_t) handles;<br>
> + execbuf.num_bo_handles = 1;<br>
> + execbuf.fence_fd = -1; // No fence<br>
> + execbuf.ring_idx = 0; // Default ring<br>
> +<br>
> + ret = ioctl(drm_fd, DRM_IOCTL_VIRTGPU_EXECBUFFER, &execbuf);<br>
> + igt_assert_f(ret == 0, "EXECBUFFER ioctl failed: %s\n",<br>
> + strerror(errno));<br>
> +<br>
> + igt_info("EXECBUFFER submitted successfully.\n");<br>
> + }<br>
> +<br>
> + igt_describe<br>
> + ("Validates that the GPU resource info ioctl returns expected metadata.");<br>
> + igt_subtest("drm-virtgpu-resource-info") {<br>
> + struct drm_virtgpu_resource_info info;<br>
> + int ret;<br>
> +<br>
> + igt_require_f(resource_created,<br>
> + "Resource must be created before this test");<br>
> +<br>
> + memset(&info, 0, sizeof(info));<br>
> + info.bo_handle = args.bo_handle;<br>
> +<br>
> + ret = ioctl(drm_fd, DRM_IOCTL_VIRTGPU_RESOURCE_INFO, &info);<br>
> + igt_assert_f(ret == 0, "RESOURCE_INFO failed: %s\n",<br>
> + strerror(errno));<br>
> + igt_assert_eq(info.res_handle, args.res_handle);<br>
> + igt_assert(info.size > 0);<br>
> +<br>
> + igt_info("Queried resource info:\n");<br>
> + igt_info(" size: %u bytes\n", info.size);<br>
> + igt_info(" res_handle %u\n", info.res_handle);<br>
> + igt_info(" blob_mem: %u\n", info.blob_mem);<br>
> + }<br>
> +<br>
> + igt_describe<br>
> + ("Transfers buffer contents from guest memory to the host.");<br>
> + igt_subtest("drm-virtgpu-3d-transfer-to-host") {<br>
> + int ret;<br>
> + struct drm_virtgpu_3d_transfer_to_host xfer = {<br>
> + .bo_handle = args.bo_handle,<br>
> + .box = {<br>
> + .x = 0,<br>
> + .y = 0,<br>
> + .z = 0,<br>
> + .w = args.width,<br>
> + .h = args.height,<br>
> + .d = 1,<br>
> + },<br>
> + .level = 0,<br>
> + .offset = 0,<br>
> + .stride = 0,<br>
> + .layer_stride = 0,<br>
> + };<br>
> +<br>
> + igt_require_f(resource_created,<br>
> + "Resource must be created before this test");<br>
> +<br>
> + ret = ioctl(drm_fd, DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST, &xfer);<br>
> + igt_assert_f(ret == 0, "TRANSFER_TO_HOST failed: %s\n",<br>
> + strerror(errno));<br>
> + igt_info("TRANSFER_TO_HOST completed\n");<br>
> + }<br>
> +<br>
> + igt_describe("Transfers buffer contents from the host to guest memory.");<br>
> + igt_subtest("drm-virtgpu-3d-transfer-from-host")<br>
> + {<br>
> + int ret;<br>
> + struct drm_virtgpu_3d_transfer_from_host xfer_in = {<br>
> + .bo_handle = args.bo_handle,<br>
> + .box = {<br>
> + .x = 0,<br>
> + .y = 0,<br>
> + .z = 0,<br>
> + .w = args.width,<br>
> + .h = args.height,<br>
> + .d = 1,<br>
> + },<br>
> + .level = 0,<br>
> + .offset = 0,<br>
> + .stride = 0,<br>
> + .layer_stride = 0,<br>
> + };<br>
> +<br>
> + igt_require_f(resource_created,<br>
> + "Resource must be created before this test");<br>
> +<br>
> + ret = ioctl(drm_fd, DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST, &xfer_in);<br>
> + igt_assert_f(ret == 0, "TRANSFER_FROM_HOST failed: %s\n", strerror(errno));<br>
> + igt_info("TRANSFER_FROM_HOST completed\n");<br>
> + }<br>
> +<br>
> + igt_describe<br>
> + ("Waits for a GPU operation to complete on a specific resource.");<br>
> + igt_subtest("drm-virtgpu-3d-wait") {<br>
> + struct drm_virtgpu_3d_wait wait = {.handle = args.bo_handle };<br>
> +<br>
> + int ret = ioctl(drm_fd, DRM_IOCTL_VIRTGPU_WAIT, &wait);<br>
> +<br>
> + if (ret == 0)<br>
> + igt_info("WAIT succeeded.\n");<br>
> + else<br>
> + igt_info("WAIT failed as expected (%s).\n",<br>
> + strerror(errno));<br>
> + }<br>
> +<br>
> + igt_describe<br>
> + ("Creates a GPU resource using the blob interface with memory flags.");<br>
> + igt_subtest("drm-virtgpu-resource-create-blob") {<br>
> + struct drm_virtgpu_resource_create_blob blob = {<br>
> + .blob_mem = VIRTGPU_BLOB_MEM_GUEST,<br>
> + .blob_flags =<br>
> + VIRTGPU_BLOB_FLAG_USE_MAPPABLE |<br>
> + VIRTGPU_BLOB_FLAG_USE_SHAREABLE,<br>
> + .size = 4096,<br>
> + .blob_id = 0,<br>
> + .cmd_size = 0,<br>
> + .cmd = (uintptr_t) NULL,<br>
> + };<br>
> +<br>
> + int ret =<br>
> + ioctl(drm_fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB,<br>
> + &blob);<br>
> + igt_assert_f(ret == 0, "Blob creation ioctl failed: %s\n",<br>
> + strerror(errno));<br>
> + igt_assert_eq(ret, 0);<br>
> + igt_assert_neq(blob.res_handle, 0);<br>
> + }<br>
> +<br>
> + igt_describe<br>
> + ("Queries different GPU capsets and prints the response payload.");<br>
> + igt_subtest("drm-virtgpu-get-caps") {<br>
> + // Test multiple capsets<br>
> + test_capset(drm_fd, 1); // VirGL<br>
> + test_capset(drm_fd, 2); // GFXSTREAM<br>
> + test_capset(drm_fd, 9999); // Invalid (expect failure)<br>
> + }<br>
> +<br>
> + igt_describe<br>
> + ("Initializes a GPU context with parameters like capset ID and debug name.");<br>
> + igt_subtest("drm-virtgpu-context-init") {<br>
> + struct drm_virtgpu_context_set_param ctx_params[2];<br>
> + struct drm_virtgpu_context_init ctx_init;<br>
> + int ret;<br>
> +<br>
> + memset(ctx_params, 0, sizeof(ctx_params));<br>
> +<br>
> + ctx_params[0].param = VIRTGPU_CONTEXT_PARAM_CAPSET_ID;<br>
> + ctx_params[0].value = 1;<br>
> +<br>
> + ctx_params[1].param = VIRTGPU_CONTEXT_PARAM_DEBUG_NAME;<br>
> + ctx_params[1].value = (uintptr_t) "IGT-Test-Context";<br>
> +<br>
> + memset(&ctx_init, 0, sizeof(ctx_init));<br>
> + ctx_init.num_params = 2;<br>
> + ctx_init.ctx_set_params = (uintptr_t)&ctx_params[0];<br>
> +<br>
> + ret = ioctl(drm_fd, DRM_IOCTL_VIRTGPU_CONTEXT_INIT, &ctx_init);<br>
> + if (ret == -1 && errno == EEXIST) {<br>
> + igt_info<br>
> + ("CONTEXT_INIT with params failed as expected (already initialized)\n");<br>
> + } else {<br>
> + igt_assert_f(ret == 0,<br>
> + "CONTEXT_INIT with params ioctl failed: %s\n",<br>
> + strerror(errno));<br>
> + igt_info("CONTEXT_INIT with parameters succeeded\n");<br>
> + }<br>
> + }<br>
> +<br>
> + igt_describe<br>
> + ("Verifies which VirtIO-GPU features are supported by querying driver parameters.");<br>
> + igt_subtest("drm-virtgpu-getparam") {<br>
> + bool found_supported = false;<br>
> + uint64_t actual_value = 0;<br>
> +<br>
> + for (size_t i = 0; i < ARRAY_SIZE(params); i++) {<br>
> + struct drm_virtgpu_getparam gp = {<br>
> + .param = params[i].id,<br>
> + .value = (uintptr_t)&actual_value,<br>
> + };<br>
> +<br>
> + int ret =<br>
> + ioctl(drm_fd, DRM_IOCTL_VIRTGPU_GETPARAM, &gp);<br>
> + if (ret == 0) {<br>
> + found_supported = true;<br>
> + igt_info("GETPARAM %s (ID=%lu): value = %llu\n",<br>
> + params[i].name, params[i].id,<br>
> + gp.value);<br>
> + } else {<br>
> + igt_info("GETPARAM %s (ID=%lu): failed - %s\n",<br>
> + params[i].name, params[i].id,<br>
> + strerror(errno));<br>
> + }<br>
> + }<br>
> +<br>
> + igt_assert_f(found_supported,<br>
> + "No GETPARAM query returned a value.");<br>
> + }<br>
> +<br>
> + igt_fixture {<br>
> + free(caps_buf);<br>
> + close(drm_fd);<br>
> + }<br>
> +}<br>
> diff --git a/tests/meson.build b/tests/meson.build<br>
> index 20ddddb89..ac85cac30 100644<br>
> --- a/tests/meson.build<br>
> +++ b/tests/meson.build<br>
> @@ -13,6 +13,7 @@ test_progs = [<br>
> 'drm_buddy',<br>
> 'drm_mm',<br>
> 'drm_read',<br>
> + 'drm_virtgpu',<br>
> 'fbdev',<br>
> 'kms_3d',<br>
> 'kms_addfb_basic',<br>
> -- <br>
> 2.48.1<br>
> <br>
<br>
</blockquote></div>