pci-sim: Add CentOS Stream 10 support

CentOS Stream 10 ships kernel 6.12 but backports IOMMU and VFIO
API changes from upstream 6.15+. The existing compat header gates
on LINUX_VERSION_CODE alone, which selects the wrong (old) API on
CentOS because the kernel reports 6.12 while the actual signatures
are 6.15-style. This prevents the module from compiling on
RHEL-family kernels.

The compat header now defines a single PCI_SIM_HAS_615_API
predicate that checks LINUX_VERSION_CODE >= 6.15 or
RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(10, 3), and all five
feature macros alias it. Adding future distro gates is a one-line
edit.

The QEMU test scripts hardcoded qemu-system-x86_64, which does
not exist on CentOS/RHEL where the binary is
/usr/libexec/qemu-kvm. All five QEMU-related scripts now
auto-detect the binary via a QEMU_BIN environment variable with
PATH-based fallback.

The DevStack build_pci_sim() function used raw apt-get calls.
It now uses devstack's is_ubuntu/is_fedora helpers with
install_package for distro-aware package selection.

Build and test documentation is updated with CentOS/Fedora
install commands and CentOS Stream 10 as a compatibility target.

A cyborg-tempest-centos-10-stream Zuul CI job is added
to the weekly-periodic and experimental pipeline to
validate pci-sim on CentOS Stream 10.

Assisted-By: Claude Code (claude-opus-4-6)
Change-Id: I7ecae754465510be9efc55667bb5ed1d5f9a5f68
Signed-off-by: Chandan Kumar (raukadah) <chkumar@redhat.com>
This commit is contained in:
Chandan Kumar (raukadah) authored and Sean Mooney committed 2026-07-09 12:33:32 +01:00
1 parent 3f9aa074b4
commit c523612230
10 files changed
+117 -43

No files matched your search

