* [PATCH v2 0/4] Add PCI configuration tests for SR-IOV VFs
@ 2026-09-21 14:37 Piórkowski, Piotr
2026-09-21 14:37 ` [PATCH v2 1/4] lib/igt_pci: Add raw configuration space helpers Piórkowski, Piotr
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Piórkowski, Piotr @ 2026-09-21 14:37 UTC (permalink / raw)
To: igt-dev; +Cc: Piotr Piórkowski
From: Piotr Piórkowski <piotr.piorkowski@intel.com>
This series introduces PCI configuration space tests for SR-IOV Virtual Functions.
It verifies the required values and read-only fields in the common PCI header, BARs,
PCI Express capabilities, and optional Power Management, AER, and ATS capabilities.
The series also adds the PCI helpers needed to read raw configuration space and find
standard and extended capabilities.
v1 -> v2:
- Dropped the unused find_pci_ext_cap_offset() helper.
- Registered sriov_pci_config in tests/meson.build.
- Enabled the VF and read its configuration space once in the fixture
instead of repeating the setup for every subtest.
- Restored the driver autoprobe state and disabled the VF in the final
fixture.
- Removed redundant informational messages.
- Simplified subtest descriptions while retaining detailed documentation.
- Corrected PCI register macro names for compatibility with pci_regs.h.
- Improved malformed conventional and extended capability chain handling.
- Added unit tests for valid, invalid, cyclic, and boundary capability
chains.
- Added sriov_pci_config to the Xe CI blocklist as a separate patch,
since it is intended for HW verification rather than recurring CI runs.
Piotr Piórkowski (4):
lib/igt_pci: Add raw configuration space helpers
tests/sriov_pci_config: Add VF core config checks
tests/sriov_pci_config: Add optional capability checks
intel-ci: Block igt@sriov_pci_config.*
lib/igt_pci.c | 90 +++++++++
lib/igt_pci.h | 8 +-
lib/tests/igt_pci.c | 66 +++++++
lib/tests/meson.build | 1 +
tests/intel-ci/xe.blocklist.txt | 1 +
tests/meson.build | 1 +
tests/sriov_pci_config.c | 320 ++++++++++++++++++++++++++++++++
7 files changed, 486 insertions(+), 1 deletion(-)
create mode 100644 lib/tests/igt_pci.c
create mode 100644 tests/sriov_pci_config.c
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 1/4] lib/igt_pci: Add raw configuration space helpers
2026-09-21 14:37 [PATCH v2 0/4] Add PCI configuration tests for SR-IOV VFs Piórkowski, Piotr
@ 2026-09-21 14:37 ` Piórkowski, Piotr
2026-09-22 11:00 ` Bernatowicz, Marcin
2026-09-21 14:37 ` [PATCH v2 2/4] tests/sriov_pci_config: Add VF core config checks Piórkowski, Piotr
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Piórkowski, Piotr @ 2026-09-21 14:37 UTC (permalink / raw)
To: igt-dev; +Cc: Piotr Piórkowski
From: Piotr Piórkowski <piotr.piorkowski@intel.com>
Add helpers to read raw PCI configuration space from sysfs and access
its contents.
Provide little-endian u16/u32 readers and standard and extended
capability lookup helpers for configuration-space buffers.
v2:
- Validate malformed and cyclic capability chains.
- Add unit tests for capability lookup and malformed chains.
Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
Assisted-by: GPT-5.6 Luna
---
lib/igt_pci.c | 90 +++++++++++++++++++++++++++++++++++++++++++
lib/igt_pci.h | 8 +++-
lib/tests/igt_pci.c | 66 +++++++++++++++++++++++++++++++
lib/tests/meson.build | 1 +
4 files changed, 164 insertions(+), 1 deletion(-)
create mode 100644 lib/tests/igt_pci.c
diff --git a/lib/igt_pci.c b/lib/igt_pci.c
index b63550b390..7cc9f2dfd6 100644
--- a/lib/igt_pci.c
+++ b/lib/igt_pci.c
@@ -8,6 +8,7 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
+#include <linux/pci_regs.h>
#include <string.h>
#include <unistd.h>
#include <pciaccess.h>
@@ -61,6 +62,95 @@ int find_pci_cap_offset(struct pci_device *dev, enum pci_cap_id cap_id)
return find_pci_cap_offset_at(dev, cap_id, PCI_CAPS_START);
}
+/**
+ * igt_pci_config_raw_read:
+ * @pci_slot: PCI device BDF (e.g. "0000:01:00.0")
+ * @buffer: destination buffer
+ * @length: number of configuration-space bytes to read
+ *
+ * Read raw PCI configuration space through the device sysfs config attribute.
+ *
+ * Returns 0 on success, otherwise a negative errno-like value.
+ */
+int igt_pci_config_raw_read(const char *pci_slot, void *buffer, size_t length)
+{
+ char path[PATH_MAX];
+ ssize_t ret;
+ int err;
+ int fd;
+
+ if (!pci_slot || !buffer || !length)
+ return -EINVAL;
+
+ snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/config", pci_slot);
+ fd = open(path, O_RDONLY | O_CLOEXEC);
+ if (fd < 0)
+ return -errno;
+
+ ret = pread(fd, buffer, length, 0);
+ err = errno;
+ close(fd);
+ if (ret < 0)
+ return -err;
+
+ return (size_t)ret == length ? 0 : -EIO;
+}
+
+uint16_t igt_pci_config_raw_read_u16(const uint8_t *config, unsigned int offset)
+{
+ return config[offset] | (config[offset + 1] << 8);
+}
+
+uint32_t igt_pci_config_raw_read_u32(const uint8_t *config, unsigned int offset)
+{
+ return igt_pci_config_raw_read_u16(config, offset) |
+ ((uint32_t)igt_pci_config_raw_read_u16(config, offset + 2) << 16);
+}
+
+int igt_pci_config_raw_find_cap_offset(const uint8_t *config, uint8_t cap_id)
+{
+ unsigned int offset = config[PCI_CAPS_START];
+ unsigned int loop = (PCI_CFG_SPACE_SIZE - PCI_TYPE0_1_HEADER_SIZE) / 2;
+
+ while (offset && loop--) {
+ if (offset < PCI_TYPE0_1_HEADER_SIZE ||
+ offset > PCI_CFG_SPACE_SIZE - 2 || offset & 3)
+ return -EINVAL;
+
+ if (config[offset] == cap_id)
+ return offset;
+
+ offset = config[offset + 1];
+ }
+
+ return offset ? -ELOOP : 0;
+}
+
+int igt_pci_config_raw_find_ext_cap_offset(const uint8_t *config, uint16_t cap_id)
+{
+ unsigned int offset = PCI_EXT_CAPS_START;
+ unsigned int loop = (PCI_EXT_CFG_SPACE_SIZE - offset) / 4;
+
+ while (loop) {
+ uint32_t header = igt_pci_config_raw_read_u32(config, offset);
+
+ loop--;
+
+ if (!header)
+ return 0;
+ if ((header & 0xffff) == cap_id)
+ return offset;
+
+ offset = (header >> 20) & 0xffc;
+ if (!offset)
+ return 0;
+ if (offset < PCI_EXT_CAPS_START || offset >= PCI_EXT_CFG_SPACE_SIZE)
+ return -EINVAL;
+ }
+
+ return -ELOOP;
+}
+
static int open_pci_driver_dir(const char *driver)
{
char path[PATH_MAX];
diff --git a/lib/igt_pci.h b/lib/igt_pci.h
index 509345b2d8..628cc24766 100644
--- a/lib/igt_pci.h
+++ b/lib/igt_pci.h
@@ -15,7 +15,8 @@ struct pci_device;
#define PCI_TYPE0_1_HEADER_SIZE 0x40
#define PCI_CAPS_START 0x34
-#define PCI_CFG_SPACE_SIZE 0x100
+#define PCI_EXT_CAPS_START 0x100
+#define PCI_EXT_CFG_SPACE_SIZE 0x1000
enum pci_cap_id {
PCI_EXPRESS_CAP_ID = 0x10
@@ -27,6 +28,11 @@ enum pci_cap_id {
#define PCI_SLOT_PWR_CTRL_PRESENT (1 << 1)
int find_pci_cap_offset(struct pci_device *dev, enum pci_cap_id cap_id);
+int igt_pci_config_raw_read(const char *pci_slot, void *buffer, size_t length);
+uint16_t igt_pci_config_raw_read_u16(const uint8_t *config, unsigned int offset);
+uint32_t igt_pci_config_raw_read_u32(const uint8_t *config, unsigned int offset);
+int igt_pci_config_raw_find_cap_offset(const uint8_t *config, uint8_t cap_id);
+int igt_pci_config_raw_find_ext_cap_offset(const uint8_t *config, uint16_t cap_id);
int igt_pci_device_unbind(const char *pci_slot);
int igt_pci_driver_bind(const char *driver, const char *pci_slot);
int igt_pci_driver_unbind(const char *driver, const char *pci_slot);
diff --git a/lib/tests/igt_pci.c b/lib/tests/igt_pci.c
new file mode 100644
index 0000000000..191edb95c5
--- /dev/null
+++ b/lib/tests/igt_pci.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#include <errno.h>
+#include <linux/pci_regs.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "igt_core.h"
+#include "igt_pci.h"
+
+static void write_u32(uint8_t *config, unsigned int offset, uint32_t value)
+{
+ config[offset] = value;
+ config[offset + 1] = value >> 8;
+ config[offset + 2] = value >> 16;
+ config[offset + 3] = value >> 24;
+}
+
+static void test_cap(void)
+{
+ uint8_t config[PCI_CFG_SPACE_SIZE] = {};
+
+ config[PCI_CAPS_START] = PCI_TYPE0_1_HEADER_SIZE;
+ config[PCI_TYPE0_1_HEADER_SIZE] = 0xaa;
+ igt_assert_eq(igt_pci_config_raw_find_cap_offset(config, 0xaa),
+ PCI_TYPE0_1_HEADER_SIZE);
+
+ config[PCI_CAPS_START] = 0xff;
+ igt_assert_eq(igt_pci_config_raw_find_cap_offset(config, 0xaa), -EINVAL);
+
+ config[PCI_CAPS_START] = PCI_TYPE0_1_HEADER_SIZE;
+ config[PCI_TYPE0_1_HEADER_SIZE] = 0xbb;
+ config[PCI_TYPE0_1_HEADER_SIZE + 1] = PCI_TYPE0_1_HEADER_SIZE;
+ igt_assert_eq(igt_pci_config_raw_find_cap_offset(config, 0xaa), -ELOOP);
+}
+
+static void test_ext_cap(void)
+{
+ uint8_t config[PCI_EXT_CFG_SPACE_SIZE] = {};
+ unsigned int offset;
+
+ write_u32(config, PCI_EXT_CAPS_START, 0xaa);
+ igt_assert_eq(igt_pci_config_raw_find_ext_cap_offset(config, 0xaa),
+ PCI_EXT_CAPS_START);
+
+ write_u32(config, PCI_EXT_CAPS_START,
+ 0xbb | (PCI_EXT_CAPS_START << 20));
+ igt_assert_eq(igt_pci_config_raw_find_ext_cap_offset(config, 0xaa), -ELOOP);
+
+ memset(config, 0, sizeof(config));
+ for (offset = PCI_EXT_CAPS_START;
+ offset < PCI_EXT_CFG_SPACE_SIZE - sizeof(uint32_t);
+ offset += sizeof(uint32_t))
+ write_u32(config, offset, 0xbb | ((offset + sizeof(uint32_t)) << 20));
+
+ igt_assert_eq(igt_pci_config_raw_find_ext_cap_offset(config, 0xaa), 0);
+}
+
+int igt_simple_main()
+{
+ test_cap();
+ test_ext_cap();
+}
\ No newline at end of file
diff --git a/lib/tests/meson.build b/lib/tests/meson.build
index f1db66d07c..0a7c903f16 100644
--- a/lib/tests/meson.build
+++ b/lib/tests/meson.build
@@ -19,6 +19,7 @@ lib_tests = [
'igt_invalid_subtest_name',
'igt_nesting',
'igt_no_exit',
+ 'igt_pci',
'igt_runnercomms_packets',
'igt_segfault',
'igt_simulation',
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 2/4] tests/sriov_pci_config: Add VF core config checks
2026-09-21 14:37 [PATCH v2 0/4] Add PCI configuration tests for SR-IOV VFs Piórkowski, Piotr
2026-09-21 14:37 ` [PATCH v2 1/4] lib/igt_pci: Add raw configuration space helpers Piórkowski, Piotr
@ 2026-09-21 14:37 ` Piórkowski, Piotr
2026-09-28 12:46 ` [v2,2/4] " Laguna, Lukasz
2026-09-21 14:37 ` [PATCH v2 3/4] tests/sriov_pci_config: Add optional capability checks Piórkowski, Piotr
2026-09-21 14:37 ` [PATCH v2 4/4] intel-ci: Block igt@sriov_pci_config.* Piórkowski, Piotr
3 siblings, 1 reply; 9+ messages in thread
From: Piórkowski, Piotr @ 2026-09-21 14:37 UTC (permalink / raw)
To: igt-dev; +Cc: Piotr Piórkowski
From: Piotr Piórkowski <piotr.piorkowski@intel.com>
Add checks for PCI configuration fields required by SR-IOV VFs.
Cover the common header, BARs, and PCI Express capability fields.
v2:
- Enable the VF and read its configuration once in the fixture.
- Restore driver autoprobe state and disable the VF during cleanup.
- Clarify test documentation and shorten runtime descriptions.
- Remove redundant informational messages.
Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
Assisted-by: GPT-5.6 Luna
---
tests/meson.build | 1 +
tests/sriov_pci_config.c | 210 +++++++++++++++++++++++++++++++++++++++
2 files changed, 211 insertions(+)
create mode 100644 tests/sriov_pci_config.c
diff --git a/tests/meson.build b/tests/meson.build
index bee2b94224..51c84c99f0 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -74,6 +74,7 @@ test_progs = [
'meta_test',
'prime_vgem',
'sriov_basic',
+ 'sriov_pci_config',
'syncobj_basic',
'syncobj_eventfd',
'syncobj_wait',
diff --git a/tests/sriov_pci_config.c b/tests/sriov_pci_config.c
new file mode 100644
index 0000000000..9f410ef23a
--- /dev/null
+++ b/tests/sriov_pci_config.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright(c) 2026 Intel Corporation. All rights reserved.
+ */
+
+#include <linux/pci_regs.h>
+
+#include "drmtest.h"
+#include "igt.h"
+#include "igt_pci.h"
+#include "igt_sriov_device.h"
+
+#define VF_PCI_EXP_DEVSTA_EPRD (1 << 6)
+#define VF_PCI_EXP_LNKSTA2_DEEMPHASIS (1 << 0)
+
+/**
+ * TEST: SR-IOV PCI configuration
+ * Category: Core
+ * Mega feature: SR-IOV
+ * Sub-category: PCI configuration
+ * Functionality: SR-IOV-related PCI configuration space
+ * Description: Validate PCI configuration fields required for SR-IOV,
+ * including Virtual Functions.
+ *
+ * SUBTEST: vf-common-header
+ * Description: Validate that the VF Vendor ID and Device ID read as 0xffff,
+ * and that the I/O, Memory, and INTx Disable bits in Command, the Immediate
+ * Readiness and Interrupt Status bits in Status, the Header Layout bits in
+ * Header Type, and the BIST Completion Code are all zero.
+ *
+ * SUBTEST: vf-bars
+ * Description: Validate that VF BAR address bits read as zero. The BAR type
+ * and attribute bits are static and may remain set; the upper dword of a
+ * 64-bit BAR must read as zero.
+ *
+ * SUBTEST: vf-pcie-capabilities
+ * Description: Validate that FLR is supported, and Phantom Functions Supported,
+ * Auxiliary Power Detected, Emergency Power Reduction Detected, Current Link
+ * Speed, Negotiated Link Width, and Link Autonomous Bandwidth Status are all
+ * zero.
+ *
+ * SUBTEST: vf-pcie-capabilities-2
+ * Description: Validate that the Current De-emphasis Level field in Link
+ * Status 2 is RsvdZ and therefore reads as zero for PCIe Capability Version 2
+ * and later.
+ */
+
+IGT_TEST_DESCRIPTION("Validate PCI configuration fields required for SR-IOV, "
+ "including Virtual Functions");
+
+static int pf_fd = -1;
+static bool autoprobe;
+static uint8_t vf_config[PCI_EXT_CFG_SPACE_SIZE];
+
+static void read_vf_config(uint8_t *config)
+{
+ char *vf_slot;
+ int ret;
+
+ vf_slot = igt_sriov_get_vf_pci_slot_alloc(pf_fd, 1);
+ igt_assert(vf_slot);
+ ret = igt_pci_config_raw_read(vf_slot, config, PCI_EXT_CFG_SPACE_SIZE);
+ free(vf_slot);
+ igt_assert_f(!ret, "Failed to read VF config space (%d)\n", ret);
+}
+
+static void check_vf_common_header(const uint8_t *config)
+{
+ uint16_t command = igt_pci_config_raw_read_u16(config, PCI_COMMAND);
+ uint16_t status = igt_pci_config_raw_read_u16(config, PCI_STATUS);
+ uint16_t vendor_id = igt_pci_config_raw_read_u16(config, PCI_VENDOR_ID);
+ uint16_t device_id = igt_pci_config_raw_read_u16(config, PCI_DEVICE_ID);
+
+ igt_assert_f(vendor_id == 0xffff, "Vendor ID: expected 0xffff, got 0x%04x\n", vendor_id);
+ igt_assert_f(device_id == 0xffff, "Device ID: expected 0xffff, got 0x%04x\n", device_id);
+ igt_assert_f(!(command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_INTX_DISABLE)),
+ "Command: expected I/O, Memory, and INTx Disable bits clear, got 0x%04x\n",
+ command);
+ igt_assert_f(!(status & (PCI_STATUS_IMM_READY | PCI_STATUS_INTERRUPT)),
+ "Status: expected Immediate Readiness and Interrupt Status bits clear, got 0x%04x\n",
+ status);
+ igt_assert_f(!(config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MASK),
+ "Header Type: expected Header Layout 0, got 0x%02x\n",
+ config[PCI_HEADER_TYPE]);
+ igt_assert_f(!(config[PCI_BIST] & PCI_BIST_CODE_MASK),
+ "BIST: expected Completion Code 0, got 0x%02x\n", config[PCI_BIST]);
+}
+
+static void check_vf_bars(const uint8_t *config)
+{
+ for (int bar = 0; bar < 6; bar++) {
+ uint32_t value =
+ igt_pci_config_raw_read_u32(config,
+ PCI_BASE_ADDRESS_0 + bar * sizeof(uint32_t));
+ bool is_mem64 = !(value & PCI_BASE_ADDRESS_SPACE) &&
+ (value & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+ PCI_BASE_ADDRESS_MEM_TYPE_64;
+
+ /* Only the address bits are hardwired to zero; type/attribute bits are static. */
+ igt_assert_f(!(value & ~0xfu), "BAR%d: expected address 0x00000000, got 0x%08x\n",
+ bar, value);
+
+ /* The upper dword of a 64-bit BAR holds pure address bits, no type bits. */
+ if (is_mem64) {
+ unsigned int upper_offset = PCI_BASE_ADDRESS_0 +
+ (bar + 1) * sizeof(uint32_t);
+ uint32_t upper =
+ igt_pci_config_raw_read_u32(config, upper_offset);
+
+ igt_assert_f(!upper, "BAR%d (upper): expected 0x00000000, got 0x%08x\n",
+ bar + 1, upper);
+ bar++;
+ }
+ }
+}
+
+static int get_pcie_cap(const uint8_t *config)
+{
+ int pcie_cap = igt_pci_config_raw_find_cap_offset(config, PCI_CAP_ID_EXP);
+
+ igt_assert_f(pcie_cap > 0, "VF has no PCI Express capability (%d)\n", pcie_cap);
+
+ return pcie_cap;
+}
+
+static void check_vf_pcie_capabilities(const uint8_t *config)
+{
+ int pcie_cap = get_pcie_cap(config);
+ uint32_t pcie_devcap = igt_pci_config_raw_read_u32(config, pcie_cap + PCI_EXP_DEVCAP);
+ uint16_t pcie_devsta = igt_pci_config_raw_read_u16(config, pcie_cap + PCI_EXP_DEVSTA);
+ uint16_t pcie_lnksta = igt_pci_config_raw_read_u16(config, pcie_cap + PCI_EXP_LNKSTA);
+
+ igt_assert_f(pcie_devcap & PCI_EXP_DEVCAP_FLR,
+ "Device Capabilities: FLR bit is clear (0x%08x)\n", pcie_devcap);
+ igt_assert_f(!(pcie_devcap & PCI_EXP_DEVCAP_PHANTOM),
+ "Device Capabilities: Phantom Functions Supported must be zero (0x%08x)\n",
+ pcie_devcap);
+ igt_assert_f(!(pcie_devsta & (PCI_EXP_DEVSTA_AUXPD |
+ VF_PCI_EXP_DEVSTA_EPRD)),
+ "Device Status: Aux Power Detected or Emergency Power Reduction Detected is set (0x%04x)\n",
+ pcie_devsta);
+ igt_assert_f(!(pcie_lnksta & (PCI_EXP_LNKSTA_CLS | PCI_EXP_LNKSTA_NLW |
+ PCI_EXP_LNKSTA_LABS)),
+ "Link Status: Current Link Speed, Negotiated Link Width, or Link Autonomous Bandwidth Status is set (0x%04x)\n",
+ pcie_lnksta);
+}
+
+static void check_vf_pcie_capabilities_2(const uint8_t *config)
+{
+ int pcie_cap = get_pcie_cap(config);
+ uint16_t flags = igt_pci_config_raw_read_u16(config, pcie_cap + PCI_EXP_FLAGS);
+ uint16_t lnksta2;
+
+ if ((flags & PCI_EXP_FLAGS_VERS) < 2)
+ igt_skip("PCI Express Capability Version 2 is not present\n");
+
+ lnksta2 = igt_pci_config_raw_read_u16(config, pcie_cap + PCI_EXP_LNKSTA2);
+ igt_assert_f(!(lnksta2 & VF_PCI_EXP_LNKSTA2_DEEMPHASIS),
+ "Link Status 2: Current De-emphasis Level must be zero (0x%04x)\n",
+ lnksta2);
+}
+
+int igt_main()
+{
+ igt_fixture() {
+ pf_fd = drm_open_driver(DRIVER_ANY);
+ igt_require(igt_sriov_is_pf(pf_fd));
+ igt_require(igt_sriov_vfs_supported(pf_fd));
+ igt_require(igt_sriov_get_enabled_vfs(pf_fd) == 0);
+ autoprobe = igt_sriov_is_driver_autoprobe_enabled(pf_fd);
+ igt_sriov_install_exit_handler(pf_fd, NULL, NULL);
+ igt_sriov_disable_driver_autoprobe(pf_fd);
+ igt_sriov_enable_vfs(pf_fd, 1);
+ igt_require_f(!igt_pci_system_reinit(), "Failed to refresh PCI state\n");
+ read_vf_config(vf_config);
+ }
+
+ igt_describe("Validate the VF PCI common header");
+ igt_subtest("vf-common-header") {
+ check_vf_common_header(vf_config);
+ }
+
+ igt_describe("Validate the VF BARs");
+ igt_subtest("vf-bars") {
+ check_vf_bars(vf_config);
+ }
+
+ igt_describe("Validate the VF PCI Express capability");
+ igt_subtest("vf-pcie-capabilities") {
+ check_vf_pcie_capabilities(vf_config);
+ }
+
+ igt_describe("Validate the VF PCI Express Capability Version 2 fields");
+ igt_subtest("vf-pcie-capabilities-2") {
+ check_vf_pcie_capabilities_2(vf_config);
+ }
+ igt_fixture() {
+ igt_abort_on_f(pf_fd < 0, "Device is not accessible\n");
+ igt_sriov_disable_vfs(pf_fd);
+ igt_abort_on_f(igt_sriov_get_enabled_vfs(pf_fd) > 0,
+ "Failed to disable VF(s)\n");
+ 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");
+ igt_sriov_clear_exit_handler();
+ close(pf_fd);
+ }
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 3/4] tests/sriov_pci_config: Add optional capability checks
2026-09-21 14:37 [PATCH v2 0/4] Add PCI configuration tests for SR-IOV VFs Piórkowski, Piotr
2026-09-21 14:37 ` [PATCH v2 1/4] lib/igt_pci: Add raw configuration space helpers Piórkowski, Piotr
2026-09-21 14:37 ` [PATCH v2 2/4] tests/sriov_pci_config: Add VF core config checks Piórkowski, Piotr
@ 2026-09-21 14:37 ` Piórkowski, Piotr
2026-09-28 12:49 ` [v2,3/4] " Laguna, Lukasz
2026-09-21 14:37 ` [PATCH v2 4/4] intel-ci: Block igt@sriov_pci_config.* Piórkowski, Piotr
3 siblings, 1 reply; 9+ messages in thread
From: Piórkowski, Piotr @ 2026-09-21 14:37 UTC (permalink / raw)
To: igt-dev; +Cc: Piotr Piórkowski
From: Piotr Piórkowski <piotr.piorkowski@intel.com>
Add subtests for the optional Power Management, Advanced Error
Reporting, and Address Translation Service capabilities.
Skip an optional-capability subtest when the capability is not exposed
by the VF.
Validate the VF ROZ fields required by the SR-IOV specification,
including Power Management Data Select/Data, AER status/mask/severity
fields, and ATS Queue Depth/STU.
v2:
- Reuse the VF configuration captured by the common fixture.
- Use PCI register definitions available from linux/pci_regs.h.
- Simplify optional-capability skips and runtime descriptions.
- Remove redundant informational messages.
Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
Assisted-by: GPT-5.6 Luna
---
tests/sriov_pci_config.c | 110 +++++++++++++++++++++++++++++++++++++++
1 file changed, 110 insertions(+)
diff --git a/tests/sriov_pci_config.c b/tests/sriov_pci_config.c
index 9f410ef23a..a3d7e86b58 100644
--- a/tests/sriov_pci_config.c
+++ b/tests/sriov_pci_config.c
@@ -43,6 +43,21 @@
* Description: Validate that the Current De-emphasis Level field in Link
* Status 2 is RsvdZ and therefore reads as zero for PCIe Capability Version 2
* and later.
+ *
+ * SUBTEST: vf-power-management-capability
+ * Description: Validate that Data Select in Power Management Control and
+ * Power Management Data are ROZ and therefore read as zero when the optional
+ * Power Management capability is present.
+ *
+ * SUBTEST: vf-advanced-error-reporting
+ * Description: Validate that the specified ROZ bits in AER Uncorrectable
+ * Error Status, Mask, and Severity, and Correctable Error Status read as zero
+ * when the optional AER capability is present.
+ *
+ * SUBTEST: vf-ats-capability
+ * Description: Validate that ATS Queue Depth and the Smallest Translation Unit
+ * (STU) are ROZ and therefore read as zero when the optional ATS capability
+ * is present.
*/
IGT_TEST_DESCRIPTION("Validate PCI configuration fields required for SR-IOV, "
@@ -161,6 +176,85 @@ static void check_vf_pcie_capabilities_2(const uint8_t *config)
lnksta2);
}
+static int get_optional_cap(const uint8_t *config, uint8_t cap_id, const char *name)
+{
+ int cap = igt_pci_config_raw_find_cap_offset(config, cap_id);
+
+ igt_assert_f(cap >= 0, "Invalid VF PCI capability list (%d)\n", cap);
+ if (!cap)
+ igt_skip("%s\n", name);
+
+ return cap;
+}
+
+static int get_optional_ext_cap(const uint8_t *config, uint16_t cap_id, const char *name)
+{
+ int cap = igt_pci_config_raw_find_ext_cap_offset(config, cap_id);
+
+ igt_assert_f(cap >= 0, "Invalid VF extended capability list (%d)\n", cap);
+ if (!cap)
+ igt_skip("%s\n", name);
+
+ return cap;
+}
+
+static void check_vf_power_management_capability(const uint8_t *config)
+{
+ int pm_cap = get_optional_cap(config, PCI_CAP_ID_PM,
+ "Power Management capability is not present");
+ uint16_t pm_ctrl = igt_pci_config_raw_read_u16(config, pm_cap + PCI_PM_CTRL);
+ uint8_t pm_data = config[pm_cap + PCI_PM_DATA_REGISTER];
+
+ igt_assert_f(!(pm_ctrl & PCI_PM_CTRL_DATA_SEL_MASK),
+ "Power Management Control: Data Select must be zero (0x%04x)\n", pm_ctrl);
+ igt_assert_f(!pm_data, "Power Management Data: expected 0x00, got 0x%02x\n", pm_data);
+}
+
+static void check_vf_advanced_error_reporting(const uint8_t *config)
+{
+ const uint32_t uncor_roz = PCI_ERR_UNC_DLP | PCI_ERR_UNC_SURPDN |
+ PCI_ERR_UNC_FCP | PCI_ERR_UNC_RX_OVER |
+ PCI_ERR_UNC_MALF_TLP | PCI_ERR_UNC_ECRC;
+ const uint32_t cor_roz = PCI_ERR_COR_RCVR | PCI_ERR_COR_BAD_TLP |
+ PCI_ERR_COR_REP_ROLL | PCI_ERR_COR_REP_TIMER;
+ int aer_cap = get_optional_ext_cap(config, PCI_EXT_CAP_ID_ERR,
+ "Advanced Error Reporting capability is not present");
+ uint32_t uncor_status = igt_pci_config_raw_read_u32(config,
+ aer_cap + PCI_ERR_UNCOR_STATUS);
+ uint32_t uncor_mask = igt_pci_config_raw_read_u32(config,
+ aer_cap + PCI_ERR_UNCOR_MASK);
+ uint32_t uncor_severity = igt_pci_config_raw_read_u32(config,
+ aer_cap + PCI_ERR_UNCOR_SEVER);
+ uint32_t cor_status = igt_pci_config_raw_read_u32(config,
+ aer_cap + PCI_ERR_COR_STATUS);
+
+ igt_assert_f(!(uncor_status & uncor_roz),
+ "AER Uncorrectable Error Status: VF ROZ bits are set (0x%08x)\n",
+ uncor_status);
+ igt_assert_f(!(uncor_mask & uncor_roz),
+ "AER Uncorrectable Error Mask: VF ROZ bits are set (0x%08x)\n",
+ uncor_mask);
+ igt_assert_f(!(uncor_severity & uncor_roz),
+ "AER Uncorrectable Error Severity: VF ROZ bits are set (0x%08x)\n",
+ uncor_severity);
+ igt_assert_f(!(cor_status & cor_roz),
+ "AER Correctable Error Status: VF ROZ bits are set (0x%08x)\n",
+ cor_status);
+}
+
+static void check_vf_ats_capability(const uint8_t *config)
+{
+ int ats_cap = get_optional_ext_cap(config, PCI_EXT_CAP_ID_ATS,
+ "ATS capability is not present");
+ uint16_t ats_capability = igt_pci_config_raw_read_u16(config, ats_cap + PCI_ATS_CAP);
+ uint16_t ats_control = igt_pci_config_raw_read_u16(config, ats_cap + PCI_ATS_CTRL);
+
+ igt_assert_f(!PCI_ATS_CAP_QDEP(ats_capability),
+ "ATS Capability: Queue Depth must be zero (0x%04x)\n", ats_capability);
+ igt_assert_f(!PCI_ATS_CTRL_STU(ats_control),
+ "ATS Control: STU must be zero (0x%04x)\n", ats_control);
+}
+
int igt_main()
{
igt_fixture() {
@@ -195,6 +289,22 @@ int igt_main()
igt_subtest("vf-pcie-capabilities-2") {
check_vf_pcie_capabilities_2(vf_config);
}
+
+ igt_describe("Validate the optional VF Power Management capability");
+ igt_subtest("vf-power-management-capability") {
+ check_vf_power_management_capability(vf_config);
+ }
+
+ igt_describe("Validate the optional VF AER capability");
+ igt_subtest("vf-advanced-error-reporting") {
+ check_vf_advanced_error_reporting(vf_config);
+ }
+
+ igt_describe("Validate the optional VF ATS capability");
+ igt_subtest("vf-ats-capability") {
+ check_vf_ats_capability(vf_config);
+ }
+
igt_fixture() {
igt_abort_on_f(pf_fd < 0, "Device is not accessible\n");
igt_sriov_disable_vfs(pf_fd);
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 4/4] intel-ci: Block igt@sriov_pci_config.*
2026-09-21 14:37 [PATCH v2 0/4] Add PCI configuration tests for SR-IOV VFs Piórkowski, Piotr
` (2 preceding siblings ...)
2026-09-21 14:37 ` [PATCH v2 3/4] tests/sriov_pci_config: Add optional capability checks Piórkowski, Piotr
@ 2026-09-21 14:37 ` Piórkowski, Piotr
2026-09-28 12:50 ` [v2,4/4] " Laguna, Lukasz
3 siblings, 1 reply; 9+ messages in thread
From: Piórkowski, Piotr @ 2026-09-21 14:37 UTC (permalink / raw)
To: igt-dev; +Cc: Piotr Piórkowski
From: Piotr Piórkowski <piotr.piorkowski@intel.com>
This test is intended for HW verification and does not need to run in
recurring CI runs.
Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
Assisted-by: GPT-5.6 Luna
---
tests/intel-ci/xe.blocklist.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/intel-ci/xe.blocklist.txt b/tests/intel-ci/xe.blocklist.txt
index 0f68df95d5..0a7e63c5ec 100644
--- a/tests/intel-ci/xe.blocklist.txt
+++ b/tests/intel-ci/xe.blocklist.txt
@@ -116,6 +116,7 @@ igt@sriov_basic@bind-unbind-vf$
##################################################################
# SR-IOV tests for HW checkout, not suited for recurring CI runs
##################################################################
+igt@sriov_pci_config.*
igt@xe_sriov_ggtt.*
##################################################################
# Chamelium V1 HDMI receiver supports a maximum resolution
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/4] lib/igt_pci: Add raw configuration space helpers
2026-09-21 14:37 ` [PATCH v2 1/4] lib/igt_pci: Add raw configuration space helpers Piórkowski, Piotr
@ 2026-09-22 11:00 ` Bernatowicz, Marcin
0 siblings, 0 replies; 9+ messages in thread
From: Bernatowicz, Marcin @ 2026-09-22 11:00 UTC (permalink / raw)
To: Piórkowski, Piotr, igt-dev
On 9/21/2026 4:37 PM, Piórkowski, Piotr wrote:
> From: Piotr Piórkowski <piotr.piorkowski@intel.com>
>
> Add helpers to read raw PCI configuration space from sysfs and access
> its contents.
> Provide little-endian u16/u32 readers and standard and extended
> capability lookup helpers for configuration-space buffers.
>
> v2:
> - Validate malformed and cyclic capability chains.
> - Add unit tests for capability lookup and malformed chains.
>
> Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
> Assisted-by: GPT-5.6 Luna
> ---
> lib/igt_pci.c | 90 +++++++++++++++++++++++++++++++++++++++++++
> lib/igt_pci.h | 8 +++-
> lib/tests/igt_pci.c | 66 +++++++++++++++++++++++++++++++
> lib/tests/meson.build | 1 +
> 4 files changed, 164 insertions(+), 1 deletion(-)
> create mode 100644 lib/tests/igt_pci.c
>
> diff --git a/lib/igt_pci.c b/lib/igt_pci.c
> index b63550b390..7cc9f2dfd6 100644
> --- a/lib/igt_pci.c
> +++ b/lib/igt_pci.c
> @@ -8,6 +8,7 @@
> #include <errno.h>
> #include <fcntl.h>
> #include <limits.h>
> +#include <linux/pci_regs.h>
> #include <string.h>
> #include <unistd.h>
> #include <pciaccess.h>
> @@ -61,6 +62,95 @@ int find_pci_cap_offset(struct pci_device *dev, enum pci_cap_id cap_id)
> return find_pci_cap_offset_at(dev, cap_id, PCI_CAPS_START);
> }
>
> +/**
> + * igt_pci_config_raw_read:
> + * @pci_slot: PCI device BDF (e.g. "0000:01:00.0")
> + * @buffer: destination buffer
> + * @length: number of configuration-space bytes to read
> + *
> + * Read raw PCI configuration space through the device sysfs config attribute.
> + *
> + * Returns 0 on success, otherwise a negative errno-like value.
> + */
> +int igt_pci_config_raw_read(const char *pci_slot, void *buffer, size_t length)
> +{
> + char path[PATH_MAX];
> + ssize_t ret;
> + int err;
> + int fd;
> +
> + if (!pci_slot || !buffer || !length)
> + return -EINVAL;
> +
> + snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/config", pci_slot);
> + fd = open(path, O_RDONLY | O_CLOEXEC);
> + if (fd < 0)
> + return -errno;
> +
> + ret = pread(fd, buffer, length, 0);
> + err = errno;
> + close(fd);
> + if (ret < 0)
> + return -err;
> +
> + return (size_t)ret == length ? 0 : -EIO;
> +}
> +
> +uint16_t igt_pci_config_raw_read_u16(const uint8_t *config, unsigned int offset)
> +{
> + return config[offset] | (config[offset + 1] << 8);
> +}
> +
> +uint32_t igt_pci_config_raw_read_u32(const uint8_t *config, unsigned int offset)
> +{
> + return igt_pci_config_raw_read_u16(config, offset) |
> + ((uint32_t)igt_pci_config_raw_read_u16(config, offset + 2) << 16);
> +}
> +
> +int igt_pci_config_raw_find_cap_offset(const uint8_t *config, uint8_t cap_id)
> +{
> + unsigned int offset = config[PCI_CAPS_START];
> + unsigned int loop = (PCI_CFG_SPACE_SIZE - PCI_TYPE0_1_HEADER_SIZE) / 2;
> +
> + while (offset && loop--) {
> + if (offset < PCI_TYPE0_1_HEADER_SIZE ||
> + offset > PCI_CFG_SPACE_SIZE - 2 || offset & 3)
> + return -EINVAL;
> +
> + if (config[offset] == cap_id)
> + return offset;
> +
> + offset = config[offset + 1];
> + }
> +
> + return offset ? -ELOOP : 0;
> +}
Can we consolidate/reuse the loop logic into a common helper shared by
igt_pci_config_raw_find_cap_offset
and find_pci_cap_offset_at ?
There's also a discrepancy in low-2-bit handling - those bits should be
masked off, not validated/rejected.
> +
> +int igt_pci_config_raw_find_ext_cap_offset(const uint8_t *config, uint16_t cap_id)
> +{
> + unsigned int offset = PCI_EXT_CAPS_START;
> + unsigned int loop = (PCI_EXT_CFG_SPACE_SIZE - offset) / 4;
> +
> + while (loop) {
> + uint32_t header = igt_pci_config_raw_read_u32(config, offset);
> +
> + loop--;
> +
> + if (!header)
> + return 0;
> + if ((header & 0xffff) == cap_id)
> + return offset;
> +
> + offset = (header >> 20) & 0xffc;
> + if (!offset)
> + return 0;
> + if (offset < PCI_EXT_CAPS_START || offset >= PCI_EXT_CFG_SPACE_SIZE)
> + return -EINVAL;
> + }
> +
> + return -ELOOP;
> +}
> +
Maybe it's worth to check a special-case an all-0xffffffff header (what
you get back when extended config space isn't implemented/accessible)
instead of walking it as real data?
> static int open_pci_driver_dir(const char *driver)
> {
> char path[PATH_MAX];
> diff --git a/lib/igt_pci.h b/lib/igt_pci.h
> index 509345b2d8..628cc24766 100644
> --- a/lib/igt_pci.h
> +++ b/lib/igt_pci.h
> @@ -15,7 +15,8 @@ struct pci_device;
>
> #define PCI_TYPE0_1_HEADER_SIZE 0x40
> #define PCI_CAPS_START 0x34
> -#define PCI_CFG_SPACE_SIZE 0x100
> +#define PCI_EXT_CAPS_START 0x100
> +#define PCI_EXT_CFG_SPACE_SIZE 0x1000
>
> enum pci_cap_id {
> PCI_EXPRESS_CAP_ID = 0x10
> @@ -27,6 +28,11 @@ enum pci_cap_id {
> #define PCI_SLOT_PWR_CTRL_PRESENT (1 << 1)
>
> int find_pci_cap_offset(struct pci_device *dev, enum pci_cap_id cap_id);
> +int igt_pci_config_raw_read(const char *pci_slot, void *buffer, size_t length);
> +uint16_t igt_pci_config_raw_read_u16(const uint8_t *config, unsigned int offset);
> +uint32_t igt_pci_config_raw_read_u32(const uint8_t *config, unsigned int offset);
> +int igt_pci_config_raw_find_cap_offset(const uint8_t *config, uint8_t cap_id);
> +int igt_pci_config_raw_find_ext_cap_offset(const uint8_t *config, uint16_t cap_id);
> int igt_pci_device_unbind(const char *pci_slot);
> int igt_pci_driver_bind(const char *driver, const char *pci_slot);
> int igt_pci_driver_unbind(const char *driver, const char *pci_slot);
> diff --git a/lib/tests/igt_pci.c b/lib/tests/igt_pci.c
> new file mode 100644
> index 0000000000..191edb95c5
> --- /dev/null
> +++ b/lib/tests/igt_pci.c
> @@ -0,0 +1,66 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +#include <errno.h>
> +#include <linux/pci_regs.h>
> +#include <stdint.h>
> +#include <string.h>
> +
> +#include "igt_core.h"
> +#include "igt_pci.h"
> +
> +static void write_u32(uint8_t *config, unsigned int offset, uint32_t value)
> +{
> + config[offset] = value;
> + config[offset + 1] = value >> 8;
> + config[offset + 2] = value >> 16;
> + config[offset + 3] = value >> 24;
> +}
> +
> +static void test_cap(void)
> +{
> + uint8_t config[PCI_CFG_SPACE_SIZE] = {};
> +
> + config[PCI_CAPS_START] = PCI_TYPE0_1_HEADER_SIZE;
> + config[PCI_TYPE0_1_HEADER_SIZE] = 0xaa;
> + igt_assert_eq(igt_pci_config_raw_find_cap_offset(config, 0xaa),
> + PCI_TYPE0_1_HEADER_SIZE);
> +
> + config[PCI_CAPS_START] = 0xff;
> + igt_assert_eq(igt_pci_config_raw_find_cap_offset(config, 0xaa), -EINVAL);
> +
> + config[PCI_CAPS_START] = PCI_TYPE0_1_HEADER_SIZE;
> + config[PCI_TYPE0_1_HEADER_SIZE] = 0xbb;
> + config[PCI_TYPE0_1_HEADER_SIZE + 1] = PCI_TYPE0_1_HEADER_SIZE;
> + igt_assert_eq(igt_pci_config_raw_find_cap_offset(config, 0xaa), -ELOOP);
> +}
> +
> +static void test_ext_cap(void)
> +{
> + uint8_t config[PCI_EXT_CFG_SPACE_SIZE] = {};
> + unsigned int offset;
> +
> + write_u32(config, PCI_EXT_CAPS_START, 0xaa);
> + igt_assert_eq(igt_pci_config_raw_find_ext_cap_offset(config, 0xaa),
> + PCI_EXT_CAPS_START);
> +
> + write_u32(config, PCI_EXT_CAPS_START,
> + 0xbb | (PCI_EXT_CAPS_START << 20));
> + igt_assert_eq(igt_pci_config_raw_find_ext_cap_offset(config, 0xaa), -ELOOP);
> +
> + memset(config, 0, sizeof(config));
> + for (offset = PCI_EXT_CAPS_START;
> + offset < PCI_EXT_CFG_SPACE_SIZE - sizeof(uint32_t);
> + offset += sizeof(uint32_t))
> + write_u32(config, offset, 0xbb | ((offset + sizeof(uint32_t)) << 20));
> +
> + igt_assert_eq(igt_pci_config_raw_find_ext_cap_offset(config, 0xaa), 0);
> +}
> +
> +int igt_simple_main()
> +{
> + test_cap();
> + test_ext_cap();
> +}
> \ No newline at end of file
> diff --git a/lib/tests/meson.build b/lib/tests/meson.build
> index f1db66d07c..0a7c903f16 100644
> --- a/lib/tests/meson.build
> +++ b/lib/tests/meson.build
> @@ -19,6 +19,7 @@ lib_tests = [
> 'igt_invalid_subtest_name',
> 'igt_nesting',
> 'igt_no_exit',
> + 'igt_pci',
> 'igt_runnercomms_packets',
> 'igt_segfault',
> 'igt_simulation',
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [v2,2/4] tests/sriov_pci_config: Add VF core config checks
2026-09-21 14:37 ` [PATCH v2 2/4] tests/sriov_pci_config: Add VF core config checks Piórkowski, Piotr
@ 2026-09-28 12:46 ` Laguna, Lukasz
0 siblings, 0 replies; 9+ messages in thread
From: Laguna, Lukasz @ 2026-09-28 12:46 UTC (permalink / raw)
To: Piórkowski, Piotr, igt-dev
On 9/21/2026 16:37, Piórkowski, Piotr wrote:
> From: Piotr Piórkowski <piotr.piorkowski@intel.com>
>
> Add checks for PCI configuration fields required by SR-IOV VFs.
> Cover the common header, BARs, and PCI Express capability fields.
>
> v2:
> - Enable the VF and read its configuration once in the fixture.
> - Restore driver autoprobe state and disable the VF during cleanup.
> - Clarify test documentation and shorten runtime descriptions.
> - Remove redundant informational messages.
>
> Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
> Assisted-by: GPT-5.6 Luna
> ---
> tests/meson.build | 1 +
> tests/sriov_pci_config.c | 210 +++++++++++++++++++++++++++++++++++++++
> 2 files changed, 211 insertions(+)
> create mode 100644 tests/sriov_pci_config.c
>
> diff --git a/tests/meson.build b/tests/meson.build
> index bee2b94224..51c84c99f0 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -74,6 +74,7 @@ test_progs = [
> 'meta_test',
> 'prime_vgem',
> 'sriov_basic',
> + 'sriov_pci_config',
> 'syncobj_basic',
> 'syncobj_eventfd',
> 'syncobj_wait',
> diff --git a/tests/sriov_pci_config.c b/tests/sriov_pci_config.c
> new file mode 100644
> index 0000000000..9f410ef23a
> --- /dev/null
> +++ b/tests/sriov_pci_config.c
> @@ -0,0 +1,210 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright(c) 2026 Intel Corporation. All rights reserved.
> + */
> +
> +#include <linux/pci_regs.h>
> +
> +#include "drmtest.h"
> +#include "igt.h"
> +#include "igt_pci.h"
> +#include "igt_sriov_device.h"
> +
> +#define VF_PCI_EXP_DEVSTA_EPRD (1 << 6)
> +#define VF_PCI_EXP_LNKSTA2_DEEMPHASIS (1 << 0)
> +
> +/**
> + * TEST: SR-IOV PCI configuration
> + * Category: Core
> + * Mega feature: SR-IOV
> + * Sub-category: PCI configuration
> + * Functionality: SR-IOV-related PCI configuration space
> + * Description: Validate PCI configuration fields required for SR-IOV,
> + * including Virtual Functions.
> + *
> + * SUBTEST: vf-common-header
> + * Description: Validate that the VF Vendor ID and Device ID read as 0xffff,
> + * and that the I/O, Memory, and INTx Disable bits in Command, the Immediate
> + * Readiness and Interrupt Status bits in Status, the Header Layout bits in
> + * Header Type, and the BIST Completion Code are all zero.
> + *
> + * SUBTEST: vf-bars
> + * Description: Validate that VF BAR address bits read as zero. The BAR type
> + * and attribute bits are static and may remain set; the upper dword of a
> + * 64-bit BAR must read as zero.
> + *
> + * SUBTEST: vf-pcie-capabilities
> + * Description: Validate that FLR is supported, and Phantom Functions Supported,
> + * Auxiliary Power Detected, Emergency Power Reduction Detected, Current Link
> + * Speed, Negotiated Link Width, and Link Autonomous Bandwidth Status are all
> + * zero.
> + *
> + * SUBTEST: vf-pcie-capabilities-2
> + * Description: Validate that the Current De-emphasis Level field in Link
> + * Status 2 is RsvdZ and therefore reads as zero for PCIe Capability Version 2
> + * and later.
> + */
> +
> +IGT_TEST_DESCRIPTION("Validate PCI configuration fields required for SR-IOV, "
> + "including Virtual Functions");
> +
> +static int pf_fd = -1;
> +static bool autoprobe;
> +static uint8_t vf_config[PCI_EXT_CFG_SPACE_SIZE];
What reason for not defining them in main?
> +
> +static void read_vf_config(uint8_t *config)
> +{
> + char *vf_slot;
> + int ret;
> +
> + vf_slot = igt_sriov_get_vf_pci_slot_alloc(pf_fd, 1);
> + igt_assert(vf_slot);
> + ret = igt_pci_config_raw_read(vf_slot, config, PCI_EXT_CFG_SPACE_SIZE);
> + free(vf_slot);
> + igt_assert_f(!ret, "Failed to read VF config space (%d)\n", ret);
> +}
> +
> +static void check_vf_common_header(const uint8_t *config)
> +{
> + uint16_t command = igt_pci_config_raw_read_u16(config, PCI_COMMAND);
> + uint16_t status = igt_pci_config_raw_read_u16(config, PCI_STATUS);
> + uint16_t vendor_id = igt_pci_config_raw_read_u16(config, PCI_VENDOR_ID);
> + uint16_t device_id = igt_pci_config_raw_read_u16(config, PCI_DEVICE_ID);
> +
> + igt_assert_f(vendor_id == 0xffff, "Vendor ID: expected 0xffff, got 0x%04x\n", vendor_id);
> + igt_assert_f(device_id == 0xffff, "Device ID: expected 0xffff, got 0x%04x\n", device_id);
> + igt_assert_f(!(command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
> + PCI_COMMAND_INTX_DISABLE)),
> + "Command: expected I/O, Memory, and INTx Disable bits clear, got 0x%04x\n",
> + command);
> + igt_assert_f(!(status & (PCI_STATUS_IMM_READY | PCI_STATUS_INTERRUPT)),
> + "Status: expected Immediate Readiness and Interrupt Status bits clear, got 0x%04x\n",
> + status);
> + igt_assert_f(!(config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MASK),
> + "Header Type: expected Header Layout 0, got 0x%02x\n",
> + config[PCI_HEADER_TYPE]);
> + igt_assert_f(!(config[PCI_BIST] & PCI_BIST_CODE_MASK),
> + "BIST: expected Completion Code 0, got 0x%02x\n", config[PCI_BIST]);
> +}
> +
> +static void check_vf_bars(const uint8_t *config)
> +{
> + for (int bar = 0; bar < 6; bar++) {
> + uint32_t value =
> + igt_pci_config_raw_read_u32(config,
> + PCI_BASE_ADDRESS_0 + bar * sizeof(uint32_t));
> + bool is_mem64 = !(value & PCI_BASE_ADDRESS_SPACE) &&
> + (value & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
> + PCI_BASE_ADDRESS_MEM_TYPE_64;
> +
> + /* Only the address bits are hardwired to zero; type/attribute bits are static. */
> + igt_assert_f(!(value & ~0xfu), "BAR%d: expected address 0x00000000, got 0x%08x\n",
> + bar, value);
> +
> + /* The upper dword of a 64-bit BAR holds pure address bits, no type bits. */
> + if (is_mem64) {
> + unsigned int upper_offset = PCI_BASE_ADDRESS_0 +
> + (bar + 1) * sizeof(uint32_t);
> + uint32_t upper =
> + igt_pci_config_raw_read_u32(config, upper_offset);
> +
> + igt_assert_f(!upper, "BAR%d (upper): expected 0x00000000, got 0x%08x\n",
> + bar + 1, upper);
> + bar++;
> + }
> + }
> +}
> +
> +static int get_pcie_cap(const uint8_t *config)
> +{
> + int pcie_cap = igt_pci_config_raw_find_cap_offset(config, PCI_CAP_ID_EXP);
> +
> + igt_assert_f(pcie_cap > 0, "VF has no PCI Express capability (%d)\n", pcie_cap);
> +
> + return pcie_cap;
> +}
> +
> +static void check_vf_pcie_capabilities(const uint8_t *config)
> +{
> + int pcie_cap = get_pcie_cap(config);
> + uint32_t pcie_devcap = igt_pci_config_raw_read_u32(config, pcie_cap + PCI_EXP_DEVCAP);
> + uint16_t pcie_devsta = igt_pci_config_raw_read_u16(config, pcie_cap + PCI_EXP_DEVSTA);
> + uint16_t pcie_lnksta = igt_pci_config_raw_read_u16(config, pcie_cap + PCI_EXP_LNKSTA);
> +
> + igt_assert_f(pcie_devcap & PCI_EXP_DEVCAP_FLR,
> + "Device Capabilities: FLR bit is clear (0x%08x)\n", pcie_devcap);
> + igt_assert_f(!(pcie_devcap & PCI_EXP_DEVCAP_PHANTOM),
> + "Device Capabilities: Phantom Functions Supported must be zero (0x%08x)\n",
> + pcie_devcap);
> + igt_assert_f(!(pcie_devsta & (PCI_EXP_DEVSTA_AUXPD |
> + VF_PCI_EXP_DEVSTA_EPRD)),
> + "Device Status: Aux Power Detected or Emergency Power Reduction Detected is set (0x%04x)\n",
> + pcie_devsta);
> + igt_assert_f(!(pcie_lnksta & (PCI_EXP_LNKSTA_CLS | PCI_EXP_LNKSTA_NLW |
> + PCI_EXP_LNKSTA_LABS)),
> + "Link Status: Current Link Speed, Negotiated Link Width, or Link Autonomous Bandwidth Status is set (0x%04x)\n",
> + pcie_lnksta);
> +}
> +
> +static void check_vf_pcie_capabilities_2(const uint8_t *config)
> +{
> + int pcie_cap = get_pcie_cap(config);
> + uint16_t flags = igt_pci_config_raw_read_u16(config, pcie_cap + PCI_EXP_FLAGS);
> + uint16_t lnksta2;
> +
> + if ((flags & PCI_EXP_FLAGS_VERS) < 2)
> + igt_skip("PCI Express Capability Version 2 is not present\n");
> +
> + lnksta2 = igt_pci_config_raw_read_u16(config, pcie_cap + PCI_EXP_LNKSTA2);
> + igt_assert_f(!(lnksta2 & VF_PCI_EXP_LNKSTA2_DEEMPHASIS),
> + "Link Status 2: Current De-emphasis Level must be zero (0x%04x)\n",
> + lnksta2);
> +}
> +
> +int igt_main()
> +{
> + igt_fixture() {
> + pf_fd = drm_open_driver(DRIVER_ANY);
> + igt_require(igt_sriov_is_pf(pf_fd));
> + igt_require(igt_sriov_vfs_supported(pf_fd));
> + igt_require(igt_sriov_get_enabled_vfs(pf_fd) == 0);
> + autoprobe = igt_sriov_is_driver_autoprobe_enabled(pf_fd);
> + igt_sriov_install_exit_handler(pf_fd, NULL, NULL);
Can you add a new line here?
> + igt_sriov_disable_driver_autoprobe(pf_fd);
> + igt_sriov_enable_vfs(pf_fd, 1);
> + igt_require_f(!igt_pci_system_reinit(), "Failed to refresh PCI state\n");
> + read_vf_config(vf_config);
> + }
> +
> + igt_describe("Validate the VF PCI common header");
> + igt_subtest("vf-common-header") {
> + check_vf_common_header(vf_config);
> + }
> +
> + igt_describe("Validate the VF BARs");
> + igt_subtest("vf-bars") {
> + check_vf_bars(vf_config);
> + }
> +
> + igt_describe("Validate the VF PCI Express capability");
> + igt_subtest("vf-pcie-capabilities") {
> + check_vf_pcie_capabilities(vf_config);
> + }
> +
> + igt_describe("Validate the VF PCI Express Capability Version 2 fields");
> + igt_subtest("vf-pcie-capabilities-2") {
> + check_vf_pcie_capabilities_2(vf_config);
> + }
> + igt_fixture() {
> + igt_abort_on_f(pf_fd < 0, "Device is not accessible\n");
> + igt_sriov_disable_vfs(pf_fd);
> + igt_abort_on_f(igt_sriov_get_enabled_vfs(pf_fd) > 0,
> + "Failed to disable VF(s)\n");
> + 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");
> + igt_sriov_clear_exit_handler();
> + close(pf_fd);
> + }
> +}
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [v2,3/4] tests/sriov_pci_config: Add optional capability checks
2026-09-21 14:37 ` [PATCH v2 3/4] tests/sriov_pci_config: Add optional capability checks Piórkowski, Piotr
@ 2026-09-28 12:49 ` Laguna, Lukasz
0 siblings, 0 replies; 9+ messages in thread
From: Laguna, Lukasz @ 2026-09-28 12:49 UTC (permalink / raw)
To: Piórkowski, Piotr, igt-dev
On 9/21/2026 16:37, Piórkowski, Piotr wrote:
> From: Piotr Piórkowski <piotr.piorkowski@intel.com>
>
> Add subtests for the optional Power Management, Advanced Error
> Reporting, and Address Translation Service capabilities.
> Skip an optional-capability subtest when the capability is not exposed
> by the VF.
> Validate the VF ROZ fields required by the SR-IOV specification,
> including Power Management Data Select/Data, AER status/mask/severity
> fields, and ATS Queue Depth/STU.
>
> v2:
> - Reuse the VF configuration captured by the common fixture.
> - Use PCI register definitions available from linux/pci_regs.h.
> - Simplify optional-capability skips and runtime descriptions.
> - Remove redundant informational messages.
>
> Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
> Assisted-by: GPT-5.6 Luna
LGTM,
Reviewed-by: Lukasz Laguna <lukasz.laguna@intel.com>
> ---
> tests/sriov_pci_config.c | 110 +++++++++++++++++++++++++++++++++++++++
> 1 file changed, 110 insertions(+)
>
> diff --git a/tests/sriov_pci_config.c b/tests/sriov_pci_config.c
> index 9f410ef23a..a3d7e86b58 100644
> --- a/tests/sriov_pci_config.c
> +++ b/tests/sriov_pci_config.c
> @@ -43,6 +43,21 @@
> * Description: Validate that the Current De-emphasis Level field in Link
> * Status 2 is RsvdZ and therefore reads as zero for PCIe Capability Version 2
> * and later.
> + *
> + * SUBTEST: vf-power-management-capability
> + * Description: Validate that Data Select in Power Management Control and
> + * Power Management Data are ROZ and therefore read as zero when the optional
> + * Power Management capability is present.
> + *
> + * SUBTEST: vf-advanced-error-reporting
> + * Description: Validate that the specified ROZ bits in AER Uncorrectable
> + * Error Status, Mask, and Severity, and Correctable Error Status read as zero
> + * when the optional AER capability is present.
> + *
> + * SUBTEST: vf-ats-capability
> + * Description: Validate that ATS Queue Depth and the Smallest Translation Unit
> + * (STU) are ROZ and therefore read as zero when the optional ATS capability
> + * is present.
> */
>
> IGT_TEST_DESCRIPTION("Validate PCI configuration fields required for SR-IOV, "
> @@ -161,6 +176,85 @@ static void check_vf_pcie_capabilities_2(const uint8_t *config)
> lnksta2);
> }
>
> +static int get_optional_cap(const uint8_t *config, uint8_t cap_id, const char *name)
> +{
> + int cap = igt_pci_config_raw_find_cap_offset(config, cap_id);
> +
> + igt_assert_f(cap >= 0, "Invalid VF PCI capability list (%d)\n", cap);
> + if (!cap)
> + igt_skip("%s\n", name);
> +
> + return cap;
> +}
> +
> +static int get_optional_ext_cap(const uint8_t *config, uint16_t cap_id, const char *name)
> +{
> + int cap = igt_pci_config_raw_find_ext_cap_offset(config, cap_id);
> +
> + igt_assert_f(cap >= 0, "Invalid VF extended capability list (%d)\n", cap);
> + if (!cap)
> + igt_skip("%s\n", name);
> +
> + return cap;
> +}
> +
> +static void check_vf_power_management_capability(const uint8_t *config)
> +{
> + int pm_cap = get_optional_cap(config, PCI_CAP_ID_PM,
> + "Power Management capability is not present");
> + uint16_t pm_ctrl = igt_pci_config_raw_read_u16(config, pm_cap + PCI_PM_CTRL);
> + uint8_t pm_data = config[pm_cap + PCI_PM_DATA_REGISTER];
> +
> + igt_assert_f(!(pm_ctrl & PCI_PM_CTRL_DATA_SEL_MASK),
> + "Power Management Control: Data Select must be zero (0x%04x)\n", pm_ctrl);
> + igt_assert_f(!pm_data, "Power Management Data: expected 0x00, got 0x%02x\n", pm_data);
> +}
> +
> +static void check_vf_advanced_error_reporting(const uint8_t *config)
> +{
> + const uint32_t uncor_roz = PCI_ERR_UNC_DLP | PCI_ERR_UNC_SURPDN |
> + PCI_ERR_UNC_FCP | PCI_ERR_UNC_RX_OVER |
> + PCI_ERR_UNC_MALF_TLP | PCI_ERR_UNC_ECRC;
> + const uint32_t cor_roz = PCI_ERR_COR_RCVR | PCI_ERR_COR_BAD_TLP |
> + PCI_ERR_COR_REP_ROLL | PCI_ERR_COR_REP_TIMER;
> + int aer_cap = get_optional_ext_cap(config, PCI_EXT_CAP_ID_ERR,
> + "Advanced Error Reporting capability is not present");
> + uint32_t uncor_status = igt_pci_config_raw_read_u32(config,
> + aer_cap + PCI_ERR_UNCOR_STATUS);
> + uint32_t uncor_mask = igt_pci_config_raw_read_u32(config,
> + aer_cap + PCI_ERR_UNCOR_MASK);
> + uint32_t uncor_severity = igt_pci_config_raw_read_u32(config,
> + aer_cap + PCI_ERR_UNCOR_SEVER);
> + uint32_t cor_status = igt_pci_config_raw_read_u32(config,
> + aer_cap + PCI_ERR_COR_STATUS);
> +
> + igt_assert_f(!(uncor_status & uncor_roz),
> + "AER Uncorrectable Error Status: VF ROZ bits are set (0x%08x)\n",
> + uncor_status);
> + igt_assert_f(!(uncor_mask & uncor_roz),
> + "AER Uncorrectable Error Mask: VF ROZ bits are set (0x%08x)\n",
> + uncor_mask);
> + igt_assert_f(!(uncor_severity & uncor_roz),
> + "AER Uncorrectable Error Severity: VF ROZ bits are set (0x%08x)\n",
> + uncor_severity);
> + igt_assert_f(!(cor_status & cor_roz),
> + "AER Correctable Error Status: VF ROZ bits are set (0x%08x)\n",
> + cor_status);
> +}
> +
> +static void check_vf_ats_capability(const uint8_t *config)
> +{
> + int ats_cap = get_optional_ext_cap(config, PCI_EXT_CAP_ID_ATS,
> + "ATS capability is not present");
> + uint16_t ats_capability = igt_pci_config_raw_read_u16(config, ats_cap + PCI_ATS_CAP);
> + uint16_t ats_control = igt_pci_config_raw_read_u16(config, ats_cap + PCI_ATS_CTRL);
> +
> + igt_assert_f(!PCI_ATS_CAP_QDEP(ats_capability),
> + "ATS Capability: Queue Depth must be zero (0x%04x)\n", ats_capability);
> + igt_assert_f(!PCI_ATS_CTRL_STU(ats_control),
> + "ATS Control: STU must be zero (0x%04x)\n", ats_control);
> +}
> +
> int igt_main()
> {
> igt_fixture() {
> @@ -195,6 +289,22 @@ int igt_main()
> igt_subtest("vf-pcie-capabilities-2") {
> check_vf_pcie_capabilities_2(vf_config);
> }
> +
> + igt_describe("Validate the optional VF Power Management capability");
> + igt_subtest("vf-power-management-capability") {
> + check_vf_power_management_capability(vf_config);
> + }
> +
> + igt_describe("Validate the optional VF AER capability");
> + igt_subtest("vf-advanced-error-reporting") {
> + check_vf_advanced_error_reporting(vf_config);
> + }
> +
> + igt_describe("Validate the optional VF ATS capability");
> + igt_subtest("vf-ats-capability") {
> + check_vf_ats_capability(vf_config);
> + }
> +
> igt_fixture() {
> igt_abort_on_f(pf_fd < 0, "Device is not accessible\n");
> igt_sriov_disable_vfs(pf_fd);
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [v2,4/4] intel-ci: Block igt@sriov_pci_config.*
2026-09-21 14:37 ` [PATCH v2 4/4] intel-ci: Block igt@sriov_pci_config.* Piórkowski, Piotr
@ 2026-09-28 12:50 ` Laguna, Lukasz
0 siblings, 0 replies; 9+ messages in thread
From: Laguna, Lukasz @ 2026-09-28 12:50 UTC (permalink / raw)
To: Piórkowski, Piotr, igt-dev
On 9/21/2026 16:37, Piórkowski, Piotr wrote:
> From: Piotr Piórkowski <piotr.piorkowski@intel.com>
>
> This test is intended for HW verification and does not need to run in
> recurring CI runs.
>
> Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
> Assisted-by: GPT-5.6 Luna
LGTM,
Reviewed-by: Lukasz Laguna <lukasz.laguna@intel.com>
> ---
> tests/intel-ci/xe.blocklist.txt | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/tests/intel-ci/xe.blocklist.txt b/tests/intel-ci/xe.blocklist.txt
> index 0f68df95d5..0a7e63c5ec 100644
> --- a/tests/intel-ci/xe.blocklist.txt
> +++ b/tests/intel-ci/xe.blocklist.txt
> @@ -116,6 +116,7 @@ igt@sriov_basic@bind-unbind-vf$
> ##################################################################
> # SR-IOV tests for HW checkout, not suited for recurring CI runs
> ##################################################################
> +igt@sriov_pci_config.*
> igt@xe_sriov_ggtt.*
> ##################################################################
> # Chamelium V1 HDMI receiver supports a maximum resolution
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-09-28 12:51 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-21 14:37 [PATCH v2 0/4] Add PCI configuration tests for SR-IOV VFs Piórkowski, Piotr
2026-09-21 14:37 ` [PATCH v2 1/4] lib/igt_pci: Add raw configuration space helpers Piórkowski, Piotr
2026-09-22 11:00 ` Bernatowicz, Marcin
2026-09-21 14:37 ` [PATCH v2 2/4] tests/sriov_pci_config: Add VF core config checks Piórkowski, Piotr
2026-09-28 12:46 ` [v2,2/4] " Laguna, Lukasz
2026-09-21 14:37 ` [PATCH v2 3/4] tests/sriov_pci_config: Add optional capability checks Piórkowski, Piotr
2026-09-28 12:49 ` [v2,3/4] " Laguna, Lukasz
2026-09-21 14:37 ` [PATCH v2 4/4] intel-ci: Block igt@sriov_pci_config.* Piórkowski, Piotr
2026-09-28 12:50 ` [v2,4/4] " Laguna, Lukasz
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.