[PATCH i-g-t 4/4] tests/intel/xe_sriov_vram: Add test checking VF access to VRAM

Laguna, Lukasz lukasz.laguna at intel.com
Wed Aug 27 13:16:49 UTC 2025


On 8/21/2025 18:53, Bernatowicz, Marcin wrote:
>
>
> On 7/17/2025 11:08 AM, Lukasz Laguna wrote:
>> Add a test to validate VF access to VRAM via BAR. The following
>> scenarios are covered:
>> - VF can access all provisioned memory via the VRAM BAR,
>> - VF cannot access memory beyond what's provisioned via the VRAM BAR,
>> - VF can access memory via the VRAM BAR after reprovisioning.
>>
>> Signed-off-by: Lukasz Laguna <lukasz.laguna at intel.com>
>> ---
>>   tests/intel/xe_sriov_vram.c | 310 ++++++++++++++++++++++++++++++++++++
>>   tests/meson.build           |   1 +
>>   2 files changed, 311 insertions(+)
>>   create mode 100644 tests/intel/xe_sriov_vram.c
>>
>> diff --git a/tests/intel/xe_sriov_vram.c b/tests/intel/xe_sriov_vram.c
>> new file mode 100644
>> index 000000000..82f0a2f09
>> --- /dev/null
>> +++ b/tests/intel/xe_sriov_vram.c
>> @@ -0,0 +1,310 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright(c) 2025 Intel Corporation. All rights reserved.
>> + */
>> +
>> +#include "drmtest.h"
>> +#include "igt_core.h"
>> +#include "igt_sriov_device.h"
>> +#include "intel_vram.h"
>> +#include "xe/xe_sriov_provisioning.h"
>> +#include "xe/xe_query.h"
>> +
>> +/**
>> + * TEST: xe_sriov_vram
>> + * Category: Core
>> + * Mega feature: SR-IOV
>> + * Sub-category: LMTT
>> + * Functionality: VRAM access
>> + * Description: Validate VF access to VRAM
>> + *
>> + * SUBTEST: vf-access-basic
>> + * Description: Verify that VF can access all the provisioned memory 
>> via VRAM BAR
>> + *
>> + * SUBTEST: vf-access-beyond
>> + * Description: Verify that VF cannot access memory beyond what's 
>> provisioned via VRAM BAR
>> + *
>> + * SUBTEST: vf-access-after-resize-down
>> + * Description: Verify that VF can access the reprovisioned memory 
>> (reduced size) via VRAM BAR
>> + *
>> + * SUBTEST: vf-access-after-resize-up
>> + * Description: Verify that VF can access the reprovisioned memory 
>> (increased size) via VRAM BAR
>> + */
>> +
>> +IGT_TEST_DESCRIPTION("Xe tests for VRAM in SR-IOV context");
>> +
>> +const size_t STEP = SZ_1M;
>> +
>> +static uint64_t get_provisioned_vram(unsigned int pf_fd, unsigned 
>> int vf_id)
>> +{
>> +    uint64_t size = 0;
>> +
>> +    /* TODO: adjust for multitile platforms */
>> +    size = xe_sriov_pf_get_provisioned_quota(pf_fd, 
>> XE_SRIOV_SHARED_RES_LMEM, vf_id, 0);
>> +
>> +    return size;
>> +}
>> +
>> +static bool validate_access_basic(struct vram_mapping *vram, 
>> unsigned int vf_id,
>> +                  uint64_t provisioned_lmem)
>> +{
>> +    uint8_t read, orig;
>> +    bool passed = true;
>> +
>> +    for (size_t offset = 0; offset < provisioned_lmem; offset += 
>> STEP) {
>> +        orig = intel_vram_read8(vram, offset);
>> +
>> +        read = intel_vram_write_readback8(vram, offset, vf_id);
>> +        if (read != vf_id) {
>> +            igt_debug("VRAM write/read check failed on VF%u (offset: 
>> %#lx, write: %u, read: %u)\n",
>> +                  vf_id, offset, vf_id, read);
>> +            passed = false;
>
> Do we want to continue after first fail (isn't it too noisy) ?

Yes, information about all offsets was already helpful when debugging 
the issue that was fixed by:

commit 3fae6918a3e27cce20ded2551f863fb05d4bef8d
Author: Michal Wajdeczko <michal.wajdeczko at intel.com>
Date:   Wed Jul 2 00:00:52 2025 +0200

     drm/xe/pf: Clear all LMTT pages on alloc

>
>> +        }
>> +
>> +        read = intel_vram_write_readback8(vram, offset, orig);
>> +        if (read != orig) {
>> +            igt_debug("Failed to restore original value on VF%u 
>> (offset: %#lx, orig: %u, read: %u)\n",
>> +                  vf_id, offset, orig, read);
>> +            passed = false;
>> +        }
>> +    }
>> +
>> +    return passed;
>> +}
>> +
>> +static void access_basic(unsigned int pf_fd, unsigned int num_vfs)
>> +{
>> +    uint64_t provisioned_lmem;
>> +    struct vram_mapping vram;
>> +    size_t vram_bar_size;
>> +    bool passed = true;
>> +
>> +    igt_sriov_disable_driver_autoprobe(pf_fd);
>> +    igt_sriov_enable_vfs(pf_fd, num_vfs);
>> +
>> +    for_each_sriov_enabled_vf(pf_fd, vf_id) {
>> +        provisioned_lmem = get_provisioned_vram(pf_fd, vf_id);
>> +        igt_debug("VF%u provisioned with %" PRIu64 " bytes of VRAM\n",
>> +              vf_id, provisioned_lmem);
>> +
>> +        vram_bar_size = intel_vram_bar_size(pf_fd, vf_id);
>> +        igt_debug("VF%u VRAM BAR size: %" PRIu64 "\n", vf_id, 
>> vram_bar_size);
>> +
>> +        if (vram_bar_size < provisioned_lmem) {
>> +            igt_sriov_disable_vfs(pf_fd);
>> +            igt_skip("VRAM BAR size is smaller than provisioned 
>> VRAM\n");
>> +        }
>> +
>> +        vram = intel_vram_mmap(pf_fd, vf_id, provisioned_lmem, 
>> PROT_READ | PROT_WRITE, 0);
>> +        igt_assert(vram.addr);
>> +
>> +        passed &= validate_access_basic(&vram, vf_id, 
>> provisioned_lmem);
>> +
>> +        intel_vram_munmap(&vram);
>> +    }
>> +
>> +    igt_sriov_disable_vfs(pf_fd);
>> +
>> +    igt_assert(passed);
>> +}
>> +
>> +static bool validate_access_beyond(struct vram_mapping *vram, 
>> unsigned int vf_id,
>> +                   uint64_t provisioned_lmem, size_t vram_bar_size)
>> +{
>> +    uint8_t read, orig;
>> +    bool passed = true;
>> +
>> +    for (size_t offset = provisioned_lmem; offset < vram_bar_size; 
>> offset += STEP) {
>> +        orig = intel_vram_read8(vram, offset);
>> +
>> +        read = intel_vram_write_readback8(vram, offset, vf_id);
>> +        if (read == vf_id) {
>> +            igt_debug("Successful VRAM write above provisioned size 
>> on VF%u (offset: %#lx)\n",
>> +                  vf_id, offset);
>
> Current wording sounds as if the test succeeded, maybe: "Unexpected 
> VRAM write beyond provisioned size ..." or "ERROR: VF%u was able to 
> write beyond provisioned VRAM ..."

That's true. Piotr pointed the same, I'll fix it. Thanks for the 
proposed messages :)

>
>> +            passed = false;
>
> Do we want to continue after first fail ?

Yes, the same case as above. I would prefer to continue. Based on the 
information about offsets to which VF is able to write we can e.g. 
deduce that the problem exists only after VF reprovisioning.

>
>> +
>> +            read = intel_vram_write_readback8(vram, offset, orig);
>> +            if (read != orig)
>> +                igt_debug("Failed to restore original value on VF%u 
>> (offset: %#lx, orig: %u, read: %u)\n",
>> +                      vf_id, offset, orig, read);
>> +        }
>> +    }
>> +
>> +    return passed;
>> +}
>> +
>> +static void access_beyond(unsigned int pf_fd, unsigned int num_vfs)
>> +{
>> +    uint64_t provisioned_lmem;
>> +    struct vram_mapping vram;
>> +    size_t vram_bar_size;
>> +    bool passed = true;
>> +
>> +    igt_sriov_disable_driver_autoprobe(pf_fd);
>> +    igt_sriov_enable_vfs(pf_fd, num_vfs);
>> +
>> +    for_each_sriov_enabled_vf(pf_fd, vf_id) {
>> +        provisioned_lmem = get_provisioned_vram(pf_fd, vf_id);
>> +        igt_debug("VF%u provisioned with %" PRIu64 " bytes of VRAM\n",
>> +              vf_id, provisioned_lmem);
>> +
>> +        vram_bar_size = intel_vram_bar_size(pf_fd, vf_id);
>> +        igt_debug("VF%u VRAM BAR size: %" PRIu64 "\n", vf_id, 
>> vram_bar_size);
>> +
>> +        if (vram_bar_size <= provisioned_lmem) {
>> +            igt_sriov_disable_vfs(pf_fd);
>> +            igt_skip("VRAM BAR size is smaller or equal to 
>> provisioned VRAM\n");
>> +        }
>> +
>> +        vram = intel_vram_mmap(pf_fd, vf_id, vram_bar_size, 
>> PROT_READ | PROT_WRITE, 0);
>> +        igt_assert(vram.addr);
>> +
>> +        passed &= validate_access_beyond(&vram, vf_id, 
>> provisioned_lmem, vram_bar_size);
>> +
>> +        intel_vram_munmap(&vram);
>> +    }
>> +
>> +    igt_sriov_disable_vfs(pf_fd);
>> +
>> +    igt_assert(passed);
>> +}
>> +
>> +static void resize_and_access(unsigned int pf_fd, bool resize_up)
>> +{
>> +    const unsigned int vf_id = 1;
>> +    uint64_t provisioned_lmem;
>> +    struct vram_mapping vram;
>> +    unsigned int total_vfs;
>> +    size_t vram_bar_size;
>> +    bool passed;
>> +
>> +    total_vfs = igt_sriov_get_total_vfs(pf_fd);
>> +
>> +    igt_sriov_disable_driver_autoprobe(pf_fd);
>> +    igt_sriov_enable_vfs(pf_fd, resize_up ? total_vfs : 1);
>> +
>> +    provisioned_lmem = get_provisioned_vram(pf_fd, vf_id);
>> +    igt_debug("VF%u provisioned with %" PRIu64 " bytes of VRAM\n", 
>> vf_id, provisioned_lmem);
>> +
>> +    igt_sriov_disable_vfs(pf_fd);
>> +    igt_sriov_enable_vfs(pf_fd, resize_up ? 1 : total_vfs);
>> +
>> +    provisioned_lmem = get_provisioned_vram(pf_fd, vf_id);
>> +    igt_debug("VF%u provisioned with %" PRIu64 " bytes of VRAM\n", 
>> vf_id, provisioned_lmem);
>> +
>> +    vram_bar_size = intel_vram_bar_size(pf_fd, vf_id);
>> +    igt_debug("VF%u VRAM BAR size: %" PRIu64 "\n", vf_id, 
>> vram_bar_size);
>> +
>> +    if (vram_bar_size <= provisioned_lmem) {
>> +        igt_sriov_disable_vfs(pf_fd);
>> +        igt_skip("VRAM BAR size is smaller or equal to provisioned 
>> VRAM\n");
>> +    }
>> +
>> +    vram = intel_vram_mmap(pf_fd, vf_id, vram_bar_size, PROT_READ | 
>> PROT_WRITE, 0);
>> +    igt_assert(vram.addr);
>> +
>> +    passed = validate_access_basic(&vram, vf_id, provisioned_lmem);
>> +    passed &= validate_access_beyond(&vram, vf_id, provisioned_lmem, 
>> vram_bar_size);
>> +
>> +    intel_vram_munmap(&vram);
>> +
>> +    igt_sriov_disable_vfs(pf_fd);
>> +
>> +    igt_assert(passed);
>> +}
>> +
>> +static bool extended_scope;
>> +
>> +static int opts_handler(int opt, int opt_index, void *data)
>> +{
>> +    switch (opt) {
>> +    case 'e':
>> +        extended_scope = true;
>> +        break;
>> +    default:
>> +        return IGT_OPT_HANDLER_ERROR;
>> +    }
>> +
>> +    return IGT_OPT_HANDLER_SUCCESS;
>> +}
>> +
>> +static const struct option long_opts[] = {
>> +    { .name = "extended", .has_arg = false, .val = 'e', },
>> +    {}
>> +};
>> +
>> +static const char help_str[] =
>> +    "  --extended\tRun the extended test scope\n";
>> +
>> +igt_main_args("", long_opts, help_str, opts_handler, NULL)
>> +{
>> +    bool autoprobe;
>> +    int pf_fd;
>> +    static struct subtest_resize_variants {
>> +        const char *name;
>> +        bool resize_up;
>> +    } resize_variant[] = {
>> +        { "up", true },
>> +        { "down", false },
>> +        { NULL },
>> +    };
>> +
>> +    igt_fixture {
>> +        pf_fd = drm_open_driver(DRIVER_XE);
>> +        igt_require(igt_sriov_is_pf(pf_fd));
>> +        igt_require(igt_sriov_get_enabled_vfs(pf_fd) == 0);
>> +        autoprobe = igt_sriov_is_driver_autoprobe_enabled(pf_fd);
>> +    }
>> +
>> +    igt_describe("Verify that VF can access all the provisioned 
>> memory via VRAM BAR");
>> +    igt_subtest_with_dynamic_f("vf-access-basic") {
>> +        if (extended_scope)
>> +            for_each_sriov_num_vfs(pf_fd, num_vfs)
>> +                igt_dynamic_f("numvfs-%d", num_vfs)
>> +                    access_basic(pf_fd, num_vfs);
>> +
>> +        for_random_sriov_num_vfs(pf_fd, num_vfs) {
>> +            igt_dynamic_f("numvfs-random") {
>> +                igt_debug("numvfs=%u\n", num_vfs);
>> +                access_basic(pf_fd, num_vfs);
>> +            }
>> +        }
>> +    }
>> +
>> +    igt_describe("Verify that VF cannot access memory beyond what's 
>> provisioned via VRAM BAR");
>> +    igt_subtest_with_dynamic_f("vf-access-beyond") {
>> +        if (extended_scope)
>> +            for_each_sriov_num_vfs(pf_fd, num_vfs)
>> +                igt_dynamic_f("numvfs-%d", num_vfs)
>> +                    access_beyond(pf_fd, num_vfs);
>> +
>> +        for_random_sriov_num_vfs(pf_fd, num_vfs) {
>> +            igt_dynamic_f("numvfs-random") {
>> +                igt_debug("numvfs=%u\n", num_vfs);
>> +                access_beyond(pf_fd, num_vfs);
>> +            }
>> +        }
>> +    }
>> +
>> +    for (const struct subtest_resize_variants *s = resize_variant; 
>> s->name; s++) {
>> +        igt_describe("Verify that VF can access the reprovisioned 
>> memory via VRAM BAR");
>> +        igt_subtest_f("vf-access-after-resize-%s", s->name) {
>> +            unsigned int total_vfs = igt_sriov_get_total_vfs(pf_fd);
>> +
>> +            igt_require(total_vfs > 1);
>> +
>> +            resize_and_access(pf_fd, s->resize_up);
>> +        }
>> +    }
>> +
>> +    igt_fixture {
>> +        igt_sriov_disable_vfs(pf_fd);
>> +        /* abort to avoid execution of next tests with enabled VFs */
>> +        igt_abort_on_f(igt_sriov_get_enabled_vfs(pf_fd) > 0, "Failed 
>> to disable VF(s)");
>> +        autoprobe ? igt_sriov_enable_driver_autoprobe(pf_fd) :
>> +                igt_sriov_disable_driver_autoprobe(pf_fd);
>> +        igt_abort_on_f(autoprobe != 
>> igt_sriov_is_driver_autoprobe_enabled(pf_fd),
>> +                   "Failed to restore sriov_drivers_autoprobe 
>> value\n");
>> +        close(pf_fd);
>> +    }
>> +}
>> diff --git a/tests/meson.build b/tests/meson.build
>> index 5c01c64e9..6054a2c34 100644
>> --- a/tests/meson.build
>> +++ b/tests/meson.build
>> @@ -329,6 +329,7 @@ intel_xe_progs = [
>>       'xe_sriov_auto_provisioning',
>>       'xe_sriov_flr',
>>       'xe_sriov_scheduling',
>> +    'xe_sriov_vram',
>>       'xe_sysfs_defaults',
>>       'xe_sysfs_preempt_timeout',
>>       'xe_sysfs_scheduler',
>


More information about the igt-dev mailing list