+15
View File
@@ -92,6 +92,15 @@
Cyborg devstack tempest tests job for >=Ussuri release
run on python 3.
parent: cyborg-multinode-tempest
- job:
name: cyborg-tempest-centos-10-stream
parent: cyborg-tempest-base
nodeset: devstack-single-node-centos-10-stream
description: |
Cyborg devstack tempest tests job to test pci-sim on
CentOS Stream 10.
- job:
name: cyborg-tempest-ipv6
parent: devstack-tempest-ipv6
@@ -123,3 +132,9 @@
- cyborg-tempest-ipv6
- cyborg-grenade
- cyborg-grenade-skip-level-always
experimental:
jobs:
- cyborg-tempest-centos-10-stream
periodic-weekly:
jobs:
- cyborg-tempest-centos-10-stream
+17 -4
View File
@@ -126,7 +126,20 @@ function build_pci_sim {
set -x
local kver=$(uname -r)
local kconfig=/boot/config-${kver}
local -a pkgs=(build-essential linux-headers-${kver} kmod)
local -a pkgs
if is_ubuntu; then
pkgs=(build-essential "linux-headers-${kver}" kmod)
elif is_fedora; then
local kpkg
case "$kver" in
*+debug) kpkg="kernel-debug-devel-${kver%+debug}" ;;
*) kpkg="kernel-devel-${kver}" ;;
esac
pkgs=(gcc make "$kpkg" kmod)
else
die $LINENO "Unsupported distro for pci-sim build"
fi
# CONFIG_DEBUG_INFO_BTF causes the kernel Makefile to invoke pahole
# (from dwarves) to generate BTF type info for the .ko. Read the
@@ -136,11 +149,11 @@ function build_pci_sim {
pkgs+=(dwarves)
fi
sudo apt-get update
sudo apt-get install -y "${pkgs[@]}"
install_package "${pkgs[@]}"
$CYBORG_DIR/tools/check-kernel-config.sh
make -C $CYBORG_DIR/pci-sim modules
make -C $CYBORG_DIR/pci-sim modules \
|| die $LINENO "pci-sim kernel module build failed"
sudo make -C $CYBORG_DIR/pci-sim modules_install
sudo depmod -a
}
+11 -1
View File
@@ -6,7 +6,9 @@ Local build
===========
Install headers for the running kernel, then build the module from the
repository root:
repository root.
On Debian/Ubuntu:
.. code-block:: console
@@ -14,6 +16,14 @@ repository root:
$ bash tools/check-kernel-config.sh
$ make -C pci-sim modules
On CentOS/Fedora/RHEL:
.. code-block:: console
$ sudo dnf install kernel-devel-$(uname -r) gcc make
$ bash tools/check-kernel-config.sh
$ make -C pci-sim modules
The module is created at ``pci-sim/fake_pci_sriov.ko``.
The build does not require a Linux git checkout. It uses the kernel build
@@ -31,6 +31,16 @@ The smoke tests are more useful when these are also enabled:
* ``CONFIG_VFIO_PCI``
* ``CONFIG_KVM``
The initial compatibility target is the current Ubuntu 26.04 generic kernel,
``7.0.0-15-generic``. Broader Ubuntu 26.04 kernel update compatibility should
be added by version-guarding specific API differences as they are found.
Compatibility targets
=====================
* Debian 13 (Trixie) kernel (``6.12.90+deb13.1-amd64``)
* Ubuntu 26.04 generic kernel (``7.0.0-15-generic``)
* CentOS Stream 10 kernel (``6.12.0-243.el10.x86_64``)
CentOS Stream 10 ships kernel 6.12 but backports IOMMU and VFIO API changes
from upstream 6.15+. The compat header uses ``RHEL_RELEASE_CODE`` guards to
select the correct API on RHEL-family kernels.
Broader kernel update compatibility should be added by version-guarding
specific API differences as they are found.
+26 -24
View File
@@ -6,37 +6,39 @@
/*
* Keep kernel API compatibility decisions in one place. The module is
* developed against newer upstream/Ubuntu kernels, while Debian 13 currently
* ships a 6.12 kernel whose IOMMU and VFIO callback tables predate some of the
* newer PASID/HWPT and VFIO region-info hooks.
* developed against newer upstream/Ubuntu kernels, while Debian 13 and
* CentOS Stream 10 currently ship a 6.12 kernel whose IOMMU and VFIO
* callback tables predate some of the newer PASID/HWPT and VFIO
* region-info hooks.
*
* CentOS Stream 10 backports the 6.15+ API changes into its 6.12
* kernel, so LINUX_VERSION_CODE alone is insufficient. The
* RHEL_RELEASE_CODE macro (defined in CentOS/RHEL kernel headers)
* gates the backported API at RHEL_RELEASE_VERSION(10, 3).
*
* These version gates intentionally select the conservative 6.12-compatible
* API for older kernels. Newer kernels keep using the richer callbacks.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
#define PCI_SIM_HAS_615_API 1
#elif defined(RHEL_RELEASE_CODE)
#if RHEL_RELEASE_VERSION(10, 3) <= RHEL_RELEASE_CODE
#define PCI_SIM_HAS_615_API 1
#else
#define PCI_SIM_HAS_615_API 0
#endif
#else
#define PCI_SIM_HAS_615_API 0
#endif
/* iommu_domain_ops.attach_dev gained the previous-domain argument later. */
#if KERNEL_VERSION(6, 15, 0) <= LINUX_VERSION_CODE
#define PCI_SIM_IOMMU_ATTACH_HAS_OLD_DOMAIN 1
#else
#define PCI_SIM_IOMMU_ATTACH_HAS_OLD_DOMAIN 0
#endif
#define PCI_SIM_IOMMU_ATTACH_HAS_OLD_DOMAIN PCI_SIM_HAS_615_API
/* iommu_ops.domain_alloc_paging_flags and IOMMU_HWPT_ALLOC_PASID are newer. */
#if KERNEL_VERSION(6, 15, 0) <= LINUX_VERSION_CODE
#define PCI_SIM_IOMMU_HAS_DOMAIN_ALLOC_PAGING_FLAGS 1
#else
#define PCI_SIM_IOMMU_HAS_DOMAIN_ALLOC_PAGING_FLAGS 0
#endif
#define PCI_SIM_IOMMU_HAS_DOMAIN_ALLOC_PAGING_FLAGS PCI_SIM_HAS_615_API
/* VFIO grew optional region-info and PASID/token callbacks after 6.12. */
#if KERNEL_VERSION(6, 15, 0) <= LINUX_VERSION_CODE
#define PCI_SIM_VFIO_HAS_GET_REGION_INFO_CAPS 1
#define PCI_SIM_VFIO_HAS_MATCH_TOKEN_UUID 1
#define PCI_SIM_VFIO_HAS_PASID_IOAS 1
#else
#define PCI_SIM_VFIO_HAS_GET_REGION_INFO_CAPS 0
#define PCI_SIM_VFIO_HAS_MATCH_TOKEN_UUID 0
#define PCI_SIM_VFIO_HAS_PASID_IOAS 0
#endif
#define PCI_SIM_VFIO_HAS_GET_REGION_INFO_CAPS PCI_SIM_HAS_615_API
#define PCI_SIM_VFIO_HAS_MATCH_TOKEN_UUID PCI_SIM_HAS_615_API
#define PCI_SIM_VFIO_HAS_PASID_IOAS PCI_SIM_HAS_615_API
#endif /* FAKE_PCI_SRIOV_COMPAT_H */
+2 -1
View File
@@ -56,10 +56,11 @@ echo GUEST_PROBE_END
def launch_qemu(image: str, vf: str) -> tuple[subprocess.Popen[bytes], int]:
"""Launch QEMU with ``vf`` assigned and return the process and PTY FD."""
qemu_bin = os.environ.get("QEMU_BIN", "qemu-system-x86_64")
cmd = [
"sudo",
"-n",
"qemu-system-x86_64",
qemu_bin,
"-nodefaults",
"-display",
"none",
+10 -3
View File
@@ -5,7 +5,7 @@
# guest-side discovery commands from the serial console.
#
# Prerequisites:
# - qemu-system-x86_64, python3, curl, timeout, sudo without a password
# - qemu-system-x86_64 or qemu-kvm, python3, curl, timeout, sudo without a password
# - a kernel that can load fake_pci_sriov.ko and vfio-pci
# - a CirrOS qcow2 image, downloaded automatically when IMAGE is missing
#
@@ -31,6 +31,13 @@ set -euo pipefail
MODULE=${MODULE:-./fake_pci_sriov.ko}
MODULE_ARGS=${MODULE_ARGS:-}
RELOAD_MODULE=${RELOAD_MODULE:-1}
if [ -z "${QEMU_BIN:-}" ]; then
if command -v qemu-system-x86_64 >/dev/null 2>&1; then
QEMU_BIN=qemu-system-x86_64
else
QEMU_BIN=/usr/libexec/qemu-kvm
fi
fi
IMAGE=${IMAGE:-/tmp/cirros-0.6.3-x86_64-disk.img}
IMAGE_URL=${IMAGE_URL:-https://github.com/cirros-dev/cirros/releases/download/0.6.3/cirros-0.6.3-x86_64-disk.img}
VENDOR=${VENDOR:-0x1d55}
@@ -79,7 +86,7 @@ SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
cd "$SCRIPT_DIR"
msg preflight
command -v qemu-system-x86_64
command -v "$QEMU_BIN"
command -v python3
sudo -n true
@@ -127,6 +134,6 @@ echo "$VF" | sudo -n tee /sys/bus/pci/drivers_probe >/dev/null
readlink -f "/sys/bus/pci/devices/$VF/driver"
msg "boot CirrOS and run guest probe"
export IMAGE VF QEMU_DEADLINE
export IMAGE VF QEMU_DEADLINE QEMU_BIN
python3 "$SCRIPT_DIR/run_cirros_vfio_guest_probe.py"
msg PASS
+2 -1
View File
@@ -43,10 +43,11 @@ def launch_qemu(
config_iso: str,
) -> tuple[subprocess.Popen[bytes], int]:
"""Launch QEMU with ``vf`` assigned and ``config_iso`` attached."""
qemu_bin = os.environ.get("QEMU_BIN", "qemu-system-x86_64")
cmd = [
"sudo",
"-n",
"qemu-system-x86_64",
qemu_bin,
"-nodefaults",
"-display",
"none",
+10 -3
View File
@@ -6,7 +6,7 @@
# verifies the emulated UART loopback path from inside the guest.
#
# Prerequisites:
# - qemu-system-x86_64, python3, xorriso, curl, timeout, sudo without a password
# - qemu-system-x86_64 or qemu-kvm, python3, xorriso, curl, timeout, sudo without a password
# - a kernel that can load fake_pci_sriov.ko and vfio-pci
# - a CirrOS qcow2 image, downloaded automatically when IMAGE is missing
#
@@ -34,6 +34,13 @@ set -euo pipefail
MODULE=${MODULE:-./fake_pci_sriov.ko}
MODULE_ARGS=${MODULE_ARGS:-}
RELOAD_MODULE=${RELOAD_MODULE:-1}
if [ -z "${QEMU_BIN:-}" ]; then
if command -v qemu-system-x86_64 >/dev/null 2>&1; then
QEMU_BIN=qemu-system-x86_64
else
QEMU_BIN=/usr/libexec/qemu-kvm
fi
fi
IMAGE=${IMAGE:-/tmp/cirros-0.6.3-x86_64-disk.img}
IMAGE_URL=${IMAGE_URL:-https://github.com/cirros-dev/cirros/releases/download/0.6.3/cirros-0.6.3-x86_64-disk.img}
VENDOR=${VENDOR:-0x1d55}
@@ -85,7 +92,7 @@ cd "$SCRIPT_DIR"
USER_DATA=${USER_DATA:-$SCRIPT_DIR/cirros_vfio_userdata_echo.sh}
msg preflight
command -v qemu-system-x86_64
command -v "$QEMU_BIN"
command -v python3
command -v xorriso
[ -r "$USER_DATA" ]
@@ -147,7 +154,7 @@ echo "$VF" | sudo -n tee /sys/bus/pci/drivers_probe >/dev/null
readlink -f "/sys/bus/pci/devices/$VF/driver"
msg "boot CirrOS with config-drive"
export IMAGE VF QEMU_DEADLINE CONFIG_ISO="$WORK/configdrive.iso"
export IMAGE VF QEMU_DEADLINE QEMU_BIN CONFIG_ISO="$WORK/configdrive.iso"
python3 "$SCRIPT_DIR/run_cirros_vfio_userdata_echo.py"
msg "recent host dmesg"
+11 -3
View File
@@ -7,7 +7,7 @@
# driver to pci_sim_vfio_pci, attached to QEMU with vfio-pci, and cleaned up.
# This is a host-side smoke test; it only verifies QEMU can start with the VF.
#
# Prerequisites: qemu-system-x86_64, timeout, sudo without a password, vfio-pci,
# Prerequisites: qemu-system-x86_64 or qemu-kvm, timeout, sudo without a password, vfio-pci,
# and a kernel that can load fake_pci_sriov.ko.
#
# Important environment variables:
@@ -15,6 +15,7 @@
# - MODULE_ARGS: optional arguments passed to insmod
# - VFS: number of VFs to create on the first PF, default 1
# - QEMU_TIMEOUT/QEMU_KILL_AFTER: bounds for the QEMU run, defaults 12s/5s
# - QEMU_BIN: QEMU binary path, auto-detected when unset
# - ALLOW_UNSAFE_INTERRUPTS: set VFIO unsafe-interrupts knob when present,
# default 1 for nested development environments
# - LOG: log file, default /tmp/fake_pci_qemu_vfio_smoke.log
@@ -27,6 +28,13 @@ set -euo pipefail
MODULE=${MODULE:-./fake_pci_sriov.ko}
MODULE_ARGS=${MODULE_ARGS:-}
if [ -z "${QEMU_BIN:-}" ]; then
if command -v qemu-system-x86_64 >/dev/null 2>&1; then
QEMU_BIN=qemu-system-x86_64
else
QEMU_BIN=/usr/libexec/qemu-kvm
fi
fi
VENDOR=${VENDOR:-0x1d55}
PF_DEVICE=${PF_DEVICE:-0x1000}
VF_DEVICE=${VF_DEVICE:-0x1001}
@@ -73,7 +81,7 @@ trap cleanup EXIT
cd "$(dirname "$0")"
msg "preflight"
command -v qemu-system-x86_64
command -v "$QEMU_BIN"
command -v timeout
sudo -n true
@@ -116,7 +124,7 @@ readlink -f "/sys/bus/pci/devices/$VF/driver"
msg "QEMU/VFIO smoke test; timeout rc=124 is expected"
set +e
sudo -n timeout --foreground --kill-after="$QEMU_KILL_AFTER" "$QEMU_TIMEOUT" \
qemu-system-x86_64 \
"$QEMU_BIN" \
-nodefaults -display none -serial none -parallel none -monitor none \
-machine q35,accel=kvm \
-m 256M \