From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by gabe.freedesktop.org (Postfix) with ESMTPS id 937F810E22F for ; Thu, 16 Mar 2023 14:22:21 +0000 (UTC) Received: by mail-wm1-x329.google.com with SMTP id c8-20020a05600c0ac800b003ed2f97a63eso3288429wmr.3 for ; Thu, 16 Mar 2023 07:22:21 -0700 (PDT) Message-ID: <5a4fa5cc-7f6a-e9b9-761b-8dfbb5ce4795@gmail.com> Date: Thu, 16 Mar 2023 16:22:18 +0200 MIME-Version: 1.0 Content-Language: en-US To: igt-dev@lists.freedesktop.org References: <20230316022659.73202-1-zack@kde.org> <20230316022659.73202-8-zack@kde.org> From: "Martin Krastev (VMware)" In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Subject: Re: [igt-dev] [PATCH i-g-t v2 7/8] igt/vmwgfx: Add reference counting tests List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: krastevm@vmware.com, banackm@vmware.com, mombasawalam@vmware.com Errors-To: igt-dev-bounces@lists.freedesktop.org Sender: "igt-dev" List-ID: From: Martin Krastev LGTM Reviewed-by: Martin Krastev Regards, Martin On 16.03.23 г. 14:55 ч., Martin Krastev wrote: > From: Maaz Mombasawala > > This test checks reference counting functionality for several permutations > of prime transfers and copies of mobs and surfaces in vmwgfx. > > Signed-off-by: Zack Rusin > Signed-off-by: Maaz Mombasawala > --- > tests/vmwgfx/meson.build | 3 +- > tests/vmwgfx/ref_count.c | 312 +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 314 insertions(+), 1 deletion(-) > create mode 100644 tests/vmwgfx/ref_count.c > > diff --git a/tests/vmwgfx/meson.build b/tests/vmwgfx/meson.build > index c84dcc28..5995b18c 100644 > --- a/tests/vmwgfx/meson.build > +++ b/tests/vmwgfx/meson.build > @@ -3,7 +3,8 @@ vmwgfx_progs = [ > 'tri', > 'execution_buffer', > 'surface_copy', > - 'mob_stress' > + 'mob_stress', > + 'ref_count' > ] > vmwgfx_deps = test_deps > > diff --git a/tests/vmwgfx/ref_count.c b/tests/vmwgfx/ref_count.c > new file mode 100644 > index 00000000..f216dcc9 > --- /dev/null > +++ b/tests/vmwgfx/ref_count.c > @@ -0,0 +1,312 @@ > +// SPDX-License-Identifier: GPL-2.0 OR MIT > +/********************************************************** > + * Copyright 2021-2022 VMware, Inc. > + * > + * Permission is hereby granted, free of charge, to any person > + * obtaining a copy of this software and associated documentation > + * files (the "Software"), to deal in the Software without > + * restriction, including without limitation the rights to use, copy, > + * modify, merge, publish, distribute, sublicense, and/or sell copies > + * of the Software, and to permit persons to whom the Software is > + * furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be > + * included in all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, > + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND > + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS > + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN > + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN > + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE > + * SOFTWARE. > + * > + **********************************************************/ > + > +#include "igt_vmwgfx.h" > + > +IGT_TEST_DESCRIPTION("Perform tests related to vmwgfx's ref_count codepaths."); > + > +static uint32 data[10] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; > + > +static void write_to_mob(int fd, struct vmw_mob *mob) > +{ > + void *write_data; > + > + write_data = vmw_ioctl_mob_map(fd, mob); > + memcpy(write_data, data, sizeof(data)); > + vmw_ioctl_mob_unmap(mob); > +} > + > +static bool verify_mob_data(int fd, struct vmw_mob *mob) > +{ > + uint32 *read_data; > + void *readback; > + uint32 i; > + bool data_is_equal = true; > + > + read_data = malloc(mob->size); > + > + readback = vmw_ioctl_mob_map(fd, mob); > + memcpy(read_data, readback, sizeof(data)); > + vmw_ioctl_mob_unmap(mob); > + > + for (i = 0; i < ARRAY_SIZE(data); i++) { > + if (read_data[i] != data[i]) { > + data_is_equal = false; > + break; > + } > + } > + > + free(read_data); > + return data_is_equal; > +} > + > +static struct vmw_surface * > +create_and_write_shareable_surface(int32 fd, SVGA3dSize surface_size) > +{ > + struct vmw_mob mob = { 0 }; > + struct vmw_surface *surface; > + > + surface = vmw_ioctl_create_surface_full( > + fd, SVGA3D_SURFACE_HINT_RENDERTARGET, SVGA3D_BUFFER, 0, > + SVGA3D_MS_PATTERN_NONE, SVGA3D_MS_QUALITY_NONE, > + SVGA3D_TEX_FILTER_NONE, 1, 1, surface_size, NULL, > + drm_vmw_surface_flag_shareable); > + > + mob.handle = surface->base.buffer_handle; > + mob.map_handle = surface->base.buffer_map_handle; > + mob.size = surface->base.buffer_size; > + > + write_to_mob(fd, &mob); > + > + return surface; > +} > + > +static bool ref_surface_and_check_contents(int32 fd, uint32 surface_handle) > +{ > + struct vmw_surface surface; > + struct vmw_mob mob = { 0 }; > + > + surface = vmw_ioctl_surface_ref(fd, surface_handle, > + DRM_VMW_HANDLE_LEGACY); > + > + mob.handle = surface.base.handle; > + mob.size = surface.base.buffer_size; > + mob.map_handle = surface.base.buffer_map_handle; > + > + return verify_mob_data(fd, &mob); > +} > + > +igt_main > +{ > + int32 fd1, fd2; > + const uint32 size = sizeof(data); > + SVGA3dSize surface_size = { .width = size, .height = 1, .depth = 1 }; > + > + igt_fixture > + { > + fd1 = drm_open_driver_render(DRIVER_VMWGFX); > + fd2 = drm_open_driver_render(DRIVER_VMWGFX); > + igt_require(fd1 != -1); > + igt_require(fd2 != -1); > + } > + > + igt_subtest("surface_prime_transfer_explicit_mob") > + { > + struct vmw_mob *mob; > + struct vmw_surface *surface; > + int32 surface_fd; > + uint32 surface_handle; > + > + mob = vmw_ioctl_mob_create(fd1, size); > + surface = vmw_ioctl_create_surface_full( > + fd1, SVGA3D_SURFACE_HINT_RENDERTARGET, SVGA3D_BUFFER, 0, > + SVGA3D_MS_PATTERN_NONE, SVGA3D_MS_QUALITY_NONE, > + SVGA3D_TEX_FILTER_NONE, 1, 1, surface_size, mob, > + drm_vmw_surface_flag_shareable); > + > + write_to_mob(fd1, mob); > + > + surface_fd = > + prime_handle_to_fd_for_mmap(fd1, surface->base.handle); > + > + vmw_ioctl_mob_close_handle(fd1, mob); > + vmw_ioctl_surface_unref(fd1, surface); > + > + surface_handle = prime_fd_to_handle(fd2, surface_fd); > + close(surface_fd); > + > + igt_assert(ref_surface_and_check_contents(fd2, surface_handle)); > + } > + > + igt_subtest("surface_prime_transfer_implicit_mob") > + { > + struct vmw_surface *surface; > + int32 surface_fd; > + uint32 surface_handle; > + > + surface = create_and_write_shareable_surface(fd1, surface_size); > + > + surface_fd = > + prime_handle_to_fd_for_mmap(fd1, surface->base.handle); > + > + vmw_ioctl_surface_unref(fd1, surface); > + > + surface_handle = prime_fd_to_handle(fd2, surface_fd); > + close(surface_fd); > + > + igt_assert(ref_surface_and_check_contents(fd2, surface_handle)); > + } > + > + igt_subtest("surface_prime_transfer_fd_dup") > + { > + int32 surface_fd1, surface_fd2; > + uint32 surface_handle; > + struct vmw_surface *surface; > + > + surface = create_and_write_shareable_surface(fd1, surface_size); > + > + surface_fd1 = > + prime_handle_to_fd_for_mmap(fd1, surface->base.handle); > + vmw_ioctl_surface_unref(fd1, surface); > + > + surface_fd2 = dup(surface_fd1); > + close(surface_fd1); > + > + surface_handle = prime_fd_to_handle(fd2, surface_fd2); > + close(surface_fd2); > + > + igt_assert(ref_surface_and_check_contents(fd2, surface_handle)); > + } > + > + igt_subtest("surface_prime_transfer_two_surfaces") > + { > + int32 surface_fd; > + uint32 surface_handle1, surface_handle2; > + struct vmw_surface *surface1, *surface2; > + > + surface1 = > + create_and_write_shareable_surface(fd1, surface_size); > + surface2 = > + create_and_write_shareable_surface(fd1, surface_size); > + > + surface_fd = > + prime_handle_to_fd_for_mmap(fd1, surface1->base.handle); > + vmw_ioctl_surface_unref(fd1, surface1); > + > + surface_handle1 = prime_fd_to_handle(fd2, surface_fd); > + close(surface_fd); > + > + surface_fd = > + prime_handle_to_fd_for_mmap(fd1, surface2->base.handle); > + vmw_ioctl_surface_unref(fd1, surface2); > + > + surface_handle2 = prime_fd_to_handle(fd2, surface_fd); > + close(surface_fd); > + > + igt_assert( > + ref_surface_and_check_contents(fd2, surface_handle1)); > + igt_assert( > + ref_surface_and_check_contents(fd2, surface_handle2)); > + } > + > + igt_subtest("surface_prime_transfer_single_surface_multiple_handle") > + { > + int32 surface_fd; > + uint32 surface_handle_old; > + uint32 surface_handle1, surface_handle2, surface_handle3; > + struct vmw_surface *surface; > + > + surface = create_and_write_shareable_surface(fd1, surface_size); > + surface_handle_old = surface->base.handle; > + > + surface_fd = > + prime_handle_to_fd_for_mmap(fd1, surface->base.handle); > + vmw_ioctl_surface_unref(fd1, surface); > + > + surface_handle1 = prime_fd_to_handle(fd1, surface_fd); > + surface_handle2 = prime_fd_to_handle(fd2, surface_fd); > + surface_handle3 = prime_fd_to_handle(fd2, surface_fd); > + close(surface_fd); > + > + igt_assert_eq_u32(surface_handle_old, surface_handle1); > + igt_assert_eq_u32(surface_handle2, surface_handle3); > + > + igt_assert( > + ref_surface_and_check_contents(fd1, surface_handle1)); > + igt_assert( > + ref_surface_and_check_contents(fd2, surface_handle2)); > + } > + > + igt_subtest("mob_repeated_unref") > + { > + struct vmw_mob *mob; > + int i = 0; > + > + mob = vmw_ioctl_mob_create(fd1, size); > + write_to_mob(fd1, mob); > + > + /* Shouldn't crash on multiple invocations */ > + for (i = 0; i < 3; i++) { > + int ret; > + struct drm_vmw_handle_close_arg arg = { > + .handle = mob->handle > + }; > + ret = drmCommandWrite(fd1, DRM_VMW_HANDLE_CLOSE, &arg, > + sizeof(arg)); > + igt_assert_eq(ret, 0); > + } > + free(mob); > + } > + > + igt_subtest("surface_repeated_unref") > + { > + struct vmw_surface *surface; > + int i = 0; > + > + surface = vmw_ioctl_create_surface_full( > + fd1, SVGA3D_SURFACE_HINT_RENDERTARGET, SVGA3D_BUFFER, 0, > + SVGA3D_MS_PATTERN_NONE, SVGA3D_MS_QUALITY_NONE, > + SVGA3D_TEX_FILTER_NONE, 1, 1, surface_size, NULL, > + drm_vmw_surface_flag_shareable); > + > + /* Shouldn't crash on multiple invocations */ > + for (i = 0; i < 3; i++) { > + struct drm_vmw_surface_arg s_arg = { > + .sid = surface->base.handle, > + .handle_type = DRM_VMW_HANDLE_LEGACY > + }; > + drmCommandWrite(fd1, DRM_VMW_UNREF_SURFACE, &s_arg, > + sizeof(s_arg)); > + } > + free(surface); > + } > + > + igt_subtest("surface_alloc_ref_unref") > + { > + struct vmw_surface *surface; > + struct vmw_surface ref_surface; > + struct vmw_mob readback_mob = { 0 }; > + > + surface = create_and_write_shareable_surface(fd1, surface_size); > + > + ref_surface = vmw_ioctl_surface_ref(fd1, surface->base.handle, > + DRM_VMW_HANDLE_LEGACY); > + > + vmw_ioctl_surface_unref(fd1, surface); > + > + readback_mob.handle = ref_surface.base.handle; > + readback_mob.size = ref_surface.base.buffer_size; > + readback_mob.map_handle = ref_surface.base.buffer_map_handle; > + > + igt_assert(verify_mob_data(fd1, &readback_mob)); > + } > + > + igt_fixture > + { > + close(fd1); > + close(fd2); > + } > +} > -- > 2.38.1 >