Igt-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: "Piórkowski, Piotr" <piotr.piorkowski@intel.com>
To: <igt-dev@lists.freedesktop.org>
Cc: "Piotr Piórkowski" <piotr.piorkowski@intel.com>
Subject: [PATCH v1 3/4] tests/sriov_pci_config: Add VF core config checks
Date: Wed, 16 Sep 2026 13:52:00 +0200	[thread overview]
Message-ID: <20260916115201.1973752-4-piotr.piorkowski@intel.com> (raw)
In-Reply-To: <20260916115201.1973752-1-piotr.piorkowski@intel.com>

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.

Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
Assisted-by: GPT-5.6 Luna
---
 tests/sriov_pci_config.c | 234 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 234 insertions(+)
 create mode 100644 tests/sriov_pci_config.c

diff --git a/tests/sriov_pci_config.c b/tests/sriov_pci_config.c
new file mode 100644
index 0000000000..9f8fd9fb50
--- /dev/null
+++ b/tests/sriov_pci_config.c
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright(c) 2026 Intel Corporation. All rights reserved.
+ */
+
+#include "drmtest.h"
+#include "igt.h"
+#include "igt_pci.h"
+#include "igt_sriov_device.h"
+
+/**
+ * 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, Phantom Functions Supported is
+ * zero, and 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 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 skip_vf_test(const char *reason)
+{
+	igt_sriov_disable_vfs(pf_fd);
+	igt_abort_on_f(igt_sriov_get_enabled_vfs(pf_fd),
+		       "Failed to disable VF(s) before skipping: %s\n", reason);
+	igt_skip("%s\n", reason);
+}
+
+typedef void (*vf_config_check_fn)(const uint8_t *config);
+
+static void with_vf_config(vf_config_check_fn check)
+{
+	uint8_t config[PCI_EXT_CFG_SPACE_SIZE];
+
+	igt_require(igt_sriov_get_enabled_vfs(pf_fd) == 0);
+	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(config);
+	check(config);
+	igt_sriov_disable_vfs(pf_fd);
+}
+
+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_info("Checking common header\n");
+	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_IMMEDIATE_READINESS | 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_COMPLETION_CODE),
+		     "BIST: expected Completion Code 0, got 0x%02x\n", config[PCI_BIST]);
+}
+
+static void check_vf_bars(const uint8_t *config)
+{
+	igt_info("Checking VF BARs\n");
+	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_info("Checking mandatory PCI Express capability\n");
+	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 |
+					  PCI_EXP_DEVSTA_EMERGENCY_PWR_REDUCED)),
+		     "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)
+		skip_vf_test("PCI Express Capability Version 2 is not present");
+
+	lnksta2 = igt_pci_config_raw_read_u16(config, pcie_cap + PCI_EXP_LNKSTA2);
+	igt_info("Checking PCI Express Capability Version 2\n");
+	igt_assert_f(!(lnksta2 & PCI_EXP_LNKSTA2_CUR_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_describe("Validate the SR-IOV VF requirements for Vendor ID, Device ID, "
+		     "Command, Status, Header Type, and BIST fields in the PCI common header");
+	igt_subtest("vf-common-header") {
+		with_vf_config(check_vf_common_header);
+	}
+
+	igt_describe("Validate the SR-IOV VF requirement that BAR address bits are zero "
+		     "while static BAR type and attribute bits remain valid");
+	igt_subtest("vf-bars") {
+		with_vf_config(check_vf_bars);
+	}
+
+	igt_describe("Validate the SR-IOV VF requirements for FLR, Phantom Functions, "
+		     "Auxiliary Power, Emergency Power Reduction, and PCIe link status fields");
+	igt_subtest("vf-pcie-capabilities") {
+		with_vf_config(check_vf_pcie_capabilities);
+	}
+
+	igt_describe("Validate the RsvdZ requirement for Current De-emphasis Level in "
+		     "Link Status 2 of PCI Express Capability Version 2 and later");
+	igt_subtest("vf-pcie-capabilities-2") {
+		with_vf_config(check_vf_pcie_capabilities_2);
+	}
+
+	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


  parent reply	other threads:[~2026-09-16 11:55 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-16 11:51 [PATCH v1 0/4] Add PCI configuration tests for SR-IOV VFs Piórkowski, Piotr
2026-09-16 11:51 ` [PATCH v1 1/4] lib/igt_pci: Add raw configuration space helpers Piórkowski, Piotr
2026-09-17 15:33   ` [v1,1/4] " Laguna, Lukasz
2026-09-16 11:51 ` [PATCH v1 2/4] lib/igt_pci: Add PCI extended capability lookup Piórkowski, Piotr
2026-09-17 15:36   ` [v1,2/4] " Laguna, Lukasz
2026-09-16 11:52 ` Piórkowski, Piotr [this message]
2026-09-17 15:38   ` [v1,3/4] tests/sriov_pci_config: Add VF core config checks Laguna, Lukasz
2026-09-16 11:52 ` [PATCH v1 4/4] tests/sriov_pci_config: Add optional capability checks Piórkowski, Piotr
2026-09-17 15:47   ` [v1,4/4] " Laguna, Lukasz
2026-09-16 19:24 ` ✓ Xe.CI.BAT: success for Add PCI configuration tests for SR-IOV VFs Patchwork
2026-09-16 20:10 ` ✓ i915.CI.BAT: " Patchwork
2026-09-16 22:49 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-09-17  4:13 ` ✓ i915.CI.Full: success " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260916115201.1973752-4-piotr.piorkowski@intel.com \
    --to=piotr.piorkowski@intel.com \
    --cc=igt-dev@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox