[PATCH i-g-t 1/3] tests/intel/xe_sriov_mmio_regs: Add tests to verify registers on VFs
Bernatowicz, Marcin
marcin.bernatowicz at linux.intel.com
Wed Sep 11 14:33:04 UTC 2024
Hi,
It appears we do not need to merge this test.
Patch can be ingored.
--
marcin
On 9/4/2024 10:46 AM, Marcin Bernatowicz wrote:
> From: Piotr Piórkowski <piotr.piorkowski at intel.com>
>
> In the case of SR-IOV, the VF has limited access to the registers.
> Add tests to verify that the VF has access only to the allowed list
> of registers and that registers dedicated to VFs are working properly.
>
> Signed-off-by: Piotr Piórkowski <piotr.piorkowski at intel.com>
> Signed-off-by: Marcin Bernatowicz <marcin.bernatowicz at linux.intel.com>
> Cc: Kamil Konieczny <kamil.konieczny at linux.intel.com>
> Cc: Lukasz Laguna <lukasz.laguna at intel.com>
> Cc: Adam Miszczak <adam.miszczak at linux.intel.com>
> Cc: Jakub Kolakowski <jakub1.kolakowski at intel.com>
> Cc: K V P Satyanarayana <satyanarayana.k.v.p at intel.com>
> Cc: C V Narasimha <narasimha.c.v at intel.com>
> ---
> tests/intel/xe_sriov_mmio_regs.c | 310 +++++++++++++++++++++++++++++++
> tests/meson.build | 1 +
> 2 files changed, 311 insertions(+)
> create mode 100644 tests/intel/xe_sriov_mmio_regs.c
>
> diff --git a/tests/intel/xe_sriov_mmio_regs.c b/tests/intel/xe_sriov_mmio_regs.c
> new file mode 100644
> index 000000000..0f16ce09e
> --- /dev/null
> +++ b/tests/intel/xe_sriov_mmio_regs.c
> @@ -0,0 +1,310 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright(c) 2024 Intel Corporation. All rights reserved.
> + */
> +#include "drmtest.h"
> +#include "igt_sriov_device.h"
> +#include "intel_chipset.h"
> +
> +#include "xe/xe_query.h"
> +#include "lib/xe/xe_mmio.h"
> +
> +/**
> + * TEST: xe_sriov_mmio_regs
> + * Category: Core
> + * Mega feature: SR-IOV
> + * Sub-category: MMIO
> + * Functionality: MMIO isolation
> + * Run type: FULL
> + * Description: Checks MMIO isolation
> + *
> + * SUBTEST: vf-cap-reg
> + * Description:
> + * Verify that VF has access to VF capability register
> + *
> + * SUBTEST: vf-scratch-regs
> + * Description:
> + * Verify that VF has RW access to VF scratch registers
> + *
> + * SUBTEST: vf-not-allowed-regs
> + * Description:
> + * Verify that VF does not have access to restricted registers
> + */
> +
> +IGT_TEST_DESCRIPTION("Xe tests for SR-IOV MMIO");
> +
> +/*
> + * Although 8 MB is reserved for the registers, they actually use only
> + * the first 4 MB
> + */
> +#define MMIO_REGS_TILE_SIZE SZ_4M
> +
> +#define VF_CAP_REG 0x1901f8
> +#define MEDIA_VF_CAP_REG 0x19030C
> +#define IS_VF_MASK 0x1
> +
> +#define SOFT_SCRATCH_COUNT 4
> +#define SOFT_SCRATCH(n) (0x190240 + (n) * 4)
> +#define MEDIA_SOFT_SCRATCH(n) (0x190310 + (n) * 4)
> +
> +#define for_each_reg(reg_addr__) \
> + for ((reg_addr__) = 0; \
> + (reg_addr__) < (MMIO_REGS_TILE_SIZE); \
> + (reg_addr__) += 0x4)
> +
> +enum reg_access_type {
> + NO_ACCESS_OR_UNDEFINED = 0,
> + RO,
> + RW,
> +};
> +
> +struct vf_regs_allowlist {
> + uint32_t start;
> + uint32_t end;
> + uint32_t mask;
> + uint32_t expected_mask;
> + enum reg_access_type access_type;
> + bool (*requires)(int pf_fd, int gt);
> +};
> +
> +static const char *stringify_reg_access_type(enum reg_access_type access_type)
> +{
> + switch (access_type) {
> + case NO_ACCESS_OR_UNDEFINED:
> + return "NO ACCESS OR UNDEFINED";
> + case RO:
> + return "RO";
> + case RW:
> + return "RW";
> + default:
> + igt_assert(0);
> + }
> +
> + return "";
> +}
> +
> +static bool has_vf_fence(int pf_fd, int gt)
> +{
> + uint16_t dev_id = intel_get_drm_devid(pf_fd);
> +
> + return (intel_graphics_ver(dev_id) < IP_VER(12, 10));
> +}
> +
> +static bool has_memirq(int pf_fd, int gt)
> +{
> + uint16_t dev_id = intel_get_drm_devid(pf_fd);
> +
> + return (intel_graphics_ver(dev_id) >= IP_VER(12, 50));
> +}
> +
> +static bool no_memirq(int pf_fd, int gt)
> +{
> + return !has_memirq(pf_fd, gt);
> +}
> +
> +static bool has_media_regs(int pf_fd, int gt)
> +{
> + uint16_t dev_id = intel_get_drm_devid(pf_fd);
> +
> + return (intel_graphics_ver(dev_id) >= IP_VER(12, 70));
> +}
> +
> +static enum reg_access_type check_vf_reg_access(int pf_fd, int gt, struct xe_mmio *vf_mmio, u_int32_t reg)
> +{
> + enum reg_access_type access = NO_ACCESS_OR_UNDEFINED;
> + uint32_t orig;
> +
> + orig = xe_mmio_gt_read32(vf_mmio, gt, reg);
> + if (orig != 0 && orig != ~0)
> + access = RO;
> +
> + xe_mmio_gt_write32(vf_mmio, gt, reg, ~orig);
> + if (xe_mmio_gt_read32(vf_mmio, gt, reg) != orig)
> + access = RW;
> +
> + xe_mmio_gt_write32(vf_mmio, gt, reg, orig);
> +
> + return access;
> +}
> +
> +static void vf_check_cap_reg(int pf_fd, unsigned int vf_id, int gt)
> +{
> + struct xe_mmio vf_mmio;
> + enum reg_access_type access_type;
> + uint32_t val;
> +
> + xe_mmio_vf_access_init(pf_fd, vf_id, &vf_mmio);
> +
> + access_type = check_vf_reg_access(pf_fd, gt, &vf_mmio, VF_CAP_REG);
> + val = xe_mmio_gt_read32(&vf_mmio, gt, VF_CAP_REG);
> +
> + xe_mmio_access_fini(&vf_mmio);
> +
> + igt_fail_on_f(access_type != RO, "VF%u capability register should be RO, Detected: %s\n",
> + vf_id, stringify_reg_access_type(access_type));
> + igt_fail_on_f(!(val & IS_VF_MASK), "VF%u capability register should report VF active\n",
> + vf_id);
> +}
> +
> +static void vf_check_scratch_regs(int pf_fd, unsigned int vf_id, int gt)
> +{
> + bool failed = false;
> + struct xe_mmio vf_mmio;
> + uint8_t i;
> +
> + xe_mmio_vf_access_init(pf_fd, vf_id, &vf_mmio);
> +
> + for (i = 0; i < SOFT_SCRATCH_COUNT; i++) {
> + enum reg_access_type access_type = check_vf_reg_access(pf_fd, gt, &vf_mmio, SOFT_SCRATCH(i));
> +
> + if (access_type != RW) {
> + igt_warn("VF%u Soft Scratch %d (%#x) register should be RW. Detected: %s\n",
> + vf_id, i, SOFT_SCRATCH(i), stringify_reg_access_type(access_type));
> + failed = true;
> + }
> + }
> +
> + xe_mmio_access_fini(&vf_mmio);
> +
> + igt_fail_on_f(failed, "At least one of VF%u Soft Scratch register is not RW.\n", vf_id);
> +}
> +
> +/* XXX: Keep sorted */
> +static const struct vf_regs_allowlist allowlist[] = {
> + { .start = 0x100000, .end = 0x10001c, .requires = has_vf_fence },
> + { .start = 0x190010, .end = 0x190010, .requires = no_memirq },
> + { .start = 0x190018, .end = 0x19001C, .requires = no_memirq },
> + { .start = 0x190030, .end = 0x190048, .requires = no_memirq },
> + { .start = 0x190060, .end = 0x190064, .requires = no_memirq },
> + { .start = 0x190070, .end = 0x190074, .requires = no_memirq },
> + { .start = 0x190090, .end = 0x190090, .requires = no_memirq },
> + { .start = 0x1900a0, .end = 0x1900a0, .requires = no_memirq },
> + { .start = 0x1900a8, .end = 0x1900ac, .requires = no_memirq },
> + { .start = 0x1900b0, .end = 0x1900b4, .requires = no_memirq },
> + { .start = 0x1900d0, .end = 0x1900d4, .requires = no_memirq },
> + { .start = 0x1900e8, .end = 0x1900ec, .requires = no_memirq },
> + { .start = 0x1900f0, .end = 0x1900f4, .requires = no_memirq },
> + { .start = 0x190100, .end = 0x190100, .requires = no_memirq },
> + { .start = 0x1901f0, .end = 0x1901f0 },
> + { .start = 0x1901f8, .end = 0x1901f8 },
> + { .start = 0x190240, .end = 0x19024c },
> + { .start = 0x190300, .end = 0x190300 },
> + { .start = 0x190304, .end = 0x190304, .requires = has_media_regs },
> + { .start = 0x19030c, .end = 0x19031c, .requires = has_media_regs },
> +};
> +
> +static int addr_range_cmp(const void *addr, const void *range)
> +{
> + if (*(uint32_t *)addr < ((const struct vf_regs_allowlist *)range)->start)
> + return -1;
> + else if (*(uint32_t *)addr > ((const struct vf_regs_allowlist *)range)->end)
> + return 1;
> + else
> + return 0;
> +}
> +
> +static bool skip_if_on_whitelist(int pf_fd, int gt, u_int32_t reg_addr)
> +{
> + struct vf_regs_allowlist *item;
> +
> + if (reg_addr < allowlist[0].start && reg_addr > allowlist[ARRAY_SIZE(allowlist) - 1].end)
> + return false;
> +
> + item = bsearch(®_addr, &allowlist[0], ARRAY_SIZE(allowlist), sizeof(allowlist[0]),
> + addr_range_cmp);
> + if (item) {
> + if (item->requires)
> + return (item->requires(pf_fd, gt)) ? true : false;
> + else
> + return true;
> + }
> +
> + return false;
> +}
> +
> +static void vf_check_not_allowed_regs(int pf_fd, unsigned int vf_id, int gt)
> +{
> + bool failed = false;
> + struct xe_mmio vf_mmio;
> + u_int32_t reg;
> +
> + xe_mmio_vf_access_init(pf_fd, vf_id, &vf_mmio);
> +
> + for_each_reg(reg) {
> + enum reg_access_type access_type;
> +
> + if (skip_if_on_whitelist(pf_fd, gt, reg))
> + continue;
> +
> + access_type = check_vf_reg_access(pf_fd, gt, &vf_mmio, reg);
> + if (access_type != NO_ACCESS_OR_UNDEFINED) {
> + igt_warn("VF%u register (%#x) shouldn't be %s.\n", vf_id, reg,
> + stringify_reg_access_type(access_type));
> + failed = true;
> + }
> + }
> +
> + xe_mmio_access_fini(&vf_mmio);
> +
> + igt_fail_on_f(failed,
> + "At least one of VF%u register, outside the allowlist, is accessible\n",
> + vf_id);
> +}
> +
> +igt_main
> +{
> + int pf_fd;
> + bool autoprobe;
> + int gt;
> +
> + 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_sriov_disable_driver_autoprobe(pf_fd);
> + igt_srandom();
> +
> + igt_sriov_enable_vfs(pf_fd, igt_sriov_get_total_vfs(pf_fd));
> + }
> +
> + igt_describe("Verify that VF has access to VF capability register");
> + igt_subtest_with_dynamic("vf-cap-reg") {
> + for_each_sriov_vf(pf_fd, vf_id)
> + xe_for_each_gt(pf_fd, gt)
> + igt_dynamic_f("vf%u-gt-%u", vf_id, gt) {
> + vf_check_cap_reg(pf_fd, vf_id, gt);
> + }
> + }
> +
> + igt_describe("Verify that VF has RW access to VF scratch registers");
> + igt_subtest_with_dynamic("vf-scratch-regs") {
> + for_each_sriov_vf(pf_fd, vf_id)
> + xe_for_each_gt(pf_fd, gt)
> + igt_dynamic_f("vf%u-gt-%u", vf_id, gt) {
> + vf_check_scratch_regs(pf_fd, vf_id, gt);
> + }
> + }
> +
> + igt_describe("Verify that VF does not have access to restricted registers");
> + igt_subtest_with_dynamic("vf-not-allowed-regs") {
> + for_each_sriov_vf(pf_fd, vf_id)
> + xe_for_each_gt(pf_fd, gt)
> + igt_dynamic_f("vf%u-gt-%u", vf_id, gt) {
> + vf_check_not_allowed_regs(pf_fd, vf_id, gt);
> + }
> + }
> +
> + 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");
> + drm_close_driver(pf_fd);
> + }
> +}
> diff --git a/tests/meson.build b/tests/meson.build
> index 00556c9d6..d7a8262ce 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -313,6 +313,7 @@ intel_xe_progs = [
> 'xe_vm',
> 'xe_waitfence',
> 'xe_spin_batch',
> + 'xe_sriov_mmio_regs',
> 'xe_sysfs_defaults',
> 'xe_sysfs_preempt_timeout',
> 'xe_sysfs_scheduler',
More information about the igt-dev
mailing list