public inbox for igt-dev@lists.freedesktop.org
 help / color / mirror / Atom feed
* [PATCH i-g-t 00/10] vmtb: Modernize SR-IOV VM Test Bench core
@ 2026-02-24  7:50 Adam Miszczak
  2026-02-24  7:50 ` [PATCH i-g-t 01/10] tools/vmtb: Update QEMU parameters Adam Miszczak
                   ` (13 more replies)
  0 siblings, 14 replies; 25+ messages in thread
From: Adam Miszczak @ 2026-02-24  7:50 UTC (permalink / raw)
  To: igt-dev; +Cc: marcin.bernatowicz, kamil.konieczny

Update and refactor VMTB core implementation, align with the current Xe KMD
SR-IOV state and prepare for a broader test coverage.

Introduced changes:
- refactor driver abstractions into common Driver/PF/VF interfaces,
  including updated sysfs/debugfs interfaces
- split VM-side abstractions into VirtualMachine, VirtualDevice and
  VfDriver with clearer responsibilities
- add auto/fair provisioning mode next to vGPU profile mode and align
  scheduling/resources handling
- support maximum VFs test config
- extend IGT/gem_wsim abstractions (object-oriented result checks,
  repeated execution support, resource-based wsim workload descriptors)
- adjust QEMU launch parameters (SSH forwarding, migration capability
  handling, disable emulated VGA)
- enable support for Panther Lake (PTL) and Battlemage (BMG) platforms with
  PCI Device IDs and vGPU profile resources

Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
Cc: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
Cc: Kamil Konieczny <kamil.konieczny@linux.intel.com>

Adam Miszczak (10):
  tools/vmtb: Update QEMU parameters
  tools/vmtb: Fix DUT selection based on card index
  tools/vmtb: Fix VM snapshot query handling
  tools/vmtb: Extend IGT and WSIM abstractions
  tools/vmtb: VF auto/fair provisioning support
  tools/vmtb: Refactor driver interfaces
  tools/vmtb: Introduce VirtualDevice class
  tools/vmtb: Redesign VirtualMachine class
  tools/vmtb: Support max VFs configuration
  tools/vmtb: Platform enabling: PTL and BMG support

 tools/vmtb/bench/configurators/pci.py         |  43 ++-
 .../vmtb/bench/configurators/vgpu_profile.py  |  37 ++-
 .../configurators/vgpu_profile_config.py      |   7 +-
 tools/vmtb/bench/configurators/vmtb_config.py |   4 +-
 tools/vmtb/bench/drivers/driver_interface.py  | 179 +++++++++---
 tools/vmtb/bench/drivers/xe.py                | 213 +++++++-------
 tools/vmtb/bench/executors/gem_wsim.py        |  45 ++-
 tools/vmtb/bench/executors/igt.py             |  36 ++-
 tools/vmtb/bench/machines/device_interface.py |  14 +-
 tools/vmtb/bench/machines/host.py             |  17 +-
 .../vmtb/bench/machines/machine_interface.py  |   6 +-
 tools/vmtb/bench/machines/physical/device.py  | 145 ++++++----
 .../machines/virtual/backends/qmp_monitor.py  |  25 +-
 tools/vmtb/bench/machines/virtual/device.py   | 179 ++++++++++++
 tools/vmtb/bench/machines/virtual/vm.py       | 263 +++++++++---------
 tools/vmtb/vmm_flows/conftest.py              | 167 ++++++++---
 .../{Flex170.json => Bmg_g21_12.json}         |  58 ++--
 .../resources/vgpu_profiles/Ptl.json          |  97 +++++++
 tools/vmtb/vmm_flows/test_basic.py            |  25 +-
 tools/vmtb/vmtb_config.json                   |   1 +
 20 files changed, 1066 insertions(+), 495 deletions(-)
 create mode 100644 tools/vmtb/bench/machines/virtual/device.py
 rename tools/vmtb/vmm_flows/resources/vgpu_profiles/{Flex170.json => Bmg_g21_12.json} (73%)
 create mode 100644 tools/vmtb/vmm_flows/resources/vgpu_profiles/Ptl.json

-- 
2.39.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH i-g-t 01/10] tools/vmtb: Update QEMU parameters
  2026-02-24  7:50 [PATCH i-g-t 00/10] vmtb: Modernize SR-IOV VM Test Bench core Adam Miszczak
@ 2026-02-24  7:50 ` Adam Miszczak
  2026-03-10 10:22   ` Bernatowicz, Marcin
  2026-02-24  7:50 ` [PATCH i-g-t 02/10] tools/vmtb: Fix DUT selection based on card index Adam Miszczak
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 25+ messages in thread
From: Adam Miszczak @ 2026-02-24  7:50 UTC (permalink / raw)
  To: igt-dev; +Cc: marcin.bernatowicz, kamil.konieczny

1. Enable SSH access to VM/Guest OS

Add QEMU options to open guest SSH connection:
- enable default emulated NIC
- redirect host's TCP port 10000+N connections to
  guest's SSH server on port 22
  (where N is booted VM number, starting from 0)

For example, login to VM0 (from host) as:
$ ssh -p 10000 gta@localhost

2. Enable migration based on VFIO driver

Set 'enable-migration' option introducing QEMU VF migration support.

VF migration is supported by a vendor specific VFIO driver (xe-vfio-pci).
In case of regular 'vfio-pci', QEMU command option 'enable-migration'
should not be explicitly enabled to prevent VM start failure:
'vfio 0000:00:02.1: VFIO migration is not supported in kernel'

3. Disable QEMU emulated VGA card

Disable standard emulated VGA on QEMU VMs to avoid issues
emerging from a bochs DRM driver.
Standard VGA is enumerated as PCI device BDF 00:02.0
on minor 0 (drm/card0) - this causes troubles with VirtualMachine class
reserving card0 for passed VF.
Also, bochs driver obscures guest dmesg with verbose debug logs.

Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
---
 tools/vmtb/bench/machines/virtual/vm.py | 14 ++++++++++----
 tools/vmtb/vmm_flows/conftest.py        | 25 +++++++++++++++----------
 2 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/tools/vmtb/bench/machines/virtual/vm.py b/tools/vmtb/bench/machines/virtual/vm.py
index e75de590d..9f4ca1de7 100644
--- a/tools/vmtb/bench/machines/virtual/vm.py
+++ b/tools/vmtb/bench/machines/virtual/vm.py
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: MIT
-# Copyright © 2024 Intel Corporation
+# Copyright © 2024-2026 Intel Corporation
 
 import base64
 import json
@@ -58,7 +58,8 @@ class VirtualMachine(MachineInterface):
 
             return timeout_wrapper
 
-    def __init__(self, vm_number: int, backing_image: str, driver: str, igt_config: VmtbIgtConfig) -> None:
+    def __init__(self, vm_number: int, backing_image: str, driver: str,
+                 igt_config: VmtbIgtConfig, vf_migration_support: bool) -> None:
         self.vf_bdf: typing.Optional[str] = None
         self.process: typing.Optional[subprocess.Popen] = None
         self.vmnum: int = vm_number
@@ -68,6 +69,7 @@ class VirtualMachine(MachineInterface):
         self.qmp_sockpath = posixpath.join('/tmp', f'mon{self.vmnum}.sock')
         self.drm_driver_name: str = driver
         self.igt_config: VmtbIgtConfig = igt_config
+        self.vf_migration: bool = vf_migration_support
 
         if not posixpath.exists(backing_image):
             logger.error('No image for VM%s', self.vmnum)
@@ -153,6 +155,9 @@ class VirtualMachine(MachineInterface):
                    '-vnc', f':{self.vmnum}',
                    '-serial', 'stdio',
                    '-m', '4096',
+                   '-vga', 'none',
+                   '-net', 'nic',
+                   '-net', f'user,hostfwd=tcp::{10000 + self.vmnum}-:22',
                    '-drive', f'file={self.image if not self.migrate_destination_vm else self.migrate_source_image}',
                    '-chardev', f'socket,path={self.questagent_sockpath},server=on,wait=off,id=qga{self.vmnum}',
                    '-device', 'virtio-serial',
@@ -161,8 +166,9 @@ class VirtualMachine(MachineInterface):
                    '-mon', f'chardev=mon{self.vmnum},mode=control']
 
         if self.vf_bdf:
-            command.extend(['-enable-kvm', '-cpu', 'host'])
-            command.extend(['-device', f'vfio-pci,host={self.vf_bdf},enable-migration=on'])
+            command.extend(['-enable-kvm', '-cpu', 'host', '-device', f'vfio-pci,host={self.vf_bdf}'])
+            if self.vf_migration:
+                command[-1] += ',enable-migration=on'
 
         if self.migrate_destination_vm:
             # If VM is migration destination - run in stopped/prelaunch state (explicit resume required)
diff --git a/tools/vmtb/vmm_flows/conftest.py b/tools/vmtb/vmm_flows/conftest.py
index 7b6eacd51..675312253 100644
--- a/tools/vmtb/vmm_flows/conftest.py
+++ b/tools/vmtb/vmm_flows/conftest.py
@@ -1,26 +1,25 @@
 # SPDX-License-Identifier: MIT
-# Copyright © 2024 Intel Corporation
+# Copyright © 2024-2026 Intel Corporation
 
 import json
 import logging
 import re
 import typing
-
 from dataclasses import dataclass
 from pathlib import Path
 
 import pytest
 
 from bench import exceptions
-from bench.helpers.helpers import (modprobe_driver, modprobe_driver_check)
-from bench.helpers.log import HOST_DMESG_FILE
-from bench.configurators.vgpu_profile_config import VgpuProfileConfigurator, VfSchedulingMode
 from bench.configurators.vgpu_profile import VgpuProfile
+from bench.configurators.vgpu_profile_config import (VfSchedulingMode,
+                                                     VgpuProfileConfigurator)
 from bench.configurators.vmtb_config import VmtbConfigurator
-from bench.machines.host import Host, Device
+from bench.helpers.helpers import modprobe_driver, modprobe_driver_check
+from bench.helpers.log import HOST_DMESG_FILE
+from bench.machines.host import Device, Host
 from bench.machines.virtual.vm import VirtualMachine
 
-
 logger = logging.getLogger('Conftest')
 
 
@@ -89,15 +88,20 @@ class VmmTestingSetup:
         self.host.load_drivers()
         self.host.discover_devices()
 
+        # VF migration requires vendor specific VFIO driver (e.g. xe-vfio-pci)
+        vf_migration_support: bool = self.host.is_driver_loaded(f'{self.host.drm_driver_name}-vfio-pci')
+
         logger.info("\nDUT info:"
                     "\n\tCard index: %s"
                     "\n\tPCI BDF: %s "
                     "\n\tDevice ID: %s (%s)"
-                    "\n\tHost DRM driver: %s",
+                    "\n\tHost DRM driver: %s"
+                    "\n\tVF migration support: %s",
                     self.host.dut_index,
                     self.get_dut().pci_info.bdf,
                     self.get_dut().pci_info.devid, self.get_dut().gpu_model,
-                    self.get_dut().driver.get_name())
+                    self.get_dut().driver.get_name(),
+                    vf_migration_support)
 
         self.vgpu_profile: VgpuProfile = self.get_vgpu_profile()
 
@@ -105,7 +109,8 @@ class VmmTestingSetup:
         self.vms: typing.List[VirtualMachine] = [
             VirtualMachine(vm_idx, self.guest_os_image,
                            vmtb_config.get_guest_config().driver,
-                           vmtb_config.get_guest_config().igt_config)
+                           vmtb_config.get_guest_config().igt_config,
+                           vf_migration_support)
             for vm_idx in range(min(self.vgpu_profile.num_vfs, self.testing_config.max_num_vms))]
 
     def get_vgpu_profile(self) -> VgpuProfile:
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH i-g-t 02/10] tools/vmtb: Fix DUT selection based on card index
  2026-02-24  7:50 [PATCH i-g-t 00/10] vmtb: Modernize SR-IOV VM Test Bench core Adam Miszczak
  2026-02-24  7:50 ` [PATCH i-g-t 01/10] tools/vmtb: Update QEMU parameters Adam Miszczak
@ 2026-02-24  7:50 ` Adam Miszczak
  2026-03-10 10:26   ` Bernatowicz, Marcin
  2026-02-24  7:50 ` [PATCH i-g-t 03/10] tools/vmtb: Fix VM snapshot query handling Adam Miszczak
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 25+ messages in thread
From: Adam Miszczak @ 2026-02-24  7:50 UTC (permalink / raw)
  To: igt-dev; +Cc: marcin.bernatowicz, kamil.konieczny

A GPU devices list need to be searched by requested card index
(device minor number) - not list index.
Implement Host.get_device() function to return Device
with a given minor number from the detected devices list,
bound to a requested DRM driver (e.g. xe).
DUT reference is now kept by the VmmTestingSetup,
not embedded within Host class.

Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
---
 tools/vmtb/bench/machines/host.py            | 12 +++++++-----
 tools/vmtb/bench/machines/physical/device.py |  5 ++++-
 tools/vmtb/vmm_flows/conftest.py             | 15 ++++++++-------
 tools/vmtb/vmm_flows/test_basic.py           |  4 ++--
 4 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/tools/vmtb/bench/machines/host.py b/tools/vmtb/bench/machines/host.py
index 666f35c26..aecc7709a 100644
--- a/tools/vmtb/bench/machines/host.py
+++ b/tools/vmtb/bench/machines/host.py
@@ -1,8 +1,7 @@
 # SPDX-License-Identifier: MIT
-# Copyright © 2024 Intel Corporation
+# Copyright © 2024-2026 Intel Corporation
 
 import logging
-import re
 import shlex
 import signal
 import subprocess
@@ -24,13 +23,12 @@ class Host(MachineInterface):
     def __init__(self) -> None:
         self.running_procs: typing.Dict[int, subprocess.Popen] = {}
         self.gpu_devices: typing.List[Device] = []
-        self.dut_index: int = 0
         # Initialize in conftest/VmmTestingSetup:
         self.drm_driver_name: str
         self.igt_config: VmtbIgtConfig
 
     def __str__(self) -> str:
-        return f'Host-{self.gpu_devices[self.dut_index].pci_info.bdf}'
+        return 'Host'
 
     @LogDecorators.parse_kmsg
     def execute(self, command: str) -> int:
@@ -181,9 +179,13 @@ class Host(MachineInterface):
 
         logger.debug("Detected GPU PCI device(s):")
         for dev in self.gpu_devices:
-            logger.debug("[%s] PCI BDF: %s / DevID: %s (%s)",
+            logger.debug("[card%s] PCI BDF: %s / DevID: %s (%s)",
                           dev.pci_info.minor_number, dev.pci_info.bdf, dev.pci_info.devid, dev.gpu_model)
 
+    def get_device(self, dev_minor: int) -> typing.Optional[Device]:
+        """Find device with a given minor number within detected GPU devices list."""
+        return next((dev for dev in self.gpu_devices if dev.pci_info.minor_number == dev_minor), None)
+
     def suspend(self, mode: SuspendMode = SuspendMode.ACPI_S3) -> None:
         """Perform host suspend cycle (ACPI S3) via rtcwake tool."""
         wakeup_delay = 10 # wakeup timer in seconds
diff --git a/tools/vmtb/bench/machines/physical/device.py b/tools/vmtb/bench/machines/physical/device.py
index 12a5d5f7d..887f607e4 100644
--- a/tools/vmtb/bench/machines/physical/device.py
+++ b/tools/vmtb/bench/machines/physical/device.py
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: MIT
-# Copyright © 2024 Intel Corporation
+# Copyright © 2024-2026 Intel Corporation
 
 import importlib
 import logging
@@ -48,6 +48,9 @@ class Device(DeviceInterface):
         self.gpu_model: str = pci.get_gpu_model(self.pci_info.devid)
         self.driver: DriverInterface = self.instantiate_driver(driver, self.pci_info.minor_number)
 
+    def __str__(self) -> str:
+        return f'Dev-{self.pci_info.bdf}'
+
     def instantiate_driver(self, driver_name: str, card_index: int) -> Any:
         module_name = f'bench.drivers.{driver_name}'
         class_name = f'{driver_name.capitalize()}Driver'
diff --git a/tools/vmtb/vmm_flows/conftest.py b/tools/vmtb/vmm_flows/conftest.py
index 675312253..3bfac01c4 100644
--- a/tools/vmtb/vmm_flows/conftest.py
+++ b/tools/vmtb/vmm_flows/conftest.py
@@ -81,12 +81,12 @@ class VmmTestingSetup:
 
         self.vgpu_profiles_dir = vmtb_config.vmtb_config_file.parent / vmtb_config.config.vgpu_profiles_path
 
-        self.host.dut_index = self.dut_index
         self.host.drm_driver_name = vmtb_config.get_host_config().driver
         self.host.igt_config = vmtb_config.get_host_config().igt_config
 
         self.host.load_drivers()
         self.host.discover_devices()
+        self.dut: Device = self.host.get_device(self.dut_index)
 
         # VF migration requires vendor specific VFIO driver (e.g. xe-vfio-pci)
         vf_migration_support: bool = self.host.is_driver_loaded(f'{self.host.drm_driver_name}-vfio-pci')
@@ -97,7 +97,7 @@ class VmmTestingSetup:
                     "\n\tDevice ID: %s (%s)"
                     "\n\tHost DRM driver: %s"
                     "\n\tVF migration support: %s",
-                    self.host.dut_index,
+                    self.dut_index,
                     self.get_dut().pci_info.bdf,
                     self.get_dut().pci_info.devid, self.get_dut().gpu_model,
                     self.get_dut().driver.get_name(),
@@ -127,11 +127,12 @@ class VmmTestingSetup:
         return vgpu_profile
 
     def get_dut(self) -> Device:
-        try:
-            return self.host.gpu_devices[self.dut_index]
-        except IndexError as exc:
-            logger.error("Invalid VMTB config - device card index = %s not available", self.dut_index)
-            raise exceptions.VmtbConfigError(f'Device card index = {self.dut_index} not available') from exc
+        if self.dut is None:
+            logger.error("Invalid VMTB config - DRM card%s is not bound to %s driver",
+                         self.dut_index, self.host.drm_driver_name)
+            raise exceptions.VmtbConfigError(f'Invalid VMTB config - DRM card{self.dut_index} device not supported')
+
+        return self.dut
 
     @property
     def get_vm(self):
diff --git a/tools/vmtb/vmm_flows/test_basic.py b/tools/vmtb/vmm_flows/test_basic.py
index 100be7652..1d3a68b36 100644
--- a/tools/vmtb/vmm_flows/test_basic.py
+++ b/tools/vmtb/vmm_flows/test_basic.py
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: MIT
-# Copyright © 2024 Intel Corporation
+# Copyright © 2024-2026 Intel Corporation
 
 import logging
 import time
@@ -82,7 +82,7 @@ class TestVmWorkload:
             logger.info("[%s] Verify result of basic WL", igt.target)
             assert igt_check(igt)
 
-        logger.info("[%s] Verify result of basic WL", ts.host)
+        logger.info("[Host %s] Verify result of basic WL", ts.get_dut())
         igt_run_check(ts.host, IgtType.EXEC_STORE)
 
     def test_wsim(self, setup_vms):
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH i-g-t 03/10] tools/vmtb: Fix VM snapshot query handling
  2026-02-24  7:50 [PATCH i-g-t 00/10] vmtb: Modernize SR-IOV VM Test Bench core Adam Miszczak
  2026-02-24  7:50 ` [PATCH i-g-t 01/10] tools/vmtb: Update QEMU parameters Adam Miszczak
  2026-02-24  7:50 ` [PATCH i-g-t 02/10] tools/vmtb: Fix DUT selection based on card index Adam Miszczak
@ 2026-02-24  7:50 ` Adam Miszczak
  2026-03-10 10:29   ` Bernatowicz, Marcin
  2026-02-24  7:50 ` [PATCH i-g-t 04/10] tools/vmtb: Extend IGT and WSIM abstractions Adam Miszczak
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 25+ messages in thread
From: Adam Miszczak @ 2026-02-24  7:50 UTC (permalink / raw)
  To: igt-dev; +Cc: marcin.bernatowicz, kamil.konieczny

QMP command 'query-named-block-nodes' is used to select a block device
for saving VM snapshot (QMP 'snapshot-save').

Add polling for the command's return message in QMP response queue.
It sporadically happened that unsolicited QMP message like:
[QMP RSP] <- {"timestamp": {...}, "event": "RTC_CHANGE" ...}
was falsely taken as a response to previously submitted
QMP 'query-named-block-nodes' command.
Hence, no 'block device node' argument is passed to
'snapshot-load' command which leads to migration tests fail.
Also, add a condition to check if a given block node
is writable (not read-only).

Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
---
 .../machines/virtual/backends/qmp_monitor.py  | 25 ++++++++++---------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/tools/vmtb/bench/machines/virtual/backends/qmp_monitor.py b/tools/vmtb/bench/machines/virtual/backends/qmp_monitor.py
index ef3c8aa1c..d364a5711 100644
--- a/tools/vmtb/bench/machines/virtual/backends/qmp_monitor.py
+++ b/tools/vmtb/bench/machines/virtual/backends/qmp_monitor.py
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: MIT
-# Copyright © 2024 Intel Corporation
+# Copyright © 2024-2026 Intel Corporation
 
 import json
 import logging
@@ -123,17 +123,18 @@ class QmpMonitor():
         ret: typing.Dict = {}
 
         qmp_msg = self.qmp_queue.get()
-        # logger.debug('[QMP RSP Queue] -> %s', qmp_msg)
-        if 'return' in qmp_msg:
-            ret = qmp_msg.get('return')
-            for block in ret:
-                if block.get('drv') == 'qcow2':
-                    node_name = block.get('node-name')
-                    # Get the most recent state snapshot from the snapshots list:
-                    snapshots = block.get('image').get('snapshots')
-                    if snapshots:
-                        snapshot_tag = snapshots[-1].get('name')
-                    break
+        while 'return' not in qmp_msg:
+            qmp_msg = self.qmp_queue.get()
+
+        ret = qmp_msg.get('return')
+        for block in ret:
+            if block.get('drv') == 'qcow2' and block.get('ro') is False:
+                node_name = block.get('node-name')
+                # Get the most recent state snapshot from the snapshots list:
+                snapshots = block.get('image').get('snapshots')
+                if snapshots:
+                    snapshot_tag = snapshots[-1].get('name')
+                break
 
         return (node_name, snapshot_tag)
 
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH i-g-t 04/10] tools/vmtb: Extend IGT and WSIM abstractions
  2026-02-24  7:50 [PATCH i-g-t 00/10] vmtb: Modernize SR-IOV VM Test Bench core Adam Miszczak
                   ` (2 preceding siblings ...)
  2026-02-24  7:50 ` [PATCH i-g-t 03/10] tools/vmtb: Fix VM snapshot query handling Adam Miszczak
@ 2026-02-24  7:50 ` Adam Miszczak
  2026-03-10 10:36   ` Bernatowicz, Marcin
  2026-02-24  7:50 ` [PATCH i-g-t 05/10] tools/vmtb: VF auto/fair provisioning support Adam Miszczak
                   ` (9 subsequent siblings)
  13 siblings, 1 reply; 25+ messages in thread
From: Adam Miszczak @ 2026-02-24  7:50 UTC (permalink / raw)
  To: igt-dev; +Cc: marcin.bernatowicz, kamil.konieczny

Introduce few improvements to IGT and gem_wsim executors:

1. Add gem_wsim workload descriptor resources config
In order to place workload files in a common resources directory,
extend VMTB config with a relevant entry and read the path in a conftest.

Implement capability for device specific workload files in wsim resources
directory (as different GPU devices may have various sets of engines).
Wsim device specific path format looks as follows:
[vmtb_root_path]/vmm_flows/resources/wsim/[device_name_abbr]/[wl_desc].wsim
e.g.:
- resources/wsim/ptl/wl.wsim
- resources/wsim/bmg/wl.wsim

2. Support gem_wsim workload files on VM
So far GemWsim was initialized with a simple string workload descriptor
passed with '-w <workload>' option.
However, multiple complex workloads are expected for a busy VF migration
scenarios - therefore it would be handy to define it as workload files.
Gem_wsim input files will be deployed as VMTB resources on a host,
whereas we want to execute it on VM as well.
Hence, content of the wsim workload file is copied to /tmp on a guest/host
and executed from that location.
In case of the host, original (resources) location will work
as a wsim file input, however temp file is still used for simplicity
and consistency (to avoid instance type checks).

3. Add IGT and WSIM results check function
Extend IgtExecutor and GemWsim with new check_results() method to allow
object-oriented approach for checking IGT/WSIM results and unify interfaces.
Existing helper - igt_check(IgtExecutor) is still supported,
but IgtExecutor.check_results() is now preferred.
Also, implement IgtExecutor's is_running() (similarly to GemWsim)
and keep the process state (ProcessResult).

Introduced change simplifies supporting both IGT and gem_wsim workloads
in busy migration tests.

4. Support IGT tests repeated execution
Few planned VF busy migration scenarios require executing short IGT tests
in a longer time slot (in a loop).
To achieve it, allow IgtExecutor to accept expected number of IGT test
repeats and reflect it in a testlist passed to the igt_runner
(multiply requested test entries).

By default, IgtExecutor's 'num_repeats' input parameter is set to 1,
so in the usual case (single IGT execution) it doesn't need to be
explicitly provided.

Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
---
 tools/vmtb/bench/configurators/vmtb_config.py |  4 +-
 tools/vmtb/bench/executors/gem_wsim.py        | 45 +++++++++++++++----
 tools/vmtb/bench/executors/igt.py             | 36 ++++++++++++---
 tools/vmtb/bench/machines/physical/device.py  |  2 +-
 tools/vmtb/vmm_flows/conftest.py              |  8 +++-
 tools/vmtb/vmtb_config.json                   |  1 +
 6 files changed, 78 insertions(+), 18 deletions(-)

diff --git a/tools/vmtb/bench/configurators/vmtb_config.py b/tools/vmtb/bench/configurators/vmtb_config.py
index 49dde4589..8fd2b87d5 100644
--- a/tools/vmtb/bench/configurators/vmtb_config.py
+++ b/tools/vmtb/bench/configurators/vmtb_config.py
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: MIT
-# Copyright © 2024 Intel Corporation
+# Copyright © 2024-2026 Intel Corporation
 
 import json
 import logging
@@ -40,6 +40,7 @@ class VmtbConfig:
     host_config: VmtbHostConfig
     guest_config: VmtbGuestConfig
     vgpu_profiles_path: str
+    wsim_wl_path: str
     guc_ver_path: str
     ci_host_dmesg_file: str
 
@@ -104,6 +105,7 @@ class VmtbConfigJsonReader:
             host_config=vmtb_host_config,
             guest_config=vmtb_guest_config,
             vgpu_profiles_path=config_json['resources']['vgpu_profiles_path'],
+            wsim_wl_path=config_json['resources']['wsim_wl_path'],
             guc_ver_path=config_json['resources']['guc_ver_path'],
             ci_host_dmesg_file=config_json['ci']['host_dmesg_file'])
 
diff --git a/tools/vmtb/bench/executors/gem_wsim.py b/tools/vmtb/bench/executors/gem_wsim.py
index 46fa2291c..0cdfcc7e4 100644
--- a/tools/vmtb/bench/executors/gem_wsim.py
+++ b/tools/vmtb/bench/executors/gem_wsim.py
@@ -1,9 +1,10 @@
 # SPDX-License-Identifier: MIT
-# Copyright © 2024 Intel Corporation
+# Copyright © 2024-2026 Intel Corporation
 
 import logging
 import re
 import typing
+from pathlib import Path
 
 from bench import exceptions
 from bench.executors.shell import ShellExecutor
@@ -23,13 +24,28 @@ PREEMPT_10MS_WORKLOAD = (f'1.DEFAULT.{int(ONE_CYCLE_DURATION_MS * 1000 / 2)}.0.0
 NON_PREEMPT_10MS_WORKLOAD = f'X.1.0,X.2.0,{PREEMPT_10MS_WORKLOAD}'
 
 class GemWsim(ShellExecutor):
-    def __init__(self, machine: MachineInterface, num_clients: int = 1, num_repeats: int = 1,
-                 workload: str = PREEMPT_10MS_WORKLOAD, timeout: int = DEFAULT_TIMEOUT) -> None:
-        super().__init__(
-            machine,
-            f'/usr/local/libexec/igt-gpu-tools/benchmarks/gem_wsim -w {workload} -c {num_clients} -r {num_repeats}',
-            timeout)
-        self.machine_id = str(machine)
+    def __init__(self, target: MachineInterface,
+                 num_clients: int = 1,
+                 num_repeats: int = 1,
+                 workload: str = PREEMPT_10MS_WORKLOAD,
+                 timeout: int = DEFAULT_TIMEOUT) -> None:
+
+        self.machine_id = str(target)
+        wl_file_path = Path(workload)
+
+        if wl_file_path.is_file():
+            # Copy workload descriptor from the source host file
+            # to the requested target machine (VM or host)
+            workload = '/tmp/igt_workload.wsim'
+            wl_desc = wl_file_path.read_text(encoding='utf-8')
+            target.write_file_content(workload, wl_desc)
+
+            logger.debug("IGT/wsim workload descriptor:\n%s", wl_desc)
+
+        wsim_path = Path(target.get_igt_config().test_dir) / 'benchmarks' / 'gem_wsim'
+        command = f'{wsim_path} -w {workload} -c {num_clients} -r {num_repeats}'
+
+        super().__init__(target, command, timeout)
 
     def __str__(self) -> str:
         return f'gem_wsim({self.machine_id}:{self.pid})'
@@ -49,6 +65,19 @@ class GemWsim(ShellExecutor):
         raise exceptions.GemWsimError(f'{self}: exit_code: {proc_result.exit_code}'
                                       f' stdout: {proc_result.stdout} stderr: {proc_result.stderr}')
 
+    def check_results(self) -> bool:
+        """Verify gem_wsim execution results. Return True for workload success, False on fail."""
+        # TODO: support also checking wsim workload: 'Verify Xe spinner batch completion'
+        try:
+            wl_results: GemWsimResult = self.wait_results()
+        except exceptions.GemWsimError as exc:
+            logger.error("[%s] WSIM failed: %s", self.target, exc)
+            return False
+
+        logger.debug("[%s] WSIM passed in %ss (%s WL/s)",
+                      self.target, wl_results.elapsed_sec, wl_results.workloads_per_sec)
+        return True
+
 
 def gem_wsim_parallel_exec_and_check(vms: typing.List[MachineInterface], workload: str, iterations: int,
                                      expected: typing.Optional[GemWsimResult] = None) -> GemWsimResult:
diff --git a/tools/vmtb/bench/executors/igt.py b/tools/vmtb/bench/executors/igt.py
index 4296464c2..a08f71d54 100644
--- a/tools/vmtb/bench/executors/igt.py
+++ b/tools/vmtb/bench/executors/igt.py
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: MIT
-# Copyright © 2024 Intel Corporation
+# Copyright © 2024-2026 Intel Corporation
 
 import enum
 import json
@@ -34,6 +34,7 @@ igt_tests: typing.Dict[IgtType, typing.Tuple[str, str]] = {
 class IgtExecutor(ExecutorInterface):
     def __init__(self, target: MachineInterface,
                  test: typing.Union[str, IgtType],
+                 num_repeats: int = 1,
                  timeout: int = DEFAULT_TIMEOUT) -> None:
         self.igt_config = target.get_igt_config()
 
@@ -46,18 +47,25 @@ class IgtExecutor(ExecutorInterface):
         self.results: typing.Dict[str, typing.Any] = {}
         self.target: MachineInterface = target
         self.igt: str = test if isinstance(test, str) else self.select_igt_variant(target.get_drm_driver_name(), test)
-        self.target.write_file_content(testlist, self.igt)
-        self.timeout: int = timeout
 
         logger.info("[%s] Execute IGT test: %s", target, self.igt)
+        if num_repeats > 1:
+            logger.debug("Repeat IGT execution %s times", num_repeats)
+            self.igt = (self.igt + '\n') * num_repeats
+
+        self.target.write_file_content(testlist, self.igt)
+        self.timeout: int = timeout
+        self.proc_result = ProcessResult()
         self.pid: int = self.target.execute(command)
 
     # Executor interface implementation
     def status(self) -> ProcessResult:
-        return self.target.execute_status(self.pid)
+        self.proc_result = self.target.execute_status(self.pid)
+        return self.proc_result
 
     def wait(self) -> ProcessResult:
-        return self.target.execute_wait(self.pid, self.timeout)
+        self.proc_result = self.target.execute_wait(self.pid, self.timeout)
+        return self.proc_result
 
     def sendsig(self, sig: signal.Signals) -> None:
         self.target.execute_signal(self.pid, sig)
@@ -69,9 +77,25 @@ class IgtExecutor(ExecutorInterface):
         self.sendsig(signal.SIGKILL)
 
     # IGT specific methods
+    def is_running(self) -> bool:
+        return not self.status().exited
+
+    def check_results(self) -> bool:
+        """Verify IGT test results. Return True for test success, False on fail."""
+        if not self.proc_result.exited:
+            self.proc_result = self.wait()
+
+        if self.proc_result.exit_code == 0 and self.did_pass():
+            logger.debug("[%s] IGT passed", self.target)
+            return True
+
+        logger.error("[%s] IGT failed: %s", self.target, self.proc_result)
+        return False
+
     def get_results_log(self) -> typing.Dict:
         # Results are cached
         if self.results:
+            logger.debug("Get available IGT results from cache")
             return self.results
         path = posixpath.join(self.igt_config.result_dir, 'results.json')
         result = self.target.read_file_content(path)
@@ -95,7 +119,7 @@ class IgtExecutor(ExecutorInterface):
                 continue
             fail_case = fail_case + aggregate[key]
 
-        logger.debug('Full IGT test results:\n%s', json.dumps(results, indent=4))
+        logger.debug("[%s] Full IGT test results:\n%s", self.target, json.dumps(results, indent=4))
 
         if fail_case > 0:
             logger.error('Test failed!')
diff --git a/tools/vmtb/bench/machines/physical/device.py b/tools/vmtb/bench/machines/physical/device.py
index 887f607e4..a487c0e5f 100644
--- a/tools/vmtb/bench/machines/physical/device.py
+++ b/tools/vmtb/bench/machines/physical/device.py
@@ -45,7 +45,7 @@ class Device(DeviceInterface):
 
     def __init__(self, bdf: str, driver: str) -> None:
         self.pci_info = self.PciInfo(bdf)
-        self.gpu_model: str = pci.get_gpu_model(self.pci_info.devid)
+        self.gpu_model = pci.get_gpu_model(self.pci_info.devid)
         self.driver: DriverInterface = self.instantiate_driver(driver, self.pci_info.minor_number)
 
     def __str__(self) -> str:
diff --git a/tools/vmtb/vmm_flows/conftest.py b/tools/vmtb/vmm_flows/conftest.py
index 3bfac01c4..28c0b5f00 100644
--- a/tools/vmtb/vmm_flows/conftest.py
+++ b/tools/vmtb/vmm_flows/conftest.py
@@ -79,8 +79,6 @@ class VmmTestingSetup:
         self.guest_os_image = vmtb_config.get_guest_config().os_image_path if cmdline_config['vm_image'] is None \
                          else cmdline_config['vm_image']
 
-        self.vgpu_profiles_dir = vmtb_config.vmtb_config_file.parent / vmtb_config.config.vgpu_profiles_path
-
         self.host.drm_driver_name = vmtb_config.get_host_config().driver
         self.host.igt_config = vmtb_config.get_host_config().igt_config
 
@@ -103,6 +101,12 @@ class VmmTestingSetup:
                     self.get_dut().driver.get_name(),
                     vf_migration_support)
 
+        vmtb_root_path = vmtb_config.vmtb_config_file.parent
+        self.vgpu_profiles_dir = vmtb_root_path / vmtb_config.config.vgpu_profiles_path
+        # Device specific wsim descriptors directory path, e.g.:
+        # [vmtb_root]/vmm_flows/resources/wsim/ptl (last subdir is lowercase key/name from pci.GpuModel class)
+        self.wsim_wl_dir = vmtb_root_path / vmtb_config.config.wsim_wl_path / self.get_dut().gpu_model.name.lower()
+
         self.vgpu_profile: VgpuProfile = self.get_vgpu_profile()
 
         # Start maximum requested number of VMs, but not more than VFs supported by the given vGPU profile
diff --git a/tools/vmtb/vmtb_config.json b/tools/vmtb/vmtb_config.json
index 640a64123..2b8fb43f3 100644
--- a/tools/vmtb/vmtb_config.json
+++ b/tools/vmtb/vmtb_config.json
@@ -23,6 +23,7 @@
     },
     "resources": {
         "vgpu_profiles_path": "vmm_flows/resources/vgpu_profiles",
+        "wsim_wl_path": "vmm_flows/resources/wsim",
         "guc_ver_path": "vmm_flows/resources/guc"
     },
     "ci": {
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH i-g-t 05/10] tools/vmtb: VF auto/fair provisioning support
  2026-02-24  7:50 [PATCH i-g-t 00/10] vmtb: Modernize SR-IOV VM Test Bench core Adam Miszczak
                   ` (3 preceding siblings ...)
  2026-02-24  7:50 ` [PATCH i-g-t 04/10] tools/vmtb: Extend IGT and WSIM abstractions Adam Miszczak
@ 2026-02-24  7:50 ` Adam Miszczak
  2026-03-10 10:38   ` Bernatowicz, Marcin
  2026-02-24  7:50 ` [PATCH i-g-t 06/10] tools/vmtb: Refactor driver interfaces Adam Miszczak
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 25+ messages in thread
From: Adam Miszczak @ 2026-02-24  7:50 UTC (permalink / raw)
  To: igt-dev; +Cc: marcin.bernatowicz, kamil.konieczny

Currently test variants allow provisioning with vGPU profiles only,
however, xe KMD supports also fair resources allocation (auto-provisioning).
Therefore, the following provisioning modes shall be supported from now:
- vGPU profile: both PF/VF resources and scheduling (via debugfs)
- fair/auto provisioning (driver defaults for resources and scheduling)
- fair/auto resources provisioning with concrete scheduling profile

Test variants are now specified as a list of 3-element tuples:
   test_variants_N = [(num_of_vfs, VfProvisioningMode.X, VfSchedulingMode.Y), ...]
Test ID printed in the following format:
   test_name[NxVF-(P:provisioning_mode S:scheduling_mode)]

Additional changes:
- align parametrized tests with the new variants format
- use Device methods: set_resources and set_scheduling
  for relevant provisioning modes
- split vGPU profile printing to resources and scheduler part
- fix PF lmem_spare getter/setter to check for LMEM presence
- detect standalone media GT for proper VF provisioning

Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
---
 .../vmtb/bench/configurators/vgpu_profile.py  | 37 +++++---
 .../configurators/vgpu_profile_config.py      |  7 +-
 tools/vmtb/bench/drivers/driver_interface.py  |  6 +-
 tools/vmtb/bench/drivers/xe.py                | 16 +++-
 tools/vmtb/bench/machines/physical/device.py  | 58 +++++++-----
 tools/vmtb/vmm_flows/conftest.py              | 89 ++++++++++++++-----
 tools/vmtb/vmm_flows/test_basic.py            | 21 +++--
 7 files changed, 164 insertions(+), 70 deletions(-)

diff --git a/tools/vmtb/bench/configurators/vgpu_profile.py b/tools/vmtb/bench/configurators/vgpu_profile.py
index 7c536c1d0..c680fdb83 100644
--- a/tools/vmtb/bench/configurators/vgpu_profile.py
+++ b/tools/vmtb/bench/configurators/vgpu_profile.py
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: MIT
-# Copyright © 2024 Intel Corporation
+# Copyright © 2024-2026 Intel Corporation
 
 import json
 import logging
@@ -55,8 +55,19 @@ class VgpuProfile:
     def print_parameters(self) -> None:
         logger.info(
             "\nvGPU Profile:\n"
-            "   Num VFs = %s\n"
-            "\nResources:\n"
+            "   Num VFs = %s\n",
+            self.num_vfs)
+        self.print_resources_config()
+        self.print_scheduler_config()
+        logger.info(
+            "\nSecurity:\n"
+            "   Reset After Vf Switch = %s\n",
+            self.security.reset_after_vf_switch
+        )
+
+    def print_resources_config(self) -> None:
+        logger.info(
+            "\nResources config:\n"
             "   PF:\n"
             "\tLMEM = %s B\n"
             "\tContexts = %s\n"
@@ -66,24 +77,24 @@ class VgpuProfile:
             "\tLMEM = %s B\n"
             "\tContexts = %s\n"
             "\tDoorbells = %s\n"
-            "\tGGTT = %s B\n"
-            "\nScheduling:\n"
+            "\tGGTT = %s B\n",
+            self.resources.pfLmem, self.resources.pfContexts, self.resources.pfDoorbells, self.resources.pfGgtt,
+            self.resources.vfLmem, self.resources.vfContexts, self.resources.vfDoorbells, self.resources.vfGgtt,
+        )
+
+    def print_scheduler_config(self) -> None:
+        logger.info(
+            "\nScheduling config:\n"
             "   Schedule If Idle = %s\n"
             "   PF:\n"
             "\tExecution Quanta = %s ms\n"
             "\tPreemption Timeout = %s us\n"
             "   VF:\n"
             "\tExecution Quanta = %s ms\n"
-            "\tPreemption Timeout = %s us\n"
-            "\nSecurity:\n"
-            "   Reset After Vf Switch = %s\n",
-            self.num_vfs,
-            self.resources.pfLmem, self.resources.pfContexts, self.resources.pfDoorbells, self.resources.pfGgtt,
-            self.resources.vfLmem, self.resources.vfContexts, self.resources.vfDoorbells, self.resources.vfGgtt,
+            "\tPreemption Timeout = %s us\n",
             self.scheduler.scheduleIfIdle,
             self.scheduler.pfExecutionQuanta, self.scheduler.pfPreemptionTimeout,
-            self.scheduler.vfExecutionQuanta, self.scheduler.vfPreemptionTimeout,
-            self.security.reset_after_vf_switch
+            self.scheduler.vfExecutionQuanta, self.scheduler.vfPreemptionTimeout
         )
 
 
diff --git a/tools/vmtb/bench/configurators/vgpu_profile_config.py b/tools/vmtb/bench/configurators/vgpu_profile_config.py
index 915cfb2b8..4bddb641e 100644
--- a/tools/vmtb/bench/configurators/vgpu_profile_config.py
+++ b/tools/vmtb/bench/configurators/vgpu_profile_config.py
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: MIT
-# Copyright © 2024 Intel Corporation
+# Copyright © 2024-2026 Intel Corporation
 
 import logging
 from enum import Enum
@@ -17,6 +17,11 @@ from bench.configurators.vgpu_profile import (VgpuProfile,
 logger = logging.getLogger('DeviceConfigurator')
 
 
+class VfProvisioningMode(Enum):
+    VGPU_PROFILE = 0
+    AUTO = 1
+
+
 class VfSchedulingMode(str, Enum):
     INFINITE = 'Infinite' # Infinite EQ/PT - HW default
     DEFAULT_PROFILE = 'Default_Profile' # Default vGPU scheduler profile
diff --git a/tools/vmtb/bench/drivers/driver_interface.py b/tools/vmtb/bench/drivers/driver_interface.py
index af2f96837..3026fece7 100644
--- a/tools/vmtb/bench/drivers/driver_interface.py
+++ b/tools/vmtb/bench/drivers/driver_interface.py
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: MIT
-# Copyright © 2024 Intel Corporation
+# Copyright © 2024-2026 Intel Corporation
 
 import abc
 import enum
@@ -65,6 +65,10 @@ class DriverInterface(abc.ABC):
     def has_lmem(self) -> bool:
         raise NotImplementedError
 
+    @abc.abstractmethod
+    def is_media_gt(self, gt_num: int) -> bool:
+        raise NotImplementedError
+
     @abc.abstractmethod
     def get_auto_provisioning(self) -> bool:
         raise NotImplementedError
diff --git a/tools/vmtb/bench/drivers/xe.py b/tools/vmtb/bench/drivers/xe.py
index 009cec5be..c2b9643bb 100644
--- a/tools/vmtb/bench/drivers/xe.py
+++ b/tools/vmtb/bench/drivers/xe.py
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: MIT
-# Copyright © 2024 Intel Corporation
+# Copyright © 2024-2026 Intel Corporation
 
 import logging
 import typing
@@ -95,11 +95,18 @@ class XeDriver(DriverInterface):
         path = self.debugfs_path / 'gt0' / 'pf' / 'lmem_spare'
         return path.exists()
 
+    def is_media_gt(self, gt_num: int) -> bool:
+        # XXX: is lack of PF's ggtt/lmem_spare or VF's ggtt/lmem_quota
+        # a best way to check for standalone media GT?
+        path = self.debugfs_path / f'gt{gt_num}' / 'pf' / 'ggtt_spare'
+        return not path.exists()
+
     def get_auto_provisioning(self) -> bool:
         raise exceptions.NotAvailableError('auto_provisioning attribute not available')
 
     def set_auto_provisioning(self, val: bool) -> None:
-        raise exceptions.NotAvailableError('auto_provisioning attribute not available')
+        # No-op - xe driver doesn't publish this attribute
+        pass
 
     def cancel_work(self) -> None:
         # Function to cancel all remaing work on GPU (for test cleanup).
@@ -129,11 +136,12 @@ class XeDriver(DriverInterface):
 
     def get_pf_lmem_spare(self, gt_num: int) -> int:
         path = self.__helper_create_debugfs_path(0, gt_num, '', 'lmem_spare')
-        return int(self.__read_debugfs(path))
+        return int(self.__read_debugfs(path)) if self.has_lmem() else 0
 
     def set_pf_lmem_spare(self, gt_num: int, val: int) -> None:
         path = self.__helper_create_debugfs_path(0, gt_num, '', 'lmem_spare')
-        self.__write_debugfs(path, str(val))
+        if self.has_lmem():
+            self.__write_debugfs(path, str(val))
 
     def get_pf_contexts_spare(self, gt_num: int) -> int:
         path = self.__helper_create_debugfs_path(0, gt_num, '', 'contexts_spare')
diff --git a/tools/vmtb/bench/machines/physical/device.py b/tools/vmtb/bench/machines/physical/device.py
index a487c0e5f..250466733 100644
--- a/tools/vmtb/bench/machines/physical/device.py
+++ b/tools/vmtb/bench/machines/physical/device.py
@@ -83,6 +83,9 @@ class Device(DeviceInterface):
     def has_lmem(self) -> bool:
         return self.driver.has_lmem()
 
+    def is_gt_media_type(self, gt_num: int) -> bool:
+        return self.driver.is_media_gt(gt_num)
+
     def create_vf(self, num: int) -> int:
         """Enable a requested number of VFs.
         Disable SRIOV drivers autoprobe to allow VFIO driver override for VFs.
@@ -156,37 +159,44 @@ class Device(DeviceInterface):
         bdf_list = [self.get_vf_bdf(vf) for vf in vf_list]
         return bdf_list
 
-    def provision(self, profile: VgpuProfile) -> None:
-        logger.info("[%s] Provision VFs - set vGPU profile for %s VFs", self.pci_info.bdf, profile.num_vfs)
+    def __set_provisioning(self, num_vfs: int, profile: VgpuProfile, set_resources: bool) -> None:
+        """Helper to write provisioning attributes over sysfs/debugfs for PF and requested number of VFs.
+        If 'set_resources' parameter is True - apply the full vGPU profile (hard resources and scheduling).
+        Otherwise, set only scheduling profile (e.g. in case of auto resources provisioning).
+        """
+        main_gt_nums = [gt_num for gt_num in range(self.get_num_gts()) if not self.is_gt_media_type(gt_num)]
 
-        num_vfs = profile.num_vfs
-        num_gts = self.get_num_gts() # Number of tiles (GTs)
-        gt_nums = [0] if num_gts == 1 else [0, 1] # Tile (GT) numbers/indexes
+        logger.info("[%s] Provision %sxVFs on main GT%s", self.pci_info.bdf, num_vfs, main_gt_nums)
 
-        for gt_num in gt_nums:
-            self.driver.set_pf_policy_sched_if_idle(gt_num, int(profile.scheduler.scheduleIfIdle))
+        for gt_num in main_gt_nums:
+            if set_resources:
+                self.set_resources(0, gt_num, profile.resources)
+            self.set_scheduling(0, gt_num, profile.scheduler)
             self.driver.set_pf_policy_reset_engine(gt_num, int(profile.security.reset_after_vf_switch))
-            self.driver.set_exec_quantum_ms(0, gt_num, profile.scheduler.pfExecutionQuanta)
-            self.driver.set_preempt_timeout_us(0, gt_num, profile.scheduler.pfPreemptionTimeout)
-            self.driver.set_doorbells_quota(0, gt_num, profile.resources.pfDoorbells)
-            # PF contexts are currently assigned by the driver and cannot be reprovisioned from sysfs
 
         for vf_num in range(1, num_vfs + 1):
-            if num_gts > 1 and num_vfs > 1:
+            gt_nums = main_gt_nums
+            if len(main_gt_nums) > 1 and num_vfs > 1:
                 # Multi-tile device Mode 2|3 - odd VFs on GT0, even on GT1
-                gt_nums = [0] if vf_num % 2 else [1]
+                gt_nums = [main_gt_nums[0] if vf_num % 2 else main_gt_nums[1]]
 
             for gt_num in gt_nums:
-                self.driver.set_lmem_quota(vf_num, gt_num, profile.resources.vfLmem)
-                self.driver.set_ggtt_quota(vf_num, gt_num, profile.resources.vfGgtt)
-                self.driver.set_contexts_quota(vf_num, gt_num, profile.resources.vfContexts)
-                self.driver.set_doorbells_quota(vf_num, gt_num, profile.resources.vfDoorbells)
-                self.driver.set_exec_quantum_ms(vf_num, gt_num, profile.scheduler.vfExecutionQuanta)
-                self.driver.set_preempt_timeout_us(vf_num, gt_num, profile.scheduler.vfPreemptionTimeout)
+                if set_resources:
+                    self.set_resources(vf_num, gt_num, profile.resources)
+                self.set_scheduling(vf_num, gt_num, profile.scheduler)
+
+    def provision(self, profile: VgpuProfile) -> None:
+        """Provision PF and VF(s) based on requested vGPU profile."""
+        self.__set_provisioning(profile.num_vfs, profile, set_resources=True)
+
+    def provision_scheduling(self, num_vfs: int, profile: VgpuProfile) -> None:
+        """Provision PF and VF(s) scheduling based on requested vGPU profile's scheduler config."""
+        self.__set_provisioning(num_vfs, profile, set_resources=False)
 
     # fn_num = 0 for PF, 1..n for VF
     def set_scheduling(self, fn_num: int, gt_num: int, scheduling_config: VgpuSchedulerConfig) -> None:
-        logger.info("[%s] Provision scheduling config for PCI Function %s", self.pci_info.bdf, fn_num)
+        """Write sysfs/debugfs PF/VF scheduling attributes."""
+        logger.debug("[%s] Set scheduling for PCI Function %s", self.pci_info.bdf, fn_num)
         if fn_num == 0:
             self.driver.set_pf_policy_sched_if_idle(gt_num, int(scheduling_config.scheduleIfIdle))
             self.driver.set_exec_quantum_ms(0, gt_num, scheduling_config.pfExecutionQuanta)
@@ -196,7 +206,8 @@ class Device(DeviceInterface):
             self.driver.set_preempt_timeout_us(fn_num, gt_num, scheduling_config.vfPreemptionTimeout)
 
     def set_resources(self, fn_num: int, gt_num: int, resources_config: VgpuResourcesConfig) -> None:
-        logger.info("[%s] Provision resources config for PCI Function %s", self.pci_info.bdf, fn_num)
+        """Write sysfs/debugfs PF/VF resources attributes."""
+        logger.debug("[%s] Set resources for PCI Function %s", self.pci_info.bdf, fn_num)
         if fn_num == 0:
             self.driver.set_pf_ggtt_spare(gt_num, resources_config.pfGgtt)
             self.driver.set_pf_lmem_spare(gt_num, resources_config.pfLmem)
@@ -227,8 +238,9 @@ class Device(DeviceInterface):
             for vf_num in range(1, num_vfs + 1):
                 self.driver.set_contexts_quota(vf_num, gt_num, 0)
                 self.driver.set_doorbells_quota(vf_num, gt_num, 0)
-                self.driver.set_ggtt_quota(vf_num, gt_num, 0)
-                self.driver.set_lmem_quota(vf_num, gt_num, 0)
+                if not self.is_gt_media_type(gt_num):
+                    self.driver.set_ggtt_quota(vf_num, gt_num, 0)
+                    self.driver.set_lmem_quota(vf_num, gt_num, 0)
 
     def cancel_work(self) -> None:
         """Drop and reset remaining GPU execution at exit."""
diff --git a/tools/vmtb/vmm_flows/conftest.py b/tools/vmtb/vmm_flows/conftest.py
index 28c0b5f00..12726416f 100644
--- a/tools/vmtb/vmm_flows/conftest.py
+++ b/tools/vmtb/vmm_flows/conftest.py
@@ -12,7 +12,8 @@ import pytest
 
 from bench import exceptions
 from bench.configurators.vgpu_profile import VgpuProfile
-from bench.configurators.vgpu_profile_config import (VfSchedulingMode,
+from bench.configurators.vgpu_profile_config import (VfProvisioningMode,
+                                                     VfSchedulingMode,
                                                      VgpuProfileConfigurator)
 from bench.configurators.vmtb_config import VmtbConfigurator
 from bench.helpers.helpers import modprobe_driver, modprobe_driver_check
@@ -39,6 +40,7 @@ class VmmTestingConfig:
     Available settings:
     - num_vfs: requested number of VFs to enable
     - max_num_vms: maximal number of VMs (the value can be different than enabled number of VFs)
+    - provisioning_mode: auto (fair resources allocation by a driver) or vGPU profile
     - scheduling_mode: requested vGPU scheduling profile (infinite maps to default 0's)
     - auto_poweron_vm: assign VFs and power on VMs automatically in setup fixture
     - auto_probe_vm_driver: probe guest DRM driver in setup fixture (VM must be powered on)
@@ -47,6 +49,7 @@ class VmmTestingConfig:
     """
     num_vfs: int = 1
     max_num_vms: int = 2
+    provisioning_mode: VfProvisioningMode = VfProvisioningMode.AUTO
     scheduling_mode: VfSchedulingMode = VfSchedulingMode.INFINITE
 
     auto_poweron_vm: bool = True
@@ -56,12 +59,14 @@ class VmmTestingConfig:
     wa_reduce_vf_lmem: bool = False
 
     def __str__(self) -> str:
-        return f'{self.num_vfs}VF'
+        test_config_id = f'{self.num_vfs}VF-(P:{self.provisioning_mode.name} S:{self.scheduling_mode.name})'
+        return test_config_id
 
     def __repr__(self) -> str:
         return (f'\nVmmTestingConfig:'
                 f'\nNum VFs = {self.num_vfs} / max num VMs = {self.max_num_vms}'
-                f'\nVF scheduling mode = {self.scheduling_mode}'
+                f'\nVF provisioning mode = {self.provisioning_mode.name}'
+                f'\nVF scheduling mode = {self.scheduling_mode.name}'
                 f'\nSetup flags:'
                 f'\n\tVM - auto power-on = {self.auto_poweron_vm}'
                 f'\n\tVM - auto DRM driver probe = {self.auto_probe_vm_driver}'
@@ -107,7 +112,9 @@ class VmmTestingSetup:
         # [vmtb_root]/vmm_flows/resources/wsim/ptl (last subdir is lowercase key/name from pci.GpuModel class)
         self.wsim_wl_dir = vmtb_root_path / vmtb_config.config.wsim_wl_path / self.get_dut().gpu_model.name.lower()
 
-        self.vgpu_profile: VgpuProfile = self.get_vgpu_profile()
+        if (self.testing_config.provisioning_mode is VfProvisioningMode.VGPU_PROFILE
+            or self.testing_config.scheduling_mode is not VfSchedulingMode.INFINITE):
+            self.vgpu_profile: VgpuProfile = self.get_vgpu_profile()
 
         # Start maximum requested number of VMs, but not more than VFs supported by the given vGPU profile
         self.vms: typing.List[VirtualMachine] = [
@@ -115,7 +122,7 @@ class VmmTestingSetup:
                            vmtb_config.get_guest_config().driver,
                            vmtb_config.get_guest_config().igt_config,
                            vf_migration_support)
-            for vm_idx in range(min(self.vgpu_profile.num_vfs, self.testing_config.max_num_vms))]
+            for vm_idx in range(min(self.testing_config.num_vfs, self.testing_config.max_num_vms))]
 
     def get_vgpu_profile(self) -> VgpuProfile:
         configurator = VgpuProfileConfigurator(self.vgpu_profiles_dir, self.get_dut().gpu_model)
@@ -126,8 +133,6 @@ class VmmTestingSetup:
             logger.error("Suitable vGPU profile not found: %s", exc)
             raise exceptions.VgpuProfileError('Invalid test setup - vGPU profile not found!')
 
-        vgpu_profile.print_parameters()
-
         return vgpu_profile
 
     def get_dut(self) -> Device:
@@ -224,20 +229,35 @@ def fixture_setup_vms(get_vmtb_config, get_cmdline_config, get_host, request):
     ts: VmmTestingSetup = VmmTestingSetup(get_vmtb_config, get_cmdline_config, host, tc)
 
     device: Device = ts.get_dut()
-    num_vfs = ts.vgpu_profile.num_vfs
+    num_vfs = ts.testing_config.num_vfs
     num_vms = ts.get_num_vms()
 
     logger.info('[Test setup: %sVF-%sVM]', num_vfs, num_vms)
 
-    # XXX: VF migration on discrete devices (with LMEM) is currently quite slow.
-    # As a temporary workaround, reduce size of LMEM assigned to VFs to speed up a state save/load process.
-    if tc.wa_reduce_vf_lmem and device.has_lmem():
-        logger.debug("W/A: reduce VFs LMEM quota to accelerate state save/restore")
-        org_vgpu_profile_vfLmem = ts.vgpu_profile.resources.vfLmem
-        # Assign max 512 MB to VF
-        ts.vgpu_profile.resources.vfLmem = min(ts.vgpu_profile.resources.vfLmem // 2, 536870912)
-
-    device.provision(ts.vgpu_profile)
+    if ts.testing_config.provisioning_mode is VfProvisioningMode.VGPU_PROFILE:
+        # XXX: Double migration is slow on discrete GPUs (with VRAM),
+        # As a workaround, reduce VRAM size assigned to VFs to speed up a save process.
+        # This w/a should be removed when a save/restore time improves.
+        if tc.wa_reduce_vf_lmem and device.has_lmem():
+            logger.debug("W/A: reduce VFs LMEM quota to accelerate state save")
+            org_vgpu_profile_vfLmem = ts.vgpu_profile.resources.vfLmem
+            # Assign max 512 MB to VF
+            ts.vgpu_profile.resources.vfLmem = min(ts.vgpu_profile.resources.vfLmem // 2, 536870912)
+
+        ts.vgpu_profile.print_parameters()
+        device.provision(ts.vgpu_profile)
+
+        # XXX: cleanup counterpart for VFs LMEM quota workaround:
+        # restore original value after vGPU profile applied
+        if tc.wa_reduce_vf_lmem and device.has_lmem():
+            ts.vgpu_profile.resources.vfLmem = org_vgpu_profile_vfLmem
+
+    else:
+        device.driver.set_auto_provisioning(True)
+        if ts.testing_config.scheduling_mode is not VfSchedulingMode.INFINITE:
+            # Auto provisioning with concrete scheduling (i.e. different than HW default: infinite)
+            ts.vgpu_profile.print_scheduler_config()
+            device.provision_scheduling(num_vfs, ts.vgpu_profile)
 
     assert device.create_vf(num_vfs) == num_vfs
 
@@ -257,10 +277,39 @@ def fixture_setup_vms(get_vmtb_config, get_cmdline_config, get_host, request):
     yield ts
 
     logger.info('[Test teardown: %sVF-%sVM]', num_vfs, num_vms)
-    # XXX: cleanup counterpart for VFs LMEM quota workaround - restore original value
-    if tc.wa_reduce_vf_lmem and device.has_lmem():
-        ts.vgpu_profile.resources.vfLmem = org_vgpu_profile_vfLmem
+    ts.teardown()
 
+
+# Obsolete fixtures 'create_Xhost_Yvm' - 'fixture_setup_vms' is preferred
+@pytest.fixture(scope='function')
+def create_1host_1vm(get_vmtb_config, get_cmdline_config, get_host):
+    num_vfs, num_vms = 1, 1
+    ts: VmmTestingSetup = VmmTestingSetup(get_vmtb_config, get_cmdline_config, get_host,
+                                          VmmTestingConfig(num_vfs, num_vms))
+
+    logger.info('[Test setup: %sVF-%sVM]', num_vfs, num_vms)
+    logger.debug(repr(ts.testing_config))
+
+    logger.info('[Test execution: %sVF-%sVM]', num_vfs, num_vms)
+    yield ts
+
+    logger.info('[Test teardown: %sVF-%sVM]', num_vfs, num_vms)
+    ts.teardown()
+
+
+@pytest.fixture(scope='function')
+def create_1host_2vm(get_vmtb_config, get_cmdline_config, get_host):
+    num_vfs, num_vms = 2, 2
+    ts: VmmTestingSetup = VmmTestingSetup(get_vmtb_config, get_cmdline_config, get_host,
+                                          VmmTestingConfig(num_vfs, num_vms))
+
+    logger.info('[Test setup: %sVF-%sVM]', num_vfs, num_vms)
+    logger.debug(repr(ts.testing_config))
+
+    logger.info('[Test execution: %sVF-%sVM]', num_vfs, num_vms)
+    yield ts
+
+    logger.info('[Test teardown: %sVF-%sVM]', num_vfs, num_vms)
     ts.teardown()
 
 
diff --git a/tools/vmtb/vmm_flows/test_basic.py b/tools/vmtb/vmm_flows/test_basic.py
index 1d3a68b36..9b8731273 100644
--- a/tools/vmtb/vmm_flows/test_basic.py
+++ b/tools/vmtb/vmm_flows/test_basic.py
@@ -7,7 +7,7 @@ from typing import List, Tuple
 
 import pytest
 
-from bench.configurators.vgpu_profile_config import VfSchedulingMode
+from bench.configurators.vgpu_profile_config import VfProvisioningMode, VfSchedulingMode
 from bench.executors.gem_wsim import (ONE_CYCLE_DURATION_MS,
                                       PREEMPT_10MS_WORKLOAD, GemWsim,
                                       GemWsimResult,
@@ -27,20 +27,23 @@ DELAY_FOR_WORKLOAD_SEC = 2 # Waiting gem_wsim to be running [seconds]
 DELAY_FOR_RELOAD_SEC = 3 # Waiting before driver reloading [seconds]
 
 
-def set_test_config(test_variants: List[Tuple[int, VfSchedulingMode]],
+def set_test_config(test_variants: List[Tuple[int, VfProvisioningMode, VfSchedulingMode]],
                     max_vms: int = 2, vf_driver_load: bool = True) -> List[VmmTestingConfig]:
     """Helper function to provide a parametrized test with a list of test configuration variants."""
     logger.debug("Init test variants: %s", test_variants)
     test_configs: List[VmmTestingConfig] = []
 
     for config in test_variants:
-        (num_vfs, scheduling_mode) = config
-        test_configs.append(VmmTestingConfig(num_vfs, max_vms, scheduling_mode, auto_probe_vm_driver=vf_driver_load))
+        (num_vfs, provisioning_mode, scheduling_mode) = config
+        test_configs.append(VmmTestingConfig(num_vfs, max_vms, provisioning_mode, scheduling_mode,
+                                             auto_probe_vm_driver=vf_driver_load))
 
     return test_configs
 
 
-test_variants_1 = [(1, VfSchedulingMode.DEFAULT_PROFILE), (2, VfSchedulingMode.DEFAULT_PROFILE)]
+test_variants_1 = [(1, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE),
+                   (2, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE),
+                   (2, VfProvisioningMode.AUTO, VfSchedulingMode.INFINITE)]
 
 @pytest.mark.parametrize('setup_vms', set_test_config(test_variants_1), ids=idfn_test_config, indirect=['setup_vms'])
 class TestVmSetup:
@@ -60,8 +63,9 @@ class TestVmSetup:
             assert driver_check(vm)
 
 
-test_variants_2 = [(1, VfSchedulingMode.DEFAULT_PROFILE), (2, VfSchedulingMode.DEFAULT_PROFILE),
-                   (4, VfSchedulingMode.DEFAULT_PROFILE)]
+test_variants_2 = [(1, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE),
+                   (2, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE),
+                   (4, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE)]
 
 @pytest.mark.parametrize('setup_vms', set_test_config(test_variants_2), ids=idfn_test_config, indirect=['setup_vms'])
 class TestVmWorkload:
@@ -102,7 +106,8 @@ class TestVmWorkload:
         logger.info("Execute wsim parallel on VMs - results: %s", result)
 
 
-test_variants_3 = [(2, VfSchedulingMode.DEFAULT_PROFILE), (4, VfSchedulingMode.DEFAULT_PROFILE)]
+test_variants_3 = [(2, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE),
+                   (4, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE)]
 
 @pytest.mark.parametrize('setup_vms', set_test_config(test_variants=test_variants_3, max_vms=4, vf_driver_load=False),
                          ids = idfn_test_config, indirect=['setup_vms'])
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH i-g-t 06/10] tools/vmtb: Refactor driver interfaces
  2026-02-24  7:50 [PATCH i-g-t 00/10] vmtb: Modernize SR-IOV VM Test Bench core Adam Miszczak
                   ` (4 preceding siblings ...)
  2026-02-24  7:50 ` [PATCH i-g-t 05/10] tools/vmtb: VF auto/fair provisioning support Adam Miszczak
@ 2026-02-24  7:50 ` Adam Miszczak
  2026-03-10 10:43   ` Bernatowicz, Marcin
  2026-02-24  7:50 ` [PATCH i-g-t 07/10] tools/vmtb: Introduce VirtualDevice class Adam Miszczak
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 25+ messages in thread
From: Adam Miszczak @ 2026-02-24  7:50 UTC (permalink / raw)
  To: igt-dev; +Cc: marcin.bernatowicz, kamil.konieczny

Introduce new common driver interface - base class for all DRM drivers.
DriverInterface exposes basic functions like bind, unbind or reset
and is extended by specialized classes representing PF and VF drivers.
Both PF and VF driver classes implement methods to read/write sysfs/debugfs:
a host uses standard Python's pathlib for filesystem operations,
guest access it over QEMU Guest-Agent commands.
Additionally, PfDriverInterface publishes functions to enable
and provision VFs, configure scheduling etc.
Concrete implementation of PF driver is provided by Xe driver class.

Additional adjustments for xe provisioning:
- scheduling configured via sysfs SRIOV admin tree:
  /sys/bus/pci/drivers/xe/[BDF]/sriov_admin
- support bulk settings (PF and all VFs) for EQ, PT and scheduling priority
- align with a new 'sched_priority' file format:
  low/normal/high strings instead of integers
- remove 'sched_if_idle' attribute support - enable strict scheduling
  via 'normal' scheduling priority
- support new debugfs 'restore_auto_provisioning' attribute
  to reenable auto-provisioning mode.
- set LMEM and GGTT quotas exclusively on a root tile
- in auto resources provisioning mode, setting scheduling parameters
  should follow VFs enabling
  (otherwise xe KMD sets custom provisioning mode for resources as well)
- Device.reset_provisioning() clears (zeroes) provisioning attributes
  and restores auto-provisioning

Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
---
 tools/vmtb/bench/drivers/driver_interface.py | 179 +++++++++++++---
 tools/vmtb/bench/drivers/xe.py               | 207 ++++++++-----------
 tools/vmtb/bench/machines/physical/device.py |  96 +++++----
 tools/vmtb/vmm_flows/conftest.py             |  14 +-
 4 files changed, 301 insertions(+), 195 deletions(-)

diff --git a/tools/vmtb/bench/drivers/driver_interface.py b/tools/vmtb/bench/drivers/driver_interface.py
index 3026fece7..0b0bd5abb 100644
--- a/tools/vmtb/bench/drivers/driver_interface.py
+++ b/tools/vmtb/bench/drivers/driver_interface.py
@@ -3,13 +3,21 @@
 
 import abc
 import enum
+import logging
 import typing
+from pathlib import Path
 
+from bench import exceptions
+from bench.machines.machine_interface import MachineInterface
+from bench.helpers.log import LogDecorators
 
-class SchedulingPriority(enum.Enum):
-    LOW = 0
-    NORMAL = 1
-    HIGH = 2
+logger = logging.getLogger('DriverInterface')
+
+
+class SchedulingPriority(str, enum.Enum):
+    LOW = 'low'
+    NORMAL = 'normal'
+    HIGH = 'high'
 
 
 class VfControl(str, enum.Enum):
@@ -23,20 +31,85 @@ class VfControl(str, enum.Enum):
 
 
 class DriverInterface(abc.ABC):
+    """Base class for DRM drivers (Physical and Virtual).
+    Provide common operations for all drivers like bind/unbind, reset etc.
+    """
+    def __init__(self, bdf: str) -> None:
+        self.pci_bdf = bdf
+        self.sysfs_device_path = Path('/sys/bus/pci/devices') / self.pci_bdf
+        self.sysfs_driver_path = Path('/sys/bus/pci/drivers') / self.get_name()
+        self.debugfs_path = Path('/sys/kernel/debug/dri') / self.pci_bdf
+
+    @abc.abstractmethod
+    def get_name(self) -> str:
+        raise NotImplementedError
+
+    @abc.abstractmethod
+    def write_sysfs(self, path: Path, value: str) -> None:
+        raise NotImplementedError
 
-    @staticmethod
     @abc.abstractmethod
-    def get_name() -> str:
+    def read_sysfs(self, path: Path) -> str:
         raise NotImplementedError
 
     @abc.abstractmethod
-    def bind(self, bdf: str) -> None:
+    def write_debugfs(self, file: str, value: str) -> None:
         raise NotImplementedError
 
     @abc.abstractmethod
-    def unbind(self, bdf: str) -> None:
+    def read_debugfs(self, file: str) -> str:
         raise NotImplementedError
 
+    @LogDecorators.parse_kmsg
+    def bind(self) -> None:
+        self.write_sysfs((self.sysfs_driver_path / 'bind'), self.pci_bdf)
+
+    @LogDecorators.parse_kmsg
+    def unbind(self) -> None:
+        self.write_sysfs((self.sysfs_driver_path / 'unbind'), self.pci_bdf)
+
+    @LogDecorators.parse_kmsg
+    def flr(self) -> None:
+        self.write_sysfs((self.sysfs_device_path / 'reset'), '1')
+
+
+class PfDriverInterface(DriverInterface, abc.ABC):
+    """Base class for PF drivers, extends common DriverInterface base class.
+    Provide operations specific for PF drivers like read/write sysfs on Host,
+    set number of VFs to enable, set/get provisioning related attributes etc.
+    """
+    @LogDecorators.parse_kmsg
+    def __write_fs(self, path: Path, value: str) -> None:
+        try:
+            path.write_text(value)
+            logger.debug("Write: %s -> %s", value, path)
+        except Exception as exc:
+            logger.error("Unable to write %s -> %s", value, path)
+            raise exceptions.HostError(f'Could not write to {path}. Error: {exc}') from exc
+
+    @LogDecorators.parse_kmsg
+    def __read_fs(self, path: Path) -> str:
+        try:
+            ret = path.read_text()
+        except Exception as exc:
+            logger.error("Unable to read %s", path)
+            raise exceptions.HostError(f'Could not read from {path}. Error: {exc}') from exc
+
+        logger.debug("Read: %s -> %s", path, ret.strip())
+        return ret
+
+    def write_sysfs(self, path: Path, value: str) -> None:
+        self.__write_fs(path, value)
+
+    def read_sysfs(self, path: Path) -> str:
+        return str(self.__read_fs(path))
+
+    def write_debugfs(self, file: str, value: str) -> None:
+        self.__write_fs(self.debugfs_path / file, value)
+
+    def read_debugfs(self, file: str) -> str:
+        return str(self.__read_fs(self.debugfs_path / file))
+
     @abc.abstractmethod
     def get_totalvfs(self) -> int:
         raise NotImplementedError
@@ -70,17 +143,14 @@ class DriverInterface(abc.ABC):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def get_auto_provisioning(self) -> bool:
-        raise NotImplementedError
-
-    @abc.abstractmethod
-    def set_auto_provisioning(self, val: bool) -> None:
+    def restore_auto_provisioning(self) -> None:
         raise NotImplementedError
 
     @abc.abstractmethod
     def cancel_work(self) -> None:
         raise NotImplementedError
 
+    # PF provisioning
     @abc.abstractmethod
     def get_pf_ggtt_spare(self, gt_num: int) -> int:
         raise NotImplementedError
@@ -113,14 +183,6 @@ class DriverInterface(abc.ABC):
     def set_pf_doorbells_spare(self, gt_num: int, val: int) -> None:
         raise NotImplementedError
 
-    @abc.abstractmethod
-    def get_pf_sched_priority(self, gt_num: int) -> SchedulingPriority:
-        raise NotImplementedError
-
-    @abc.abstractmethod
-    def set_pf_sched_priority(self, gt_num: int, val: SchedulingPriority) -> None:
-        raise NotImplementedError
-
     @abc.abstractmethod
     def get_pf_policy_reset_engine(self, gt_num: int) -> int:
         raise NotImplementedError
@@ -137,14 +199,7 @@ class DriverInterface(abc.ABC):
     def set_pf_policy_sample_period_ms(self, gt_num: int, val: int) -> None:
         raise NotImplementedError
 
-    @abc.abstractmethod
-    def get_pf_policy_sched_if_idle(self, gt_num: int) -> int:
-        raise NotImplementedError
-
-    @abc.abstractmethod
-    def set_pf_policy_sched_if_idle(self, gt_num: int, val: int) -> None:
-        raise NotImplementedError
-
+    # VF provisioning
     @abc.abstractmethod
     def get_ggtt_quota(self, vf_num: int, gt_num: int) -> int:
         raise NotImplementedError
@@ -177,20 +232,53 @@ class DriverInterface(abc.ABC):
     def set_doorbells_quota(self, vf_num: int, gt_num: int, val: int) -> None:
         raise NotImplementedError
 
+    # Scheduling provisioning
+    @abc.abstractmethod
+    def get_exec_quantum_ms(self, fn_num: int) -> int:
+        "Get execution quantum (ms) for PF/VF (EQ/exec_quantum_ms)."
+        raise NotImplementedError
+
+    @abc.abstractmethod
+    def set_exec_quantum_ms(self, fn_num: int, val: int) -> None:
+        "Set execution quantum (ms) for PF/VF (EQ/exec_quantum_ms)."
+        raise NotImplementedError
+
+    @abc.abstractmethod
+    def set_bulk_exec_quantum_ms(self, val: int) -> None:
+        "Set execution quantum (ms) for PF and all VFs (EQ/exec_quantum_ms)."
+        raise NotImplementedError
+
+    @abc.abstractmethod
+    def get_preempt_timeout_us(self, fn_num: int) -> int:
+        "Get preemption timeout (us) for PF/VF (PT/preempt_timeout_us)."
+        raise NotImplementedError
+
+    @abc.abstractmethod
+    def set_preempt_timeout_us(self, fn_num: int, val: int) -> None:
+        "Set preemption timeout (us) for PF/VF (PT/preempt_timeout_us)."
+        raise NotImplementedError
+
     @abc.abstractmethod
-    def get_exec_quantum_ms(self, vf_num: int, gt_num: int) -> int:
+    def set_bulk_preempt_timeout_us(self, val: int) -> None:
+        "Set preemption timeout (us) for PF and all VFs (PT/preempt_timeout_us)."
         raise NotImplementedError
 
     @abc.abstractmethod
-    def set_exec_quantum_ms(self, vf_num: int, gt_num: int, val: int) -> None:
+    def get_sched_priority(self, fn_num: int) -> SchedulingPriority:
+        "Get scheduling priority (sched_priority) of PF/VF: low, normal or high."
         raise NotImplementedError
 
     @abc.abstractmethod
-    def get_preempt_timeout_us(self, vf_num: int, gt_num: int) -> int:
+    def set_pf_sched_priority(self, val: SchedulingPriority) -> None:
+        "Set scheduling priority (sched_priority) for PF only."
+        # Independent sched_prio setting is available only for PF
         raise NotImplementedError
 
     @abc.abstractmethod
-    def set_preempt_timeout_us(self, vf_num: int, gt_num: int, val: int) -> None:
+    def set_bulk_sched_priority(self, val: SchedulingPriority) -> None:
+        "Set scheduling priority (sched_priority) for PF and all VFs."
+        # Set sched_prio for PF and all VFs.
+        # Setting sched_priority for a single VF independently is not supported currently.
         raise NotImplementedError
 
     @abc.abstractmethod
@@ -200,3 +288,28 @@ class DriverInterface(abc.ABC):
     @abc.abstractmethod
     def get_ggtt_available(self, gt_num: int) -> typing.Tuple[int, int]:
         raise NotImplementedError
+
+
+class VfDriver(DriverInterface):
+    """Base class for VF drivers, extends common DriverInterface base class.
+    Provide operations specific for VF drivers like read/write sysfs on Guest/VM.
+    """
+    def __init__(self, bdf: str, vm: MachineInterface) -> None:
+        # VirtualMachine instance is required for VM filesystem access via QEMU Guest-Agent
+        self.vm: MachineInterface = vm
+        super().__init__(bdf)
+
+    def get_name(self) -> str:
+        return self.vm.get_drm_driver_name()
+
+    def write_sysfs(self, path: Path, value: str) -> None:
+        self.vm.write_file_content(str(path), value)
+
+    def read_sysfs(self, path: Path) -> str:
+        return self.vm.read_file_content(str(path))
+
+    def write_debugfs(self, file: str, value: str) -> None:
+        self.vm.write_file_content(str(self.debugfs_path / file), value)
+
+    def read_debugfs(self, file: str) -> str:
+        return self.vm.read_file_content(str(self.debugfs_path / file))
diff --git a/tools/vmtb/bench/drivers/xe.py b/tools/vmtb/bench/drivers/xe.py
index c2b9643bb..26e4e0a08 100644
--- a/tools/vmtb/bench/drivers/xe.py
+++ b/tools/vmtb/bench/drivers/xe.py
@@ -2,85 +2,42 @@
 # Copyright © 2024-2026 Intel Corporation
 
 import logging
+import re
 import typing
 from pathlib import Path
 
-from bench import exceptions
-from bench.drivers.driver_interface import (DriverInterface,
+from bench.drivers.driver_interface import (PfDriverInterface,
                                             SchedulingPriority, VfControl)
-from bench.helpers.log import LogDecorators
 
 logger = logging.getLogger('XeDriver')
 
 
-class XeDriver(DriverInterface):
-    def __init__(self, card_index: int) -> None:
-        self.sysfs_card_path = Path(f'/sys/class/drm/card{card_index}')
-        self.debugfs_path = Path(f'/sys/kernel/debug/dri/{card_index}')
-
-    @staticmethod
-    def get_name() -> str:
+class XeDriver(PfDriverInterface):
+    """Xe driver abstraction class, implements PfDriverInterface.
+    Provide xe specific sysfs/debugfs access and other operations on Host.
+    """
+    def get_name(self) -> str:
         return 'xe'
 
-    @LogDecorators.parse_kmsg
-    def __write_fs(self, base_path: Path, name: str, value: str) -> None:
-        path = base_path / name
-        try:
-            path.write_text(value)
-            logger.debug("Write: %s -> %s", value, path)
-        except Exception as exc:
-            logger.error("Unable to write %s -> %s", value, path)
-            raise exceptions.HostError(f'Could not write to {path}. Error: {exc}') from exc
-
-    @LogDecorators.parse_kmsg
-    def __read_fs(self,  base_path: Path, name: str) -> str:
-        path = base_path / name
-        try:
-            ret = path.read_text()
-        except Exception as exc:
-            logger.error("Unable to read %s", path)
-            raise exceptions.HostError(f'Could not read from {path}. Error: {exc}') from exc
-
-        logger.debug("Read: %s -> %s", path, ret.strip())
-        return ret
-
-    def __write_sysfs(self, name: str, value: str) -> None:
-        self.__write_fs(self.sysfs_card_path / 'device', name, value)
-
-    def __read_sysfs(self, name: str) -> str:
-        return str(self.__read_fs(self.sysfs_card_path / 'device', name))
-
-    def __write_debugfs(self, name: str, value: str) -> None:
-        self.__write_fs(self.debugfs_path, name, value)
-
-    def __read_debugfs(self, name: str) -> str:
-        return str(self.__read_fs(self.debugfs_path, name))
-
-    def bind(self, bdf: str) -> None:
-        self.__write_sysfs('driver/bind', bdf)
-
-    def unbind(self, bdf: str) -> None:
-        self.__write_sysfs('driver/unbind', bdf)
-
     def get_totalvfs(self) -> int:
-        return int(self.__read_sysfs('sriov_totalvfs'))
+        return int(self.read_sysfs(self.sysfs_device_path / 'sriov_totalvfs'))
 
     def get_numvfs(self) -> int:
-        return int(self.__read_sysfs('sriov_numvfs'))
+        return int(self.read_sysfs(self.sysfs_device_path / 'sriov_numvfs'))
 
     def set_numvfs(self, val: int) -> None:
-        self.__write_sysfs('sriov_numvfs', str(val))
+        self.write_sysfs(self.sysfs_device_path / 'sriov_numvfs', str(val))
 
     def get_drivers_autoprobe(self) -> int:
-        return int(self.__read_sysfs('sriov_drivers_autoprobe'))
+        return int(self.read_sysfs(self.sysfs_device_path / 'sriov_drivers_autoprobe'))
 
     def set_drivers_autoprobe(self, val: int) -> None:
-        self.__write_sysfs('sriov_drivers_autoprobe', str(val))
+        self.write_sysfs(self.sysfs_device_path / 'sriov_drivers_autoprobe', str(val))
 
     def get_num_gts(self) -> int:
         gt_num = 0
         # Fixme: tile0 only at the moment, add support for multiple tiles if needed
-        path = self.sysfs_card_path / 'device' / 'tile0' / 'gt'
+        path = self.sysfs_device_path / 'tile0' / 'gt'
 
         if path.exists():
             gt_num = 1
@@ -101,12 +58,9 @@ class XeDriver(DriverInterface):
         path = self.debugfs_path / f'gt{gt_num}' / 'pf' / 'ggtt_spare'
         return not path.exists()
 
-    def get_auto_provisioning(self) -> bool:
-        raise exceptions.NotAvailableError('auto_provisioning attribute not available')
-
-    def set_auto_provisioning(self, val: bool) -> None:
-        # No-op - xe driver doesn't publish this attribute
-        pass
+    def restore_auto_provisioning(self) -> None:
+        path = self.debugfs_path / 'sriov' / 'restore_auto_provisioning'
+        self.write_debugfs(str(path), str(1))
 
     def cancel_work(self) -> None:
         # Function to cancel all remaing work on GPU (for test cleanup).
@@ -114,84 +68,77 @@ class XeDriver(DriverInterface):
         pass
 
     # Create debugfs path to given parameter (without a base part):
-    # gt@gt_num/[pf|vf@vf_num]/@attr
-    # @vf_num: VF number (1-based) or 0 for PF
+    # gt@gt_num/[pf|vf@fn_num]/@attr
+    # @fn_num: VF number (1-based) or 0 for PF
     # @gt_num: GT instance number
     # @subdir: subdirectory for attribute or empty string if not exists
     # @attr: iov parameter name
     # Returns: iov debugfs path to @attr
-    def __helper_create_debugfs_path(self, vf_num: int, gt_num: int, subdir: str, attr: str) -> str:
-        vf_gt_part = f'gt{gt_num}/pf' if vf_num == 0 else f'gt{gt_num}/vf{vf_num}'
-        return f'{vf_gt_part}/{subdir}/{attr}'
+    def __helper_create_debugfs_path(self, fn_num: int, gt_num: int, subdir: str, attr: str) -> str:
+        gt_fn_part = f'gt{gt_num}/pf' if fn_num == 0 else f'gt{gt_num}/vf{fn_num}'
+        return f'{gt_fn_part}/{subdir}/{attr}'
+
+    # Create sysfs sriov_admin path to given scheduling parameter (without a base part):
+    # sriov_admin/[pf|vf@fn_num]/profile/@attr
+    # @fn_num: VF number (1-based) or 0 for PF
+    # @attr: iov parameter name
+    # Returns: iov sysfs path to @attr
+    def __helper_create_sriov_admin_path(self, fn_num: int, attr: str) -> str:
+        fn_part = 'pf' if fn_num == 0 else f'vf{fn_num}'
+        return f'sriov_admin/{fn_part}/profile/{attr}'
 
     # PF spare resources
     # Debugfs location: [SRIOV debugfs base path]/gtM/pf/xxx_spare
     def get_pf_ggtt_spare(self, gt_num: int) -> int:
         path = self.__helper_create_debugfs_path(0, gt_num, '', 'ggtt_spare')
-        return int(self.__read_debugfs(path))
+        return int(self.read_debugfs(path))
 
     def set_pf_ggtt_spare(self, gt_num: int, val: int) -> None:
         path = self.__helper_create_debugfs_path(0, gt_num, '',  'ggtt_spare')
-        self.__write_debugfs(path, str(val))
+        self.write_debugfs(path, str(val))
 
     def get_pf_lmem_spare(self, gt_num: int) -> int:
         path = self.__helper_create_debugfs_path(0, gt_num, '', 'lmem_spare')
-        return int(self.__read_debugfs(path)) if self.has_lmem() else 0
+        return int(self.read_debugfs(path)) if self.has_lmem() else 0
 
     def set_pf_lmem_spare(self, gt_num: int, val: int) -> None:
         path = self.__helper_create_debugfs_path(0, gt_num, '', 'lmem_spare')
         if self.has_lmem():
-            self.__write_debugfs(path, str(val))
+            self.write_debugfs(path, str(val))
 
     def get_pf_contexts_spare(self, gt_num: int) -> int:
         path = self.__helper_create_debugfs_path(0, gt_num, '', 'contexts_spare')
-        return int(self.__read_debugfs(path))
+        return int(self.read_debugfs(path))
 
     def set_pf_contexts_spare(self, gt_num: int, val: int) -> None:
         path = self.__helper_create_debugfs_path(0, gt_num, '', 'contexts_spare')
-        self.__write_debugfs(path, str(val))
+        self.write_debugfs(path, str(val))
 
     def get_pf_doorbells_spare(self, gt_num: int) -> int:
         path = self.__helper_create_debugfs_path(0, gt_num, '', 'doorbells_spare')
-        return int(self.__read_debugfs(path))
+        return int(self.read_debugfs(path))
 
     def set_pf_doorbells_spare(self, gt_num: int, val: int) -> None:
         path = self.__helper_create_debugfs_path(0, gt_num, '', 'doorbells_spare')
-        self.__write_debugfs(path, str(val))
+        self.write_debugfs(path, str(val))
 
     # PF specific provisioning parameters
     # Debugfs location: [SRIOV debugfs base path]/gtM/pf
-    def get_pf_sched_priority(self, gt_num: int) -> SchedulingPriority:
-        logger.warning("PF sched_priority param not available")
-        return SchedulingPriority.LOW
-
-    def set_pf_sched_priority(self, gt_num: int, val: SchedulingPriority) -> None:
-        logger.warning("PF sched_priority param not available")
-
     def get_pf_policy_reset_engine(self, gt_num: int) -> int:
         path = self.__helper_create_debugfs_path(0, gt_num, '', 'reset_engine')
-        return int(self.__read_debugfs(path))
+        return int(self.read_debugfs(path))
 
     def set_pf_policy_reset_engine(self, gt_num: int, val: int) -> None:
         path = self.__helper_create_debugfs_path(0, gt_num, '', 'reset_engine')
-        self.__write_debugfs(path, str(val))
+        self.write_debugfs(path, str(val))
 
     def get_pf_policy_sample_period_ms(self, gt_num: int) -> int:
         path = self.__helper_create_debugfs_path(0, gt_num, '', 'sample_period_ms')
-        return int(self.__read_debugfs(path))
+        return int(self.read_debugfs(path))
 
     def set_pf_policy_sample_period_ms(self, gt_num: int, val: int) -> None:
         path = self.__helper_create_debugfs_path(0, gt_num, '', 'sample_period_ms')
-        self.__write_debugfs(path, str(val))
-
-    def get_pf_policy_sched_if_idle(self, gt_num: int) -> int:
-        path = self.__helper_create_debugfs_path(0, gt_num, '', 'sched_if_idle')
-        return int(self.__read_debugfs(path))
-
-    def set_pf_policy_sched_if_idle(self, gt_num: int, val: int) -> None:
-        # In order to set strict scheduling policy, PF scheduling priority needs to be default
-        path = self.__helper_create_debugfs_path(0, gt_num, '', 'sched_if_idle')
-        self.__write_debugfs(path, str(val))
+        self.write_debugfs(path, str(val))
 
     # VF and PF provisioning parameters
     # Debugfs location: [SRIOV debugfs base path]/gtM/[pf|vfN]
@@ -202,7 +149,7 @@ class XeDriver(DriverInterface):
             return 0
 
         path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'ggtt_quota')
-        return int(self.__read_debugfs(path))
+        return int(self.read_debugfs(path))
 
     def set_ggtt_quota(self, vf_num: int, gt_num: int, val: int) -> None:
         if vf_num == 0:
@@ -210,7 +157,7 @@ class XeDriver(DriverInterface):
             return
 
         path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'ggtt_quota')
-        self.__write_debugfs(path, str(val))
+        self.write_debugfs(path, str(val))
 
     def get_lmem_quota(self, vf_num: int, gt_num: int) -> int:
         if vf_num == 0:
@@ -218,7 +165,7 @@ class XeDriver(DriverInterface):
             return 0
 
         path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'lmem_quota')
-        return int(self.__read_debugfs(path)) if self.has_lmem() else 0
+        return int(self.read_debugfs(path)) if self.has_lmem() else 0
 
     def set_lmem_quota(self, vf_num: int, gt_num: int, val: int) -> None:
         if vf_num == 0:
@@ -227,7 +174,7 @@ class XeDriver(DriverInterface):
 
         path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'lmem_quota')
         if self.has_lmem():
-            self.__write_debugfs(path, str(val))
+            self.write_debugfs(path, str(val))
 
     def get_contexts_quota(self, vf_num: int, gt_num: int) -> int:
         if vf_num == 0:
@@ -235,7 +182,7 @@ class XeDriver(DriverInterface):
             return 0
 
         path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'contexts_quota')
-        return int(self.__read_debugfs(path))
+        return int(self.read_debugfs(path))
 
     def set_contexts_quota(self, vf_num: int, gt_num: int, val: int) -> None:
         if vf_num == 0:
@@ -243,7 +190,7 @@ class XeDriver(DriverInterface):
             return
 
         path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'contexts_quota')
-        self.__write_debugfs(path, str(val))
+        self.write_debugfs(path, str(val))
 
     def get_doorbells_quota(self, vf_num: int, gt_num: int) -> int:
         if vf_num == 0:
@@ -251,7 +198,7 @@ class XeDriver(DriverInterface):
             return 0
 
         path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'doorbells_quota')
-        return int(self.__read_debugfs(path))
+        return int(self.read_debugfs(path))
 
     def set_doorbells_quota(self, vf_num: int, gt_num: int, val: int) -> None:
         if vf_num == 0:
@@ -259,23 +206,51 @@ class XeDriver(DriverInterface):
             return
 
         path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'doorbells_quota')
-        self.__write_debugfs(path, str(val))
+        self.write_debugfs(path, str(val))
+
+    # VF and PF scheduling parameters
+    # Sysfs location: [SRIOV sysfs base path]/sriov_admin/[pf|vfN]/profile
+    # @fn_num: VF number (1-based) or 0 for PF
+    def get_exec_quantum_ms(self, fn_num: int) -> int:
+        sriov_admin_path = self.__helper_create_sriov_admin_path(fn_num, 'exec_quantum_ms')
+        return int(self.read_sysfs(self.sysfs_device_path / sriov_admin_path))
+
+    def set_exec_quantum_ms(self, fn_num: int, val: int) -> None:
+        sriov_admin_path = self.__helper_create_sriov_admin_path(fn_num, 'exec_quantum_ms')
+        self.write_sysfs(self.sysfs_device_path / sriov_admin_path, str(val))
+
+    def set_bulk_exec_quantum_ms(self, val: int) -> None:
+        self.write_sysfs(self.sysfs_device_path / 'sriov_admin/.bulk_profile/exec_quantum_ms', str(val))
+
+    def get_preempt_timeout_us(self, fn_num: int) -> int:
+        sriov_admin_path = self.__helper_create_sriov_admin_path(fn_num, 'preempt_timeout_us')
+        return int(self.read_sysfs(self.sysfs_device_path / sriov_admin_path))
+
+    def set_preempt_timeout_us(self, fn_num: int, val: int) -> None:
+        sriov_admin_path = self.__helper_create_sriov_admin_path(fn_num, 'preempt_timeout_us')
+        self.write_sysfs(self.sysfs_device_path / sriov_admin_path, str(val))
+
+    def set_bulk_preempt_timeout_us(self, val: int) -> None:
+        self.write_sysfs(self.sysfs_device_path / 'sriov_admin/.bulk_profile/preempt_timeout_us', str(val))
+
+    def get_sched_priority(self, fn_num: int) -> SchedulingPriority:
+        sriov_admin_path = self.__helper_create_sriov_admin_path(fn_num, 'sched_priority')
+        ret = self.read_sysfs(self.sysfs_device_path / sriov_admin_path).rstrip()
 
-    def get_exec_quantum_ms(self, vf_num: int, gt_num: int) -> int:
-        path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'exec_quantum_ms')
-        return int(self.__read_debugfs(path))
+        match = re.search(r'\[(low|normal|high)\]', ret)
+        if match:
+            return SchedulingPriority(match.group(1))
 
-    def set_exec_quantum_ms(self, vf_num: int, gt_num: int, val: int) -> None:
-        path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'exec_quantum_ms')
-        self.__write_debugfs(path, str(val))
+        logger.error("Unexpected sched_priority value (must be low/normal/high)")
+        raise ValueError('Unexpected sched_priority value (must be low/normal/high)')
 
-    def get_preempt_timeout_us(self, vf_num: int, gt_num: int) -> int:
-        path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'preempt_timeout_us')
-        return int(self.__read_debugfs(path))
+    def set_pf_sched_priority(self, val: SchedulingPriority) -> None:
+        # Independent sched_prio setting is available for PF only
+        sriov_admin_path = self.__helper_create_sriov_admin_path(0, 'sched_priority')
+        self.write_sysfs(self.sysfs_device_path / sriov_admin_path, val)
 
-    def set_preempt_timeout_us(self, vf_num: int, gt_num: int, val: int) -> None:
-        path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'preempt_timeout_us')
-        self.__write_debugfs(path, str(val))
+    def set_bulk_sched_priority(self, val: SchedulingPriority) -> None:
+        self.write_sysfs(self.sysfs_device_path / 'sriov_admin/.bulk_profile/sched_priority', val)
 
     # Control state of the running VF (WO)
     # Debugfs location: [SRIOV debugfs base path]/gtM/vfN/control
@@ -285,7 +260,7 @@ class XeDriver(DriverInterface):
     # For debug purposes only.
     def set_vf_control(self, vf_num: int, val: VfControl) -> None:
         path = self.__helper_create_debugfs_path(vf_num, 0, '', 'control')
-        self.__write_debugfs(path, val)
+        self.write_debugfs(path, val)
 
     # Read [attribute]_available value from debugfs:
     # /sys/kernel/debug/dri/[card_index]/gt@gt_num/pf/@attr_available
diff --git a/tools/vmtb/bench/machines/physical/device.py b/tools/vmtb/bench/machines/physical/device.py
index 250466733..f1f24c65c 100644
--- a/tools/vmtb/bench/machines/physical/device.py
+++ b/tools/vmtb/bench/machines/physical/device.py
@@ -11,7 +11,7 @@ from bench import exceptions
 from bench.configurators import pci
 from bench.configurators.vgpu_profile import (VgpuProfile, VgpuResourcesConfig,
                                               VgpuSchedulerConfig)
-from bench.drivers.driver_interface import DriverInterface, SchedulingPriority
+from bench.drivers.driver_interface import PfDriverInterface, SchedulingPriority
 from bench.helpers.log import LogDecorators
 from bench.machines.device_interface import DeviceInterface
 
@@ -46,12 +46,12 @@ class Device(DeviceInterface):
     def __init__(self, bdf: str, driver: str) -> None:
         self.pci_info = self.PciInfo(bdf)
         self.gpu_model = pci.get_gpu_model(self.pci_info.devid)
-        self.driver: DriverInterface = self.instantiate_driver(driver, self.pci_info.minor_number)
+        self.driver: PfDriverInterface = self.instantiate_driver(self.pci_info.bdf, driver)
 
     def __str__(self) -> str:
         return f'Dev-{self.pci_info.bdf}'
 
-    def instantiate_driver(self, driver_name: str, card_index: int) -> Any:
+    def instantiate_driver(self, bdf: str, driver_name: str) -> Any:
         module_name = f'bench.drivers.{driver_name}'
         class_name = f'{driver_name.capitalize()}Driver'
 
@@ -62,7 +62,7 @@ class Device(DeviceInterface):
             logging.error("Driver module/class is not available: %s", exc)
             raise exceptions.VmtbConfigError(f'Requested driver module {driver_name} is not available!')
 
-        return driver_class(card_index)
+        return driver_class(bdf)
 
     def set_drivers_autoprobe(self, val: bool) -> None:
         self.driver.set_drivers_autoprobe(int(val))
@@ -164,26 +164,27 @@ class Device(DeviceInterface):
         If 'set_resources' parameter is True - apply the full vGPU profile (hard resources and scheduling).
         Otherwise, set only scheduling profile (e.g. in case of auto resources provisioning).
         """
-        main_gt_nums = [gt_num for gt_num in range(self.get_num_gts()) if not self.is_gt_media_type(gt_num)]
-
+        all_gt_nums = list(range(self.get_num_gts()))
+        main_gt_nums = [gt_num for gt_num in all_gt_nums if not self.is_gt_media_type(gt_num)]
         logger.info("[%s] Provision %sxVFs on main GT%s", self.pci_info.bdf, num_vfs, main_gt_nums)
 
-        for gt_num in main_gt_nums:
+        for gt_num in all_gt_nums:
             if set_resources:
                 self.set_resources(0, gt_num, profile.resources)
-            self.set_scheduling(0, gt_num, profile.scheduler)
             self.driver.set_pf_policy_reset_engine(gt_num, int(profile.security.reset_after_vf_switch))
 
+        self.set_scheduling(0, profile.scheduler)
+
         for vf_num in range(1, num_vfs + 1):
-            gt_nums = main_gt_nums
             if len(main_gt_nums) > 1 and num_vfs > 1:
                 # Multi-tile device Mode 2|3 - odd VFs on GT0, even on GT1
-                gt_nums = [main_gt_nums[0] if vf_num % 2 else main_gt_nums[1]]
+                all_gt_nums = [main_gt_nums[0] if vf_num % 2 else main_gt_nums[1]]
 
-            for gt_num in gt_nums:
+            for gt_num in all_gt_nums:
                 if set_resources:
                     self.set_resources(vf_num, gt_num, profile.resources)
-                self.set_scheduling(vf_num, gt_num, profile.scheduler)
+
+            self.set_scheduling(vf_num, profile.scheduler)
 
     def provision(self, profile: VgpuProfile) -> None:
         """Provision PF and VF(s) based on requested vGPU profile."""
@@ -194,44 +195,47 @@ class Device(DeviceInterface):
         self.__set_provisioning(num_vfs, profile, set_resources=False)
 
     # fn_num = 0 for PF, 1..n for VF
-    def set_scheduling(self, fn_num: int, gt_num: int, scheduling_config: VgpuSchedulerConfig) -> None:
-        """Write sysfs/debugfs PF/VF scheduling attributes."""
+    def set_scheduling(self, fn_num: int, scheduling_config: VgpuSchedulerConfig) -> None:
+        """Write sysfs PF/VF scheduling attributes."""
         logger.debug("[%s] Set scheduling for PCI Function %s", self.pci_info.bdf, fn_num)
+
         if fn_num == 0:
-            self.driver.set_pf_policy_sched_if_idle(gt_num, int(scheduling_config.scheduleIfIdle))
-            self.driver.set_exec_quantum_ms(0, gt_num, scheduling_config.pfExecutionQuanta)
-            self.driver.set_preempt_timeout_us(0, gt_num, scheduling_config.pfPreemptionTimeout)
+            eq, pt = scheduling_config.pfExecutionQuanta, scheduling_config.pfPreemptionTimeout
         else:
-            self.driver.set_exec_quantum_ms(fn_num, gt_num, scheduling_config.vfExecutionQuanta)
-            self.driver.set_preempt_timeout_us(fn_num, gt_num, scheduling_config.vfPreemptionTimeout)
+            eq, pt = scheduling_config.vfExecutionQuanta, scheduling_config.vfPreemptionTimeout
+
+        self.driver.set_exec_quantum_ms(fn_num, eq)
+        self.driver.set_preempt_timeout_us(fn_num, pt)
+
+        if scheduling_config.scheduleIfIdle:
+            self.driver.set_bulk_sched_priority(SchedulingPriority.NORMAL)
 
     def set_resources(self, fn_num: int, gt_num: int, resources_config: VgpuResourcesConfig) -> None:
-        """Write sysfs/debugfs PF/VF resources attributes."""
+        """Write debugfs PF/VF resources attributes."""
         logger.debug("[%s] Set resources for PCI Function %s", self.pci_info.bdf, fn_num)
         if fn_num == 0:
-            self.driver.set_pf_ggtt_spare(gt_num, resources_config.pfGgtt)
-            self.driver.set_pf_lmem_spare(gt_num, resources_config.pfLmem)
+            if not self.is_gt_media_type(gt_num):
+                self.driver.set_pf_ggtt_spare(gt_num, resources_config.pfGgtt)
+                self.driver.set_pf_lmem_spare(gt_num, resources_config.pfLmem)
             self.driver.set_pf_contexts_spare(gt_num, resources_config.pfContexts)
             self.driver.set_pf_doorbells_spare(gt_num, resources_config.pfDoorbells)
         else:
-            self.driver.set_ggtt_quota(fn_num, gt_num, resources_config.vfGgtt)
-            self.driver.set_lmem_quota(fn_num, gt_num, resources_config.vfLmem)
+            if not self.is_gt_media_type(gt_num):
+                self.driver.set_ggtt_quota(fn_num, gt_num, resources_config.vfGgtt)
+                self.driver.set_lmem_quota(fn_num, gt_num, resources_config.vfLmem)
             self.driver.set_contexts_quota(fn_num, gt_num, resources_config.vfContexts)
             self.driver.set_doorbells_quota(fn_num, gt_num, resources_config.vfDoorbells)
 
-    def reset_provisioning(self, num_vfs: int) -> None:
-        """Clear provisioning config for a requested number of VFs.
-        Function calls the sysfs control interface to clear VF provisioning settings
-        and restores the auto provisioning mode.
-        """
-        logger.info("[%s] Reset %s VFs provisioning configuration", self.pci_info.bdf, num_vfs)
+    def clear_provisioning_attributes(self, num_vfs: int) -> None:
+        """Clear provisioning attributes for a requested number of VFs."""
+        # Provisioning config are likely wiped out by (xe) debugfs/restore_auto_provisioning,
+        # but explicit clear shouldn't harm.
+        self.driver.set_bulk_sched_priority(SchedulingPriority.LOW)
+        self.driver.set_bulk_exec_quantum_ms(0)
+        self.driver.set_bulk_preempt_timeout_us(0)
+
         for gt_num in range(self.get_num_gts()):
-            if self.get_scheduling_priority(gt_num) != SchedulingPriority.LOW:
-                self.set_scheduling_priority(gt_num, SchedulingPriority.LOW)
-            self.driver.set_pf_policy_sched_if_idle(gt_num, 0)
             self.driver.set_pf_policy_reset_engine(gt_num, 0)
-            self.driver.set_exec_quantum_ms(0, gt_num, 0)
-            self.driver.set_preempt_timeout_us(0, gt_num, 0)
             self.driver.set_doorbells_quota(0, gt_num, 0)
             # PF contexts cannot be set from sysfs
 
@@ -242,14 +246,24 @@ class Device(DeviceInterface):
                     self.driver.set_ggtt_quota(vf_num, gt_num, 0)
                     self.driver.set_lmem_quota(vf_num, gt_num, 0)
 
+    def reset_provisioning(self, num_vfs: int) -> None:
+        """Clear provisioning config for a given number of VFs and restore auto provisioning mode."""
+        logger.info("[%s] Reset %sxVF provisioning configuration", self.pci_info.bdf, num_vfs)
+        self.clear_provisioning_attributes(num_vfs)
+        self.driver.restore_auto_provisioning()
+
     def cancel_work(self) -> None:
         """Drop and reset remaining GPU execution at exit."""
         self.driver.cancel_work()
 
-    def get_scheduling_priority(self, gt_num: int) -> SchedulingPriority:
-        return self.driver.get_pf_sched_priority(gt_num)
+    def get_scheduling_priority(self, fn_num: int) -> SchedulingPriority:
+        """Get scheduling priority for a given VF or PF."""
+        return self.driver.get_sched_priority(fn_num)
+
+    def set_scheduling_priority(self, val: SchedulingPriority) -> None:
+        """Set scheduling priority for PF and all VFs. Normal priority enables strict scheduling."""
+        self.driver.set_bulk_sched_priority(val)
 
-    def set_scheduling_priority(self, gt_num: int, val: SchedulingPriority) -> None:
-        # In order to set scheduling priority, strict scheduling policy needs to be default
-        # self.drm_driver.set_pf_policy_sched_if_idle(gt_num, 0)
-        self.driver.set_pf_sched_priority(gt_num, val)
+    def set_pf_scheduling_priority(self, val: SchedulingPriority) -> None:
+        """Set scheduling priority for PF only. High prioritizes PF execution over VFs."""
+        self.driver.set_pf_sched_priority(val)
diff --git a/tools/vmtb/vmm_flows/conftest.py b/tools/vmtb/vmm_flows/conftest.py
index 12726416f..a2a6b6680 100644
--- a/tools/vmtb/vmm_flows/conftest.py
+++ b/tools/vmtb/vmm_flows/conftest.py
@@ -253,14 +253,18 @@ def fixture_setup_vms(get_vmtb_config, get_cmdline_config, get_host, request):
             ts.vgpu_profile.resources.vfLmem = org_vgpu_profile_vfLmem
 
     else:
-        device.driver.set_auto_provisioning(True)
-        if ts.testing_config.scheduling_mode is not VfSchedulingMode.INFINITE:
-            # Auto provisioning with concrete scheduling (i.e. different than HW default: infinite)
-            ts.vgpu_profile.print_scheduler_config()
-            device.provision_scheduling(num_vfs, ts.vgpu_profile)
+        device.driver.restore_auto_provisioning()
 
     assert device.create_vf(num_vfs) == num_vfs
 
+    if (ts.testing_config.provisioning_mode is VfProvisioningMode.AUTO and
+        ts.testing_config.scheduling_mode is not VfSchedulingMode.INFINITE):
+        # Auto resources provisioning with concrete scheduling (i.e. different than HW default: infinite).
+        # Scheduler params override must be done after enabling VFs
+        # to allow hard resources auto provisioning by KMD.
+        ts.vgpu_profile.print_scheduler_config()
+        device.provision_scheduling(num_vfs, ts.vgpu_profile)
+
     if tc.auto_poweron_vm:
         bdf_list = [device.get_vf_bdf(vf) for vf in range(1, num_vms + 1)]
         for vm, bdf in zip(ts.get_vm, bdf_list):
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH i-g-t 07/10] tools/vmtb: Introduce VirtualDevice class
  2026-02-24  7:50 [PATCH i-g-t 00/10] vmtb: Modernize SR-IOV VM Test Bench core Adam Miszczak
                   ` (5 preceding siblings ...)
  2026-02-24  7:50 ` [PATCH i-g-t 06/10] tools/vmtb: Refactor driver interfaces Adam Miszczak
@ 2026-02-24  7:50 ` Adam Miszczak
  2026-03-10 10:45   ` Bernatowicz, Marcin
  2026-02-24  7:50 ` [PATCH i-g-t 08/10] tools/vmtb: Redesign VirtualMachine class Adam Miszczak
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 25+ messages in thread
From: Adam Miszczak @ 2026-02-24  7:50 UTC (permalink / raw)
  To: igt-dev; +Cc: marcin.bernatowicz, kamil.konieczny

VirtualDevice represents GPU device enumerated on VM/Guest OS
(composited into VirtualMachine class).
Implement methods common of all devices like bind/unbind driver,
number of GTs as well as VF specific getter of assigned resources
read from debugfs self_config file.
Similarly to physical Device, PciInfo instance with PCI BDF,
Device ID and minor device is embedded as inner class.

VirtualDevice needs to keep a reference to the VirtualMachine
(and pass it to VfDriver) to access Guest OS via QEMU Guest-Agent
running on VM level.

Additionally:
- add dir_list function to a common MachineInterface
  (used currently by VirtualDevice)
- remove physical device specific functions:
  create/remove VF from a base DeviceInterface class.
- adjust debugfs/self_config reader

Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
---
 tools/vmtb/bench/machines/device_interface.py |  14 +-
 tools/vmtb/bench/machines/host.py             |   5 +
 .../vmtb/bench/machines/machine_interface.py  |   6 +-
 tools/vmtb/bench/machines/virtual/device.py   | 179 ++++++++++++++++++
 tools/vmtb/bench/machines/virtual/vm.py       |   5 +
 5 files changed, 198 insertions(+), 11 deletions(-)
 create mode 100644 tools/vmtb/bench/machines/virtual/device.py

diff --git a/tools/vmtb/bench/machines/device_interface.py b/tools/vmtb/bench/machines/device_interface.py
index e8d4068e8..0eff493f0 100644
--- a/tools/vmtb/bench/machines/device_interface.py
+++ b/tools/vmtb/bench/machines/device_interface.py
@@ -1,19 +1,13 @@
 # SPDX-License-Identifier: MIT
-# Copyright © 2024 Intel Corporation
+# Copyright © 2024-2026 Intel Corporation
 
 import abc
 
 
 class DeviceInterface(abc.ABC):
-
-    @abc.abstractmethod
-    def create_vf(self, num: int) -> int:
-        raise NotImplementedError
-
-    @abc.abstractmethod
-    def remove_vfs(self) -> int:
-        raise NotImplementedError
-
+    """Base class for devices (Physical and Virtual).
+    Provide common operations for all devices like bind/unbind driver.
+    """
     @abc.abstractmethod
     def bind_driver(self) -> None:
         raise NotImplementedError
diff --git a/tools/vmtb/bench/machines/host.py b/tools/vmtb/bench/machines/host.py
index aecc7709a..b6cfb62ef 100644
--- a/tools/vmtb/bench/machines/host.py
+++ b/tools/vmtb/bench/machines/host.py
@@ -99,6 +99,11 @@ class Host(MachineInterface):
     def dir_exists(self, path: str) -> bool:
         return Path(path).is_dir()
 
+    def dir_list(self, path: str) -> typing.List[str]:
+        # TODO: implement, currently no-op to fulfill MachineInterface requirement
+        logger.warning("Host.dir_list() is not implemented yet!")
+        return []
+
     def get_drm_driver_name(self) -> str:
         # Used as a part of MachineInterface for helpers
         return self.drm_driver_name
diff --git a/tools/vmtb/bench/machines/machine_interface.py b/tools/vmtb/bench/machines/machine_interface.py
index 8daa2cda3..d67c3db74 100644
--- a/tools/vmtb/bench/machines/machine_interface.py
+++ b/tools/vmtb/bench/machines/machine_interface.py
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: MIT
-# Copyright © 2024 Intel Corporation
+# Copyright © 2024-2026 Intel Corporation
 
 import abc
 import enum
@@ -56,6 +56,10 @@ class MachineInterface(metaclass=abc.ABCMeta):
     def dir_exists(self, path: str) -> bool:
         raise NotImplementedError
 
+    @abc.abstractmethod
+    def dir_list(self, path: str) -> typing.List[str]:
+        raise NotImplementedError
+
     @abc.abstractmethod
     def get_drm_driver_name(self) -> str:
         raise NotImplementedError
diff --git a/tools/vmtb/bench/machines/virtual/device.py b/tools/vmtb/bench/machines/virtual/device.py
new file mode 100644
index 000000000..c838db59d
--- /dev/null
+++ b/tools/vmtb/bench/machines/virtual/device.py
@@ -0,0 +1,179 @@
+# SPDX-License-Identifier: MIT
+# Copyright © 2025-2026 Intel Corporation
+
+import logging
+import re
+import typing
+
+from bench import exceptions
+from bench.configurators import pci
+from bench.drivers.driver_interface import DriverInterface, VfDriver
+from bench.machines.device_interface import DeviceInterface
+from bench.machines.machine_interface import MachineInterface
+
+logger = logging.getLogger('VirtualDevice')
+
+
+class VirtualDevice(DeviceInterface):
+    class PciInfo:
+        def __init__(self, bdf: str, vm: MachineInterface) -> None:
+            self.bdf: str = bdf
+            self.vm: MachineInterface = vm
+            self.devid: str = self.get_device_id(self.bdf)
+            self.minor_number: int = self.get_device_minor_number(self.bdf)
+
+        def get_device_minor_number(self, bdf: str) -> int:
+            drm_dir = f'/sys/bus/pci/devices/{bdf}/drm'
+
+            for dir_name in self.vm.dir_list(drm_dir):
+                if 'card' in dir_name:
+                    index_match = re.match(r'card(?P<card_index>\d+)', dir_name)
+                    if index_match:
+                        return int(index_match.group('card_index'))
+
+            logger.error("Could not determine minor number (card index) for device %s", bdf)
+            raise exceptions.HostError(f'Could not determine minor number (card index) for device {bdf}')
+
+        def get_device_id(self, bdf: str) -> str:
+            device_file = f'/sys/bus/pci/devices/{bdf}/device'
+            devid = self.vm.read_file_content(device_file)
+
+            return devid.strip()[2:] # Strip whitespaces and 0x
+
+    def __init__(self, bdf: str, vm: MachineInterface) -> None:
+        self.pci_info = self.PciInfo(bdf, vm)
+        self.gpu_model = pci.get_gpu_model(self.pci_info.devid)
+        # Reference to VirtualMachine - required for Guest-Agent use (e.g. guest file read/write):
+        self.vm: MachineInterface = vm
+        self.driver: DriverInterface = VfDriver(self.pci_info.bdf, self.vm)
+
+        # Resources provisioned to the VF/VM:
+        self._lmem_size: typing.Optional[int] = None
+        self._ggtt_size: typing.Optional[int] = None
+        self._contexts: typing.Optional[int] = None
+        self._doorbells: typing.Optional[int] = None
+        # Tile mask is relevant for multi-tile devices:
+        self._tile_mask: typing.Optional[int] = None
+
+    def __str__(self) -> str:
+        return f'VirtualDevice-{self.pci_info.bdf}'
+
+    def bind_driver(self) -> None:
+        logger.debug("Bind %s driver to virtual device - PCI BDF: %s",
+                     self.vm.get_drm_driver_name(), self.pci_info.bdf)
+        self.driver.bind()
+
+    def unbind_driver(self) -> None:
+        logger.debug("Unbind %s driver from virtual device - PCI BDF: %s",
+                     self.vm.get_drm_driver_name(), self.pci_info.bdf)
+        self.driver.unbind()
+
+    @property
+    def lmem_size(self) -> typing.Optional[int]:
+        if self._lmem_size is None:
+            self.get_debugfs_selfconfig()
+
+        return self._lmem_size
+
+    @property
+    def ggtt_size(self) -> typing.Optional[int]:
+        if self._ggtt_size is None:
+            self.get_debugfs_selfconfig()
+
+        return self._ggtt_size
+
+    @property
+    def contexts(self) -> typing.Optional[int]:
+        if self._contexts is None:
+            self.get_debugfs_selfconfig()
+
+        return self._contexts
+
+    @property
+    def doorbells(self) -> typing.Optional[int]:
+        if self._doorbells is None:
+            self.get_debugfs_selfconfig()
+
+        return self._doorbells
+
+    @property
+    def tile_mask(self) -> typing.Optional[int]:
+        if self._tile_mask is None:
+            self.get_debugfs_selfconfig()
+
+        return self._tile_mask
+
+    def get_num_gts(self) -> int:
+        """Get number of GTs for a device based on exposed sysfs gt nodes."""
+        gt_num = 0
+        # Fixme: tile0 only at the moment, add support for multiple tiles if needed
+        path = self.driver.sysfs_device_path / 'tile0'
+
+        if self.vm.dir_exists(str(path / 'gt')):
+            gt_num = 1
+        else:
+            while self.vm.dir_exists(str(path / f'gt{gt_num}')):
+                gt_num += 1
+
+        return gt_num
+
+    # helper_convert_units_to_bytes - convert size with units to bytes
+    # @size_str: multiple-byte unit size with suffix (K/M/G)
+    # Returns: size in bytes
+    # TODO: function perhaps could be moved to some new utils module
+    # improve - consider regex to handle various formats eg. both M and MB
+    def helper_convert_units_to_bytes(self, size_str: str) -> int:
+        size_str = size_str.upper()
+        size_int = 0
+
+        if size_str.endswith('B'):
+            size_int = int(size_str[0:-1])
+        elif size_str.endswith('K'):
+            size_int = int(size_str[0:-1]) * 1024
+        elif size_str.endswith('M'):
+            size_int = int(size_str[0:-1]) * 1024**2
+        elif size_str.endswith('G'):
+            size_int = int(size_str[0:-1]) * 1024**3
+
+        return size_int
+
+    # __parse_selfconfig_size - parses size string from debugfs/self_config
+    # GGTT/LMEM size on xe has the following format:
+    # GGTT size:      536870912 (512 MiB)
+    # whereas on i915 (unit suffix):
+    # GGTT size:     524288K
+    # @size_str: size string read from self_config file
+    # (with unit suffix (B/K/M/G) or in bytes (without suffix))
+    # Returns: size in bytes
+    def __parse_selfconfig_size(self, size_str: str) -> int:
+        retval = 0
+        size_match = re.search(r'(?P<size_units>^\d+[BKMG])|(?P<size_bytes>^\d+)', size_str.strip())
+        if size_match:
+            if size_match.group('size_units'):
+                # i915 specific format (in B/K/M/G units)
+                retval = self.helper_convert_units_to_bytes(size_match.group('size_units'))
+            elif size_match.group('size_bytes'):
+                # Xe specific format (in Bytes)
+                retval = int(size_match.group('size_bytes'))
+            else:
+                logger.warning("Unexpected size pattern match!")
+
+        return retval
+
+    def get_debugfs_selfconfig(self, gt_num: int = 0) -> None:
+        """Read hard resources allocated to VF from debugfs selfconfig file."""
+        out = self.driver.read_debugfs(f'gt{gt_num}/vf/self_config')
+
+        for line in out.splitlines():
+            param, value = line.split(':')
+
+            if param == 'GGTT size':
+                self._ggtt_size = self.__parse_selfconfig_size(value)
+            elif param == 'LMEM size':
+                self._lmem_size = self.__parse_selfconfig_size(value)
+            elif param.find('contexts') != -1:
+                self._contexts = int(value)
+            elif param.find('doorbells') != -1:
+                self._doorbells = int(value)
+            elif param == 'tile mask':
+                self._tile_mask = int(value, base=16)
diff --git a/tools/vmtb/bench/machines/virtual/vm.py b/tools/vmtb/bench/machines/virtual/vm.py
index 9f4ca1de7..312e87e4b 100644
--- a/tools/vmtb/bench/machines/virtual/vm.py
+++ b/tools/vmtb/bench/machines/virtual/vm.py
@@ -518,6 +518,11 @@ class VirtualMachine(MachineInterface):
             return False
         return True
 
+    def dir_list(self, path: str) -> typing.List[str]:
+        # TODO: implement, currently no-op to fulfill MachineInterface requirement
+        logger.warning("VirtualMachine.dir_list() is not implemented yet!")
+        return []
+
     def link_exists(self, path: str) -> bool:
         pid = self.execute(f'/bin/sh -c "[ -h {path} ]"')
         status = self.execute_wait(pid)
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH i-g-t 08/10] tools/vmtb: Redesign VirtualMachine class
  2026-02-24  7:50 [PATCH i-g-t 00/10] vmtb: Modernize SR-IOV VM Test Bench core Adam Miszczak
                   ` (6 preceding siblings ...)
  2026-02-24  7:50 ` [PATCH i-g-t 07/10] tools/vmtb: Introduce VirtualDevice class Adam Miszczak
@ 2026-02-24  7:50 ` Adam Miszczak
  2026-03-10 10:47   ` Bernatowicz, Marcin
  2026-02-24  7:50 ` [PATCH i-g-t 09/10] tools/vmtb: Support max VFs configuration Adam Miszczak
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 25+ messages in thread
From: Adam Miszczak @ 2026-02-24  7:50 UTC (permalink / raw)
  To: igt-dev; +Cc: marcin.bernatowicz, kamil.konieczny

Split original VirtualMachine class into specialized abstractions:
VirtualMachine, VirtualDevice and VfDriver.
Extend new VirtualMachine with new functions to load and remove DRM driver
and discover devices on Guest OS.

Redesigned abstractions have the following responsibilities:
- VirtualMachine supports operations like start/stop VM, load/unload driver,
  enumerate virtual devices, execute process on guest,
  power states handling, save/load state etc.
- VirtualDevice represents GPU device visible on a guest OS
  (resources allocated to VF, local PCI BDF, Device ID)
- VfDriver handles low-level functions of virtual device
  as sysfs/debugfs access

New implementation provides placeholders for multiple VFs passed to VM,
but currently only single VF (one virtual GPU per VM) is supported.

Additionally, create separate VM/Guest kernel log files,
located in a root VMTB directory.
VM dmesg is also propagated to logfile.log as previously.

Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
---
 tools/vmtb/bench/machines/virtual/vm.py | 252 +++++++++++-------------
 tools/vmtb/vmm_flows/conftest.py        |   7 +-
 2 files changed, 116 insertions(+), 143 deletions(-)

diff --git a/tools/vmtb/bench/machines/virtual/vm.py b/tools/vmtb/bench/machines/virtual/vm.py
index 312e87e4b..2469af965 100644
--- a/tools/vmtb/bench/machines/virtual/vm.py
+++ b/tools/vmtb/bench/machines/virtual/vm.py
@@ -4,14 +4,14 @@
 import base64
 import json
 import logging
-import os
-import posixpath
+import re
 import shlex
 import signal
 import subprocess
 import threading
 import time
 import typing
+from pathlib import Path
 from types import FrameType
 
 from bench import exceptions
@@ -21,6 +21,7 @@ from bench.machines.machine_interface import (DEFAULT_TIMEOUT,
                                               SuspendMode)
 from bench.machines.virtual.backends.guestagent import GuestAgentBackend
 from bench.machines.virtual.backends.qmp_monitor import QmpMonitor
+from bench.machines.virtual.device import VirtualDevice
 
 logger = logging.getLogger('VirtualMachine')
 
@@ -60,40 +61,34 @@ class VirtualMachine(MachineInterface):
 
     def __init__(self, vm_number: int, backing_image: str, driver: str,
                  igt_config: VmtbIgtConfig, vf_migration_support: bool) -> None:
-        self.vf_bdf: typing.Optional[str] = None
-        self.process: typing.Optional[subprocess.Popen] = None
         self.vmnum: int = vm_number
-        self.card_num: int = 0
-        self.sysfs_prefix_path = posixpath.join('/sys/class/drm/', f'card{str(self.card_num)}')
-        self.questagent_sockpath = posixpath.join('/tmp', f'qga{self.vmnum}.sock')
-        self.qmp_sockpath = posixpath.join('/tmp', f'mon{self.vmnum}.sock')
         self.drm_driver_name: str = driver
         self.igt_config: VmtbIgtConfig = igt_config
         self.vf_migration: bool = vf_migration_support
 
-        if not posixpath.exists(backing_image):
+        # Passed VFs and VirtualDevices list - placeholder for multiple VFs passed to single VM:
+        # currently only one VF/VirtualDevice per VM supported (ie. passed_vf_bdfs[0]).
+        # TODO: add support for multiple VFs/VirtualDevices per VM
+        self.passed_vf_bdfs: typing.List[str] = []
+        self.gpu_devices: typing.List[VirtualDevice] = []
+        self.process: typing.Optional[subprocess.Popen] = None
+
+        self.questagent_sockpath = Path('/tmp') / f'qga{self.vmnum}.sock'
+        self.qmp_sockpath = Path('/tmp') / f'mon{self.vmnum}.sock'
+
+        if not Path(backing_image).exists():
             logger.error('No image for VM%s', self.vmnum)
             raise exceptions.GuestError(f'No image for VM{self.vmnum}')
+
         self.image: str = self.__create_qemu_image(backing_image)
+
         self.migrate_source_image: typing.Optional[str] = None
         self.migrate_destination_vm: bool = False
 
-        # Resources provisioned to the VF/VM:
-        self._lmem_size: typing.Optional[int] = None
-        self._ggtt_size: typing.Optional[int] = None
-        self._contexts: typing.Optional[int] = None
-        self._doorbells: typing.Optional[int] = None
-
-        # GT number and tile is relevant mainly for multi-tile devices
-        # List of all GTs used by a given VF:
-        # - for single-tile: only root [0]
-        # - for multi-tile Mode 2/3: either root [0] or remote [1]
-        # - for multi-tile Mode 1: spans on both tiles [0, 1]
-        self._gt_nums: typing.List[int] = []
-        self._tile_mask: typing.Optional[int] = None
+        self.dmesg_logger = self.__setup_dmesg_logger()
 
     def __str__(self) -> str:
-        return f'VM{self.vmnum}_{self.vf_bdf}'
+        return f'VM{self.vmnum}-VF:{self.passed_vf_bdfs[0] if self.passed_vf_bdfs else 'N/A'}'
 
     def __del__(self) -> None:
         if not self.is_running():
@@ -112,6 +107,18 @@ class VirtualMachine(MachineInterface):
             print('QEMU did not terminate, killing it')
             self.process.kill()
 
+    def __setup_dmesg_logger(self) -> logging.Logger:
+        """Configure VM dmesg logger.
+        Logs are directed to dedicated vm[NUM]_dmesg.log and propagated to logfile.log.
+        """
+        dmesg_logger = logging.getLogger(f'VM{self.vmnum}-kmsg')
+        # Remove any existing logger handlers to avoid duplicated prints for parametrized tests
+        dmesg_logger.handlers.clear()
+        dmesg_log_handler = logging.FileHandler(f'vm{self.vmnum}_dmesg.log')
+        dmesg_logger.addHandler(dmesg_log_handler)
+
+        return dmesg_logger
+
     def __get_backing_file_format(self, backing_file: str) -> typing.Any:
         """Get the format of the backing image file using qemu-img info."""
         command = ['qemu-img', 'info', '--output=json', backing_file]
@@ -143,14 +150,13 @@ class VirtualMachine(MachineInterface):
         return output_image
 
     def __log_qemu_output(self, out: typing.TextIO) -> None:
-        stdoutlog = logging.getLogger(f'VM{self.vmnum}-kmsg')
         for line in iter(out.readline, ''):
-            stdoutlog.debug(line.strip())
+            self.dmesg_logger.debug(line.strip())
 
     def __sockets_exists(self) -> bool:
-        return os.path.exists(self.questagent_sockpath) and os.path.exists(self.qmp_sockpath)
+        return self.questagent_sockpath.exists() and self.qmp_sockpath.exists()
 
-    def __get_popen_command(self) -> typing.List[str]:
+    def __prepare_qemu_command(self) -> typing.List[str]:
         command = ['qemu-system-x86_64',
                    '-vnc', f':{self.vmnum}',
                    '-serial', 'stdio',
@@ -165,8 +171,8 @@ class VirtualMachine(MachineInterface):
                    '-chardev', f'socket,id=mon{self.vmnum},path=/tmp/mon{self.vmnum}.sock,server=on,wait=off',
                    '-mon', f'chardev=mon{self.vmnum},mode=control']
 
-        if self.vf_bdf:
-            command.extend(['-enable-kvm', '-cpu', 'host', '-device', f'vfio-pci,host={self.vf_bdf}'])
+        if self.passed_vf_bdfs:
+            command.extend(['-enable-kvm', '-cpu', 'host', '-device', f'vfio-pci,host={self.passed_vf_bdfs[0]}'])
             if self.vf_migration:
                 command[-1] += ',enable-migration=on'
 
@@ -185,77 +191,82 @@ class VirtualMachine(MachineInterface):
             cur = cur[key]
         return cur
 
-    @property
-    def get_vm_num(self) -> int:
-        return self.vmnum
-
     def assign_vf(self, vf_bdf: str) -> None:
-        self.vf_bdf = vf_bdf
+        """Pass VFs to VM - required to run QEMU (prior to VM power on)"""
+        self.passed_vf_bdfs.append(vf_bdf)
 
     def set_migration_source(self, src_image: str) -> None:
         self.migrate_source_image = src_image
         self.migrate_destination_vm = True
 
-    @property
-    def lmem_size(self) -> typing.Optional[int]:
-        if self._lmem_size is None:
-            self.helper_get_debugfs_selfconfig()
-
-        return self._lmem_size
-
-    @property
-    def ggtt_size(self) -> typing.Optional[int]:
-        if self._ggtt_size is None:
-            self.helper_get_debugfs_selfconfig()
-
-        return self._ggtt_size
-
-    @property
-    def contexts(self) -> typing.Optional[int]:
-        if self._contexts is None:
-            self.helper_get_debugfs_selfconfig()
-
-        return self._contexts
-
-    @property
-    def doorbells(self) -> typing.Optional[int]:
-        if self._doorbells is None:
-            self.helper_get_debugfs_selfconfig()
-
-        return self._doorbells
-
-    @property
-    def tile_mask(self) -> typing.Optional[int]:
-        if self._tile_mask is None:
-            self.helper_get_debugfs_selfconfig()
-
-        return self._tile_mask
-
-    @property
-    def gt_nums(self) -> typing.List[int]:
-        self._gt_nums = self.get_gt_num_from_sysfs()
-        if not self._gt_nums:
-            logger.warning("VM sysfs: missing GT index")
-            self._gt_nums = [0]
-
-        return self._gt_nums
-
-    def get_gt_num_from_sysfs(self) -> typing.List[int]:
-        # Get GT number of VF passed to a VM, based on an exisitng a sysfs path
-        vm_gt_num = []
-        if self.dir_exists(posixpath.join(self.sysfs_prefix_path, 'gt/gt0')):
-            vm_gt_num.append(0)
-        if self.dir_exists(posixpath.join(self.sysfs_prefix_path, 'gt/gt1')):
-            vm_gt_num.append(1)
-
-        return vm_gt_num
-
     def get_drm_driver_name(self) -> str:
         return self.drm_driver_name
 
     def get_igt_config(self) -> VmtbIgtConfig:
         return self.igt_config
 
+    def get_dut(self) -> VirtualDevice:
+        # Currently only one first enumerated device is supported (virtual card0)
+        return self.gpu_devices[0]
+
+    def is_drm_driver_loaded(self) -> bool:
+        return self.dir_exists(f'/sys/bus/pci/drivers/{self.drm_driver_name}')
+
+    def load_drm_driver(self) -> None:
+        """Load (modprobe) guest DRM driver."""
+        if not self.is_drm_driver_loaded():
+            logger.debug("VirtualMachine - load DRM driver")
+            drv_probe_pid = self.execute(f'modprobe {self.drm_driver_name}')
+            if self.execute_wait(drv_probe_pid).exit_code != 0:
+                logger.error("%s driver probe failed on guest!", self.drm_driver_name)
+                raise exceptions.GuestError(f'{self.drm_driver_name} driver probe failed on guest!')
+
+    def unload_drm_driver(self) -> None:
+        """Unload (remove) guest DRM driver."""
+        logger.debug("VirtualMachine - unload DRM driver")
+        for device in self.gpu_devices:
+            logger.debug("Unbind %s from virtual device %s", self.drm_driver_name, device.pci_info.bdf)
+            device.unbind_driver()
+
+        rmmod_pid = self.execute(f'modprobe -rf {self.drm_driver_name}')
+        if self.execute_wait(rmmod_pid).exit_code != 0:
+            logger.error("DRM driver remove failed!")
+            raise exceptions.HostError('DRM driver remove failed!')
+
+        logger.debug("%s successfully removed", self.drm_driver_name)
+
+    def discover_devices(self) -> None:
+        """Detect all (virtual) PCI GPU devices on the guest and initialize VirtualDevice list."""
+        if not self.is_drm_driver_loaded():
+            logger.error("Unable to discover devices on guest - %s driver is not loaded!", self.drm_driver_name)
+            raise exceptions.HostError(
+                f'Unable to discover devices on guest - {self.drm_driver_name} driver is not loaded!')
+
+        detected_devices: typing.List[VirtualDevice] = []
+        drv_path = Path('/sys/bus/pci/drivers/') / self.drm_driver_name
+
+        dev_dir_ls = self.dir_list(str(drv_path))
+
+        # Look for a directory name with a PCI BDF (e.g. 0000:1a:00.0)
+        for bdf in dev_dir_ls:
+            match = re.match(r'\d{4}(?::[0-9a-z-A-Z]{2}){2}.[0-7]', bdf)
+            if match:
+                device = VirtualDevice(bdf, self)
+                detected_devices.append(device)
+
+        # Output list of detected devices sorted by an ascending card index (device minor number)
+        self.gpu_devices = sorted(detected_devices, key=lambda dev: dev.pci_info.minor_number)
+
+        if not self.gpu_devices:
+            logger.error("Virtualized GPU PCI device (bound to %s driver) not detected!", self.drm_driver_name)
+            raise exceptions.GuestError(
+                f'Virtualized GPU PCI device (bound to {self.drm_driver_name} driver) not detected!')
+
+        logger.debug("Detected virtualized GPU PCI device(s):")
+        for dev in self.gpu_devices:
+            logger.debug("[virtual card%s] PCI BDF: %s / DevID: %s (%s)",
+                          dev.pci_info.minor_number, dev.pci_info.bdf, dev.pci_info.devid, dev.gpu_model)
+
     @Decorators.timeout_signal
     def poweron(self) -> None:
         logger.debug('Powering on VM%s', self.vmnum)
@@ -263,7 +274,7 @@ class VirtualMachine(MachineInterface):
             logger.warning('VM%s already running', self.vmnum)
             return
 
-        command = self.__get_popen_command()
+        command = self.__prepare_qemu_command()
         # We don't want to kill the process created here (like 'with' would do) so disable the following linter issue:
         # R1732: consider-using-with (Consider using 'with' for resource-allocating operations)
         # pylint: disable=R1732
@@ -292,8 +303,8 @@ class VirtualMachine(MachineInterface):
                 logger.info('waiting for socket')
                 time.sleep(1)
             # Passing five minutes timeout for every command
-            self.ga = GuestAgentBackend(self.questagent_sockpath, 300)
-            self.qm = QmpMonitor(self.qmp_sockpath, 300)
+            self.ga = GuestAgentBackend(str(self.questagent_sockpath), 300)
+            self.qm = QmpMonitor(str(self.qmp_sockpath), 300)
             vm_status = self.qm.query_status()
 
             if not self.migrate_destination_vm and vm_status != 'running':
@@ -317,6 +328,7 @@ class VirtualMachine(MachineInterface):
 
     @Decorators.timeout_signal
     def poweroff(self) -> None:
+        """Power off VM via the Guest-Agent guest-shutdown(powerdown) command."""
         logger.debug('Powering off VM%s', self.vmnum)
         assert self.process
         if not self.is_running():
@@ -338,8 +350,9 @@ class VirtualMachine(MachineInterface):
 
             if self.__sockets_exists():
                 # Remove leftovers and notify about unclear qemu shutdown
-                os.remove(self.questagent_sockpath)
-                os.remove(self.qmp_sockpath)
+                self.questagent_sockpath.unlink()
+                self.qmp_sockpath.unlink()
+                logger.error('VM%s was not gracefully powered off - sockets exist', self.vmnum)
                 raise exceptions.GuestError(f'VM{self.vmnum} was not gracefully powered off - sockets exist')
 
     def reboot(self) -> None:
@@ -441,7 +454,7 @@ class VirtualMachine(MachineInterface):
         ret = execout.get('return')
         if ret:
             pid: int = ret.get('pid')
-            logger.debug('Running %s on VM%s with pid %s', command, self.vmnum, pid)
+            logger.debug("Run command on VM%s: %s (PID: %s)", self.vmnum, command, pid)
             return pid
 
         logger.error('Command %s did not return pid', command)
@@ -519,9 +532,12 @@ class VirtualMachine(MachineInterface):
         return True
 
     def dir_list(self, path: str) -> typing.List[str]:
-        # TODO: implement, currently no-op to fulfill MachineInterface requirement
-        logger.warning("VirtualMachine.dir_list() is not implemented yet!")
-        return []
+        pid = self.execute(f'/bin/sh -c "ls {path}"')
+        status: ProcessResult = self.execute_wait(pid)
+        if status.exit_code:
+            raise exceptions.GuestError(f'VM ls failed - error: {status.exit_code}')
+
+        return status.stdout.split()
 
     def link_exists(self, path: str) -> bool:
         pid = self.execute(f'/bin/sh -c "[ -h {path} ]"')
@@ -571,45 +587,3 @@ class VirtualMachine(MachineInterface):
             raise exceptions.GuestError(f'VM{self.vmnum} state load error: {job_error}')
 
         logger.debug('VM state load finished successfully')
-
-    # helper_convert_units_to_bytes - convert size with units to bytes
-    # @size_str: multiple-byte unit size with suffix (K/M/G)
-    # Returns: size in bytes
-    # TODO: function perhaps could be moved to some new utils module
-    # improve - consider regex to handle various formats eg. both M and MB
-    def helper_convert_units_to_bytes(self, size_str: str) -> int:
-        size_str = size_str.upper()
-        size_int = 0
-
-        if size_str.endswith('B'):
-            size_int = int(size_str[0:-1])
-        elif size_str.endswith('K'):
-            size_int = int(size_str[0:-1]) * 1024
-        elif size_str.endswith('M'):
-            size_int = int(size_str[0:-1]) * 1024**2
-        elif size_str.endswith('G'):
-            size_int = int(size_str[0:-1]) * 1024**3
-
-        return size_int
-
-    # helper_get_debugfs_selfconfig - read resources allocated to VF from debugfs:
-    # /sys/kernel/debug/dri/@card/gt@gt_num/iov/self_config
-    # @card: card number
-    # @gt_num: GT instance number
-    def helper_get_debugfs_selfconfig(self, card: int = 0, gt_num: int = 0) -> None:
-        path = posixpath.join(f'/sys/kernel/debug/dri/{card}/gt{gt_num}/iov/self_config')
-        out = self.read_file_content(path)
-
-        for line in out.splitlines():
-            param, value = line.split(':')
-
-            if param == 'GGTT size':
-                self._ggtt_size = self.helper_convert_units_to_bytes(value)
-            elif param == 'LMEM size':
-                self._lmem_size = self.helper_convert_units_to_bytes(value)
-            elif param == 'contexts':
-                self._contexts = int(value)
-            elif param == 'doorbells':
-                self._doorbells = int(value)
-            elif param == 'tile mask':
-                self._tile_mask = int(value, base=16)
diff --git a/tools/vmtb/vmm_flows/conftest.py b/tools/vmtb/vmm_flows/conftest.py
index a2a6b6680..ae149d652 100644
--- a/tools/vmtb/vmm_flows/conftest.py
+++ b/tools/vmtb/vmm_flows/conftest.py
@@ -16,7 +16,6 @@ from bench.configurators.vgpu_profile_config import (VfProvisioningMode,
                                                      VfSchedulingMode,
                                                      VgpuProfileConfigurator)
 from bench.configurators.vmtb_config import VmtbConfigurator
-from bench.helpers.helpers import modprobe_driver, modprobe_driver_check
 from bench.helpers.log import HOST_DMESG_FILE
 from bench.machines.host import Device, Host
 from bench.machines.virtual.vm import VirtualMachine
@@ -273,9 +272,9 @@ def fixture_setup_vms(get_vmtb_config, get_cmdline_config, get_host, request):
         ts.poweron_vms()
 
         if tc.auto_probe_vm_driver:
-            modprobe_cmds = [modprobe_driver(vm) for vm in ts.get_vm]
-            for i, cmd in enumerate(modprobe_cmds):
-                assert modprobe_driver_check(ts.get_vm[i], cmd), f'modprobe failed on VM{i}'
+            for vm in ts.get_vm:
+                vm.load_drm_driver()
+                vm.discover_devices()
 
     logger.info('[Test execution: %sVF-%sVM]', num_vfs, num_vms)
     yield ts
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH i-g-t 09/10] tools/vmtb: Support max VFs configuration
  2026-02-24  7:50 [PATCH i-g-t 00/10] vmtb: Modernize SR-IOV VM Test Bench core Adam Miszczak
                   ` (7 preceding siblings ...)
  2026-02-24  7:50 ` [PATCH i-g-t 08/10] tools/vmtb: Redesign VirtualMachine class Adam Miszczak
@ 2026-02-24  7:50 ` Adam Miszczak
  2026-03-10 10:52   ` Bernatowicz, Marcin
  2026-02-24  7:50 ` [PATCH i-g-t 10/10] tools/vmtb: Platform enabling: PTL and BMG support Adam Miszczak
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 25+ messages in thread
From: Adam Miszczak @ 2026-02-24  7:50 UTC (permalink / raw)
  To: igt-dev; +Cc: marcin.bernatowicz, kamil.konieczny

Enable maximum VFs test configuration variant, for both:
auto-provisioning and vGPU profiles.
Max VFs is device-specific value read via sysfs.
For auto-provisioning, max VFs always equals sysfs/sriov_totalvfs,
but the highest supported number of VFs defined by vGPU profiles
may differ from the hardware max value.

Max VFs test config variant can be requested by passing MAX_VFS label
to VmmTestingConfig structure (num_vfs) or convenience tuple, for example:
test_variants = [(MAX_VFS, VfProvisioningMode.AUTO, VfSchedulingMode.INFINITE),
                 (MAX_VFS, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE)]

Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
---
 tools/vmtb/vmm_flows/conftest.py | 29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/tools/vmtb/vmm_flows/conftest.py b/tools/vmtb/vmm_flows/conftest.py
index ae149d652..02c297f93 100644
--- a/tools/vmtb/vmm_flows/conftest.py
+++ b/tools/vmtb/vmm_flows/conftest.py
@@ -32,6 +32,10 @@ def pytest_addoption(parser):
                      help='Device card index for test execution')
 
 
+# Label indicating Max VFs configurarion variant, intended for pass to VmmTestingConfig.
+MAX_VFS = "Max"
+
+
 @dataclass
 class VmmTestingConfig:
     """Structure represents test configuration used by a setup fixture.
@@ -54,16 +58,23 @@ class VmmTestingConfig:
     auto_poweron_vm: bool = True
     auto_probe_vm_driver: bool = True
     unload_host_drivers_on_teardown: bool = False
+    enable_max_vfs: bool = False
     # Temporary W/A: reduce size of LMEM assigned to VFs to speed up a VF state save-restore process
     wa_reduce_vf_lmem: bool = False
 
+    def __post_init__(self):
+        if self.num_vfs is MAX_VFS:
+            self.enable_max_vfs = True
+            self.num_vfs = 0 # Actual value set in VmmTestingSetup
+
     def __str__(self) -> str:
-        test_config_id = f'{self.num_vfs}VF-(P:{self.provisioning_mode.name} S:{self.scheduling_mode.name})'
+        test_config_id = (f'{self.num_vfs if not self.enable_max_vfs else "Max"}VF'
+                          + f'-(P:{self.provisioning_mode.name} S:{self.scheduling_mode.name})')
         return test_config_id
 
     def __repr__(self) -> str:
         return (f'\nVmmTestingConfig:'
-                f'\nNum VFs = {self.num_vfs} / max num VMs = {self.max_num_vms}'
+                f'\nNum VFs = {self.num_vfs if not self.enable_max_vfs else "Max"} / max num VMs = {self.max_num_vms}'
                 f'\nVF provisioning mode = {self.provisioning_mode.name}'
                 f'\nVF scheduling mode = {self.scheduling_mode.name}'
                 f'\nSetup flags:'
@@ -89,6 +100,7 @@ class VmmTestingSetup:
         self.host.load_drivers()
         self.host.discover_devices()
         self.dut: Device = self.host.get_device(self.dut_index)
+        self.total_vfs: int = self.get_dut().driver.get_totalvfs()
 
         # VF migration requires vendor specific VFIO driver (e.g. xe-vfio-pci)
         vf_migration_support: bool = self.host.is_driver_loaded(f'{self.host.drm_driver_name}-vfio-pci')
@@ -98,11 +110,13 @@ class VmmTestingSetup:
                     "\n\tPCI BDF: %s "
                     "\n\tDevice ID: %s (%s)"
                     "\n\tHost DRM driver: %s"
-                    "\n\tVF migration support: %s",
+                    "\n\tMax VFs supported: %s"
+                    "\n\tVF migration supported: %s",
                     self.dut_index,
                     self.get_dut().pci_info.bdf,
                     self.get_dut().pci_info.devid, self.get_dut().gpu_model,
                     self.get_dut().driver.get_name(),
+                    self.total_vfs,
                     vf_migration_support)
 
         vmtb_root_path = vmtb_config.vmtb_config_file.parent
@@ -115,6 +129,9 @@ class VmmTestingSetup:
             or self.testing_config.scheduling_mode is not VfSchedulingMode.INFINITE):
             self.vgpu_profile: VgpuProfile = self.get_vgpu_profile()
 
+        if self.testing_config.provisioning_mode is VfProvisioningMode.AUTO and self.testing_config.enable_max_vfs:
+            self.testing_config.num_vfs = self.total_vfs
+
         # Start maximum requested number of VMs, but not more than VFs supported by the given vGPU profile
         self.vms: typing.List[VirtualMachine] = [
             VirtualMachine(vm_idx, self.guest_os_image,
@@ -125,6 +142,12 @@ class VmmTestingSetup:
 
     def get_vgpu_profile(self) -> VgpuProfile:
         configurator = VgpuProfileConfigurator(self.vgpu_profiles_dir, self.get_dut().gpu_model)
+        if self.testing_config.enable_max_vfs:
+            # Get a vGPU profile with the most VFs (not necessarily equal to sysfs/sriov_totalvfs)
+            self.testing_config.num_vfs = max(configurator.supported_vgpu_profiles.vf_resources,
+                                              key=lambda profile: profile.vf_count).vf_count
+            logger.debug("Max VFs supported by vGPU profiles: %s", self.testing_config.num_vfs)
+
         try:
             vgpu_profile = configurator.get_vgpu_profile(self.testing_config.num_vfs,
                                                          self.testing_config.scheduling_mode)
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH i-g-t 10/10] tools/vmtb: Platform enabling: PTL and BMG support
  2026-02-24  7:50 [PATCH i-g-t 00/10] vmtb: Modernize SR-IOV VM Test Bench core Adam Miszczak
                   ` (8 preceding siblings ...)
  2026-02-24  7:50 ` [PATCH i-g-t 09/10] tools/vmtb: Support max VFs configuration Adam Miszczak
@ 2026-02-24  7:50 ` Adam Miszczak
  2026-03-10 10:52   ` Bernatowicz, Marcin
  2026-02-24 11:49 ` ✓ Xe.CI.BAT: success for vmtb: Modernize SR-IOV VM Test Bench core Patchwork
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 25+ messages in thread
From: Adam Miszczak @ 2026-02-24  7:50 UTC (permalink / raw)
  To: igt-dev; +Cc: marcin.bernatowicz, kamil.konieczny

Add PCI Device IDs and example vGPU profiles for
Panther Lake (PTL) and Battlemage (BMG).
Remove unused ATS-M references.

Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
---
 tools/vmtb/bench/configurators/pci.py         | 43 +++++---
 .../{Flex170.json => Bmg_g21_12.json}         | 58 +++++------
 .../resources/vgpu_profiles/Ptl.json          | 97 +++++++++++++++++++
 3 files changed, 154 insertions(+), 44 deletions(-)
 rename tools/vmtb/vmm_flows/resources/vgpu_profiles/{Flex170.json => Bmg_g21_12.json} (73%)
 create mode 100644 tools/vmtb/vmm_flows/resources/vgpu_profiles/Ptl.json

diff --git a/tools/vmtb/bench/configurators/pci.py b/tools/vmtb/bench/configurators/pci.py
index 8e8afb138..0b524d3c2 100644
--- a/tools/vmtb/bench/configurators/pci.py
+++ b/tools/vmtb/bench/configurators/pci.py
@@ -1,13 +1,13 @@
 # SPDX-License-Identifier: MIT
-# Copyright © 2024 Intel Corporation
+# Copyright © 2024-2026 Intel Corporation
 
 import enum
 import typing
 
 
 class GpuModel(str, enum.Enum):
-    ATSM150 = 'Arctic Sound M150 (ATS-M1)'
-    ATSM75 = 'Arctic Sound M75 (ATS-M3)'
+    PTL = 'Panther Lake (PTL)'
+    BMG = 'Battlemage (BMG)'
     Unknown = 'Unknown'
 
     def __str__(self) -> str:
@@ -21,28 +21,41 @@ def get_gpu_model(pci_id: str) -> GpuModel:
 
 def get_vgpu_profiles_file(gpu_model: GpuModel) -> str:
     """Return vGPU profile definition JSON file for a given GPU model."""
-    if gpu_model == GpuModel.ATSM150:
-        vgpu_device_file = 'Flex170.json'
-    elif gpu_model == GpuModel.ATSM75:
-        vgpu_device_file = 'Flex140.json'
+    if gpu_model == GpuModel.PTL:
+        vgpu_device_file = 'Ptl.json'
+    elif gpu_model == GpuModel.BMG:
+        vgpu_device_file = 'Bmg_g21_12.json'
     else: # GpuModel.Unknown
         vgpu_device_file = 'N/A'
 
     return vgpu_device_file
 
 
-# PCI Device IDs: ATS-M150 (M1)
-_atsm150_pci_ids = {
-    '56C0': GpuModel.ATSM150,
-    '56C2': GpuModel.ATSM150
+# PCI Device IDs: PTL
+_ptl_pci_ids = {
+    'B080': GpuModel.PTL,
+    'B081': GpuModel.PTL,
+    'B082': GpuModel.PTL,
+    'B083': GpuModel.PTL,
+    'B084': GpuModel.PTL,
+    'B085': GpuModel.PTL,
+    'B086': GpuModel.PTL,
+    'B087': GpuModel.PTL,
+    'B08F': GpuModel.PTL,
+    'B090': GpuModel.PTL,
+    'B0A0': GpuModel.PTL,
+    'B0B0': GpuModel.PTL,
+    'FD80': GpuModel.PTL,
+    'FD81': GpuModel.PTL
 }
 
 
-# PCI Device IDs: ATS-M75 (M3)
-_atsm75_pci_ids = {
-    '56C1': GpuModel.ATSM75
+# PCI Device IDs: BMG (G21 - VRAM: 12GB / other)
+_bmg_pci_ids = {
+    'E20B': GpuModel.BMG # B36 / 12GB
 }
 
 
 # All PCI Device IDs to GPU Device Names mapping
-pci_ids: typing.Dict[str, GpuModel] = {**_atsm150_pci_ids, **_atsm75_pci_ids}
+pci_ids: typing.Dict[str, GpuModel] = {**_ptl_pci_ids,
+                                       **_bmg_pci_ids}
diff --git a/tools/vmtb/vmm_flows/resources/vgpu_profiles/Flex170.json b/tools/vmtb/vmm_flows/resources/vgpu_profiles/Bmg_g21_12.json
similarity index 73%
rename from tools/vmtb/vmm_flows/resources/vgpu_profiles/Flex170.json
rename to tools/vmtb/vmm_flows/resources/vgpu_profiles/Bmg_g21_12.json
index ff1fa7e20..75ca907ab 100644
--- a/tools/vmtb/vmm_flows/resources/vgpu_profiles/Flex170.json
+++ b/tools/vmtb/vmm_flows/resources/vgpu_profiles/Bmg_g21_12.json
@@ -1,58 +1,58 @@
 {
-    "version": "1.1",
+    "version": "1.2",
     "PFResources": {
         "Default": "MinimumPFResources",
         "Profile": {
             "MinimumPFResources": {
-                "LocalMemoryEccOn": 402653184,
-                "LocalMemoryEccOff": 402653184,
-                "Contexts": 1024,
+                "LocalMemoryEccOn": 134217728,
+                "LocalMemoryEccOff": 134217728,
+                "Contexts": 256,
                 "Doorbells": 16,
-                "GGTTSize": 268435456
+                "GGTTSize": 67108864
             }
         }
     },
     "vGPUResources": {
         "Default": null,
         "Profile": {
-            "Flex170_16": {
+            "Bmg_12": {
                 "VFCount": 1,
-                "LocalMemoryEccOff": 16777216000,
-                "LocalMemoryEccOn": 2147483648,
+                "LocalMemoryEccOff": 12717129728,
+                "LocalMemoryEccOn": 12717129728,
                 "Contexts": 1024,
                 "Doorbells": 240,
                 "GGTTSize": 4026531840
             },
-            "Flex170_8": {
+            "Bmg_6": {
                 "VFCount": 2,
-                "LocalMemoryEccOff": 8388608000,
-                "LocalMemoryEccOn": 2147483648,
+                "LocalMemoryEccOff": 6341787648,
+                "LocalMemoryEccOn": 6341787648,
                 "Contexts": 1024,
                 "Doorbells": 120,
                 "GGTTSize": 2013265920
             },
-            "Flex170_4": {
-                "VFCount": 4,
-                "LocalMemoryEccOff": 4194304000,
-                "LocalMemoryEccOn": 2147483648,
+            "Bmg_4": {
+                "VFCount": 3,
+                "LocalMemoryEccOff": 4211081216,
+                "LocalMemoryEccOn": 4211081216,
                 "Contexts": 1024,
-                "Doorbells": 60,
-                "GGTTSize": 1006632960
+                "Doorbells": 80,
+                "GGTTSize": 1342177280
             },
-            "Flex170_2": {
-                "VFCount": 8,
-                "LocalMemoryEccOff": 2097152000,
-                "LocalMemoryEccOn": 1073741824,
+            "Bmg_2": {
+                "VFCount": 6,
+                "LocalMemoryEccOff": 2080374784,
+                "LocalMemoryEccOn": 2080374784,
                 "Contexts": 1024,
-                "Doorbells": 30,
-                "GGTTSize": 503316480
+                "Doorbells": 40,
+                "GGTTSize": 671088640
             },
-            "Flex170_1": {
-                "VFCount": 16,
-                "LocalMemoryEccOff": 1048576000,
-                "LocalMemoryEccOn": 536870912,
+            "Bmg_1": {
+                "VFCount": 12,
+                "LocalMemoryEccOff": 1023410176,
+                "LocalMemoryEccOn": 1023410176,
                 "Contexts": 1024,
-                "Doorbells": 15,
+                "Doorbells": 20,
                 "GGTTSize": 251658240
             }
         }
@@ -110,4 +110,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tools/vmtb/vmm_flows/resources/vgpu_profiles/Ptl.json b/tools/vmtb/vmm_flows/resources/vgpu_profiles/Ptl.json
new file mode 100644
index 000000000..efc61bce1
--- /dev/null
+++ b/tools/vmtb/vmm_flows/resources/vgpu_profiles/Ptl.json
@@ -0,0 +1,97 @@
+{
+    "version": "0.1",
+    "PFResources": {
+        "Default": "MinimumPFResources",
+        "Profile": {
+            "MinimumPFResources": {
+                "LocalMemoryEccOn": 0,
+                "LocalMemoryEccOff": 0,
+                "Contexts": 256,
+                "Doorbells": 16,
+                "GGTTSize": 67108864
+            }
+        }
+    },
+    "vGPUResources": {
+        "Default": null,
+        "Profile": {
+            "Ptl_1": {
+                "VFCount": 1,
+                "LocalMemoryEccOff": 0,
+                "LocalMemoryEccOn": 0,
+                "Contexts": 1024,
+                "Doorbells": 240,
+                "GGTTSize": 4026531840
+            },
+            "Ptl_2": {
+                "VFCount": 2,
+                "LocalMemoryEccOff": 0,
+                "LocalMemoryEccOn": 0,
+                "Contexts": 1024,
+                "Doorbells": 120,
+                "GGTTSize": 2013265920
+            },
+            "Ptl_4": {
+                "VFCount": 4,
+                "LocalMemoryEccOff": 0,
+                "LocalMemoryEccOn": 0,
+                "Contexts": 1024,
+                "Doorbells": 60,
+                "GGTTSize": 1006632960
+            }
+        }
+    },
+    "vGPUScheduler": {
+        "Default": "Flexible_30fps_GPUTimeSlicing",
+        "Profile": {
+            "Flexible_30fps_GPUTimeSlicing": {
+                "GPUTimeSlicing": {
+                    "ScheduleIfIdle": false,
+                    "PFExecutionQuantum": 20,
+                    "PFPreemptionTimeout": 20000,
+                    "VFAttributes": {
+                        "VFExecutionQuantum": "lambda VFCount : max( 32 // VFCount, 1)",
+                        "VFPreemptionTimeout": "lambda VFCount : 128000 if (VFCount == 1) else max( 64000 // VFCount, 16000)"
+                    }
+                }
+            },
+            "Fixed_30fps_GPUTimeSlicing": {
+                "GPUTimeSlicing": {
+                    "ScheduleIfIdle": true,
+                    "PFExecutionQuantum": 20,
+                    "PFPreemptionTimeout": 20000,
+                    "VFAttributes": {
+                        "VFExecutionQuantum": "lambda VFCount : max( 32 // VFCount, 1)",
+                        "VFPreemptionTimeout": "lambda VFCount : 128000 if (VFCount == 1) else max( 64000 // VFCount, 16000)"
+                    }
+                }
+            },
+            "Flexible_BurstableQoS_GPUTimeSlicing": {
+                "GPUTimeSlicing": {
+                    "ScheduleIfIdle": false,
+                    "PFExecutionQuantum": 20,
+                    "PFPreemptionTimeout": 20000,
+                    "VFAttributes": {
+                        "VFExecutionQuantum": "lambda VFCount : min((2000 // max(VFCount-1,1)*0.5, 50))",
+                        "VFPreemptionTimeout": "lambda VFCount : (2000 // max(VFCount-1,1) - min((2000 // max(VFCount-1,1))*0.5, 50))*1000"
+                    }
+                }
+            }
+        }
+    },
+    "vGPUSecurity": {
+        "Default": "Disabled",
+        "Profile": {
+            "Disabled": {
+                "ResetAfterVfSwitch": false,
+                "GuCSamplingPeriod": 0,
+                "GuCThresholdCATError": 0,
+                "GuCThresholdPageFault": 0,
+                "GuCThresholdH2GStorm": 0,
+                "GuCThresholdDbStorm": 0,
+                "GuCThresholdGTIrqStorm": 0,
+                "GuCThresholdEngineReset": 0
+            }
+        }
+    }
+}
\ No newline at end of file
-- 
2.39.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* ✓ Xe.CI.BAT: success for vmtb: Modernize SR-IOV VM Test Bench core
  2026-02-24  7:50 [PATCH i-g-t 00/10] vmtb: Modernize SR-IOV VM Test Bench core Adam Miszczak
                   ` (9 preceding siblings ...)
  2026-02-24  7:50 ` [PATCH i-g-t 10/10] tools/vmtb: Platform enabling: PTL and BMG support Adam Miszczak
@ 2026-02-24 11:49 ` Patchwork
  2026-02-24 12:43 ` ✓ i915.CI.BAT: " Patchwork
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2026-02-24 11:49 UTC (permalink / raw)
  To: Adam Miszczak; +Cc: igt-dev

[-- Attachment #1: Type: text/plain, Size: 1362 bytes --]

== Series Details ==

Series: vmtb: Modernize SR-IOV VM Test Bench core
URL   : https://patchwork.freedesktop.org/series/162037/
State : success

== Summary ==

CI Bug Log - changes from XEIGT_8768_BAT -> XEIGTPW_14603_BAT
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  

Participating hosts (14 -> 14)
------------------------------

  No changes in participating hosts

Known issues
------------

  Here are the changes found in XEIGTPW_14603_BAT that come from known issues:

### IGT changes ###

#### Possible fixes ####

  * igt@xe_waitfence@reltime:
    - bat-dg2-oem2:       [FAIL][1] ([Intel XE#6520]) -> [PASS][2]
   [1]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8768/bat-dg2-oem2/igt@xe_waitfence@reltime.html
   [2]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/bat-dg2-oem2/igt@xe_waitfence@reltime.html

  
  [Intel XE#6520]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6520


Build changes
-------------

  * IGT: IGT_8768 -> IGTPW_14603

  IGTPW_14603: 18d15cf4696eeed1a1a42e326a93422d55684846 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  IGT_8768: 8768
  xe-4591-45a3045fc0dc46a893cb8bbe304afafd4120c904: 45a3045fc0dc46a893cb8bbe304afafd4120c904

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/index.html

[-- Attachment #2: Type: text/html, Size: 1924 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* ✓ i915.CI.BAT: success for vmtb: Modernize SR-IOV VM Test Bench core
  2026-02-24  7:50 [PATCH i-g-t 00/10] vmtb: Modernize SR-IOV VM Test Bench core Adam Miszczak
                   ` (10 preceding siblings ...)
  2026-02-24 11:49 ` ✓ Xe.CI.BAT: success for vmtb: Modernize SR-IOV VM Test Bench core Patchwork
@ 2026-02-24 12:43 ` Patchwork
  2026-02-24 16:27 ` ✗ i915.CI.Full: failure " Patchwork
  2026-02-24 20:21 ` ✗ Xe.CI.FULL: " Patchwork
  13 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2026-02-24 12:43 UTC (permalink / raw)
  To: Adam Miszczak; +Cc: igt-dev

[-- Attachment #1: Type: text/plain, Size: 1918 bytes --]

== Series Details ==

Series: vmtb: Modernize SR-IOV VM Test Bench core
URL   : https://patchwork.freedesktop.org/series/162037/
State : success

== Summary ==

CI Bug Log - changes from IGT_8768 -> IGTPW_14603
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/index.html

Participating hosts (43 -> 41)
------------------------------

  Missing    (2): bat-dg2-13 fi-snb-2520m 

Known issues
------------

  Here are the changes found in IGTPW_14603 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@i915_selftest@live@workarounds:
    - bat-dg2-14:         [PASS][1] -> [DMESG-FAIL][2] ([i915#12061]) +1 other test dmesg-fail
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/bat-dg2-14/igt@i915_selftest@live@workarounds.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/bat-dg2-14/igt@i915_selftest@live@workarounds.html

  
#### Possible fixes ####

  * igt@i915_selftest@live@workarounds:
    - bat-arls-5:         [DMESG-FAIL][3] ([i915#12061]) -> [PASS][4] +1 other test pass
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/bat-arls-5/igt@i915_selftest@live@workarounds.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/bat-arls-5/igt@i915_selftest@live@workarounds.html

  
  [i915#12061]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12061


Build changes
-------------

  * CI: CI-20190529 -> None
  * IGT: IGT_8768 -> IGTPW_14603

  CI-20190529: 20190529
  CI_DRM_18022: 45a3045fc0dc46a893cb8bbe304afafd4120c904 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_14603: 18d15cf4696eeed1a1a42e326a93422d55684846 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  IGT_8768: 8768

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/index.html

[-- Attachment #2: Type: text/html, Size: 2607 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* ✗ i915.CI.Full: failure for vmtb: Modernize SR-IOV VM Test Bench core
  2026-02-24  7:50 [PATCH i-g-t 00/10] vmtb: Modernize SR-IOV VM Test Bench core Adam Miszczak
                   ` (11 preceding siblings ...)
  2026-02-24 12:43 ` ✓ i915.CI.BAT: " Patchwork
@ 2026-02-24 16:27 ` Patchwork
  2026-02-24 20:21 ` ✗ Xe.CI.FULL: " Patchwork
  13 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2026-02-24 16:27 UTC (permalink / raw)
  To: Adam Miszczak; +Cc: igt-dev

[-- Attachment #1: Type: text/plain, Size: 126777 bytes --]

== Series Details ==

Series: vmtb: Modernize SR-IOV VM Test Bench core
URL   : https://patchwork.freedesktop.org/series/162037/
State : failure

== Summary ==

CI Bug Log - changes from IGT_8768_full -> IGTPW_14603_full
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with IGTPW_14603_full absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in IGTPW_14603_full, please notify your bug team (I915-ci-infra@lists.freedesktop.org) to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/index.html

Participating hosts (9 -> 9)
------------------------------

  No changes in participating hosts

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in IGTPW_14603_full:

### IGT changes ###

#### Possible regressions ####

  * igt@i915_module_load@fault-injection@uc_fw_rsa_data_create:
    - shard-mtlp:         [PASS][1] -> [INCOMPLETE][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-mtlp-1/igt@i915_module_load@fault-injection@uc_fw_rsa_data_create.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-1/igt@i915_module_load@fault-injection@uc_fw_rsa_data_create.html

  * igt@perf_pmu@module-unload:
    - shard-glk:          NOTRUN -> [ABORT][3]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-glk2/igt@perf_pmu@module-unload.html
    - shard-rkl:          NOTRUN -> [ABORT][4]
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-7/igt@perf_pmu@module-unload.html

  
New tests
---------

  New tests have been introduced between IGT_8768_full and IGTPW_14603_full:

### New IGT tests (32) ###

  * igt@i915_module_load@2x-tiling-y:
    - Statuses :
    - Exec time: [None] s

  * igt@i915_module_load@dmabuf-shared-protected-dst-is-context-refcounted:
    - Statuses :
    - Exec time: [None] s

  * igt@i915_module_load@dpms-mode-unset-non-lpsp:
    - Statuses :
    - Exec time: [None] s

  * igt@i915_module_load@dsc-with-bpc:
    - Statuses :
    - Exec time: [None] s

  * igt@i915_module_load@fbc-1p-primscrn-pri-shrfb-draw-render:
    - Statuses :
    - Exec time: [None] s

  * igt@i915_module_load@fbc-psr2-sprite-render:
    - Statuses :
    - Exec time: [None] s

  * igt@i915_module_load@fbcpsr-1p-primscrn-pri-shrfb-draw-mmap-wc:
    - Statuses :
    - Exec time: [None] s

  * igt@i915_module_load@linear-addfb:
    - Statuses :
    - Exec time: [None] s

  * igt@i915_module_load@mi-rpc:
    - Statuses :
    - Exec time: [None] s

  * igt@i915_module_load@multi-wait-submitted-signaled:
    - Statuses :
    - Exec time: [None] s

  * igt@i915_module_load@psr2-cursor-mmap-cpu:
    - Statuses :
    - Exec time: [None] s

  * igt@i915_module_load@query-busy:
    - Statuses :
    - Exec time: [None] s

  * igt@i915_module_load@rc6:
    - Statuses :
    - Exec time: [None] s

  * igt@i915_module_load@wait-delayed-signal:
    - Statuses :
    - Exec time: [None] s

  * igt@kms_async_flips@test-cursor@pipe-a-vga-1:
    - Statuses : 1 pass(s)
    - Exec time: [0.13] s

  * igt@kms_async_flips@test-cursor@pipe-b-vga-1:
    - Statuses : 1 pass(s)
    - Exec time: [0.14] s

  * igt@kms_atomic@crtc-invalid-params@pipe-a-vga-1:
    - Statuses : 1 pass(s)
    - Exec time: [0.28] s

  * igt@kms_color@ctm-0-75@pipe-a-vga-1:
    - Statuses : 1 pass(s)
    - Exec time: [1.79] s

  * igt@kms_color@ctm-0-75@pipe-b-vga-1:
    - Statuses : 1 pass(s)
    - Exec time: [1.68] s

  * igt@kms_display_modes@extended-mode-basic@pipe-a-hdmi-a-1-pipe-b-vga-1:
    - Statuses : 1 pass(s)
    - Exec time: [0.75] s

  * igt@kms_display_modes@extended-mode-basic@pipe-a-vga-1-pipe-b-hdmi-a-1:
    - Statuses : 1 pass(s)
    - Exec time: [0.53] s

  * igt@kms_display_modes@extended-mode-basic@pipe-b-hdmi-a-1-pipe-a-vga-1:
    - Statuses : 1 pass(s)
    - Exec time: [0.75] s

  * igt@kms_display_modes@extended-mode-basic@pipe-b-vga-1-pipe-a-hdmi-a-1:
    - Statuses : 1 pass(s)
    - Exec time: [0.73] s

  * igt@kms_flip_event_leak@basic@pipe-a-vga-1:
    - Statuses : 1 pass(s)
    - Exec time: [0.33] s

  * igt@kms_flip_event_leak@basic@pipe-b-vga-1:
    - Statuses : 1 pass(s)
    - Exec time: [0.20] s

  * igt@kms_frontbuffer_tracking@pipe-fbc-rte@pipe-b-vga-1:
    - Statuses : 1 pass(s)
    - Exec time: [3.31] s

  * igt@kms_invalid_mode@bad-vsync-start@pipe-a-vga-1:
    - Statuses : 1 pass(s)
    - Exec time: [0.12] s

  * igt@kms_invalid_mode@bad-vsync-start@pipe-b-vga-1:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@kms_invalid_mode@uint-max-clock@pipe-a-vga-1:
    - Statuses : 1 pass(s)
    - Exec time: [0.12] s

  * igt@kms_invalid_mode@uint-max-clock@pipe-b-vga-1:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@kms_vblank@ts-continuation-modeset-rpm@pipe-b-vga-1:
    - Statuses : 1 skip(s)
    - Exec time: [11.31] s

  * igt@kms_vblank@ts-continuation-suspend@pipe-b-vga-1:
    - Statuses : 1 pass(s)
    - Exec time: [0.84] s

  

Known issues
------------

  Here are the changes found in IGTPW_14603_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@api_intel_bb@object-reloc-keep-cache:
    - shard-rkl:          NOTRUN -> [SKIP][5] ([i915#8411]) +1 other test skip
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-3/igt@api_intel_bb@object-reloc-keep-cache.html

  * igt@device_reset@cold-reset-bound:
    - shard-tglu:         NOTRUN -> [SKIP][6] ([i915#11078])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-3/igt@device_reset@cold-reset-bound.html

  * igt@drm_buddy@drm_buddy:
    - shard-tglu-1:       NOTRUN -> [SKIP][7] ([i915#15678])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@drm_buddy@drm_buddy.html

  * igt@gem_bad_reloc@negative-reloc-bltcopy:
    - shard-mtlp:         NOTRUN -> [SKIP][8] ([i915#3281]) +2 other tests skip
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-4/igt@gem_bad_reloc@negative-reloc-bltcopy.html
    - shard-dg2:          NOTRUN -> [SKIP][9] ([i915#3281]) +2 other tests skip
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-4/igt@gem_bad_reloc@negative-reloc-bltcopy.html
    - shard-dg1:          NOTRUN -> [SKIP][10] ([i915#3281]) +2 other tests skip
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-17/igt@gem_bad_reloc@negative-reloc-bltcopy.html

  * igt@gem_basic@multigpu-create-close:
    - shard-dg1:          NOTRUN -> [SKIP][11] ([i915#7697])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-12/igt@gem_basic@multigpu-create-close.html

  * igt@gem_ccs@ctrl-surf-copy-new-ctx:
    - shard-rkl:          NOTRUN -> [SKIP][12] ([i915#9323])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@gem_ccs@ctrl-surf-copy-new-ctx.html

  * igt@gem_ccs@large-ctrl-surf-copy:
    - shard-dg1:          NOTRUN -> [SKIP][13] ([i915#13008])
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-13/igt@gem_ccs@large-ctrl-surf-copy.html

  * igt@gem_close_race@multigpu-basic-process:
    - shard-tglu:         NOTRUN -> [SKIP][14] ([i915#7697])
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-4/igt@gem_close_race@multigpu-basic-process.html
    - shard-rkl:          NOTRUN -> [SKIP][15] ([i915#14544] / [i915#7697])
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@gem_close_race@multigpu-basic-process.html

  * igt@gem_create@create-ext-cpu-access-big:
    - shard-dg2:          [PASS][16] -> [FAIL][17] ([i915#15454])
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg2-7/igt@gem_create@create-ext-cpu-access-big.html
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-6/igt@gem_create@create-ext-cpu-access-big.html

  * igt@gem_create@create-ext-cpu-access-sanity-check:
    - shard-tglu:         NOTRUN -> [SKIP][18] ([i915#6335])
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-4/igt@gem_create@create-ext-cpu-access-sanity-check.html
    - shard-mtlp:         NOTRUN -> [SKIP][19] ([i915#6335])
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-7/igt@gem_create@create-ext-cpu-access-sanity-check.html
    - shard-rkl:          NOTRUN -> [SKIP][20] ([i915#6335])
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-7/igt@gem_create@create-ext-cpu-access-sanity-check.html

  * igt@gem_ctx_persistence@legacy-engines-hang:
    - shard-snb:          NOTRUN -> [SKIP][21] ([i915#1099]) +1 other test skip
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-snb4/igt@gem_ctx_persistence@legacy-engines-hang.html

  * igt@gem_ctx_sseu@mmap-args:
    - shard-tglu-1:       NOTRUN -> [SKIP][22] ([i915#280]) +1 other test skip
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@gem_ctx_sseu@mmap-args.html

  * igt@gem_eio@in-flight-suspend:
    - shard-rkl:          [PASS][23] -> [INCOMPLETE][24] ([i915#13390])
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-8/igt@gem_eio@in-flight-suspend.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@gem_eio@in-flight-suspend.html

  * igt@gem_eio@unwedge-stress:
    - shard-snb:          NOTRUN -> [FAIL][25] ([i915#8898]) +1 other test fail
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-snb4/igt@gem_eio@unwedge-stress.html

  * igt@gem_eio@unwedge-stress@blt:
    - shard-mtlp:         NOTRUN -> [SKIP][26] ([i915#15314])
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-7/igt@gem_eio@unwedge-stress@blt.html

  * igt@gem_exec_balancer@noheartbeat:
    - shard-dg2:          NOTRUN -> [SKIP][27] ([i915#8555])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-11/igt@gem_exec_balancer@noheartbeat.html
    - shard-dg1:          NOTRUN -> [SKIP][28] ([i915#8555])
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-13/igt@gem_exec_balancer@noheartbeat.html
    - shard-mtlp:         NOTRUN -> [SKIP][29] ([i915#8555])
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-5/igt@gem_exec_balancer@noheartbeat.html

  * igt@gem_exec_balancer@parallel-balancer:
    - shard-rkl:          NOTRUN -> [SKIP][30] ([i915#4525])
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@gem_exec_balancer@parallel-balancer.html

  * igt@gem_exec_fence@syncobj-backward-timeline-chain-engines:
    - shard-snb:          NOTRUN -> [SKIP][31] +129 other tests skip
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-snb4/igt@gem_exec_fence@syncobj-backward-timeline-chain-engines.html

  * igt@gem_exec_params@rsvd2-dirt:
    - shard-mtlp:         NOTRUN -> [SKIP][32] ([i915#5107])
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-6/igt@gem_exec_params@rsvd2-dirt.html
    - shard-dg2:          NOTRUN -> [SKIP][33] ([i915#5107])
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-5/igt@gem_exec_params@rsvd2-dirt.html

  * igt@gem_exec_reloc@basic-write-read-noreloc:
    - shard-rkl:          NOTRUN -> [SKIP][34] ([i915#3281]) +10 other tests skip
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@gem_exec_reloc@basic-write-read-noreloc.html

  * igt@gem_exec_schedule@preempt-queue-contexts:
    - shard-dg1:          NOTRUN -> [SKIP][35] ([i915#4812]) +1 other test skip
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-14/igt@gem_exec_schedule@preempt-queue-contexts.html

  * igt@gem_lmem_swapping@heavy-verify-multi:
    - shard-tglu-1:       NOTRUN -> [SKIP][36] ([i915#4613]) +1 other test skip
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@gem_lmem_swapping@heavy-verify-multi.html

  * igt@gem_lmem_swapping@heavy-verify-random-ccs:
    - shard-tglu:         NOTRUN -> [SKIP][37] ([i915#4613])
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-9/igt@gem_lmem_swapping@heavy-verify-random-ccs.html

  * igt@gem_lmem_swapping@parallel-multi:
    - shard-rkl:          NOTRUN -> [SKIP][38] ([i915#4613]) +5 other tests skip
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-2/igt@gem_lmem_swapping@parallel-multi.html

  * igt@gem_lmem_swapping@parallel-random-verify-ccs:
    - shard-glk:          NOTRUN -> [SKIP][39] ([i915#4613]) +2 other tests skip
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-glk6/igt@gem_lmem_swapping@parallel-random-verify-ccs.html

  * igt@gem_mmap_gtt@cpuset-big-copy-odd:
    - shard-dg1:          NOTRUN -> [SKIP][40] ([i915#4077]) +1 other test skip
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-17/igt@gem_mmap_gtt@cpuset-big-copy-odd.html

  * igt@gem_mmap_gtt@cpuset-big-copy-xy:
    - shard-mtlp:         NOTRUN -> [SKIP][41] ([i915#4077])
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-1/igt@gem_mmap_gtt@cpuset-big-copy-xy.html
    - shard-dg2:          NOTRUN -> [SKIP][42] ([i915#4077])
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-6/igt@gem_mmap_gtt@cpuset-big-copy-xy.html

  * igt@gem_mmap_offset@clear-via-pagefault:
    - shard-mtlp:         [PASS][43] -> [ABORT][44] ([i915#14809]) +1 other test abort
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-mtlp-8/igt@gem_mmap_offset@clear-via-pagefault.html
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-5/igt@gem_mmap_offset@clear-via-pagefault.html

  * igt@gem_mmap_wc@bad-offset:
    - shard-mtlp:         NOTRUN -> [SKIP][45] ([i915#4083])
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-4/igt@gem_mmap_wc@bad-offset.html
    - shard-dg2:          NOTRUN -> [SKIP][46] ([i915#4083])
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-4/igt@gem_mmap_wc@bad-offset.html
    - shard-dg1:          NOTRUN -> [SKIP][47] ([i915#4083])
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-17/igt@gem_mmap_wc@bad-offset.html

  * igt@gem_partial_pwrite_pread@reads-snoop:
    - shard-dg1:          NOTRUN -> [SKIP][48] ([i915#3282]) +1 other test skip
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-17/igt@gem_partial_pwrite_pread@reads-snoop.html
    - shard-mtlp:         NOTRUN -> [SKIP][49] ([i915#3282]) +1 other test skip
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-4/igt@gem_partial_pwrite_pread@reads-snoop.html
    - shard-dg2:          NOTRUN -> [SKIP][50] ([i915#3282])
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-4/igt@gem_partial_pwrite_pread@reads-snoop.html

  * igt@gem_partial_pwrite_pread@writes-after-reads-uncached:
    - shard-rkl:          NOTRUN -> [SKIP][51] ([i915#3282]) +3 other tests skip
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-3/igt@gem_partial_pwrite_pread@writes-after-reads-uncached.html

  * igt@gem_pxp@create-protected-buffer:
    - shard-dg1:          NOTRUN -> [SKIP][52] ([i915#4270]) +1 other test skip
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-13/igt@gem_pxp@create-protected-buffer.html

  * igt@gem_pxp@reject-modify-context-protection-off-2:
    - shard-dg2:          NOTRUN -> [SKIP][53] ([i915#4270]) +1 other test skip
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-6/igt@gem_pxp@reject-modify-context-protection-off-2.html

  * igt@gem_render_copy@y-tiled-ccs-to-y-tiled:
    - shard-dg2:          NOTRUN -> [SKIP][54] ([i915#5190] / [i915#8428]) +2 other tests skip
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-1/igt@gem_render_copy@y-tiled-ccs-to-y-tiled.html

  * igt@gem_render_copy@y-tiled-ccs-to-y-tiled-ccs:
    - shard-mtlp:         NOTRUN -> [SKIP][55] ([i915#8428]) +3 other tests skip
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-4/igt@gem_render_copy@y-tiled-ccs-to-y-tiled-ccs.html

  * igt@gem_set_tiling_vs_blt@tiled-to-tiled:
    - shard-dg2:          NOTRUN -> [SKIP][56] ([i915#4079])
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-7/igt@gem_set_tiling_vs_blt@tiled-to-tiled.html
    - shard-dg1:          NOTRUN -> [SKIP][57] ([i915#4079])
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-14/igt@gem_set_tiling_vs_blt@tiled-to-tiled.html
    - shard-mtlp:         NOTRUN -> [SKIP][58] ([i915#4079])
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-2/igt@gem_set_tiling_vs_blt@tiled-to-tiled.html

  * igt@gem_tiled_partial_pwrite_pread@reads:
    - shard-rkl:          NOTRUN -> [SKIP][59] ([i915#14544] / [i915#3282])
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@gem_tiled_partial_pwrite_pread@reads.html

  * igt@gem_unfence_active_buffers:
    - shard-dg1:          NOTRUN -> [SKIP][60] ([i915#4879])
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-13/igt@gem_unfence_active_buffers.html

  * igt@gem_userptr_blits@coherency-unsync:
    - shard-rkl:          NOTRUN -> [SKIP][61] ([i915#14544] / [i915#3297])
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@gem_userptr_blits@coherency-unsync.html

  * igt@gem_userptr_blits@create-destroy-unsync:
    - shard-tglu-1:       NOTRUN -> [SKIP][62] ([i915#3297])
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@gem_userptr_blits@create-destroy-unsync.html

  * igt@gem_userptr_blits@invalid-mmap-offset-unsync:
    - shard-rkl:          NOTRUN -> [SKIP][63] ([i915#3297])
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-8/igt@gem_userptr_blits@invalid-mmap-offset-unsync.html

  * igt@gem_userptr_blits@unsync-unmap-after-close:
    - shard-tglu:         NOTRUN -> [SKIP][64] ([i915#3297])
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-3/igt@gem_userptr_blits@unsync-unmap-after-close.html

  * igt@gem_workarounds@suspend-resume-context:
    - shard-rkl:          [PASS][65] -> [INCOMPLETE][66] ([i915#13356])
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-5/igt@gem_workarounds@suspend-resume-context.html
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-3/igt@gem_workarounds@suspend-resume-context.html

  * igt@gen9_exec_parse@bb-chained:
    - shard-rkl:          NOTRUN -> [SKIP][67] ([i915#2527]) +2 other tests skip
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-8/igt@gen9_exec_parse@bb-chained.html

  * igt@gen9_exec_parse@bb-start-cmd:
    - shard-dg1:          NOTRUN -> [SKIP][68] ([i915#2527]) +3 other tests skip
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-18/igt@gen9_exec_parse@bb-start-cmd.html
    - shard-mtlp:         NOTRUN -> [SKIP][69] ([i915#2856]) +1 other test skip
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-8/igt@gen9_exec_parse@bb-start-cmd.html
    - shard-dg2:          NOTRUN -> [SKIP][70] ([i915#2856]) +1 other test skip
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-3/igt@gen9_exec_parse@bb-start-cmd.html

  * igt@gen9_exec_parse@unaligned-jump:
    - shard-tglu:         NOTRUN -> [SKIP][71] ([i915#2527] / [i915#2856]) +2 other tests skip
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-6/igt@gen9_exec_parse@unaligned-jump.html

  * igt@i915_drm_fdinfo@most-busy-idle-check-all:
    - shard-mtlp:         NOTRUN -> [SKIP][72] ([i915#14073]) +6 other tests skip
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-1/igt@i915_drm_fdinfo@most-busy-idle-check-all.html

  * igt@i915_drm_fdinfo@most-busy-idle-check-all@vecs0:
    - shard-dg1:          NOTRUN -> [SKIP][73] ([i915#14073]) +5 other tests skip
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-16/igt@i915_drm_fdinfo@most-busy-idle-check-all@vecs0.html

  * igt@i915_drm_fdinfo@most-busy-idle-check-all@vecs1:
    - shard-dg2:          NOTRUN -> [SKIP][74] ([i915#14073]) +7 other tests skip
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-6/igt@i915_drm_fdinfo@most-busy-idle-check-all@vecs1.html

  * igt@i915_module_load@reload-no-display:
    - shard-tglu-1:       NOTRUN -> [DMESG-WARN][75] ([i915#13029] / [i915#14545])
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@i915_module_load@reload-no-display.html

  * igt@i915_pm_freq_api@freq-reset:
    - shard-rkl:          NOTRUN -> [SKIP][76] ([i915#8399])
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@i915_pm_freq_api@freq-reset.html

  * igt@i915_pm_freq_mult@media-freq@gt0:
    - shard-tglu-1:       NOTRUN -> [SKIP][77] ([i915#6590]) +1 other test skip
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@i915_pm_freq_mult@media-freq@gt0.html

  * igt@i915_pm_rc6_residency@rc6-fence:
    - shard-tglu-1:       NOTRUN -> [WARN][78] ([i915#13790] / [i915#2681]) +1 other test warn
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@i915_pm_rc6_residency@rc6-fence.html

  * igt@i915_pm_rps@thresholds:
    - shard-mtlp:         NOTRUN -> [SKIP][79] ([i915#11681])
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-5/igt@i915_pm_rps@thresholds.html
    - shard-dg2:          NOTRUN -> [SKIP][80] ([i915#11681])
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-5/igt@i915_pm_rps@thresholds.html
    - shard-dg1:          NOTRUN -> [SKIP][81] ([i915#11681])
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-16/igt@i915_pm_rps@thresholds.html

  * igt@i915_pm_sseu@full-enable:
    - shard-rkl:          NOTRUN -> [SKIP][82] ([i915#4387])
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-3/igt@i915_pm_sseu@full-enable.html

  * igt@i915_suspend@basic-s2idle-without-i915:
    - shard-dg1:          [PASS][83] -> [DMESG-WARN][84] ([i915#4391] / [i915#4423])
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg1-12/igt@i915_suspend@basic-s2idle-without-i915.html
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-13/igt@i915_suspend@basic-s2idle-without-i915.html

  * igt@kms_addfb_basic@bo-too-small-due-to-tiling:
    - shard-dg1:          NOTRUN -> [SKIP][85] ([i915#4212])
   [85]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-17/igt@kms_addfb_basic@bo-too-small-due-to-tiling.html
    - shard-mtlp:         NOTRUN -> [SKIP][86] ([i915#4212]) +1 other test skip
   [86]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-4/igt@kms_addfb_basic@bo-too-small-due-to-tiling.html
    - shard-dg2:          NOTRUN -> [SKIP][87] ([i915#4212])
   [87]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-4/igt@kms_addfb_basic@bo-too-small-due-to-tiling.html

  * igt@kms_addfb_basic@invalid-smem-bo-on-discrete:
    - shard-tglu:         NOTRUN -> [SKIP][88] ([i915#12454] / [i915#12712])
   [88]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-6/igt@kms_addfb_basic@invalid-smem-bo-on-discrete.html

  * igt@kms_atomic_transition@plane-toggle-modeset-transition@pipe-a-edp-1:
    - shard-mtlp:         [PASS][89] -> [FAIL][90] ([i915#5956]) +1 other test fail
   [89]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-mtlp-6/igt@kms_atomic_transition@plane-toggle-modeset-transition@pipe-a-edp-1.html
   [90]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-4/igt@kms_atomic_transition@plane-toggle-modeset-transition@pipe-a-edp-1.html

  * igt@kms_big_fb@4-tiled-16bpp-rotate-0:
    - shard-rkl:          NOTRUN -> [SKIP][91] ([i915#5286]) +6 other tests skip
   [91]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-8/igt@kms_big_fb@4-tiled-16bpp-rotate-0.html

  * igt@kms_big_fb@4-tiled-addfb-size-overflow:
    - shard-dg1:          NOTRUN -> [SKIP][92] ([i915#5286])
   [92]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-12/igt@kms_big_fb@4-tiled-addfb-size-overflow.html

  * igt@kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0-hflip:
    - shard-tglu-1:       NOTRUN -> [SKIP][93] ([i915#5286]) +1 other test skip
   [93]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0-hflip.html
    - shard-dg1:          NOTRUN -> [SKIP][94] ([i915#4538] / [i915#5286]) +2 other tests skip
   [94]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-18/igt@kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0-hflip.html

  * igt@kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0:
    - shard-tglu:         NOTRUN -> [SKIP][95] ([i915#5286]) +3 other tests skip
   [95]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-2/igt@kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0.html

  * igt@kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0-hflip:
    - shard-rkl:          NOTRUN -> [SKIP][96] ([i915#14544] / [i915#5286])
   [96]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0-hflip.html
    - shard-mtlp:         [PASS][97] -> [FAIL][98] ([i915#15733] / [i915#5138])
   [97]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-mtlp-1/igt@kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0-hflip.html
   [98]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-4/igt@kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0-hflip.html

  * igt@kms_big_fb@linear-16bpp-rotate-270:
    - shard-mtlp:         NOTRUN -> [SKIP][99] +9 other tests skip
   [99]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-6/igt@kms_big_fb@linear-16bpp-rotate-270.html
    - shard-dg1:          NOTRUN -> [SKIP][100] ([i915#3638]) +1 other test skip
   [100]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-13/igt@kms_big_fb@linear-16bpp-rotate-270.html

  * igt@kms_big_fb@linear-max-hw-stride-64bpp-rotate-0-hflip:
    - shard-rkl:          NOTRUN -> [SKIP][101] ([i915#14544] / [i915#3828])
   [101]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_big_fb@linear-max-hw-stride-64bpp-rotate-0-hflip.html

  * igt@kms_big_fb@y-tiled-64bpp-rotate-0:
    - shard-dg2:          NOTRUN -> [SKIP][102] ([i915#4538] / [i915#5190]) +2 other tests skip
   [102]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-6/igt@kms_big_fb@y-tiled-64bpp-rotate-0.html

  * igt@kms_big_fb@y-tiled-64bpp-rotate-270:
    - shard-rkl:          NOTRUN -> [SKIP][103] ([i915#3638]) +1 other test skip
   [103]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-3/igt@kms_big_fb@y-tiled-64bpp-rotate-270.html

  * igt@kms_big_fb@yf-tiled-16bpp-rotate-90:
    - shard-dg1:          NOTRUN -> [SKIP][104] ([i915#4538]) +1 other test skip
   [104]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-12/igt@kms_big_fb@yf-tiled-16bpp-rotate-90.html

  * igt@kms_big_fb@yf-tiled-addfb-size-offset-overflow:
    - shard-mtlp:         NOTRUN -> [SKIP][105] ([i915#6187])
   [105]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-7/igt@kms_big_fb@yf-tiled-addfb-size-offset-overflow.html
    - shard-dg2:          NOTRUN -> [SKIP][106] ([i915#5190])
   [106]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-11/igt@kms_big_fb@yf-tiled-addfb-size-offset-overflow.html

  * igt@kms_ccs@bad-aux-stride-y-tiled-ccs@pipe-d-hdmi-a-1:
    - shard-tglu:         NOTRUN -> [SKIP][107] ([i915#6095]) +79 other tests skip
   [107]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-6/igt@kms_ccs@bad-aux-stride-y-tiled-ccs@pipe-d-hdmi-a-1.html

  * igt@kms_ccs@bad-pixel-format-4-tiled-dg2-rc-ccs-cc@pipe-a-hdmi-a-3:
    - shard-dg2:          NOTRUN -> [SKIP][108] ([i915#6095]) +32 other tests skip
   [108]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-8/igt@kms_ccs@bad-pixel-format-4-tiled-dg2-rc-ccs-cc@pipe-a-hdmi-a-3.html

  * igt@kms_ccs@bad-pixel-format-4-tiled-mtl-rc-ccs-cc@pipe-c-hdmi-a-2:
    - shard-glk:          NOTRUN -> [SKIP][109] +163 other tests skip
   [109]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-glk6/igt@kms_ccs@bad-pixel-format-4-tiled-mtl-rc-ccs-cc@pipe-c-hdmi-a-2.html

  * igt@kms_ccs@bad-rotation-90-4-tiled-lnl-ccs:
    - shard-rkl:          NOTRUN -> [SKIP][110] ([i915#12313]) +2 other tests skip
   [110]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@kms_ccs@bad-rotation-90-4-tiled-lnl-ccs.html

  * igt@kms_ccs@bad-rotation-90-4-tiled-mtl-mc-ccs@pipe-c-hdmi-a-2:
    - shard-rkl:          NOTRUN -> [SKIP][111] ([i915#14098] / [i915#6095]) +43 other tests skip
   [111]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-7/igt@kms_ccs@bad-rotation-90-4-tiled-mtl-mc-ccs@pipe-c-hdmi-a-2.html

  * igt@kms_ccs@crc-primary-basic-4-tiled-mtl-mc-ccs:
    - shard-tglu-1:       NOTRUN -> [SKIP][112] ([i915#6095]) +24 other tests skip
   [112]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_ccs@crc-primary-basic-4-tiled-mtl-mc-ccs.html

  * igt@kms_ccs@crc-primary-rotation-180-4-tiled-mtl-mc-ccs@pipe-d-hdmi-a-1:
    - shard-dg2:          NOTRUN -> [SKIP][113] ([i915#10307] / [i915#10434] / [i915#6095]) +4 other tests skip
   [113]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-4/igt@kms_ccs@crc-primary-rotation-180-4-tiled-mtl-mc-ccs@pipe-d-hdmi-a-1.html

  * igt@kms_ccs@crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc@pipe-c-dp-3:
    - shard-dg2:          NOTRUN -> [SKIP][114] ([i915#10307] / [i915#6095]) +137 other tests skip
   [114]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-11/igt@kms_ccs@crc-primary-rotation-180-y-tiled-gen12-rc-ccs-cc@pipe-c-dp-3.html

  * igt@kms_ccs@crc-sprite-planes-basic-4-tiled-dg2-rc-ccs@pipe-b-hdmi-a-2:
    - shard-rkl:          NOTRUN -> [SKIP][115] ([i915#14544] / [i915#6095]) +5 other tests skip
   [115]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_ccs@crc-sprite-planes-basic-4-tiled-dg2-rc-ccs@pipe-b-hdmi-a-2.html

  * igt@kms_ccs@crc-sprite-planes-basic-4-tiled-dg2-rc-ccs@pipe-c-hdmi-a-2:
    - shard-rkl:          NOTRUN -> [SKIP][116] ([i915#14098] / [i915#14544] / [i915#6095]) +4 other tests skip
   [116]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_ccs@crc-sprite-planes-basic-4-tiled-dg2-rc-ccs@pipe-c-hdmi-a-2.html

  * igt@kms_ccs@crc-sprite-planes-basic-4-tiled-lnl-ccs:
    - shard-tglu-1:       NOTRUN -> [SKIP][117] ([i915#12313])
   [117]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_ccs@crc-sprite-planes-basic-4-tiled-lnl-ccs.html

  * igt@kms_ccs@missing-ccs-buffer-y-tiled-ccs@pipe-b-hdmi-a-1:
    - shard-rkl:          NOTRUN -> [SKIP][118] ([i915#6095]) +59 other tests skip
   [118]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-8/igt@kms_ccs@missing-ccs-buffer-y-tiled-ccs@pipe-b-hdmi-a-1.html

  * igt@kms_ccs@missing-ccs-buffer-yf-tiled-ccs@pipe-a-edp-1:
    - shard-mtlp:         NOTRUN -> [SKIP][119] ([i915#6095]) +24 other tests skip
   [119]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-7/igt@kms_ccs@missing-ccs-buffer-yf-tiled-ccs@pipe-a-edp-1.html

  * igt@kms_ccs@random-ccs-data-4-tiled-bmg-ccs:
    - shard-dg2:          NOTRUN -> [SKIP][120] ([i915#12313])
   [120]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-7/igt@kms_ccs@random-ccs-data-4-tiled-bmg-ccs.html
    - shard-dg1:          NOTRUN -> [SKIP][121] ([i915#12313]) +1 other test skip
   [121]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-12/igt@kms_ccs@random-ccs-data-4-tiled-bmg-ccs.html
    - shard-tglu:         NOTRUN -> [SKIP][122] ([i915#12313])
   [122]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-6/igt@kms_ccs@random-ccs-data-4-tiled-bmg-ccs.html
    - shard-mtlp:         NOTRUN -> [SKIP][123] ([i915#12313])
   [123]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-2/igt@kms_ccs@random-ccs-data-4-tiled-bmg-ccs.html

  * igt@kms_ccs@random-ccs-data-4-tiled-mtl-mc-ccs@pipe-d-hdmi-a-3:
    - shard-dg1:          NOTRUN -> [SKIP][124] ([i915#6095]) +172 other tests skip
   [124]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-13/igt@kms_ccs@random-ccs-data-4-tiled-mtl-mc-ccs@pipe-d-hdmi-a-3.html

  * igt@kms_cdclk@plane-scaling:
    - shard-dg1:          NOTRUN -> [SKIP][125] ([i915#3742])
   [125]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-17/igt@kms_cdclk@plane-scaling.html

  * igt@kms_cdclk@plane-scaling@pipe-d-hdmi-a-1:
    - shard-dg2:          NOTRUN -> [SKIP][126] ([i915#13783]) +3 other tests skip
   [126]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-4/igt@kms_cdclk@plane-scaling@pipe-d-hdmi-a-1.html

  * igt@kms_chamelium_color@ctm-0-25:
    - shard-dg2:          NOTRUN -> [SKIP][127] +4 other tests skip
   [127]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-1/igt@kms_chamelium_color@ctm-0-25.html

  * igt@kms_chamelium_color@ctm-0-50:
    - shard-tglu-1:       NOTRUN -> [SKIP][128] +31 other tests skip
   [128]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_chamelium_color@ctm-0-50.html

  * igt@kms_chamelium_edid@hdmi-edid-read:
    - shard-rkl:          NOTRUN -> [SKIP][129] ([i915#11151] / [i915#14544] / [i915#7828]) +1 other test skip
   [129]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_chamelium_edid@hdmi-edid-read.html

  * igt@kms_chamelium_frames@dp-crc-fast:
    - shard-dg2:          NOTRUN -> [SKIP][130] ([i915#11151] / [i915#7828]) +2 other tests skip
   [130]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-3/igt@kms_chamelium_frames@dp-crc-fast.html

  * igt@kms_chamelium_frames@hdmi-aspect-ratio:
    - shard-mtlp:         NOTRUN -> [SKIP][131] ([i915#11151] / [i915#7828]) +2 other tests skip
   [131]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-8/igt@kms_chamelium_frames@hdmi-aspect-ratio.html

  * igt@kms_chamelium_frames@hdmi-frame-dump:
    - shard-dg1:          NOTRUN -> [SKIP][132] ([i915#11151] / [i915#7828]) +3 other tests skip
   [132]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-17/igt@kms_chamelium_frames@hdmi-frame-dump.html

  * igt@kms_chamelium_hpd@dp-hpd-after-suspend:
    - shard-tglu-1:       NOTRUN -> [SKIP][133] ([i915#11151] / [i915#7828]) +3 other tests skip
   [133]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_chamelium_hpd@dp-hpd-after-suspend.html

  * igt@kms_chamelium_hpd@dp-hpd-fast:
    - shard-tglu:         NOTRUN -> [SKIP][134] ([i915#11151] / [i915#7828]) +6 other tests skip
   [134]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-3/igt@kms_chamelium_hpd@dp-hpd-fast.html

  * igt@kms_chamelium_hpd@vga-hpd-fast:
    - shard-rkl:          NOTRUN -> [SKIP][135] ([i915#11151] / [i915#7828]) +7 other tests skip
   [135]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-2/igt@kms_chamelium_hpd@vga-hpd-fast.html

  * igt@kms_color_pipeline@plane-lut1d-ctm3x4-lut1d:
    - shard-dg1:          [PASS][136] -> [DMESG-WARN][137] ([i915#4423])
   [136]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg1-18/igt@kms_color_pipeline@plane-lut1d-ctm3x4-lut1d.html
   [137]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-17/igt@kms_color_pipeline@plane-lut1d-ctm3x4-lut1d.html

  * igt@kms_content_protection@atomic:
    - shard-tglu-1:       NOTRUN -> [SKIP][138] ([i915#6944] / [i915#7116] / [i915#7118] / [i915#9424])
   [138]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_content_protection@atomic.html

  * igt@kms_content_protection@atomic-dpms-hdcp14:
    - shard-rkl:          NOTRUN -> [SKIP][139] ([i915#6944])
   [139]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-7/igt@kms_content_protection@atomic-dpms-hdcp14.html

  * igt@kms_content_protection@atomic-dpms-hdcp14@pipe-a-dp-3:
    - shard-dg2:          NOTRUN -> [FAIL][140] ([i915#7173]) +1 other test fail
   [140]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-11/igt@kms_content_protection@atomic-dpms-hdcp14@pipe-a-dp-3.html

  * igt@kms_content_protection@content-type-change:
    - shard-tglu:         NOTRUN -> [SKIP][141] ([i915#6944] / [i915#9424])
   [141]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-4/igt@kms_content_protection@content-type-change.html

  * igt@kms_content_protection@dp-mst-type-0:
    - shard-rkl:          NOTRUN -> [SKIP][142] ([i915#15330] / [i915#3116]) +1 other test skip
   [142]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@kms_content_protection@dp-mst-type-0.html

  * igt@kms_content_protection@dp-mst-type-0-hdcp14:
    - shard-dg2:          NOTRUN -> [SKIP][143] ([i915#15330])
   [143]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-3/igt@kms_content_protection@dp-mst-type-0-hdcp14.html
    - shard-rkl:          NOTRUN -> [SKIP][144] ([i915#15330])
   [144]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-7/igt@kms_content_protection@dp-mst-type-0-hdcp14.html
    - shard-dg1:          NOTRUN -> [SKIP][145] ([i915#15330])
   [145]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-18/igt@kms_content_protection@dp-mst-type-0-hdcp14.html
    - shard-tglu:         NOTRUN -> [SKIP][146] ([i915#15330])
   [146]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-5/igt@kms_content_protection@dp-mst-type-0-hdcp14.html
    - shard-mtlp:         NOTRUN -> [SKIP][147] ([i915#15330])
   [147]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-8/igt@kms_content_protection@dp-mst-type-0-hdcp14.html

  * igt@kms_content_protection@dp-mst-type-1:
    - shard-tglu-1:       NOTRUN -> [SKIP][148] ([i915#15330] / [i915#3116] / [i915#3299])
   [148]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_content_protection@dp-mst-type-1.html

  * igt@kms_content_protection@lic-type-0:
    - shard-dg1:          NOTRUN -> [SKIP][149] ([i915#6944] / [i915#9424])
   [149]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-13/igt@kms_content_protection@lic-type-0.html

  * igt@kms_content_protection@lic-type-1:
    - shard-rkl:          NOTRUN -> [SKIP][150] ([i915#6944] / [i915#9424])
   [150]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-8/igt@kms_content_protection@lic-type-1.html

  * igt@kms_content_protection@uevent-hdcp14:
    - shard-tglu:         NOTRUN -> [SKIP][151] ([i915#6944]) +1 other test skip
   [151]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-3/igt@kms_content_protection@uevent-hdcp14.html

  * igt@kms_cursor_crc@cursor-onscreen-256x85:
    - shard-tglu:         [PASS][152] -> [FAIL][153] ([i915#13566]) +1 other test fail
   [152]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-tglu-10/igt@kms_cursor_crc@cursor-onscreen-256x85.html
   [153]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-5/igt@kms_cursor_crc@cursor-onscreen-256x85.html
    - shard-rkl:          [PASS][154] -> [FAIL][155] ([i915#13566])
   [154]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-2/igt@kms_cursor_crc@cursor-onscreen-256x85.html
   [155]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-3/igt@kms_cursor_crc@cursor-onscreen-256x85.html

  * igt@kms_cursor_crc@cursor-random-128x42:
    - shard-tglu:         NOTRUN -> [FAIL][156] ([i915#13566]) +1 other test fail
   [156]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-6/igt@kms_cursor_crc@cursor-random-128x42.html

  * igt@kms_cursor_crc@cursor-random-256x85:
    - shard-rkl:          NOTRUN -> [FAIL][157] ([i915#13566]) +4 other tests fail
   [157]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_cursor_crc@cursor-random-256x85.html

  * igt@kms_cursor_crc@cursor-rapid-movement-64x21:
    - shard-mtlp:         NOTRUN -> [SKIP][158] ([i915#8814]) +1 other test skip
   [158]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-6/igt@kms_cursor_crc@cursor-rapid-movement-64x21.html

  * igt@kms_cursor_crc@cursor-sliding-32x32:
    - shard-tglu:         NOTRUN -> [SKIP][159] ([i915#3555]) +4 other tests skip
   [159]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-8/igt@kms_cursor_crc@cursor-sliding-32x32.html
    - shard-mtlp:         NOTRUN -> [SKIP][160] ([i915#3555] / [i915#8814])
   [160]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-3/igt@kms_cursor_crc@cursor-sliding-32x32.html

  * igt@kms_cursor_crc@cursor-sliding-512x170:
    - shard-mtlp:         NOTRUN -> [SKIP][161] ([i915#13049]) +1 other test skip
   [161]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-7/igt@kms_cursor_crc@cursor-sliding-512x170.html
    - shard-dg2:          NOTRUN -> [SKIP][162] ([i915#13049]) +1 other test skip
   [162]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-11/igt@kms_cursor_crc@cursor-sliding-512x170.html
    - shard-rkl:          NOTRUN -> [SKIP][163] ([i915#13049])
   [163]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-7/igt@kms_cursor_crc@cursor-sliding-512x170.html
    - shard-tglu:         NOTRUN -> [SKIP][164] ([i915#13049]) +1 other test skip
   [164]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-4/igt@kms_cursor_crc@cursor-sliding-512x170.html

  * igt@kms_cursor_crc@cursor-sliding-512x512:
    - shard-tglu-1:       NOTRUN -> [SKIP][165] ([i915#13049]) +1 other test skip
   [165]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_cursor_crc@cursor-sliding-512x512.html
    - shard-dg1:          NOTRUN -> [SKIP][166] ([i915#13049]) +1 other test skip
   [166]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-18/igt@kms_cursor_crc@cursor-sliding-512x512.html

  * igt@kms_cursor_crc@cursor-sliding-64x21:
    - shard-tglu-1:       NOTRUN -> [FAIL][167] ([i915#13566]) +1 other test fail
   [167]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_cursor_crc@cursor-sliding-64x21.html

  * igt@kms_cursor_legacy@cursora-vs-flipb-varying-size:
    - shard-rkl:          NOTRUN -> [SKIP][168] ([i915#14544]) +5 other tests skip
   [168]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_cursor_legacy@cursora-vs-flipb-varying-size.html

  * igt@kms_cursor_legacy@cursorb-vs-flipa-varying-size:
    - shard-tglu:         NOTRUN -> [SKIP][169] +43 other tests skip
   [169]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-4/igt@kms_cursor_legacy@cursorb-vs-flipa-varying-size.html
    - shard-mtlp:         NOTRUN -> [SKIP][170] ([i915#9809]) +1 other test skip
   [170]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-7/igt@kms_cursor_legacy@cursorb-vs-flipa-varying-size.html
    - shard-dg2:          NOTRUN -> [SKIP][171] ([i915#13046] / [i915#5354])
   [171]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-11/igt@kms_cursor_legacy@cursorb-vs-flipa-varying-size.html

  * igt@kms_cursor_legacy@short-busy-flip-before-cursor-atomic-transitions-varying-size:
    - shard-rkl:          NOTRUN -> [SKIP][172] ([i915#14544] / [i915#4103])
   [172]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_cursor_legacy@short-busy-flip-before-cursor-atomic-transitions-varying-size.html

  * igt@kms_cursor_legacy@short-busy-flip-before-cursor-toggle:
    - shard-rkl:          NOTRUN -> [SKIP][173] ([i915#4103])
   [173]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-8/igt@kms_cursor_legacy@short-busy-flip-before-cursor-toggle.html

  * igt@kms_dirtyfb@psr-dirtyfb-ioctl:
    - shard-rkl:          NOTRUN -> [SKIP][174] ([i915#9723])
   [174]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@kms_dirtyfb@psr-dirtyfb-ioctl.html

  * igt@kms_dither@fb-8bpc-vs-panel-8bpc:
    - shard-dg2:          NOTRUN -> [SKIP][175] ([i915#3555]) +1 other test skip
   [175]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-4/igt@kms_dither@fb-8bpc-vs-panel-8bpc.html
    - shard-dg1:          NOTRUN -> [SKIP][176] ([i915#3555]) +1 other test skip
   [176]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-17/igt@kms_dither@fb-8bpc-vs-panel-8bpc.html

  * igt@kms_dp_aux_dev:
    - shard-rkl:          NOTRUN -> [SKIP][177] ([i915#1257])
   [177]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-2/igt@kms_dp_aux_dev.html

  * igt@kms_dp_link_training@non-uhbr-mst:
    - shard-tglu:         NOTRUN -> [SKIP][178] ([i915#13749])
   [178]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-3/igt@kms_dp_link_training@non-uhbr-mst.html

  * igt@kms_dp_link_training@uhbr-mst:
    - shard-tglu:         NOTRUN -> [SKIP][179] ([i915#13748])
   [179]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-6/igt@kms_dp_link_training@uhbr-mst.html

  * igt@kms_draw_crc@draw-method-mmap-gtt:
    - shard-dg1:          NOTRUN -> [SKIP][180] ([i915#8812])
   [180]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-13/igt@kms_draw_crc@draw-method-mmap-gtt.html
    - shard-mtlp:         NOTRUN -> [SKIP][181] ([i915#3555] / [i915#8812])
   [181]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-7/igt@kms_draw_crc@draw-method-mmap-gtt.html
    - shard-dg2:          NOTRUN -> [SKIP][182] ([i915#8812])
   [182]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-11/igt@kms_draw_crc@draw-method-mmap-gtt.html

  * igt@kms_dsc@dsc-basic:
    - shard-rkl:          NOTRUN -> [SKIP][183] ([i915#3555] / [i915#3840])
   [183]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-2/igt@kms_dsc@dsc-basic.html

  * igt@kms_dsc@dsc-with-bpc:
    - shard-tglu:         NOTRUN -> [SKIP][184] ([i915#3555] / [i915#3840])
   [184]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-8/igt@kms_dsc@dsc-with-bpc.html

  * igt@kms_dsc@dsc-with-bpc-formats:
    - shard-dg1:          NOTRUN -> [SKIP][185] ([i915#3555] / [i915#3840])
   [185]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-12/igt@kms_dsc@dsc-with-bpc-formats.html

  * igt@kms_dsc@dsc-with-formats:
    - shard-tglu-1:       NOTRUN -> [SKIP][186] ([i915#3555] / [i915#3840])
   [186]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_dsc@dsc-with-formats.html

  * igt@kms_fbcon_fbt@psr:
    - shard-rkl:          NOTRUN -> [SKIP][187] ([i915#14544] / [i915#3955])
   [187]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_fbcon_fbt@psr.html

  * igt@kms_feature_discovery@display-2x:
    - shard-rkl:          NOTRUN -> [SKIP][188] ([i915#1839])
   [188]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-8/igt@kms_feature_discovery@display-2x.html

  * igt@kms_flip@2x-flip-vs-dpms:
    - shard-dg1:          NOTRUN -> [SKIP][189] ([i915#9934]) +1 other test skip
   [189]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-16/igt@kms_flip@2x-flip-vs-dpms.html

  * igt@kms_flip@2x-flip-vs-fences:
    - shard-tglu-1:       NOTRUN -> [SKIP][190] ([i915#3637] / [i915#9934]) +1 other test skip
   [190]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_flip@2x-flip-vs-fences.html

  * igt@kms_flip@2x-flip-vs-fences-interruptible:
    - shard-rkl:          NOTRUN -> [SKIP][191] ([i915#9934]) +8 other tests skip
   [191]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-8/igt@kms_flip@2x-flip-vs-fences-interruptible.html

  * igt@kms_flip@2x-flip-vs-panning-vs-hang:
    - shard-dg2:          NOTRUN -> [SKIP][192] ([i915#9934])
   [192]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-4/igt@kms_flip@2x-flip-vs-panning-vs-hang.html
    - shard-mtlp:         NOTRUN -> [SKIP][193] ([i915#3637] / [i915#9934])
   [193]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-4/igt@kms_flip@2x-flip-vs-panning-vs-hang.html

  * igt@kms_flip@2x-flip-vs-suspend:
    - shard-glk:          NOTRUN -> [INCOMPLETE][194] ([i915#12314] / [i915#12745] / [i915#4839] / [i915#6113])
   [194]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-glk5/igt@kms_flip@2x-flip-vs-suspend.html

  * igt@kms_flip@2x-flip-vs-suspend@ab-hdmi-a1-hdmi-a2:
    - shard-glk:          NOTRUN -> [INCOMPLETE][195] ([i915#12314] / [i915#4839] / [i915#6113])
   [195]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-glk5/igt@kms_flip@2x-flip-vs-suspend@ab-hdmi-a1-hdmi-a2.html

  * igt@kms_flip@2x-flip-vs-suspend@ab-vga1-hdmi-a1:
    - shard-snb:          [PASS][196] -> [TIMEOUT][197] ([i915#14033]) +1 other test timeout
   [196]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-snb7/igt@kms_flip@2x-flip-vs-suspend@ab-vga1-hdmi-a1.html
   [197]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-snb5/igt@kms_flip@2x-flip-vs-suspend@ab-vga1-hdmi-a1.html

  * igt@kms_flip@2x-plain-flip-ts-check-interruptible:
    - shard-tglu:         NOTRUN -> [SKIP][198] ([i915#3637] / [i915#9934]) +2 other tests skip
   [198]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-2/igt@kms_flip@2x-plain-flip-ts-check-interruptible.html

  * igt@kms_flip@flip-vs-blocking-wf-vblank@a-hdmi-a1:
    - shard-tglu:         [PASS][199] -> [FAIL][200] ([i915#14600]) +1 other test fail
   [199]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-tglu-2/igt@kms_flip@flip-vs-blocking-wf-vblank@a-hdmi-a1.html
   [200]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-6/igt@kms_flip@flip-vs-blocking-wf-vblank@a-hdmi-a1.html

  * igt@kms_flip@flip-vs-suspend-interruptible:
    - shard-glk:          NOTRUN -> [INCOMPLETE][201] ([i915#12745] / [i915#4839])
   [201]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-glk9/igt@kms_flip@flip-vs-suspend-interruptible.html

  * igt@kms_flip@flip-vs-suspend-interruptible@a-hdmi-a1:
    - shard-glk:          NOTRUN -> [INCOMPLETE][202] ([i915#12745])
   [202]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-glk9/igt@kms_flip@flip-vs-suspend-interruptible@a-hdmi-a1.html

  * igt@kms_flip_scaled_crc@flip-32bpp-yftile-to-32bpp-yftileccs-upscaling:
    - shard-tglu:         NOTRUN -> [SKIP][203] ([i915#15643])
   [203]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-6/igt@kms_flip_scaled_crc@flip-32bpp-yftile-to-32bpp-yftileccs-upscaling.html

  * igt@kms_flip_scaled_crc@flip-32bpp-yftile-to-64bpp-yftile-upscaling:
    - shard-dg1:          NOTRUN -> [SKIP][204] ([i915#15643])
   [204]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-17/igt@kms_flip_scaled_crc@flip-32bpp-yftile-to-64bpp-yftile-upscaling.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytileccs-upscaling:
    - shard-tglu-1:       NOTRUN -> [SKIP][205] ([i915#15643]) +2 other tests skip
   [205]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytileccs-upscaling.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling:
    - shard-mtlp:         NOTRUN -> [SKIP][206] ([i915#15643]) +1 other test skip
   [206]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-5/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytilegen12rcccs-upscaling.html

  * igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-16bpp-4tile-upscaling:
    - shard-rkl:          NOTRUN -> [SKIP][207] ([i915#15643]) +3 other tests skip
   [207]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-16bpp-4tile-upscaling.html

  * igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-upscaling:
    - shard-dg2:          NOTRUN -> [SKIP][208] ([i915#15643] / [i915#5190]) +1 other test skip
   [208]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-1/igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-upscaling.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-mmap-wc:
    - shard-dg1:          NOTRUN -> [SKIP][209] ([i915#8708]) +9 other tests skip
   [209]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-13/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-pwrite:
    - shard-mtlp:         NOTRUN -> [SKIP][210] ([i915#1825]) +9 other tests skip
   [210]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-4/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-draw-pwrite.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-onoff:
    - shard-snb:          [PASS][211] -> [SKIP][212] +20 other tests skip
   [211]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-snb4/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-onoff.html
   [212]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-snb6/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-spr-indfb-onoff.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-offscreen-pri-shrfb-draw-mmap-gtt:
    - shard-mtlp:         NOTRUN -> [SKIP][213] ([i915#15104])
   [213]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-5/igt@kms_frontbuffer_tracking@fbcpsr-1p-offscreen-pri-shrfb-draw-mmap-gtt.html
    - shard-dg2:          NOTRUN -> [SKIP][214] ([i915#15104])
   [214]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-11/igt@kms_frontbuffer_tracking@fbcpsr-1p-offscreen-pri-shrfb-draw-mmap-gtt.html
    - shard-dg1:          NOTRUN -> [SKIP][215] ([i915#15104])
   [215]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-13/igt@kms_frontbuffer_tracking@fbcpsr-1p-offscreen-pri-shrfb-draw-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-offscreen-pri-shrfb-draw-pwrite:
    - shard-dg2:          NOTRUN -> [SKIP][216] ([i915#15102])
   [216]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-1/igt@kms_frontbuffer_tracking@fbcpsr-1p-offscreen-pri-shrfb-draw-pwrite.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-mmap-cpu:
    - shard-tglu-1:       NOTRUN -> [SKIP][217] ([i915#15102]) +6 other tests skip
   [217]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-mmap-cpu.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-shrfb-draw-mmap-wc:
    - shard-dg2:          NOTRUN -> [SKIP][218] ([i915#8708]) +7 other tests skip
   [218]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-1/igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-pri-shrfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-indfb-draw-blt:
    - shard-dg1:          NOTRUN -> [SKIP][219] ([i915#15102])
   [219]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-18/igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-indfb-draw-blt.html

  * igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-indfb-draw-mmap-gtt:
    - shard-rkl:          NOTRUN -> [SKIP][220] ([i915#15102]) +4 other tests skip
   [220]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-7/igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-indfb-draw-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-mmap-cpu:
    - shard-dg2:          NOTRUN -> [SKIP][221] ([i915#10433] / [i915#15102] / [i915#3458])
   [221]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-4/igt@kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-draw-mmap-cpu.html

  * igt@kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-move:
    - shard-tglu:         NOTRUN -> [SKIP][222] ([i915#15102]) +22 other tests skip
   [222]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-7/igt@kms_frontbuffer_tracking@psr-1p-primscrn-spr-indfb-move.html

  * igt@kms_frontbuffer_tracking@psr-1p-rte:
    - shard-rkl:          NOTRUN -> [SKIP][223] ([i915#14544] / [i915#15102] / [i915#3023]) +3 other tests skip
   [223]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_frontbuffer_tracking@psr-1p-rte.html

  * igt@kms_frontbuffer_tracking@psr-2p-primscrn-indfb-msflip-blt:
    - shard-dg1:          NOTRUN -> [SKIP][224] +14 other tests skip
   [224]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-16/igt@kms_frontbuffer_tracking@psr-2p-primscrn-indfb-msflip-blt.html

  * igt@kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-pwrite:
    - shard-rkl:          NOTRUN -> [SKIP][225] ([i915#1825]) +38 other tests skip
   [225]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-8/igt@kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-pwrite.html

  * igt@kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-render:
    - shard-dg2:          NOTRUN -> [SKIP][226] ([i915#5354]) +2 other tests skip
   [226]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-1/igt@kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-render.html
    - shard-rkl:          NOTRUN -> [SKIP][227] ([i915#14544] / [i915#1825]) +3 other tests skip
   [227]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-render.html

  * igt@kms_frontbuffer_tracking@psr-2p-scndscrn-pri-indfb-draw-mmap-gtt:
    - shard-mtlp:         NOTRUN -> [SKIP][228] ([i915#8708]) +3 other tests skip
   [228]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-5/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-pri-indfb-draw-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@psr-indfb-scaledprimary:
    - shard-dg2:          NOTRUN -> [SKIP][229] ([i915#15102] / [i915#3458]) +3 other tests skip
   [229]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-3/igt@kms_frontbuffer_tracking@psr-indfb-scaledprimary.html

  * igt@kms_frontbuffer_tracking@psr-modesetfrombusy:
    - shard-rkl:          NOTRUN -> [SKIP][230] ([i915#15102] / [i915#3023]) +15 other tests skip
   [230]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-8/igt@kms_frontbuffer_tracking@psr-modesetfrombusy.html
    - shard-dg1:          NOTRUN -> [SKIP][231] ([i915#15102] / [i915#3458]) +5 other tests skip
   [231]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-17/igt@kms_frontbuffer_tracking@psr-modesetfrombusy.html

  * igt@kms_hdr@brightness-with-hdr:
    - shard-tglu:         NOTRUN -> [SKIP][232] ([i915#12713])
   [232]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-4/igt@kms_hdr@brightness-with-hdr.html

  * igt@kms_hdr@static-swap:
    - shard-dg1:          NOTRUN -> [SKIP][233] ([i915#3555] / [i915#8228]) +1 other test skip
   [233]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-13/igt@kms_hdr@static-swap.html

  * igt@kms_hdr@static-toggle-dpms:
    - shard-mtlp:         NOTRUN -> [SKIP][234] ([i915#12713] / [i915#3555] / [i915#8228])
   [234]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-7/igt@kms_hdr@static-toggle-dpms.html
    - shard-rkl:          NOTRUN -> [SKIP][235] ([i915#3555] / [i915#8228])
   [235]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-7/igt@kms_hdr@static-toggle-dpms.html
    - shard-tglu:         NOTRUN -> [SKIP][236] ([i915#3555] / [i915#8228])
   [236]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-4/igt@kms_hdr@static-toggle-dpms.html

  * igt@kms_joiner@basic-big-joiner:
    - shard-tglu:         NOTRUN -> [SKIP][237] ([i915#15460])
   [237]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-4/igt@kms_joiner@basic-big-joiner.html

  * igt@kms_joiner@invalid-modeset-big-joiner:
    - shard-rkl:          NOTRUN -> [SKIP][238] ([i915#14544] / [i915#15460])
   [238]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_joiner@invalid-modeset-big-joiner.html

  * igt@kms_joiner@switch-modeset-ultra-joiner-big-joiner:
    - shard-dg1:          NOTRUN -> [SKIP][239] ([i915#15638] / [i915#15722])
   [239]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-16/igt@kms_joiner@switch-modeset-ultra-joiner-big-joiner.html

  * igt@kms_multipipe_modeset@basic-max-pipe-crc-check:
    - shard-rkl:          NOTRUN -> [SKIP][240] ([i915#1839] / [i915#4816])
   [240]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-2/igt@kms_multipipe_modeset@basic-max-pipe-crc-check.html

  * igt@kms_panel_fitting@atomic-fastset:
    - shard-tglu:         NOTRUN -> [SKIP][241] ([i915#6301]) +1 other test skip
   [241]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-6/igt@kms_panel_fitting@atomic-fastset.html

  * igt@kms_panel_fitting@legacy:
    - shard-dg2:          NOTRUN -> [SKIP][242] ([i915#6301])
   [242]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-7/igt@kms_panel_fitting@legacy.html
    - shard-rkl:          NOTRUN -> [SKIP][243] ([i915#6301])
   [243]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-2/igt@kms_panel_fitting@legacy.html
    - shard-dg1:          NOTRUN -> [SKIP][244] ([i915#6301])
   [244]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-12/igt@kms_panel_fitting@legacy.html

  * igt@kms_pipe_stress@stress-xrgb8888-yftiled:
    - shard-tglu-1:       NOTRUN -> [SKIP][245] ([i915#14712])
   [245]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_pipe_stress@stress-xrgb8888-yftiled.html

  * igt@kms_plane@pixel-format-4-tiled-dg2-mc-ccs-modifier:
    - shard-rkl:          NOTRUN -> [SKIP][246] ([i915#15709]) +5 other tests skip
   [246]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@kms_plane@pixel-format-4-tiled-dg2-mc-ccs-modifier.html

  * igt@kms_plane@pixel-format-4-tiled-dg2-rc-ccs-cc-modifier:
    - shard-tglu:         NOTRUN -> [SKIP][247] ([i915#15709]) +3 other tests skip
   [247]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-5/igt@kms_plane@pixel-format-4-tiled-dg2-rc-ccs-cc-modifier.html

  * igt@kms_plane@pixel-format-4-tiled-mtl-rc-ccs-modifier-source-clamping:
    - shard-dg1:          NOTRUN -> [SKIP][248] ([i915#15709]) +1 other test skip
   [248]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-14/igt@kms_plane@pixel-format-4-tiled-mtl-rc-ccs-modifier-source-clamping.html
    - shard-dg2:          NOTRUN -> [SKIP][249] ([i915#15709]) +1 other test skip
   [249]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-6/igt@kms_plane@pixel-format-4-tiled-mtl-rc-ccs-modifier-source-clamping.html

  * igt@kms_plane@pixel-format-y-tiled-gen12-rc-ccs-modifier@pipe-b-plane-7:
    - shard-tglu-1:       NOTRUN -> [SKIP][250] ([i915#15608]) +1 other test skip
   [250]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_plane@pixel-format-y-tiled-gen12-rc-ccs-modifier@pipe-b-plane-7.html

  * igt@kms_plane@pixel-format-y-tiled-modifier@pipe-b-plane-7:
    - shard-dg1:          NOTRUN -> [SKIP][251] ([i915#15608]) +1 other test skip
   [251]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-12/igt@kms_plane@pixel-format-y-tiled-modifier@pipe-b-plane-7.html

  * igt@kms_plane@pixel-format-yf-tiled-modifier-source-clamping:
    - shard-mtlp:         NOTRUN -> [SKIP][252] ([i915#15709])
   [252]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-5/igt@kms_plane@pixel-format-yf-tiled-modifier-source-clamping.html
    - shard-rkl:          NOTRUN -> [SKIP][253] ([i915#14544] / [i915#15709])
   [253]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_plane@pixel-format-yf-tiled-modifier-source-clamping.html

  * igt@kms_plane@pixel-format-yf-tiled-modifier@pipe-b-plane-4:
    - shard-glk10:        NOTRUN -> [SKIP][254] +41 other tests skip
   [254]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-glk10/igt@kms_plane@pixel-format-yf-tiled-modifier@pipe-b-plane-4.html

  * igt@kms_plane_multiple@2x-tiling-4:
    - shard-rkl:          NOTRUN -> [SKIP][255] ([i915#13958] / [i915#14544])
   [255]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_plane_multiple@2x-tiling-4.html
    - shard-tglu-1:       NOTRUN -> [SKIP][256] ([i915#13958])
   [256]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_plane_multiple@2x-tiling-4.html

  * igt@kms_plane_multiple@2x-tiling-y:
    - shard-rkl:          NOTRUN -> [SKIP][257] ([i915#13958])
   [257]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@kms_plane_multiple@2x-tiling-y.html

  * igt@kms_plane_multiple@tiling-4:
    - shard-rkl:          NOTRUN -> [SKIP][258] ([i915#14259])
   [258]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@kms_plane_multiple@tiling-4.html
    - shard-dg1:          NOTRUN -> [SKIP][259] ([i915#14259])
   [259]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-14/igt@kms_plane_multiple@tiling-4.html
    - shard-tglu:         NOTRUN -> [SKIP][260] ([i915#14259])
   [260]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-7/igt@kms_plane_multiple@tiling-4.html

  * igt@kms_plane_scaling@intel-max-src-size:
    - shard-tglu-1:       NOTRUN -> [SKIP][261] ([i915#6953])
   [261]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_plane_scaling@intel-max-src-size.html

  * igt@kms_plane_scaling@plane-upscale-20x20-with-rotation@pipe-a:
    - shard-rkl:          NOTRUN -> [SKIP][262] ([i915#15329]) +7 other tests skip
   [262]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@kms_plane_scaling@plane-upscale-20x20-with-rotation@pipe-a.html

  * igt@kms_plane_scaling@plane-upscale-factor-0-25-with-rotation@pipe-c:
    - shard-rkl:          NOTRUN -> [SKIP][263] ([i915#14544] / [i915#15329]) +3 other tests skip
   [263]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_plane_scaling@plane-upscale-factor-0-25-with-rotation@pipe-c.html

  * igt@kms_pm_backlight@brightness-with-dpms:
    - shard-rkl:          NOTRUN -> [SKIP][264] ([i915#12343])
   [264]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@kms_pm_backlight@brightness-with-dpms.html
    - shard-dg1:          NOTRUN -> [SKIP][265] ([i915#12343])
   [265]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-13/igt@kms_pm_backlight@brightness-with-dpms.html
    - shard-tglu:         NOTRUN -> [SKIP][266] ([i915#12343])
   [266]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-6/igt@kms_pm_backlight@brightness-with-dpms.html
    - shard-dg2:          NOTRUN -> [SKIP][267] ([i915#12343])
   [267]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-5/igt@kms_pm_backlight@brightness-with-dpms.html

  * igt@kms_pm_backlight@fade-with-dpms:
    - shard-rkl:          NOTRUN -> [SKIP][268] ([i915#5354])
   [268]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-8/igt@kms_pm_backlight@fade-with-dpms.html
    - shard-tglu:         NOTRUN -> [SKIP][269] ([i915#9812])
   [269]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-3/igt@kms_pm_backlight@fade-with-dpms.html

  * igt@kms_pm_dc@dc3co-vpb-simulation:
    - shard-tglu:         NOTRUN -> [SKIP][270] ([i915#9685])
   [270]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-7/igt@kms_pm_dc@dc3co-vpb-simulation.html

  * igt@kms_pm_dc@dc5-psr:
    - shard-tglu-1:       NOTRUN -> [SKIP][271] ([i915#9685])
   [271]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_pm_dc@dc5-psr.html

  * igt@kms_pm_dc@dc5-retention-flops:
    - shard-dg1:          NOTRUN -> [SKIP][272] ([i915#3828])
   [272]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-16/igt@kms_pm_dc@dc5-retention-flops.html

  * igt@kms_pm_dc@dc9-dpms:
    - shard-rkl:          NOTRUN -> [SKIP][273] ([i915#15739])
   [273]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@kms_pm_dc@dc9-dpms.html

  * igt@kms_pm_lpsp@kms-lpsp:
    - shard-rkl:          NOTRUN -> [SKIP][274] ([i915#14544] / [i915#9340])
   [274]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_pm_lpsp@kms-lpsp.html
    - shard-tglu-1:       NOTRUN -> [SKIP][275] ([i915#3828])
   [275]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_pm_lpsp@kms-lpsp.html

  * igt@kms_pm_rpm@modeset-non-lpsp:
    - shard-rkl:          [PASS][276] -> [SKIP][277] ([i915#15073]) +1 other test skip
   [276]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-4/igt@kms_pm_rpm@modeset-non-lpsp.html
   [277]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@kms_pm_rpm@modeset-non-lpsp.html

  * igt@kms_pm_rpm@modeset-non-lpsp-stress-no-wait:
    - shard-dg1:          [PASS][278] -> [SKIP][279] ([i915#15073]) +3 other tests skip
   [278]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg1-18/igt@kms_pm_rpm@modeset-non-lpsp-stress-no-wait.html
   [279]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-14/igt@kms_pm_rpm@modeset-non-lpsp-stress-no-wait.html

  * igt@kms_prime@basic-modeset-hybrid:
    - shard-rkl:          NOTRUN -> [SKIP][280] ([i915#6524]) +2 other tests skip
   [280]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-2/igt@kms_prime@basic-modeset-hybrid.html

  * igt@kms_psr2_sf@fbc-pr-cursor-plane-move-continuous-exceed-fully-sf:
    - shard-glk10:        NOTRUN -> [SKIP][281] ([i915#11520])
   [281]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-glk10/igt@kms_psr2_sf@fbc-pr-cursor-plane-move-continuous-exceed-fully-sf.html

  * igt@kms_psr2_sf@fbc-pr-overlay-plane-move-continuous-exceed-sf:
    - shard-snb:          NOTRUN -> [SKIP][282] ([i915#11520]) +1 other test skip
   [282]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-snb5/igt@kms_psr2_sf@fbc-pr-overlay-plane-move-continuous-exceed-sf.html

  * igt@kms_psr2_sf@fbc-pr-overlay-primary-update-sf-dmg-area:
    - shard-tglu-1:       NOTRUN -> [SKIP][283] ([i915#11520]) +1 other test skip
   [283]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_psr2_sf@fbc-pr-overlay-primary-update-sf-dmg-area.html

  * igt@kms_psr2_sf@fbc-psr2-cursor-plane-update-sf:
    - shard-rkl:          NOTRUN -> [SKIP][284] ([i915#11520]) +6 other tests skip
   [284]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-7/igt@kms_psr2_sf@fbc-psr2-cursor-plane-update-sf.html

  * igt@kms_psr2_sf@fbc-psr2-cursor-plane-update-sf@pipe-a-edp-1:
    - shard-mtlp:         NOTRUN -> [SKIP][285] ([i915#9808]) +2 other tests skip
   [285]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-8/igt@kms_psr2_sf@fbc-psr2-cursor-plane-update-sf@pipe-a-edp-1.html

  * igt@kms_psr2_sf@psr2-cursor-plane-move-continuous-exceed-fully-sf:
    - shard-dg1:          NOTRUN -> [SKIP][286] ([i915#11520]) +1 other test skip
   [286]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-14/igt@kms_psr2_sf@psr2-cursor-plane-move-continuous-exceed-fully-sf.html
    - shard-tglu:         NOTRUN -> [SKIP][287] ([i915#11520]) +4 other tests skip
   [287]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-7/igt@kms_psr2_sf@psr2-cursor-plane-move-continuous-exceed-fully-sf.html
    - shard-dg2:          NOTRUN -> [SKIP][288] ([i915#11520])
   [288]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-8/igt@kms_psr2_sf@psr2-cursor-plane-move-continuous-exceed-fully-sf.html

  * igt@kms_psr2_sf@psr2-overlay-plane-update-sf-dmg-area:
    - shard-glk:          NOTRUN -> [SKIP][289] ([i915#11520]) +3 other tests skip
   [289]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-glk6/igt@kms_psr2_sf@psr2-overlay-plane-update-sf-dmg-area.html

  * igt@kms_psr2_sf@psr2-primary-plane-update-sf-dmg-area-big-fb:
    - shard-rkl:          NOTRUN -> [SKIP][290] ([i915#11520] / [i915#14544])
   [290]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_psr2_sf@psr2-primary-plane-update-sf-dmg-area-big-fb.html

  * igt@kms_psr2_su@page_flip-xrgb8888:
    - shard-mtlp:         NOTRUN -> [SKIP][291] ([i915#4348])
   [291]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-8/igt@kms_psr2_su@page_flip-xrgb8888.html
    - shard-dg2:          NOTRUN -> [SKIP][292] ([i915#9683])
   [292]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-3/igt@kms_psr2_su@page_flip-xrgb8888.html
    - shard-rkl:          NOTRUN -> [SKIP][293] ([i915#9683]) +1 other test skip
   [293]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-3/igt@kms_psr2_su@page_flip-xrgb8888.html
    - shard-dg1:          NOTRUN -> [SKIP][294] ([i915#9683])
   [294]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-18/igt@kms_psr2_su@page_flip-xrgb8888.html
    - shard-tglu:         NOTRUN -> [SKIP][295] ([i915#9683])
   [295]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-5/igt@kms_psr2_su@page_flip-xrgb8888.html

  * igt@kms_psr@fbc-pr-primary-mmap-gtt:
    - shard-dg2:          NOTRUN -> [SKIP][296] ([i915#1072] / [i915#9732]) +6 other tests skip
   [296]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-8/igt@kms_psr@fbc-pr-primary-mmap-gtt.html

  * igt@kms_psr@fbc-psr2-sprite-mmap-gtt:
    - shard-dg1:          NOTRUN -> [SKIP][297] ([i915#1072] / [i915#9732]) +7 other tests skip
   [297]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-17/igt@kms_psr@fbc-psr2-sprite-mmap-gtt.html

  * igt@kms_psr@fbc-psr2-sprite-render:
    - shard-rkl:          NOTRUN -> [SKIP][298] ([i915#1072] / [i915#9732]) +19 other tests skip
   [298]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@kms_psr@fbc-psr2-sprite-render.html

  * igt@kms_psr@pr-primary-mmap-cpu:
    - shard-mtlp:         NOTRUN -> [SKIP][299] ([i915#9688]) +8 other tests skip
   [299]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-1/igt@kms_psr@pr-primary-mmap-cpu.html

  * igt@kms_psr@psr-sprite-plane-move:
    - shard-tglu-1:       NOTRUN -> [SKIP][300] ([i915#9732]) +11 other tests skip
   [300]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_psr@psr-sprite-plane-move.html

  * igt@kms_psr@psr2-cursor-plane-onoff:
    - shard-tglu:         NOTRUN -> [SKIP][301] ([i915#9732]) +13 other tests skip
   [301]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-4/igt@kms_psr@psr2-cursor-plane-onoff.html

  * igt@kms_psr@psr2-primary-mmap-gtt:
    - shard-rkl:          NOTRUN -> [SKIP][302] ([i915#1072] / [i915#14544] / [i915#9732]) +6 other tests skip
   [302]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_psr@psr2-primary-mmap-gtt.html

  * igt@kms_rotation_crc@multiplane-rotation:
    - shard-glk:          NOTRUN -> [INCOMPLETE][303] ([i915#15492])
   [303]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-glk2/igt@kms_rotation_crc@multiplane-rotation.html

  * igt@kms_rotation_crc@primary-yf-tiled-reflect-x-90:
    - shard-rkl:          NOTRUN -> [SKIP][304] ([i915#5289])
   [304]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@kms_rotation_crc@primary-yf-tiled-reflect-x-90.html

  * igt@kms_scaling_modes@scaling-mode-none:
    - shard-rkl:          NOTRUN -> [SKIP][305] ([i915#3555]) +2 other tests skip
   [305]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-2/igt@kms_scaling_modes@scaling-mode-none.html
    - shard-mtlp:         NOTRUN -> [SKIP][306] ([i915#3555] / [i915#5030] / [i915#9041])
   [306]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-2/igt@kms_scaling_modes@scaling-mode-none.html

  * igt@kms_scaling_modes@scaling-mode-none@pipe-a-edp-1:
    - shard-mtlp:         NOTRUN -> [SKIP][307] ([i915#5030]) +2 other tests skip
   [307]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-2/igt@kms_scaling_modes@scaling-mode-none@pipe-a-edp-1.html

  * igt@kms_scaling_modes@scaling-mode-none@pipe-d-edp-1:
    - shard-mtlp:         NOTRUN -> [SKIP][308] ([i915#5030] / [i915#9041])
   [308]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-2/igt@kms_scaling_modes@scaling-mode-none@pipe-d-edp-1.html

  * igt@kms_setmode@clone-exclusive-crtc:
    - shard-tglu-1:       NOTRUN -> [SKIP][309] ([i915#3555]) +2 other tests skip
   [309]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@kms_setmode@clone-exclusive-crtc.html

  * igt@kms_setmode@invalid-clone-exclusive-crtc:
    - shard-mtlp:         NOTRUN -> [SKIP][310] ([i915#3555] / [i915#8809] / [i915#8823])
   [310]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-2/igt@kms_setmode@invalid-clone-exclusive-crtc.html

  * igt@kms_vblank@ts-continuation-suspend@pipe-a-hdmi-a-2:
    - shard-rkl:          [PASS][311] -> [INCOMPLETE][312] ([i915#12276]) +1 other test incomplete
   [311]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-3/igt@kms_vblank@ts-continuation-suspend@pipe-a-hdmi-a-2.html
   [312]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_vblank@ts-continuation-suspend@pipe-a-hdmi-a-2.html

  * igt@kms_vrr@flip-basic-fastset:
    - shard-rkl:          NOTRUN -> [SKIP][313] ([i915#9906])
   [313]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-7/igt@kms_vrr@flip-basic-fastset.html

  * igt@kms_vrr@flip-dpms:
    - shard-rkl:          NOTRUN -> [SKIP][314] ([i915#15243] / [i915#3555])
   [314]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@kms_vrr@flip-dpms.html

  * igt@kms_vrr@negative-basic:
    - shard-dg2:          [PASS][315] -> [SKIP][316] ([i915#3555] / [i915#9906])
   [315]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg2-11/igt@kms_vrr@negative-basic.html
   [316]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-4/igt@kms_vrr@negative-basic.html
    - shard-rkl:          NOTRUN -> [SKIP][317] ([i915#3555] / [i915#9906])
   [317]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-8/igt@kms_vrr@negative-basic.html

  * igt@kms_vrr@seamless-rr-switch-drrs:
    - shard-tglu:         NOTRUN -> [SKIP][318] ([i915#9906])
   [318]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-8/igt@kms_vrr@seamless-rr-switch-drrs.html

  * igt@perf@mi-rpc:
    - shard-rkl:          NOTRUN -> [SKIP][319] ([i915#2434])
   [319]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@perf@mi-rpc.html

  * igt@perf@per-context-mode-unprivileged:
    - shard-rkl:          NOTRUN -> [SKIP][320] ([i915#2435])
   [320]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@perf@per-context-mode-unprivileged.html

  * igt@perf_pmu@busy-double-start:
    - shard-dg1:          [PASS][321] -> [FAIL][322] ([i915#4349]) +1 other test fail
   [321]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg1-12/igt@perf_pmu@busy-double-start.html
   [322]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-18/igt@perf_pmu@busy-double-start.html

  * igt@perf_pmu@module-unload:
    - shard-tglu-1:       NOTRUN -> [ABORT][323] ([i915#13029])
   [323]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-1/igt@perf_pmu@module-unload.html

  * igt@perf_pmu@rc6-all-gts:
    - shard-rkl:          NOTRUN -> [SKIP][324] ([i915#8516])
   [324]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-3/igt@perf_pmu@rc6-all-gts.html

  * igt@perf_pmu@rc6-suspend:
    - shard-glk10:        NOTRUN -> [INCOMPLETE][325] ([i915#13356])
   [325]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-glk10/igt@perf_pmu@rc6-suspend.html

  * igt@prime_vgem@basic-read:
    - shard-rkl:          NOTRUN -> [SKIP][326] ([i915#3291] / [i915#3708])
   [326]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@prime_vgem@basic-read.html

  * igt@prime_vgem@fence-write-hang:
    - shard-rkl:          NOTRUN -> [SKIP][327] ([i915#3708])
   [327]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@prime_vgem@fence-write-hang.html

  * igt@sriov_basic@bind-unbind-vf@vf-4:
    - shard-tglu:         NOTRUN -> [FAIL][328] ([i915#12910]) +9 other tests fail
   [328]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-8/igt@sriov_basic@bind-unbind-vf@vf-4.html

  * igt@tools_test@sysfs_l3_parity:
    - shard-rkl:          NOTRUN -> [SKIP][329] +25 other tests skip
   [329]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@tools_test@sysfs_l3_parity.html
    - shard-dg1:          NOTRUN -> [SKIP][330] ([i915#4818])
   [330]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-13/igt@tools_test@sysfs_l3_parity.html
    - shard-mtlp:         NOTRUN -> [SKIP][331] ([i915#4818])
   [331]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-5/igt@tools_test@sysfs_l3_parity.html
    - shard-dg2:          NOTRUN -> [SKIP][332] ([i915#4818])
   [332]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-11/igt@tools_test@sysfs_l3_parity.html

  
#### Possible fixes ####

  * igt@gem_pxp@protected-raw-src-copy-not-readible:
    - shard-rkl:          [SKIP][333] ([i915#4270]) -> [PASS][334] +1 other test pass
   [333]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-4/igt@gem_pxp@protected-raw-src-copy-not-readible.html
   [334]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@gem_pxp@protected-raw-src-copy-not-readible.html

  * igt@gem_workarounds@suspend-resume-fd:
    - shard-rkl:          [INCOMPLETE][335] ([i915#13356]) -> [PASS][336]
   [335]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-3/igt@gem_workarounds@suspend-resume-fd.html
   [336]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-7/igt@gem_workarounds@suspend-resume-fd.html

  * igt@i915_pm_rps@reset:
    - shard-snb:          [INCOMPLETE][337] ([i915#13729] / [i915#13821]) -> [PASS][338]
   [337]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-snb6/igt@i915_pm_rps@reset.html
   [338]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-snb6/igt@i915_pm_rps@reset.html

  * igt@i915_power@sanity:
    - shard-mtlp:         [SKIP][339] ([i915#7984]) -> [PASS][340]
   [339]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-mtlp-5/igt@i915_power@sanity.html
   [340]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-4/igt@i915_power@sanity.html

  * igt@i915_selftest@live@workarounds:
    - shard-dg2:          [DMESG-FAIL][341] ([i915#12061]) -> [PASS][342] +1 other test pass
   [341]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg2-3/igt@i915_selftest@live@workarounds.html
   [342]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-7/igt@i915_selftest@live@workarounds.html

  * igt@i915_suspend@fence-restore-tiled2untiled:
    - shard-rkl:          [INCOMPLETE][343] ([i915#4817]) -> [PASS][344]
   [343]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-4/igt@i915_suspend@fence-restore-tiled2untiled.html
   [344]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-8/igt@i915_suspend@fence-restore-tiled2untiled.html

  * igt@kms_cursor_crc@cursor-onscreen-64x21:
    - shard-rkl:          [FAIL][345] ([i915#13566]) -> [PASS][346] +1 other test pass
   [345]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-7/igt@kms_cursor_crc@cursor-onscreen-64x21.html
   [346]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-8/igt@kms_cursor_crc@cursor-onscreen-64x21.html

  * igt@kms_cursor_crc@cursor-sliding-128x42:
    - shard-tglu:         [FAIL][347] ([i915#13566]) -> [PASS][348] +3 other tests pass
   [347]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-tglu-3/igt@kms_cursor_crc@cursor-sliding-128x42.html
   [348]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-tglu-8/igt@kms_cursor_crc@cursor-sliding-128x42.html

  * igt@kms_cursor_legacy@cursora-vs-flipb-varying-size:
    - shard-snb:          [SKIP][349] -> [PASS][350] +16 other tests pass
   [349]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-snb6/igt@kms_cursor_legacy@cursora-vs-flipb-varying-size.html
   [350]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-snb4/igt@kms_cursor_legacy@cursora-vs-flipb-varying-size.html

  * igt@kms_frontbuffer_tracking@fbc-suspend:
    - shard-rkl:          [INCOMPLETE][351] ([i915#10056]) -> [PASS][352]
   [351]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_frontbuffer_tracking@fbc-suspend.html
   [352]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@kms_frontbuffer_tracking@fbc-suspend.html

  * igt@kms_hdr@static-swap:
    - shard-dg2:          [SKIP][353] ([i915#3555] / [i915#8228]) -> [PASS][354]
   [353]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg2-3/igt@kms_hdr@static-swap.html
   [354]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-11/igt@kms_hdr@static-swap.html

  * igt@kms_plane_cursor@primary@pipe-c-edp-1-size-128:
    - shard-mtlp:         [FAIL][355] ([i915#15733]) -> [PASS][356] +1 other test pass
   [355]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-mtlp-4/igt@kms_plane_cursor@primary@pipe-c-edp-1-size-128.html
   [356]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-1/igt@kms_plane_cursor@primary@pipe-c-edp-1-size-128.html

  * igt@kms_pm_rpm@i2c:
    - shard-dg1:          [DMESG-WARN][357] ([i915#4423]) -> [PASS][358] +2 other tests pass
   [357]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg1-16/igt@kms_pm_rpm@i2c.html
   [358]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-12/igt@kms_pm_rpm@i2c.html

  * igt@kms_pm_rpm@modeset-lpsp:
    - shard-dg2:          [SKIP][359] ([i915#15073]) -> [PASS][360] +3 other tests pass
   [359]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg2-8/igt@kms_pm_rpm@modeset-lpsp.html
   [360]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-4/igt@kms_pm_rpm@modeset-lpsp.html

  * igt@kms_pm_rpm@modeset-non-lpsp-stress-no-wait:
    - shard-rkl:          [SKIP][361] ([i915#15073]) -> [PASS][362] +2 other tests pass
   [361]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-8/igt@kms_pm_rpm@modeset-non-lpsp-stress-no-wait.html
   [362]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@kms_pm_rpm@modeset-non-lpsp-stress-no-wait.html

  * igt@perf_pmu@busy-double-start@rcs0:
    - shard-mtlp:         [FAIL][363] ([i915#4349]) -> [PASS][364]
   [363]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-mtlp-4/igt@perf_pmu@busy-double-start@rcs0.html
   [364]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-8/igt@perf_pmu@busy-double-start@rcs0.html

  * igt@perf_pmu@busy-idle-check-all@vcs0:
    - shard-dg2:          [FAIL][365] ([i915#4349]) -> [PASS][366] +5 other tests pass
   [365]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg2-5/igt@perf_pmu@busy-idle-check-all@vcs0.html
   [366]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-1/igt@perf_pmu@busy-idle-check-all@vcs0.html

  
#### Warnings ####

  * igt@api_intel_bb@blit-reloc-purge-cache:
    - shard-rkl:          [SKIP][367] ([i915#14544] / [i915#8411]) -> [SKIP][368] ([i915#8411])
   [367]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@api_intel_bb@blit-reloc-purge-cache.html
   [368]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-3/igt@api_intel_bb@blit-reloc-purge-cache.html

  * igt@gem_ccs@block-multicopy-inplace:
    - shard-rkl:          [SKIP][369] ([i915#3555] / [i915#9323]) -> [SKIP][370] ([i915#14544] / [i915#3555] / [i915#9323])
   [369]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-7/igt@gem_ccs@block-multicopy-inplace.html
   [370]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@gem_ccs@block-multicopy-inplace.html

  * igt@gem_ccs@ctrl-surf-copy:
    - shard-rkl:          [SKIP][371] ([i915#14544] / [i915#3555] / [i915#9323]) -> [SKIP][372] ([i915#3555] / [i915#9323])
   [371]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@gem_ccs@ctrl-surf-copy.html
   [372]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@gem_ccs@ctrl-surf-copy.html

  * igt@gem_ccs@suspend-resume:
    - shard-rkl:          [SKIP][373] ([i915#14544] / [i915#9323]) -> [SKIP][374] ([i915#9323])
   [373]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@gem_ccs@suspend-resume.html
   [374]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-2/igt@gem_ccs@suspend-resume.html

  * igt@gem_ctx_sseu@engines:
    - shard-rkl:          [SKIP][375] ([i915#14544] / [i915#280]) -> [SKIP][376] ([i915#280])
   [375]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@gem_ctx_sseu@engines.html
   [376]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-2/igt@gem_ctx_sseu@engines.html

  * igt@gem_exec_balancer@parallel-ordering:
    - shard-rkl:          [SKIP][377] ([i915#14544] / [i915#4525]) -> [SKIP][378] ([i915#4525])
   [377]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@gem_exec_balancer@parallel-ordering.html
   [378]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@gem_exec_balancer@parallel-ordering.html

  * igt@gem_exec_reloc@basic-cpu-wc-active:
    - shard-rkl:          [SKIP][379] ([i915#14544] / [i915#3281]) -> [SKIP][380] ([i915#3281]) +2 other tests skip
   [379]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@gem_exec_reloc@basic-cpu-wc-active.html
   [380]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@gem_exec_reloc@basic-cpu-wc-active.html

  * igt@gem_exec_reloc@basic-gtt-cpu:
    - shard-rkl:          [SKIP][381] ([i915#3281]) -> [SKIP][382] ([i915#14544] / [i915#3281]) +2 other tests skip
   [381]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-3/igt@gem_exec_reloc@basic-gtt-cpu.html
   [382]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@gem_exec_reloc@basic-gtt-cpu.html

  * igt@gem_lmem_swapping@random-engines:
    - shard-rkl:          [SKIP][383] ([i915#4613]) -> [SKIP][384] ([i915#14544] / [i915#4613])
   [383]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-7/igt@gem_lmem_swapping@random-engines.html
   [384]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@gem_lmem_swapping@random-engines.html

  * igt@gem_pread@bench:
    - shard-rkl:          [SKIP][385] ([i915#3282]) -> [SKIP][386] ([i915#14544] / [i915#3282]) +2 other tests skip
   [385]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-2/igt@gem_pread@bench.html
   [386]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@gem_pread@bench.html

  * igt@gen9_exec_parse@basic-rejected:
    - shard-rkl:          [SKIP][387] ([i915#2527]) -> [SKIP][388] ([i915#14544] / [i915#2527])
   [387]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-3/igt@gen9_exec_parse@basic-rejected.html
   [388]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@gen9_exec_parse@basic-rejected.html

  * igt@i915_module_load@fault-injection:
    - shard-mtlp:         [ABORT][389] ([i915#15342] / [i915#15481]) -> [ABORT][390] ([i915#15481])
   [389]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-mtlp-1/igt@i915_module_load@fault-injection.html
   [390]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-mtlp-1/igt@i915_module_load@fault-injection.html

  * igt@kms_big_fb@4-tiled-8bpp-rotate-270:
    - shard-dg1:          [SKIP][391] ([i915#4423] / [i915#4538] / [i915#5286]) -> [SKIP][392] ([i915#4538] / [i915#5286])
   [391]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg1-18/igt@kms_big_fb@4-tiled-8bpp-rotate-270.html
   [392]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-14/igt@kms_big_fb@4-tiled-8bpp-rotate-270.html

  * igt@kms_big_fb@4-tiled-addfb-size-offset-overflow:
    - shard-rkl:          [SKIP][393] ([i915#5286]) -> [SKIP][394] ([i915#14544] / [i915#5286]) +1 other test skip
   [393]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-8/igt@kms_big_fb@4-tiled-addfb-size-offset-overflow.html
   [394]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_big_fb@4-tiled-addfb-size-offset-overflow.html

  * igt@kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-180-hflip:
    - shard-rkl:          [SKIP][395] ([i915#14544] / [i915#5286]) -> [SKIP][396] ([i915#5286]) +1 other test skip
   [395]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-180-hflip.html
   [396]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-7/igt@kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-180-hflip.html

  * igt@kms_big_fb@linear-32bpp-rotate-270:
    - shard-rkl:          [SKIP][397] ([i915#3638]) -> [SKIP][398] ([i915#14544] / [i915#3638])
   [397]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-7/igt@kms_big_fb@linear-32bpp-rotate-270.html
   [398]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_big_fb@linear-32bpp-rotate-270.html

  * igt@kms_big_fb@yf-tiled-addfb:
    - shard-rkl:          [SKIP][399] ([i915#14544]) -> [SKIP][400] +4 other tests skip
   [399]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_big_fb@yf-tiled-addfb.html
   [400]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@kms_big_fb@yf-tiled-addfb.html

  * igt@kms_ccs@bad-aux-stride-yf-tiled-ccs@pipe-a-hdmi-a-2:
    - shard-rkl:          [SKIP][401] ([i915#6095]) -> [SKIP][402] ([i915#14544] / [i915#6095]) +10 other tests skip
   [401]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-3/igt@kms_ccs@bad-aux-stride-yf-tiled-ccs@pipe-a-hdmi-a-2.html
   [402]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_ccs@bad-aux-stride-yf-tiled-ccs@pipe-a-hdmi-a-2.html

  * igt@kms_ccs@crc-primary-suspend-4-tiled-dg2-rc-ccs@pipe-c-hdmi-a-2:
    - shard-rkl:          [SKIP][403] ([i915#14098] / [i915#6095]) -> [SKIP][404] ([i915#14098] / [i915#14544] / [i915#6095]) +12 other tests skip
   [403]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-3/igt@kms_ccs@crc-primary-suspend-4-tiled-dg2-rc-ccs@pipe-c-hdmi-a-2.html
   [404]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_ccs@crc-primary-suspend-4-tiled-dg2-rc-ccs@pipe-c-hdmi-a-2.html

  * igt@kms_ccs@crc-primary-suspend-yf-tiled-ccs:
    - shard-rkl:          [SKIP][405] ([i915#14098] / [i915#14544] / [i915#6095]) -> [SKIP][406] ([i915#14098] / [i915#6095]) +2 other tests skip
   [405]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_ccs@crc-primary-suspend-yf-tiled-ccs.html
   [406]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-3/igt@kms_ccs@crc-primary-suspend-yf-tiled-ccs.html

  * igt@kms_ccs@crc-primary-suspend-yf-tiled-ccs@pipe-a-hdmi-a-2:
    - shard-rkl:          [SKIP][407] ([i915#14544] / [i915#6095]) -> [SKIP][408] ([i915#6095])
   [407]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_ccs@crc-primary-suspend-yf-tiled-ccs@pipe-a-hdmi-a-2.html
   [408]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-3/igt@kms_ccs@crc-primary-suspend-yf-tiled-ccs@pipe-a-hdmi-a-2.html

  * igt@kms_ccs@random-ccs-data-4-tiled-mtl-mc-ccs:
    - shard-dg1:          [SKIP][409] ([i915#4423] / [i915#6095]) -> [SKIP][410] ([i915#6095])
   [409]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg1-18/igt@kms_ccs@random-ccs-data-4-tiled-mtl-mc-ccs.html
   [410]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-13/igt@kms_ccs@random-ccs-data-4-tiled-mtl-mc-ccs.html

  * igt@kms_cdclk@mode-transition:
    - shard-rkl:          [SKIP][411] ([i915#3742]) -> [SKIP][412] ([i915#14544] / [i915#3742])
   [411]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-2/igt@kms_cdclk@mode-transition.html
   [412]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_cdclk@mode-transition.html

  * igt@kms_chamelium_hpd@dp-hpd-enable-disable-mode:
    - shard-rkl:          [SKIP][413] ([i915#11151] / [i915#14544] / [i915#7828]) -> [SKIP][414] ([i915#11151] / [i915#7828]) +1 other test skip
   [413]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_chamelium_hpd@dp-hpd-enable-disable-mode.html
   [414]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@kms_chamelium_hpd@dp-hpd-enable-disable-mode.html

  * igt@kms_chamelium_hpd@hdmi-hpd-enable-disable-mode:
    - shard-rkl:          [SKIP][415] ([i915#11151] / [i915#7828]) -> [SKIP][416] ([i915#11151] / [i915#14544] / [i915#7828]) +1 other test skip
   [415]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-5/igt@kms_chamelium_hpd@hdmi-hpd-enable-disable-mode.html
   [416]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_chamelium_hpd@hdmi-hpd-enable-disable-mode.html

  * igt@kms_content_protection@atomic:
    - shard-dg2:          [FAIL][417] ([i915#7173]) -> [SKIP][418] ([i915#6944] / [i915#7118] / [i915#9424])
   [417]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg2-11/igt@kms_content_protection@atomic.html
   [418]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-5/igt@kms_content_protection@atomic.html

  * igt@kms_content_protection@atomic-dpms-hdcp14:
    - shard-dg2:          [SKIP][419] ([i915#6944]) -> [FAIL][420] ([i915#7173])
   [419]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg2-1/igt@kms_content_protection@atomic-dpms-hdcp14.html
   [420]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-11/igt@kms_content_protection@atomic-dpms-hdcp14.html

  * igt@kms_content_protection@dp-mst-lic-type-0:
    - shard-rkl:          [SKIP][421] ([i915#15330] / [i915#3116]) -> [SKIP][422] ([i915#14544] / [i915#15330] / [i915#3116])
   [421]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-7/igt@kms_content_protection@dp-mst-lic-type-0.html
   [422]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_content_protection@dp-mst-lic-type-0.html

  * igt@kms_content_protection@legacy:
    - shard-rkl:          [SKIP][423] ([i915#6944] / [i915#7118] / [i915#9424]) -> [SKIP][424] ([i915#14544] / [i915#6944] / [i915#7118] / [i915#9424])
   [423]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-7/igt@kms_content_protection@legacy.html
   [424]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_content_protection@legacy.html

  * igt@kms_content_protection@lic-type-0:
    - shard-dg2:          [SKIP][425] ([i915#6944] / [i915#9424]) -> [FAIL][426] ([i915#7173])
   [425]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg2-3/igt@kms_content_protection@lic-type-0.html
   [426]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-11/igt@kms_content_protection@lic-type-0.html

  * igt@kms_content_protection@mei-interface:
    - shard-dg1:          [SKIP][427] ([i915#9433]) -> [SKIP][428] ([i915#6944] / [i915#9424])
   [427]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg1-12/igt@kms_content_protection@mei-interface.html
   [428]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-17/igt@kms_content_protection@mei-interface.html

  * igt@kms_content_protection@srm:
    - shard-dg2:          [FAIL][429] ([i915#7173]) -> [SKIP][430] ([i915#6944] / [i915#7118])
   [429]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg2-11/igt@kms_content_protection@srm.html
   [430]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-6/igt@kms_content_protection@srm.html

  * igt@kms_cursor_crc@cursor-random-512x170:
    - shard-rkl:          [SKIP][431] ([i915#13049] / [i915#14544]) -> [SKIP][432] ([i915#13049])
   [431]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_cursor_crc@cursor-random-512x170.html
   [432]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-2/igt@kms_cursor_crc@cursor-random-512x170.html

  * igt@kms_cursor_crc@cursor-rapid-movement-32x10:
    - shard-rkl:          [SKIP][433] ([i915#14544] / [i915#3555]) -> [SKIP][434] ([i915#3555]) +2 other tests skip
   [433]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_cursor_crc@cursor-rapid-movement-32x10.html
   [434]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-4/igt@kms_cursor_crc@cursor-rapid-movement-32x10.html

  * igt@kms_cursor_crc@cursor-rapid-movement-32x32:
    - shard-rkl:          [SKIP][435] ([i915#3555]) -> [SKIP][436] ([i915#14544] / [i915#3555]) +1 other test skip
   [435]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-7/igt@kms_cursor_crc@cursor-rapid-movement-32x32.html
   [436]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_cursor_crc@cursor-rapid-movement-32x32.html

  * igt@kms_dsc@dsc-fractional-bpp-with-bpc:
    - shard-rkl:          [SKIP][437] ([i915#14544] / [i915#3840]) -> [SKIP][438] ([i915#3840])
   [437]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_dsc@dsc-fractional-bpp-with-bpc.html
   [438]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-7/igt@kms_dsc@dsc-fractional-bpp-with-bpc.html

  * igt@kms_feature_discovery@chamelium:
    - shard-rkl:          [SKIP][439] ([i915#14544] / [i915#4854]) -> [SKIP][440] ([i915#4854])
   [439]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_feature_discovery@chamelium.html
   [440]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-3/igt@kms_feature_discovery@chamelium.html

  * igt@kms_feature_discovery@psr1:
    - shard-rkl:          [SKIP][441] ([i915#658]) -> [SKIP][442] ([i915#14544] / [i915#658])
   [441]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-4/igt@kms_feature_discovery@psr1.html
   [442]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_feature_discovery@psr1.html

  * igt@kms_flip@2x-flip-vs-dpms-off-vs-modeset-interruptible:
    - shard-rkl:          [SKIP][443] ([i915#14544] / [i915#9934]) -> [SKIP][444] ([i915#9934]) +2 other tests skip
   [443]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_flip@2x-flip-vs-dpms-off-vs-modeset-interruptible.html
   [444]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-3/igt@kms_flip@2x-flip-vs-dpms-off-vs-modeset-interruptible.html

  * igt@kms_flip@2x-single-buffer-flip-vs-dpms-off-vs-modeset:
    - shard-rkl:          [SKIP][445] ([i915#9934]) -> [SKIP][446] ([i915#14544] / [i915#9934]) +3 other tests skip
   [445]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-7/igt@kms_flip@2x-single-buffer-flip-vs-dpms-off-vs-modeset.html
   [446]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_flip@2x-single-buffer-flip-vs-dpms-off-vs-modeset.html

  * igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-32bpp-4tiledg2rcccs-downscaling:
    - shard-rkl:          [SKIP][447] ([i915#14544] / [i915#15643]) -> [SKIP][448] ([i915#15643]) +1 other test skip
   [447]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-32bpp-4tiledg2rcccs-downscaling.html
   [448]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-2/igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-32bpp-4tiledg2rcccs-downscaling.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-offscreen-pri-indfb-draw-mmap-gtt:
    - shard-rkl:          [SKIP][449] ([i915#14544] / [i915#15102]) -> [SKIP][450] ([i915#15102]) +1 other test skip
   [449]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_frontbuffer_tracking@fbcpsr-1p-offscreen-pri-indfb-draw-mmap-gtt.html
   [450]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-2/igt@kms_frontbuffer_tracking@fbcpsr-1p-offscreen-pri-indfb-draw-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-indfb-fliptrack-mmap-gtt:
    - shard-rkl:          [SKIP][451] -> [SKIP][452] ([i915#14544]) +5 other tests skip
   [451]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-8/igt@kms_frontbuffer_tracking@fbcpsr-2p-indfb-fliptrack-mmap-gtt.html
   [452]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_frontbuffer_tracking@fbcpsr-2p-indfb-fliptrack-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-mmap-cpu:
    - shard-rkl:          [SKIP][453] ([i915#15102] / [i915#3023]) -> [SKIP][454] ([i915#14544] / [i915#15102] / [i915#3023]) +3 other tests skip
   [453]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-3/igt@kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-mmap-cpu.html
   [454]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_frontbuffer_tracking@fbcpsr-rgb101010-draw-mmap-cpu.html

  * igt@kms_frontbuffer_tracking@fbcpsr-rgb565-draw-mmap-gtt:
    - shard-rkl:          [SKIP][455] ([i915#14544] / [i915#15102] / [i915#3023]) -> [SKIP][456] ([i915#15102] / [i915#3023]) +5 other tests skip
   [455]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_frontbuffer_tracking@fbcpsr-rgb565-draw-mmap-gtt.html
   [456]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-2/igt@kms_frontbuffer_tracking@fbcpsr-rgb565-draw-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@fbcpsr-suspend:
    - shard-dg2:          [SKIP][457] ([i915#10433] / [i915#15102] / [i915#3458]) -> [SKIP][458] ([i915#15102] / [i915#3458])
   [457]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg2-4/igt@kms_frontbuffer_tracking@fbcpsr-suspend.html
   [458]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-6/igt@kms_frontbuffer_tracking@fbcpsr-suspend.html

  * igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-indfb-draw-mmap-wc:
    - shard-rkl:          [SKIP][459] ([i915#15102]) -> [SKIP][460] ([i915#14544] / [i915#15102]) +1 other test skip
   [459]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-3/igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-indfb-draw-mmap-wc.html
   [460]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_frontbuffer_tracking@psr-1p-offscreen-pri-indfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@psr-2p-scndscrn-indfb-msflip-blt:
    - shard-rkl:          [SKIP][461] ([i915#14544] / [i915#1825]) -> [SKIP][462] ([i915#1825]) +5 other tests skip
   [461]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-indfb-msflip-blt.html
   [462]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-indfb-msflip-blt.html

  * igt@kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-mmap-gtt:
    - shard-rkl:          [SKIP][463] ([i915#1825]) -> [SKIP][464] ([i915#14544] / [i915#1825]) +7 other tests skip
   [463]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-4/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-mmap-gtt.html
   [464]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-pri-shrfb-draw-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@psr-slowdraw:
    - shard-dg2:          [SKIP][465] ([i915#15102] / [i915#3458]) -> [SKIP][466] ([i915#10433] / [i915#15102] / [i915#3458]) +1 other test skip
   [465]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg2-6/igt@kms_frontbuffer_tracking@psr-slowdraw.html
   [466]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-4/igt@kms_frontbuffer_tracking@psr-slowdraw.html

  * igt@kms_hdr@brightness-with-hdr:
    - shard-dg2:          [SKIP][467] ([i915#12713]) -> [SKIP][468] ([i915#13331])
   [467]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg2-8/igt@kms_hdr@brightness-with-hdr.html
   [468]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg2-11/igt@kms_hdr@brightness-with-hdr.html
    - shard-dg1:          [SKIP][469] ([i915#12713]) -> [SKIP][470] ([i915#1187] / [i915#12713])
   [469]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-dg1-14/igt@kms_hdr@brightness-with-hdr.html
   [470]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-dg1-13/igt@kms_hdr@brightness-with-hdr.html

  * igt@kms_joiner@invalid-modeset-ultra-joiner:
    - shard-rkl:          [SKIP][471] ([i915#15458]) -> [SKIP][472] ([i915#14544] / [i915#15458])
   [471]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-7/igt@kms_joiner@invalid-modeset-ultra-joiner.html
   [472]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_joiner@invalid-modeset-ultra-joiner.html

  * igt@kms_plane@pixel-format-4-tiled-bmg-ccs-modifier-source-clamping:
    - shard-rkl:          [SKIP][473] ([i915#15709]) -> [SKIP][474] ([i915#14544] / [i915#15709])
   [473]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-3/igt@kms_plane@pixel-format-4-tiled-bmg-ccs-modifier-source-clamping.html
   [474]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_plane@pixel-format-4-tiled-bmg-ccs-modifier-source-clamping.html

  * igt@kms_pm_backlight@fade:
    - shard-rkl:          [SKIP][475] ([i915#14544] / [i915#5354]) -> [SKIP][476] ([i915#5354])
   [475]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_pm_backlight@fade.html
   [476]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-7/igt@kms_pm_backlight@fade.html

  * igt@kms_pm_dc@dc5-retention-flops:
    - shard-rkl:          [SKIP][477] ([i915#3828]) -> [SKIP][478] ([i915#14544] / [i915#3828])
   [477]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-4/igt@kms_pm_dc@dc5-retention-flops.html
   [478]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_pm_dc@dc5-retention-flops.html

  * igt@kms_pm_dc@dc6-psr:
    - shard-rkl:          [SKIP][479] ([i915#14544] / [i915#9685]) -> [SKIP][480] ([i915#9685])
   [479]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_pm_dc@dc6-psr.html
   [480]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-8/igt@kms_pm_dc@dc6-psr.html

  * igt@kms_pm_rpm@package-g7:
    - shard-rkl:          [SKIP][481] ([i915#14544] / [i915#15403]) -> [SKIP][482] ([i915#15403])
   [481]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_pm_rpm@package-g7.html
   [482]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-5/igt@kms_pm_rpm@package-g7.html

  * igt@kms_psr2_sf@pr-cursor-plane-move-continuous-exceed-fully-sf:
    - shard-rkl:          [SKIP][483] ([i915#11520] / [i915#14544]) -> [SKIP][484] ([i915#11520]) +3 other tests skip
   [483]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_psr2_sf@pr-cursor-plane-move-continuous-exceed-fully-sf.html
   [484]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-8/igt@kms_psr2_sf@pr-cursor-plane-move-continuous-exceed-fully-sf.html

  * igt@kms_psr2_sf@pr-overlay-plane-move-continuous-exceed-sf:
    - shard-rkl:          [SKIP][485] ([i915#11520]) -> [SKIP][486] ([i915#11520] / [i915#14544]) +3 other tests skip
   [485]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-4/igt@kms_psr2_sf@pr-overlay-plane-move-continuous-exceed-sf.html
   [486]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_psr2_sf@pr-overlay-plane-move-continuous-exceed-sf.html

  * igt@kms_psr@fbc-psr-sprite-blt:
    - shard-rkl:          [SKIP][487] ([i915#1072] / [i915#14544] / [i915#9732]) -> [SKIP][488] ([i915#1072] / [i915#9732]) +4 other tests skip
   [487]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-6/igt@kms_psr@fbc-psr-sprite-blt.html
   [488]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-7/igt@kms_psr@fbc-psr-sprite-blt.html

  * igt@kms_psr@pr-cursor-plane-onoff:
    - shard-rkl:          [SKIP][489] ([i915#1072] / [i915#9732]) -> [SKIP][490] ([i915#1072] / [i915#14544] / [i915#9732]) +4 other tests skip
   [489]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-7/igt@kms_psr@pr-cursor-plane-onoff.html
   [490]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_psr@pr-cursor-plane-onoff.html

  * igt@kms_rotation_crc@primary-yf-tiled-reflect-x-180:
    - shard-rkl:          [SKIP][491] ([i915#5289]) -> [SKIP][492] ([i915#14544] / [i915#5289])
   [491]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-7/igt@kms_rotation_crc@primary-yf-tiled-reflect-x-180.html
   [492]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_rotation_crc@primary-yf-tiled-reflect-x-180.html

  * igt@kms_vrr@flip-suspend:
    - shard-rkl:          [SKIP][493] ([i915#15243] / [i915#3555]) -> [SKIP][494] ([i915#14544] / [i915#15243] / [i915#3555])
   [493]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_8768/shard-rkl-7/igt@kms_vrr@flip-suspend.html
   [494]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/shard-rkl-6/igt@kms_vrr@flip-suspend.html

  
  [i915#10056]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10056
  [i915#10307]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10307
  [i915#10433]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10433
  [i915#10434]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10434
  [i915#1072]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1072
  [i915#1099]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1099
  [i915#11078]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11078
  [i915#11151]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11151
  [i915#11520]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11520
  [i915#11681]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11681
  [i915#1187]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1187
  [i915#12061]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12061
  [i915#12276]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12276
  [i915#12313]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12313
  [i915#12314]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12314
  [i915#12343]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12343
  [i915#12454]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12454
  [i915#1257]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1257
  [i915#12712]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12712
  [i915#12713]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12713
  [i915#12745]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12745
  [i915#12910]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12910
  [i915#13008]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13008
  [i915#13029]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13029
  [i915#13046]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13046
  [i915#13049]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13049
  [i915#13331]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13331
  [i915#13356]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13356
  [i915#13390]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13390
  [i915#13566]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13566
  [i915#13729]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13729
  [i915#13748]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13748
  [i915#13749]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13749
  [i915#13783]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13783
  [i915#13790]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13790
  [i915#13821]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13821
  [i915#13958]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13958
  [i915#14033]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14033
  [i915#14073]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14073
  [i915#14098]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14098
  [i915#14259]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14259
  [i915#14544]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14544
  [i915#14545]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14545
  [i915#14600]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14600
  [i915#14712]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14712
  [i915#14809]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14809
  [i915#15073]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15073
  [i915#15102]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15102
  [i915#15104]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15104
  [i915#15243]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15243
  [i915#15314]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15314
  [i915#15329]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15329
  [i915#15330]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15330
  [i915#15342]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15342
  [i915#15403]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15403
  [i915#15454]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15454
  [i915#15458]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15458
  [i915#15460]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15460
  [i915#15481]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15481
  [i915#15492]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15492
  [i915#15608]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15608
  [i915#15638]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15638
  [i915#15643]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15643
  [i915#15678]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15678
  [i915#15709]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15709
  [i915#15722]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15722
  [i915#15733]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15733
  [i915#15739]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15739
  [i915#1825]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1825
  [i915#1839]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1839
  [i915#2434]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2434
  [i915#2435]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2435
  [i915#2527]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2527
  [i915#2681]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2681
  [i915#280]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/280
  [i915#2856]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2856
  [i915#3023]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3023
  [i915#3116]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3116
  [i915#3281]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3281
  [i915#3282]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3282
  [i915#3291]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3291
  [i915#3297]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3297
  [i915#3299]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3299
  [i915#3458]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3458
  [i915#3555]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3555
  [i915#3637]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3637
  [i915#3638]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3638
  [i915#3708]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3708
  [i915#3742]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3742
  [i915#3828]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3828
  [i915#3840]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3840
  [i915#3955]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3955
  [i915#4077]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4077
  [i915#4079]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4079
  [i915#4083]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4083
  [i915#4103]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4103
  [i915#4212]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4212
  [i915#4270]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4270
  [i915#4348]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4348
  [i915#4349]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4349
  [i915#4387]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4387
  [i915#4391]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4391
  [i915#4423]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4423
  [i915#4525]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4525
  [i915#4538]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4538
  [i915#4613]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4613
  [i915#4812]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4812
  [i915#4816]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4816
  [i915#4817]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4817
  [i915#4818]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4818
  [i915#4839]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4839
  [i915#4854]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4854
  [i915#4879]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4879
  [i915#5030]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5030
  [i915#5107]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5107
  [i915#5138]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5138
  [i915#5190]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5190
  [i915#5286]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5286
  [i915#5289]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5289
  [i915#5354]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5354
  [i915#5956]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5956
  [i915#6095]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6095
  [i915#6113]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6113
  [i915#6187]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6187
  [i915#6301]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6301
  [i915#6335]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6335
  [i915#6524]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6524
  [i915#658]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/658
  [i915#6590]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6590
  [i915#6944]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6944
  [i915#6953]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/6953
  [i915#7116]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/7116
  [i915#7118]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/7118
  [i915#7173]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/7173
  [i915#7697]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/7697
  [i915#7828]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/7828
  [i915#7984]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/7984
  [i915#8228]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8228
  [i915#8399]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8399
  [i915#8411]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8411
  [i915#8428]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8428
  [i915#8516]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8516
  [i915#8555]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8555
  [i915#8708]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8708
  [i915#8809]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8809
  [i915#8812]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8812
  [i915#8814]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8814
  [i915#8823]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8823
  [i915#8898]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/8898
  [i915#9041]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9041
  [i915#9323]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9323
  [i915#9340]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9340
  [i915#9424]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9424
  [i915#9433]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9433
  [i915#9683]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9683
  [i915#9685]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9685
  [i915#9688]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9688
  [i915#9723]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9723
  [i915#9732]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9732
  [i915#9808]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9808
  [i915#9809]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9809
  [i915#9812]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9812
  [i915#9906]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9906
  [i915#9934]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9934


Build changes
-------------

  * CI: CI-20190529 -> None
  * IGT: IGT_8768 -> IGTPW_14603

  CI-20190529: 20190529
  CI_DRM_18022: 45a3045fc0dc46a893cb8bbe304afafd4120c904 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_14603: 18d15cf4696eeed1a1a42e326a93422d55684846 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  IGT_8768: 8768

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_14603/index.html

[-- Attachment #2: Type: text/html, Size: 170828 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* ✗ Xe.CI.FULL: failure for vmtb: Modernize SR-IOV VM Test Bench core
  2026-02-24  7:50 [PATCH i-g-t 00/10] vmtb: Modernize SR-IOV VM Test Bench core Adam Miszczak
                   ` (12 preceding siblings ...)
  2026-02-24 16:27 ` ✗ i915.CI.Full: failure " Patchwork
@ 2026-02-24 20:21 ` Patchwork
  13 siblings, 0 replies; 25+ messages in thread
From: Patchwork @ 2026-02-24 20:21 UTC (permalink / raw)
  To: Adam Miszczak; +Cc: igt-dev

[-- Attachment #1: Type: text/plain, Size: 46173 bytes --]

== Series Details ==

Series: vmtb: Modernize SR-IOV VM Test Bench core
URL   : https://patchwork.freedesktop.org/series/162037/
State : failure

== Summary ==

CI Bug Log - changes from XEIGT_8768_FULL -> XEIGTPW_14603_FULL
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with XEIGTPW_14603_FULL absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in XEIGTPW_14603_FULL, please notify your bug team (I915-ci-infra@lists.freedesktop.org) to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

Participating hosts (2 -> 2)
------------------------------

  No changes in participating hosts

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in XEIGTPW_14603_FULL:

### IGT changes ###

#### Possible regressions ####

  * igt@kms_cursor_legacy@single-move@pipe-b:
    - shard-bmg:          NOTRUN -> [DMESG-WARN][1]
   [1]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-3/igt@kms_cursor_legacy@single-move@pipe-b.html

  
New tests
---------

  New tests have been introduced between XEIGT_8768_FULL and XEIGTPW_14603_FULL:

### New IGT tests (9) ###

  * igt@xe_exec_store@basic-all@engine-drm_xe_engine_class_compute-instance-0-tile-0-region-vram0:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@xe_exec_store@basic-all@engine-drm_xe_engine_class_copy-instance-0-tile-0-region-vram0:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@xe_exec_store@basic-all@engine-drm_xe_engine_class_render-instance-0-tile-0-region-vram0:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@xe_exec_store@basic-all@engine-drm_xe_engine_class_video_decode-instance-0-tile-1-region-vram0:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@xe_exec_store@basic-all@engine-drm_xe_engine_class_video_decode-instance-1-tile-1-region-system:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@xe_exec_store@basic-all@engine-drm_xe_engine_class_video_decode-instance-1-tile-1-region-vram0:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@xe_exec_store@basic-all@engine-drm_xe_engine_class_video_enhance-instance-0-tile-1-region-vram0:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@xe_exec_store@basic-all@engine-drm_xe_engine_class_video_enhance-instance-1-tile-1-region-system:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  * igt@xe_exec_store@basic-all@engine-drm_xe_engine_class_video_enhance-instance-1-tile-1-region-vram0:
    - Statuses : 1 pass(s)
    - Exec time: [0.00] s

  

Known issues
------------

  Here are the changes found in XEIGTPW_14603_FULL that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@kms_addfb_basic@invalid-smem-bo-on-discrete:
    - shard-lnl:          NOTRUN -> [SKIP][2] ([Intel XE#3157])
   [2]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-8/igt@kms_addfb_basic@invalid-smem-bo-on-discrete.html

  * igt@kms_async_flips@async-flip-with-page-flip-events-linear:
    - shard-lnl:          [PASS][3] -> [FAIL][4] ([Intel XE#5993]) +3 other tests fail
   [3]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8768/shard-lnl-7/igt@kms_async_flips@async-flip-with-page-flip-events-linear.html
   [4]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-5/igt@kms_async_flips@async-flip-with-page-flip-events-linear.html

  * igt@kms_atomic_transition@plane-all-modeset-transition-fencing:
    - shard-lnl:          NOTRUN -> [SKIP][5] ([Intel XE#3279]) +1 other test skip
   [5]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-8/igt@kms_atomic_transition@plane-all-modeset-transition-fencing.html

  * igt@kms_big_fb@4-tiled-8bpp-rotate-90:
    - shard-lnl:          NOTRUN -> [SKIP][6] ([Intel XE#1407]) +3 other tests skip
   [6]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-7/igt@kms_big_fb@4-tiled-8bpp-rotate-90.html
    - shard-bmg:          NOTRUN -> [SKIP][7] ([Intel XE#2327]) +1 other test skip
   [7]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-3/igt@kms_big_fb@4-tiled-8bpp-rotate-90.html

  * igt@kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip:
    - shard-lnl:          NOTRUN -> [SKIP][8] ([Intel XE#3658])
   [8]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-5/igt@kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip.html

  * igt@kms_big_fb@linear-max-hw-stride-64bpp-rotate-0-hflip:
    - shard-bmg:          NOTRUN -> [SKIP][9] ([Intel XE#7059])
   [9]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-5/igt@kms_big_fb@linear-max-hw-stride-64bpp-rotate-0-hflip.html

  * igt@kms_big_fb@yf-tiled-addfb:
    - shard-bmg:          NOTRUN -> [SKIP][10] ([Intel XE#2328])
   [10]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-4/igt@kms_big_fb@yf-tiled-addfb.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-async-flip:
    - shard-lnl:          NOTRUN -> [SKIP][11] ([Intel XE#1124]) +11 other tests skip
   [11]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-7/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-async-flip.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-180:
    - shard-bmg:          NOTRUN -> [SKIP][12] ([Intel XE#1124]) +5 other tests skip
   [12]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-4/igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-180.html

  * igt@kms_bw@connected-linear-tiling-3-displays-2160x1440p:
    - shard-bmg:          NOTRUN -> [SKIP][13] ([Intel XE#2314] / [Intel XE#2894])
   [13]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-3/igt@kms_bw@connected-linear-tiling-3-displays-2160x1440p.html

  * igt@kms_bw@linear-tiling-2-displays-3840x2160p:
    - shard-lnl:          NOTRUN -> [SKIP][14] ([Intel XE#367])
   [14]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-2/igt@kms_bw@linear-tiling-2-displays-3840x2160p.html

  * igt@kms_bw@linear-tiling-4-displays-2560x1440p:
    - shard-bmg:          NOTRUN -> [SKIP][15] ([Intel XE#367])
   [15]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-6/igt@kms_bw@linear-tiling-4-displays-2560x1440p.html

  * igt@kms_bw@linear-tiling-4-displays-3840x2160p:
    - shard-lnl:          NOTRUN -> [SKIP][16] ([Intel XE#1512])
   [16]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-8/igt@kms_bw@linear-tiling-4-displays-3840x2160p.html

  * igt@kms_ccs@bad-aux-stride-4-tiled-mtl-rc-ccs-cc:
    - shard-bmg:          NOTRUN -> [SKIP][17] ([Intel XE#2887]) +8 other tests skip
   [17]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-2/igt@kms_ccs@bad-aux-stride-4-tiled-mtl-rc-ccs-cc.html

  * igt@kms_ccs@crc-primary-suspend-y-tiled-gen12-rc-ccs:
    - shard-lnl:          NOTRUN -> [SKIP][18] ([Intel XE#3432])
   [18]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-7/igt@kms_ccs@crc-primary-suspend-y-tiled-gen12-rc-ccs.html

  * igt@kms_ccs@crc-sprite-planes-basic-4-tiled-mtl-mc-ccs:
    - shard-lnl:          NOTRUN -> [SKIP][19] ([Intel XE#2887]) +17 other tests skip
   [19]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-3/igt@kms_ccs@crc-sprite-planes-basic-4-tiled-mtl-mc-ccs.html

  * igt@kms_ccs@random-ccs-data-4-tiled-bmg-ccs:
    - shard-lnl:          NOTRUN -> [SKIP][20] ([Intel XE#2669]) +3 other tests skip
   [20]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-7/igt@kms_ccs@random-ccs-data-4-tiled-bmg-ccs.html

  * igt@kms_chamelium_color@gamma:
    - shard-lnl:          NOTRUN -> [SKIP][21] ([Intel XE#306]) +1 other test skip
   [21]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-2/igt@kms_chamelium_color@gamma.html

  * igt@kms_chamelium_frames@vga-frame-dump:
    - shard-lnl:          NOTRUN -> [SKIP][22] ([Intel XE#373]) +11 other tests skip
   [22]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-8/igt@kms_chamelium_frames@vga-frame-dump.html

  * igt@kms_chamelium_hpd@hdmi-hpd-after-hibernate:
    - shard-bmg:          NOTRUN -> [SKIP][23] ([Intel XE#2252]) +2 other tests skip
   [23]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-8/igt@kms_chamelium_hpd@hdmi-hpd-after-hibernate.html

  * igt@kms_color_pipeline@plane-ctm3x4-lut1d@pipe-c-plane-2:
    - shard-lnl:          NOTRUN -> [FAIL][24] ([Intel XE#7305]) +9 other tests fail
   [24]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-8/igt@kms_color_pipeline@plane-ctm3x4-lut1d@pipe-c-plane-2.html

  * igt@kms_content_protection@atomic-dpms-hdcp14@pipe-a-dp-2:
    - shard-bmg:          NOTRUN -> [FAIL][25] ([Intel XE#3304]) +1 other test fail
   [25]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-2/igt@kms_content_protection@atomic-dpms-hdcp14@pipe-a-dp-2.html

  * igt@kms_content_protection@dp-mst-lic-type-1:
    - shard-bmg:          NOTRUN -> [SKIP][26] ([Intel XE#2390] / [Intel XE#6974]) +1 other test skip
   [26]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-4/igt@kms_content_protection@dp-mst-lic-type-1.html

  * igt@kms_content_protection@legacy:
    - shard-lnl:          NOTRUN -> [SKIP][27] ([Intel XE#3278]) +1 other test skip
   [27]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-4/igt@kms_content_protection@legacy.html

  * igt@kms_content_protection@mei-interface:
    - shard-lnl:          NOTRUN -> [SKIP][28] ([Intel XE#1468])
   [28]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-6/igt@kms_content_protection@mei-interface.html

  * igt@kms_cursor_crc@cursor-random-512x170:
    - shard-lnl:          NOTRUN -> [SKIP][29] ([Intel XE#2321]) +3 other tests skip
   [29]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-4/igt@kms_cursor_crc@cursor-random-512x170.html

  * igt@kms_cursor_crc@cursor-rapid-movement-128x42:
    - shard-lnl:          NOTRUN -> [SKIP][30] ([Intel XE#1424]) +4 other tests skip
   [30]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-1/igt@kms_cursor_crc@cursor-rapid-movement-128x42.html

  * igt@kms_cursor_crc@cursor-rapid-movement-512x512:
    - shard-bmg:          NOTRUN -> [SKIP][31] ([Intel XE#2321])
   [31]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-8/igt@kms_cursor_crc@cursor-rapid-movement-512x512.html

  * igt@kms_cursor_legacy@cursora-vs-flipb-legacy:
    - shard-lnl:          NOTRUN -> [SKIP][32] ([Intel XE#309]) +5 other tests skip
   [32]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-4/igt@kms_cursor_legacy@cursora-vs-flipb-legacy.html

  * igt@kms_cursor_legacy@single-move:
    - shard-bmg:          NOTRUN -> [INCOMPLETE][33] ([Intel XE#6819]) +1 other test incomplete
   [33]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-3/igt@kms_cursor_legacy@single-move.html

  * igt@kms_dp_link_training@non-uhbr-mst:
    - shard-bmg:          NOTRUN -> [SKIP][34] ([Intel XE#4354])
   [34]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-9/igt@kms_dp_link_training@non-uhbr-mst.html

  * igt@kms_dp_link_training@uhbr-mst:
    - shard-lnl:          NOTRUN -> [SKIP][35] ([Intel XE#4354]) +1 other test skip
   [35]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-5/igt@kms_dp_link_training@uhbr-mst.html

  * igt@kms_dp_linktrain_fallback@dp-fallback:
    - shard-lnl:          NOTRUN -> [SKIP][36] ([Intel XE#4294])
   [36]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-4/igt@kms_dp_linktrain_fallback@dp-fallback.html

  * igt@kms_dp_linktrain_fallback@dsc-fallback:
    - shard-lnl:          NOTRUN -> [SKIP][37] ([Intel XE#4331])
   [37]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-1/igt@kms_dp_linktrain_fallback@dsc-fallback.html

  * igt@kms_fbc_dirty_rect@fbc-dirty-rectangle-different-formats:
    - shard-lnl:          NOTRUN -> [SKIP][38] ([Intel XE#4422])
   [38]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-1/igt@kms_fbc_dirty_rect@fbc-dirty-rectangle-different-formats.html

  * igt@kms_fbcon_fbt@psr:
    - shard-bmg:          NOTRUN -> [SKIP][39] ([Intel XE#776])
   [39]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-8/igt@kms_fbcon_fbt@psr.html

  * igt@kms_feature_discovery@dp-mst:
    - shard-lnl:          NOTRUN -> [SKIP][40] ([Intel XE#1137])
   [40]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-7/igt@kms_feature_discovery@dp-mst.html

  * igt@kms_flip@2x-flip-vs-rmfb-interruptible:
    - shard-lnl:          NOTRUN -> [SKIP][41] ([Intel XE#1421]) +7 other tests skip
   [41]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-3/igt@kms_flip@2x-flip-vs-rmfb-interruptible.html

  * igt@kms_flip@flip-vs-absolute-wf_vblank@a-hdmi-a3:
    - shard-bmg:          [PASS][42] -> [ABORT][43] ([Intel XE#5545] / [Intel XE#6652]) +1 other test abort
   [42]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8768/shard-bmg-7/igt@kms_flip@flip-vs-absolute-wf_vblank@a-hdmi-a3.html
   [43]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-2/igt@kms_flip@flip-vs-absolute-wf_vblank@a-hdmi-a3.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-upscaling:
    - shard-bmg:          NOTRUN -> [SKIP][44] ([Intel XE#7178]) +2 other tests skip
   [44]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-4/igt@kms_flip_scaled_crc@flip-32bpp-ytileccs-to-64bpp-ytile-upscaling.html

  * igt@kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling:
    - shard-lnl:          NOTRUN -> [SKIP][45] ([Intel XE#1397] / [Intel XE#1745])
   [45]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-3/igt@kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling.html

  * igt@kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling@pipe-a-default-mode:
    - shard-lnl:          NOTRUN -> [SKIP][46] ([Intel XE#1397])
   [46]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-3/igt@kms_flip_scaled_crc@flip-64bpp-linear-to-32bpp-linear-downscaling@pipe-a-default-mode.html

  * igt@kms_flip_scaled_crc@flip-64bpp-yftile-to-32bpp-yftile-upscaling:
    - shard-lnl:          NOTRUN -> [SKIP][47] ([Intel XE#7178]) +6 other tests skip
   [47]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-5/igt@kms_flip_scaled_crc@flip-64bpp-yftile-to-32bpp-yftile-upscaling.html

  * igt@kms_flip_scaled_crc@flip-nv12-linear-to-nv12-linear-reflect-x:
    - shard-bmg:          NOTRUN -> [SKIP][48] ([Intel XE#7179])
   [48]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-7/igt@kms_flip_scaled_crc@flip-nv12-linear-to-nv12-linear-reflect-x.html

  * igt@kms_force_connector_basic@force-connector-state:
    - shard-lnl:          NOTRUN -> [SKIP][49] ([Intel XE#352]) +1 other test skip
   [49]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-4/igt@kms_force_connector_basic@force-connector-state.html

  * igt@kms_frontbuffer_tracking@drrs-1p-offscreen-pri-shrfb-draw-blt:
    - shard-lnl:          NOTRUN -> [SKIP][50] ([Intel XE#6312]) +2 other tests skip
   [50]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-5/igt@kms_frontbuffer_tracking@drrs-1p-offscreen-pri-shrfb-draw-blt.html

  * igt@kms_frontbuffer_tracking@drrs-rgb101010-draw-blt:
    - shard-bmg:          NOTRUN -> [SKIP][51] ([Intel XE#2311]) +16 other tests skip
   [51]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-7/igt@kms_frontbuffer_tracking@drrs-rgb101010-draw-blt.html

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-mmap-wc:
    - shard-bmg:          NOTRUN -> [SKIP][52] ([Intel XE#4141]) +6 other tests skip
   [52]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-2/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-mmap-wc.html

  * igt@kms_frontbuffer_tracking@fbc-tiling-y:
    - shard-lnl:          NOTRUN -> [SKIP][53] ([Intel XE#1469])
   [53]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-2/igt@kms_frontbuffer_tracking@fbc-tiling-y.html

  * igt@kms_frontbuffer_tracking@fbcdrrs-argb161616f-draw-render:
    - shard-bmg:          NOTRUN -> [SKIP][54] ([Intel XE#7061]) +4 other tests skip
   [54]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-3/igt@kms_frontbuffer_tracking@fbcdrrs-argb161616f-draw-render.html

  * igt@kms_frontbuffer_tracking@fbcdrrs-rgb101010-draw-blt:
    - shard-lnl:          NOTRUN -> [SKIP][55] ([Intel XE#651]) +14 other tests skip
   [55]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-4/igt@kms_frontbuffer_tracking@fbcdrrs-rgb101010-draw-blt.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-indfb-msflip-blt:
    - shard-bmg:          NOTRUN -> [SKIP][56] ([Intel XE#2313]) +15 other tests skip
   [56]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-9/igt@kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-indfb-msflip-blt.html

  * igt@kms_frontbuffer_tracking@psr-2p-scndscrn-shrfb-plflip-blt:
    - shard-lnl:          NOTRUN -> [SKIP][57] ([Intel XE#656]) +41 other tests skip
   [57]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-4/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-shrfb-plflip-blt.html

  * igt@kms_frontbuffer_tracking@psr-abgr161616f-draw-blt:
    - shard-lnl:          NOTRUN -> [SKIP][58] ([Intel XE#7061]) +5 other tests skip
   [58]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-4/igt@kms_frontbuffer_tracking@psr-abgr161616f-draw-blt.html

  * igt@kms_hdmi_inject@inject-audio:
    - shard-lnl:          NOTRUN -> [SKIP][59] ([Intel XE#1470] / [Intel XE#2853])
   [59]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-1/igt@kms_hdmi_inject@inject-audio.html

  * igt@kms_hdr@static-toggle:
    - shard-lnl:          NOTRUN -> [SKIP][60] ([Intel XE#1503])
   [60]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-6/igt@kms_hdr@static-toggle.html

  * igt@kms_joiner@basic-force-big-joiner:
    - shard-lnl:          NOTRUN -> [SKIP][61] ([Intel XE#7086])
   [61]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-2/igt@kms_joiner@basic-force-big-joiner.html

  * igt@kms_joiner@basic-ultra-joiner:
    - shard-lnl:          NOTRUN -> [SKIP][62] ([Intel XE#6900]) +1 other test skip
   [62]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-4/igt@kms_joiner@basic-ultra-joiner.html

  * igt@kms_plane@pixel-format-4-tiled-bmg-ccs-modifier@pipe-b-plane-5:
    - shard-bmg:          NOTRUN -> [SKIP][63] ([Intel XE#7130]) +1 other test skip
   [63]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-3/igt@kms_plane@pixel-format-4-tiled-bmg-ccs-modifier@pipe-b-plane-5.html

  * igt@kms_plane@pixel-format-4-tiled-lnl-ccs-modifier@pipe-a-plane-5:
    - shard-lnl:          NOTRUN -> [SKIP][64] ([Intel XE#7130]) +1 other test skip
   [64]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-1/igt@kms_plane@pixel-format-4-tiled-lnl-ccs-modifier@pipe-a-plane-5.html

  * igt@kms_plane@pixel-format-4-tiled-mtl-rc-ccs-modifier:
    - shard-bmg:          NOTRUN -> [SKIP][65] ([Intel XE#7283])
   [65]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-8/igt@kms_plane@pixel-format-4-tiled-mtl-rc-ccs-modifier.html

  * igt@kms_plane@pixel-format-yf-tiled-modifier:
    - shard-lnl:          NOTRUN -> [SKIP][66] ([Intel XE#7283]) +5 other tests skip
   [66]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-7/igt@kms_plane@pixel-format-yf-tiled-modifier.html

  * igt@kms_plane_multiple@2x-tiling-yf:
    - shard-lnl:          NOTRUN -> [SKIP][67] ([Intel XE#4596]) +1 other test skip
   [67]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-6/igt@kms_plane_multiple@2x-tiling-yf.html

  * igt@kms_plane_scaling@plane-downscale-factor-0-5-with-pixel-format@pipe-c:
    - shard-lnl:          NOTRUN -> [SKIP][68] ([Intel XE#2763] / [Intel XE#6886]) +11 other tests skip
   [68]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-4/igt@kms_plane_scaling@plane-downscale-factor-0-5-with-pixel-format@pipe-c.html

  * igt@kms_pm_dc@dc3co-vpb-simulation:
    - shard-bmg:          NOTRUN -> [SKIP][69] ([Intel XE#2391])
   [69]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-5/igt@kms_pm_dc@dc3co-vpb-simulation.html

  * igt@kms_pm_rpm@dpms-mode-unset-non-lpsp:
    - shard-lnl:          NOTRUN -> [SKIP][70] ([Intel XE#1439] / [Intel XE#836])
   [70]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-8/igt@kms_pm_rpm@dpms-mode-unset-non-lpsp.html

  * igt@kms_pm_rpm@modeset-non-lpsp-stress-no-wait:
    - shard-lnl:          NOTRUN -> [SKIP][71] ([Intel XE#1439] / [Intel XE#3141]) +1 other test skip
   [71]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-2/igt@kms_pm_rpm@modeset-non-lpsp-stress-no-wait.html

  * igt@kms_pm_rpm@package-g7:
    - shard-lnl:          NOTRUN -> [SKIP][72] ([Intel XE#6813])
   [72]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-4/igt@kms_pm_rpm@package-g7.html

  * igt@kms_psr2_sf@fbc-psr2-cursor-plane-move-continuous-exceed-fully-sf:
    - shard-lnl:          NOTRUN -> [SKIP][73] ([Intel XE#1406] / [Intel XE#2893] / [Intel XE#4608])
   [73]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-1/igt@kms_psr2_sf@fbc-psr2-cursor-plane-move-continuous-exceed-fully-sf.html

  * igt@kms_psr2_sf@fbc-psr2-cursor-plane-move-continuous-exceed-fully-sf@pipe-b-edp-1:
    - shard-lnl:          NOTRUN -> [SKIP][74] ([Intel XE#1406] / [Intel XE#4608]) +1 other test skip
   [74]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-1/igt@kms_psr2_sf@fbc-psr2-cursor-plane-move-continuous-exceed-fully-sf@pipe-b-edp-1.html

  * igt@kms_psr2_sf@pr-overlay-plane-move-continuous-sf:
    - shard-lnl:          NOTRUN -> [SKIP][75] ([Intel XE#1406] / [Intel XE#2893]) +7 other tests skip
   [75]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-1/igt@kms_psr2_sf@pr-overlay-plane-move-continuous-sf.html

  * igt@kms_psr2_sf@psr2-cursor-plane-update-sf:
    - shard-bmg:          NOTRUN -> [SKIP][76] ([Intel XE#1406] / [Intel XE#1489]) +3 other tests skip
   [76]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-4/igt@kms_psr2_sf@psr2-cursor-plane-update-sf.html

  * igt@kms_psr2_su@page_flip-nv12:
    - shard-lnl:          NOTRUN -> [SKIP][77] ([Intel XE#1128] / [Intel XE#1406]) +1 other test skip
   [77]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-1/igt@kms_psr2_su@page_flip-nv12.html

  * igt@kms_psr@fbc-psr2-suspend@edp-1:
    - shard-lnl:          NOTRUN -> [SKIP][78] ([Intel XE#1406] / [Intel XE#4609])
   [78]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-2/igt@kms_psr@fbc-psr2-suspend@edp-1.html

  * igt@kms_psr@pr-cursor-plane-move:
    - shard-bmg:          NOTRUN -> [SKIP][79] ([Intel XE#1406] / [Intel XE#2234] / [Intel XE#2850]) +7 other tests skip
   [79]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-9/igt@kms_psr@pr-cursor-plane-move.html

  * igt@kms_psr@pr-no-drrs:
    - shard-lnl:          NOTRUN -> [SKIP][80] ([Intel XE#1406]) +5 other tests skip
   [80]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-2/igt@kms_psr@pr-no-drrs.html

  * igt@kms_psr_stress_test@flip-primary-invalidate-overlay:
    - shard-lnl:          [PASS][81] -> [SKIP][82] ([Intel XE#1406] / [Intel XE#4692])
   [81]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8768/shard-lnl-5/igt@kms_psr_stress_test@flip-primary-invalidate-overlay.html
   [82]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-6/igt@kms_psr_stress_test@flip-primary-invalidate-overlay.html

  * igt@kms_rotation_crc@primary-y-tiled-reflect-x-0:
    - shard-lnl:          NOTRUN -> [SKIP][83] ([Intel XE#1127])
   [83]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-7/igt@kms_rotation_crc@primary-y-tiled-reflect-x-0.html

  * igt@kms_rotation_crc@primary-y-tiled-reflect-x-270:
    - shard-lnl:          NOTRUN -> [SKIP][84] ([Intel XE#3414] / [Intel XE#3904])
   [84]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-4/igt@kms_rotation_crc@primary-y-tiled-reflect-x-270.html

  * igt@kms_rotation_crc@sprite-rotation-90-pos-100-0:
    - shard-bmg:          NOTRUN -> [SKIP][85] ([Intel XE#3414] / [Intel XE#3904])
   [85]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-1/igt@kms_rotation_crc@sprite-rotation-90-pos-100-0.html

  * igt@kms_scaling_modes@scaling-mode-center:
    - shard-bmg:          NOTRUN -> [SKIP][86] ([Intel XE#2413])
   [86]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-3/igt@kms_scaling_modes@scaling-mode-center.html

  * igt@kms_setmode@basic-clone-single-crtc:
    - shard-bmg:          NOTRUN -> [SKIP][87] ([Intel XE#1435])
   [87]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-9/igt@kms_setmode@basic-clone-single-crtc.html

  * igt@kms_setmode@basic@pipe-b-edp-1:
    - shard-lnl:          [PASS][88] -> [FAIL][89] ([Intel XE#6361]) +2 other tests fail
   [88]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8768/shard-lnl-1/igt@kms_setmode@basic@pipe-b-edp-1.html
   [89]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-1/igt@kms_setmode@basic@pipe-b-edp-1.html

  * igt@kms_sharpness_filter@invalid-filter-with-scaling-mode:
    - shard-bmg:          NOTRUN -> [SKIP][90] ([Intel XE#6503]) +1 other test skip
   [90]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-6/igt@kms_sharpness_filter@invalid-filter-with-scaling-mode.html

  * igt@kms_vrr@cmrr@pipe-a-edp-1:
    - shard-lnl:          [PASS][91] -> [FAIL][92] ([Intel XE#4459]) +1 other test fail
   [91]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8768/shard-lnl-1/igt@kms_vrr@cmrr@pipe-a-edp-1.html
   [92]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-1/igt@kms_vrr@cmrr@pipe-a-edp-1.html

  * igt@kms_vrr@flip-dpms:
    - shard-bmg:          NOTRUN -> [SKIP][93] ([Intel XE#1499])
   [93]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-5/igt@kms_vrr@flip-dpms.html

  * igt@kms_vrr@negative-basic:
    - shard-lnl:          NOTRUN -> [SKIP][94] ([Intel XE#1499]) +1 other test skip
   [94]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-1/igt@kms_vrr@negative-basic.html

  * igt@xe_compute@ccs-mode-basic:
    - shard-bmg:          NOTRUN -> [SKIP][95] ([Intel XE#6599])
   [95]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-5/igt@xe_compute@ccs-mode-basic.html

  * igt@xe_eudebug@basic-connect:
    - shard-lnl:          NOTRUN -> [SKIP][96] ([Intel XE#4837]) +9 other tests skip
   [96]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-6/igt@xe_eudebug@basic-connect.html

  * igt@xe_eudebug@discovery-race-vmbind:
    - shard-bmg:          NOTRUN -> [SKIP][97] ([Intel XE#4837]) +3 other tests skip
   [97]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-4/igt@xe_eudebug@discovery-race-vmbind.html

  * igt@xe_eudebug_online@pagefault-write-stress:
    - shard-lnl:          NOTRUN -> [SKIP][98] ([Intel XE#6665])
   [98]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-8/igt@xe_eudebug_online@pagefault-write-stress.html

  * igt@xe_eudebug_online@resume-one:
    - shard-lnl:          NOTRUN -> [SKIP][99] ([Intel XE#4837] / [Intel XE#6665]) +5 other tests skip
   [99]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-7/igt@xe_eudebug_online@resume-one.html

  * igt@xe_eudebug_online@stopped-thread:
    - shard-bmg:          NOTRUN -> [SKIP][100] ([Intel XE#4837] / [Intel XE#6665]) +1 other test skip
   [100]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-7/igt@xe_eudebug_online@stopped-thread.html

  * igt@xe_evict@evict-beng-large-external-cm:
    - shard-lnl:          NOTRUN -> [SKIP][101] ([Intel XE#6540] / [Intel XE#688]) +11 other tests skip
   [101]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-5/igt@xe_evict@evict-beng-large-external-cm.html

  * igt@xe_exec_basic@multigpu-many-execqueues-many-vm-basic-defer-mmap:
    - shard-bmg:          NOTRUN -> [SKIP][102] ([Intel XE#2322]) +5 other tests skip
   [102]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-2/igt@xe_exec_basic@multigpu-many-execqueues-many-vm-basic-defer-mmap.html

  * igt@xe_exec_basic@multigpu-no-exec-bindexecqueue-rebind:
    - shard-lnl:          NOTRUN -> [SKIP][103] ([Intel XE#1392]) +10 other tests skip
   [103]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-4/igt@xe_exec_basic@multigpu-no-exec-bindexecqueue-rebind.html

  * igt@xe_exec_fault_mode@many-multi-queue-userptr-invalidate-race-imm:
    - shard-bmg:          NOTRUN -> [SKIP][104] ([Intel XE#7136]) +2 other tests skip
   [104]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-9/igt@xe_exec_fault_mode@many-multi-queue-userptr-invalidate-race-imm.html

  * igt@xe_exec_fault_mode@twice-multi-queue-userptr-imm:
    - shard-lnl:          NOTRUN -> [SKIP][105] ([Intel XE#7136]) +15 other tests skip
   [105]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-3/igt@xe_exec_fault_mode@twice-multi-queue-userptr-imm.html

  * igt@xe_exec_multi_queue@one-queue-preempt-mode-fault-userptr-invalidate:
    - shard-lnl:          NOTRUN -> [SKIP][106] ([Intel XE#6874]) +40 other tests skip
   [106]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-1/igt@xe_exec_multi_queue@one-queue-preempt-mode-fault-userptr-invalidate.html

  * igt@xe_exec_multi_queue@two-queues-preempt-mode-fault-dyn-priority-smem:
    - shard-bmg:          NOTRUN -> [SKIP][107] ([Intel XE#6874]) +16 other tests skip
   [107]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-7/igt@xe_exec_multi_queue@two-queues-preempt-mode-fault-dyn-priority-smem.html

  * igt@xe_exec_threads@threads-multi-queue-cm-basic:
    - shard-bmg:          NOTRUN -> [SKIP][108] ([Intel XE#7138]) +2 other tests skip
   [108]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-1/igt@xe_exec_threads@threads-multi-queue-cm-basic.html

  * igt@xe_exec_threads@threads-multi-queue-fd-userptr-invalidate:
    - shard-lnl:          NOTRUN -> [SKIP][109] ([Intel XE#7138]) +8 other tests skip
   [109]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-3/igt@xe_exec_threads@threads-multi-queue-fd-userptr-invalidate.html

  * igt@xe_live_ktest@xe_eudebug:
    - shard-lnl:          NOTRUN -> [SKIP][110] ([Intel XE#2833])
   [110]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-5/igt@xe_live_ktest@xe_eudebug.html

  * igt@xe_multigpu_svm@mgpu-concurrent-access-basic:
    - shard-bmg:          NOTRUN -> [SKIP][111] ([Intel XE#6964]) +2 other tests skip
   [111]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-8/igt@xe_multigpu_svm@mgpu-concurrent-access-basic.html

  * igt@xe_multigpu_svm@mgpu-migration-basic:
    - shard-lnl:          NOTRUN -> [SKIP][112] ([Intel XE#6964]) +2 other tests skip
   [112]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-3/igt@xe_multigpu_svm@mgpu-migration-basic.html

  * igt@xe_oa@oa-tlb-invalidate:
    - shard-lnl:          NOTRUN -> [SKIP][113] ([Intel XE#2248] / [Intel XE#7325])
   [113]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-5/igt@xe_oa@oa-tlb-invalidate.html

  * igt@xe_pm@d3cold-basic:
    - shard-lnl:          NOTRUN -> [SKIP][114] ([Intel XE#2284] / [Intel XE#366]) +1 other test skip
   [114]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-4/igt@xe_pm@d3cold-basic.html

  * igt@xe_pm@d3cold-mocs:
    - shard-bmg:          NOTRUN -> [SKIP][115] ([Intel XE#2284])
   [115]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-9/igt@xe_pm@d3cold-mocs.html

  * igt@xe_pmu@all-fn-engine-activity-load:
    - shard-lnl:          NOTRUN -> [SKIP][116] ([Intel XE#4650])
   [116]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-2/igt@xe_pmu@all-fn-engine-activity-load.html

  * igt@xe_query@multigpu-query-hwconfig:
    - shard-bmg:          NOTRUN -> [SKIP][117] ([Intel XE#944]) +2 other tests skip
   [117]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-6/igt@xe_query@multigpu-query-hwconfig.html

  * igt@xe_query@multigpu-query-invalid-size:
    - shard-lnl:          NOTRUN -> [SKIP][118] ([Intel XE#944]) +4 other tests skip
   [118]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-2/igt@xe_query@multigpu-query-invalid-size.html

  * igt@xe_sriov_auto_provisioning@exclusive-ranges:
    - shard-lnl:          NOTRUN -> [SKIP][119] ([Intel XE#4130])
   [119]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-5/igt@xe_sriov_auto_provisioning@exclusive-ranges.html

  * igt@xe_sriov_flr@flr-twice:
    - shard-lnl:          NOTRUN -> [SKIP][120] ([Intel XE#4273])
   [120]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-2/igt@xe_sriov_flr@flr-twice.html

  * igt@xe_sriov_flr@flr-vfs-parallel:
    - shard-bmg:          [PASS][121] -> [FAIL][122] ([Intel XE#6569])
   [121]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8768/shard-bmg-1/igt@xe_sriov_flr@flr-vfs-parallel.html
   [122]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-9/igt@xe_sriov_flr@flr-vfs-parallel.html

  * igt@xe_sriov_scheduling@nonpreempt-engine-resets:
    - shard-lnl:          NOTRUN -> [SKIP][123] ([Intel XE#4351])
   [123]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-4/igt@xe_sriov_scheduling@nonpreempt-engine-resets.html

  * igt@xe_sriov_vram@vf-access-beyond:
    - shard-lnl:          NOTRUN -> [SKIP][124] ([Intel XE#6376] / [Intel XE#7330]) +1 other test skip
   [124]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-8/igt@xe_sriov_vram@vf-access-beyond.html

  * igt@xe_survivability@runtime-survivability:
    - shard-lnl:          NOTRUN -> [SKIP][125] ([Intel XE#6529] / [Intel XE#7331])
   [125]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-5/igt@xe_survivability@runtime-survivability.html

  
#### Possible fixes ####

  * igt@intel_hwmon@hwmon-write:
    - shard-bmg:          [FAIL][126] ([Intel XE#4665]) -> [PASS][127]
   [126]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8768/shard-bmg-8/igt@intel_hwmon@hwmon-write.html
   [127]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-7/igt@intel_hwmon@hwmon-write.html

  * igt@kms_bw@linear-tiling-1-displays-2560x1440p:
    - shard-bmg:          [SKIP][128] ([Intel XE#367]) -> [PASS][129]
   [128]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8768/shard-bmg-4/igt@kms_bw@linear-tiling-1-displays-2560x1440p.html
   [129]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-5/igt@kms_bw@linear-tiling-1-displays-2560x1440p.html

  * igt@kms_pm_dc@dc5-dpms:
    - shard-lnl:          [FAIL][130] ([Intel XE#7340]) -> [PASS][131]
   [130]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8768/shard-lnl-1/igt@kms_pm_dc@dc5-dpms.html
   [131]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-8/igt@kms_pm_dc@dc5-dpms.html

  * igt@xe_pmu@gt-frequency:
    - shard-lnl:          [FAIL][132] -> [PASS][133] +1 other test pass
   [132]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8768/shard-lnl-7/igt@xe_pmu@gt-frequency.html
   [133]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-lnl-8/igt@xe_pmu@gt-frequency.html

  
#### Warnings ####

  * igt@kms_content_protection@atomic-dpms:
    - shard-bmg:          [FAIL][134] ([Intel XE#1178] / [Intel XE#3304]) -> [ABORT][135] ([Intel XE#6652])
   [134]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8768/shard-bmg-5/igt@kms_content_protection@atomic-dpms.html
   [135]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-2/igt@kms_content_protection@atomic-dpms.html

  * igt@kms_hdr@brightness-with-hdr:
    - shard-bmg:          [SKIP][136] ([Intel XE#3544]) -> [SKIP][137] ([Intel XE#3374] / [Intel XE#3544])
   [136]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8768/shard-bmg-2/igt@kms_hdr@brightness-with-hdr.html
   [137]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-7/igt@kms_hdr@brightness-with-hdr.html

  * igt@xe_fault_injection@probe-fail-guc-xe_guc_ct_send_recv:
    - shard-bmg:          [ABORT][138] ([Intel XE#5466]) -> [ABORT][139] ([Intel XE#5466] / [Intel XE#6652])
   [138]: https://intel-gfx-ci.01.org/tree/intel-xe/IGT_8768/shard-bmg-7/igt@xe_fault_injection@probe-fail-guc-xe_guc_ct_send_recv.html
   [139]: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/shard-bmg-6/igt@xe_fault_injection@probe-fail-guc-xe_guc_ct_send_recv.html

  
  [Intel XE#1124]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1124
  [Intel XE#1127]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1127
  [Intel XE#1128]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1128
  [Intel XE#1137]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1137
  [Intel XE#1178]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1178
  [Intel XE#1392]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1392
  [Intel XE#1397]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1397
  [Intel XE#1406]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1406
  [Intel XE#1407]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1407
  [Intel XE#1421]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1421
  [Intel XE#1424]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1424
  [Intel XE#1435]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1435
  [Intel XE#1439]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1439
  [Intel XE#1468]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1468
  [Intel XE#1469]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1469
  [Intel XE#1470]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1470
  [Intel XE#1489]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1489
  [Intel XE#1499]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1499
  [Intel XE#1503]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1503
  [Intel XE#1512]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1512
  [Intel XE#1745]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1745
  [Intel XE#2234]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2234
  [Intel XE#2248]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2248
  [Intel XE#2252]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2252
  [Intel XE#2284]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2284
  [Intel XE#2311]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2311
  [Intel XE#2313]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2313
  [Intel XE#2314]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2314
  [Intel XE#2321]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2321
  [Intel XE#2322]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2322
  [Intel XE#2327]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2327
  [Intel XE#2328]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2328
  [Intel XE#2390]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2390
  [Intel XE#2391]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2391
  [Intel XE#2413]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2413
  [Intel XE#2669]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2669
  [Intel XE#2763]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2763
  [Intel XE#2833]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2833
  [Intel XE#2850]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2850
  [Intel XE#2853]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2853
  [Intel XE#2887]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2887
  [Intel XE#2893]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2893
  [Intel XE#2894]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2894
  [Intel XE#306]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/306
  [Intel XE#309]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/309
  [Intel XE#3141]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3141
  [Intel XE#3157]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3157
  [Intel XE#3278]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3278
  [Intel XE#3279]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3279
  [Intel XE#3304]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3304
  [Intel XE#3374]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3374
  [Intel XE#3414]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3414
  [Intel XE#3432]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3432
  [Intel XE#352]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/352
  [Intel XE#3544]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3544
  [Intel XE#3658]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3658
  [Intel XE#366]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/366
  [Intel XE#367]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/367
  [Intel XE#373]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/373
  [Intel XE#3904]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3904
  [Intel XE#4130]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4130
  [Intel XE#4141]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4141
  [Intel XE#4273]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4273
  [Intel XE#4294]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4294
  [Intel XE#4331]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4331
  [Intel XE#4351]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4351
  [Intel XE#4354]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4354
  [Intel XE#4422]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4422
  [Intel XE#4459]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4459
  [Intel XE#4596]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4596
  [Intel XE#4608]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4608
  [Intel XE#4609]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4609
  [Intel XE#4650]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4650
  [Intel XE#4665]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4665
  [Intel XE#4692]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4692
  [Intel XE#4837]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4837
  [Intel XE#5466]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5466
  [Intel XE#5545]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5545
  [Intel XE#5993]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5993
  [Intel XE#6312]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6312
  [Intel XE#6361]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6361
  [Intel XE#6376]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6376
  [Intel XE#6503]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6503
  [Intel XE#651]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/651
  [Intel XE#6529]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6529
  [Intel XE#6540]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6540
  [Intel XE#656]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/656
  [Intel XE#6569]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6569
  [Intel XE#6599]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6599
  [Intel XE#6652]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6652
  [Intel XE#6665]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6665
  [Intel XE#6813]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6813
  [Intel XE#6819]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6819
  [Intel XE#6874]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6874
  [Intel XE#688]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/688
  [Intel XE#6886]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6886
  [Intel XE#6900]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6900
  [Intel XE#6964]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6964
  [Intel XE#6974]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6974
  [Intel XE#7059]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7059
  [Intel XE#7061]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7061
  [Intel XE#7086]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7086
  [Intel XE#7130]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7130
  [Intel XE#7136]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7136
  [Intel XE#7138]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7138
  [Intel XE#7178]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7178
  [Intel XE#7179]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7179
  [Intel XE#7283]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7283
  [Intel XE#7305]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7305
  [Intel XE#7325]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7325
  [Intel XE#7330]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7330
  [Intel XE#7331]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7331
  [Intel XE#7340]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/7340
  [Intel XE#776]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/776
  [Intel XE#836]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/836
  [Intel XE#944]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/944


Build changes
-------------

  * IGT: IGT_8768 -> IGTPW_14603

  IGTPW_14603: 18d15cf4696eeed1a1a42e326a93422d55684846 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  IGT_8768: 8768
  xe-4591-45a3045fc0dc46a893cb8bbe304afafd4120c904: 45a3045fc0dc46a893cb8bbe304afafd4120c904

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/IGTPW_14603/index.html

[-- Attachment #2: Type: text/html, Size: 52600 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH i-g-t 01/10] tools/vmtb: Update QEMU parameters
  2026-02-24  7:50 ` [PATCH i-g-t 01/10] tools/vmtb: Update QEMU parameters Adam Miszczak
@ 2026-03-10 10:22   ` Bernatowicz, Marcin
  0 siblings, 0 replies; 25+ messages in thread
From: Bernatowicz, Marcin @ 2026-03-10 10:22 UTC (permalink / raw)
  To: Adam Miszczak, igt-dev; +Cc: kamil.konieczny


On 2/24/2026 8:50 AM, Adam Miszczak wrote:
> 1. Enable SSH access to VM/Guest OS
>
> Add QEMU options to open guest SSH connection:
> - enable default emulated NIC
> - redirect host's TCP port 10000+N connections to
>    guest's SSH server on port 22
>    (where N is booted VM number, starting from 0)
>
> For example, login to VM0 (from host) as:
> $ ssh -p 10000 gta@localhost
>
> 2. Enable migration based on VFIO driver
>
> Set 'enable-migration' option introducing QEMU VF migration support.
>
> VF migration is supported by a vendor specific VFIO driver (xe-vfio-pci).
> In case of regular 'vfio-pci', QEMU command option 'enable-migration'
> should not be explicitly enabled to prevent VM start failure:
> 'vfio 0000:00:02.1: VFIO migration is not supported in kernel'
>
> 3. Disable QEMU emulated VGA card
>
> Disable standard emulated VGA on QEMU VMs to avoid issues
> emerging from a bochs DRM driver.
> Standard VGA is enumerated as PCI device BDF 00:02.0
> on minor 0 (drm/card0) - this causes troubles with VirtualMachine class
> reserving card0 for passed VF.
> Also, bochs driver obscures guest dmesg with verbose debug logs.
>
> Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
> ---
>   tools/vmtb/bench/machines/virtual/vm.py | 14 ++++++++++----
>   tools/vmtb/vmm_flows/conftest.py        | 25 +++++++++++++++----------
>   2 files changed, 25 insertions(+), 14 deletions(-)
>
> diff --git a/tools/vmtb/bench/machines/virtual/vm.py b/tools/vmtb/bench/machines/virtual/vm.py
> index e75de590d..9f4ca1de7 100644
> --- a/tools/vmtb/bench/machines/virtual/vm.py
> +++ b/tools/vmtb/bench/machines/virtual/vm.py
> @@ -1,5 +1,5 @@
>   # SPDX-License-Identifier: MIT
> -# Copyright © 2024 Intel Corporation
> +# Copyright © 2024-2026 Intel Corporation
>   
>   import base64
>   import json
> @@ -58,7 +58,8 @@ class VirtualMachine(MachineInterface):
>   
>               return timeout_wrapper
>   
> -    def __init__(self, vm_number: int, backing_image: str, driver: str, igt_config: VmtbIgtConfig) -> None:
> +    def __init__(self, vm_number: int, backing_image: str, driver: str,
> +                 igt_config: VmtbIgtConfig, vf_migration_support: bool) -> None:
>           self.vf_bdf: typing.Optional[str] = None
>           self.process: typing.Optional[subprocess.Popen] = None
>           self.vmnum: int = vm_number
> @@ -68,6 +69,7 @@ class VirtualMachine(MachineInterface):
>           self.qmp_sockpath = posixpath.join('/tmp', f'mon{self.vmnum}.sock')
>           self.drm_driver_name: str = driver
>           self.igt_config: VmtbIgtConfig = igt_config
> +        self.vf_migration: bool = vf_migration_support
>   
>           if not posixpath.exists(backing_image):
>               logger.error('No image for VM%s', self.vmnum)
> @@ -153,6 +155,9 @@ class VirtualMachine(MachineInterface):
>                      '-vnc', f':{self.vmnum}',
>                      '-serial', 'stdio',
>                      '-m', '4096',
> +                   '-vga', 'none',
> +                   '-net', 'nic',
> +                   '-net', f'user,hostfwd=tcp::{10000 + self.vmnum}-:22',
>                      '-drive', f'file={self.image if not self.migrate_destination_vm else self.migrate_source_image}',
>                      '-chardev', f'socket,path={self.questagent_sockpath},server=on,wait=off,id=qga{self.vmnum}',
>                      '-device', 'virtio-serial',
> @@ -161,8 +166,9 @@ class VirtualMachine(MachineInterface):
>                      '-mon', f'chardev=mon{self.vmnum},mode=control']
>   
>           if self.vf_bdf:
> -            command.extend(['-enable-kvm', '-cpu', 'host'])
> -            command.extend(['-device', f'vfio-pci,host={self.vf_bdf},enable-migration=on'])
> +            command.extend(['-enable-kvm', '-cpu', 'host', '-device', f'vfio-pci,host={self.vf_bdf}'])
> +            if self.vf_migration:
> +                command[-1] += ',enable-migration=on'
>   
>           if self.migrate_destination_vm:
>               # If VM is migration destination - run in stopped/prelaunch state (explicit resume required)
> diff --git a/tools/vmtb/vmm_flows/conftest.py b/tools/vmtb/vmm_flows/conftest.py
> index 7b6eacd51..675312253 100644
> --- a/tools/vmtb/vmm_flows/conftest.py
> +++ b/tools/vmtb/vmm_flows/conftest.py
> @@ -1,26 +1,25 @@
>   # SPDX-License-Identifier: MIT
> -# Copyright © 2024 Intel Corporation
> +# Copyright © 2024-2026 Intel Corporation
>   
>   import json
>   import logging
>   import re
>   import typing
> -
>   from dataclasses import dataclass
>   from pathlib import Path
>   
>   import pytest
>   
>   from bench import exceptions
> -from bench.helpers.helpers import (modprobe_driver, modprobe_driver_check)
> -from bench.helpers.log import HOST_DMESG_FILE
> -from bench.configurators.vgpu_profile_config import VgpuProfileConfigurator, VfSchedulingMode
>   from bench.configurators.vgpu_profile import VgpuProfile
> +from bench.configurators.vgpu_profile_config import (VfSchedulingMode,
> +                                                     VgpuProfileConfigurator)
>   from bench.configurators.vmtb_config import VmtbConfigurator
> -from bench.machines.host import Host, Device
> +from bench.helpers.helpers import modprobe_driver, modprobe_driver_check
> +from bench.helpers.log import HOST_DMESG_FILE
> +from bench.machines.host import Device, Host
>   from bench.machines.virtual.vm import VirtualMachine
>   
> -
>   logger = logging.getLogger('Conftest')
>   
>   
> @@ -89,15 +88,20 @@ class VmmTestingSetup:
>           self.host.load_drivers()
>           self.host.discover_devices()
>   
> +        # VF migration requires vendor specific VFIO driver (e.g. xe-vfio-pci)
> +        vf_migration_support: bool = self.host.is_driver_loaded(f'{self.host.drm_driver_name}-vfio-pci')
> +
>           logger.info("\nDUT info:"
>                       "\n\tCard index: %s"
>                       "\n\tPCI BDF: %s "
>                       "\n\tDevice ID: %s (%s)"
> -                    "\n\tHost DRM driver: %s",
> +                    "\n\tHost DRM driver: %s"
> +                    "\n\tVF migration support: %s",
>                       self.host.dut_index,
>                       self.get_dut().pci_info.bdf,
>                       self.get_dut().pci_info.devid, self.get_dut().gpu_model,
> -                    self.get_dut().driver.get_name())
> +                    self.get_dut().driver.get_name(),
> +                    vf_migration_support)
>   
>           self.vgpu_profile: VgpuProfile = self.get_vgpu_profile()
>   
> @@ -105,7 +109,8 @@ class VmmTestingSetup:
>           self.vms: typing.List[VirtualMachine] = [
>               VirtualMachine(vm_idx, self.guest_os_image,
>                              vmtb_config.get_guest_config().driver,
> -                           vmtb_config.get_guest_config().igt_config)
> +                           vmtb_config.get_guest_config().igt_config,
> +                           vf_migration_support)
>               for vm_idx in range(min(self.vgpu_profile.num_vfs, self.testing_config.max_num_vms))]
LGTM,
Reviewed-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
>   
>       def get_vgpu_profile(self) -> VgpuProfile:

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH i-g-t 02/10] tools/vmtb: Fix DUT selection based on card index
  2026-02-24  7:50 ` [PATCH i-g-t 02/10] tools/vmtb: Fix DUT selection based on card index Adam Miszczak
@ 2026-03-10 10:26   ` Bernatowicz, Marcin
  0 siblings, 0 replies; 25+ messages in thread
From: Bernatowicz, Marcin @ 2026-03-10 10:26 UTC (permalink / raw)
  To: Adam Miszczak, igt-dev; +Cc: kamil.konieczny


On 2/24/2026 8:50 AM, Adam Miszczak wrote:
> A GPU devices list need to be searched by requested card index
> (device minor number) - not list index.
> Implement Host.get_device() function to return Device
> with a given minor number from the detected devices list,
> bound to a requested DRM driver (e.g. xe).
> DUT reference is now kept by the VmmTestingSetup,
> not embedded within Host class.
>
> Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
> ---
>   tools/vmtb/bench/machines/host.py            | 12 +++++++-----
>   tools/vmtb/bench/machines/physical/device.py |  5 ++++-
>   tools/vmtb/vmm_flows/conftest.py             | 15 ++++++++-------
>   tools/vmtb/vmm_flows/test_basic.py           |  4 ++--
>   4 files changed, 21 insertions(+), 15 deletions(-)
>
> diff --git a/tools/vmtb/bench/machines/host.py b/tools/vmtb/bench/machines/host.py
> index 666f35c26..aecc7709a 100644
> --- a/tools/vmtb/bench/machines/host.py
> +++ b/tools/vmtb/bench/machines/host.py
> @@ -1,8 +1,7 @@
>   # SPDX-License-Identifier: MIT
> -# Copyright © 2024 Intel Corporation
> +# Copyright © 2024-2026 Intel Corporation
>   
>   import logging
> -import re
>   import shlex
>   import signal
>   import subprocess
> @@ -24,13 +23,12 @@ class Host(MachineInterface):
>       def __init__(self) -> None:
>           self.running_procs: typing.Dict[int, subprocess.Popen] = {}
>           self.gpu_devices: typing.List[Device] = []
> -        self.dut_index: int = 0
>           # Initialize in conftest/VmmTestingSetup:
>           self.drm_driver_name: str
>           self.igt_config: VmtbIgtConfig
>   
>       def __str__(self) -> str:
> -        return f'Host-{self.gpu_devices[self.dut_index].pci_info.bdf}'
> +        return 'Host'
>   
>       @LogDecorators.parse_kmsg
>       def execute(self, command: str) -> int:
> @@ -181,9 +179,13 @@ class Host(MachineInterface):
>   
>           logger.debug("Detected GPU PCI device(s):")
>           for dev in self.gpu_devices:
> -            logger.debug("[%s] PCI BDF: %s / DevID: %s (%s)",
> +            logger.debug("[card%s] PCI BDF: %s / DevID: %s (%s)",
>                             dev.pci_info.minor_number, dev.pci_info.bdf, dev.pci_info.devid, dev.gpu_model)
>   
> +    def get_device(self, dev_minor: int) -> typing.Optional[Device]:
> +        """Find device with a given minor number within detected GPU devices list."""
> +        return next((dev for dev in self.gpu_devices if dev.pci_info.minor_number == dev_minor), None)
> +
>       def suspend(self, mode: SuspendMode = SuspendMode.ACPI_S3) -> None:
>           """Perform host suspend cycle (ACPI S3) via rtcwake tool."""
>           wakeup_delay = 10 # wakeup timer in seconds
> diff --git a/tools/vmtb/bench/machines/physical/device.py b/tools/vmtb/bench/machines/physical/device.py
> index 12a5d5f7d..887f607e4 100644
> --- a/tools/vmtb/bench/machines/physical/device.py
> +++ b/tools/vmtb/bench/machines/physical/device.py
> @@ -1,5 +1,5 @@
>   # SPDX-License-Identifier: MIT
> -# Copyright © 2024 Intel Corporation
> +# Copyright © 2024-2026 Intel Corporation
>   
>   import importlib
>   import logging
> @@ -48,6 +48,9 @@ class Device(DeviceInterface):
>           self.gpu_model: str = pci.get_gpu_model(self.pci_info.devid)
>           self.driver: DriverInterface = self.instantiate_driver(driver, self.pci_info.minor_number)
>   
> +    def __str__(self) -> str:
> +        return f'Dev-{self.pci_info.bdf}'
> +
>       def instantiate_driver(self, driver_name: str, card_index: int) -> Any:
>           module_name = f'bench.drivers.{driver_name}'
>           class_name = f'{driver_name.capitalize()}Driver'
> diff --git a/tools/vmtb/vmm_flows/conftest.py b/tools/vmtb/vmm_flows/conftest.py
> index 675312253..3bfac01c4 100644
> --- a/tools/vmtb/vmm_flows/conftest.py
> +++ b/tools/vmtb/vmm_flows/conftest.py
> @@ -81,12 +81,12 @@ class VmmTestingSetup:
>   
>           self.vgpu_profiles_dir = vmtb_config.vmtb_config_file.parent / vmtb_config.config.vgpu_profiles_path
>   
> -        self.host.dut_index = self.dut_index
>           self.host.drm_driver_name = vmtb_config.get_host_config().driver
>           self.host.igt_config = vmtb_config.get_host_config().igt_config
>   
>           self.host.load_drivers()
>           self.host.discover_devices()
> +        self.dut: Device = self.host.get_device(self.dut_index)
>   
>           # VF migration requires vendor specific VFIO driver (e.g. xe-vfio-pci)
>           vf_migration_support: bool = self.host.is_driver_loaded(f'{self.host.drm_driver_name}-vfio-pci')
> @@ -97,7 +97,7 @@ class VmmTestingSetup:
>                       "\n\tDevice ID: %s (%s)"
>                       "\n\tHost DRM driver: %s"
>                       "\n\tVF migration support: %s",
> -                    self.host.dut_index,
> +                    self.dut_index,
>                       self.get_dut().pci_info.bdf,
>                       self.get_dut().pci_info.devid, self.get_dut().gpu_model,
>                       self.get_dut().driver.get_name(),
> @@ -127,11 +127,12 @@ class VmmTestingSetup:
>           return vgpu_profile
>   
>       def get_dut(self) -> Device:
> -        try:
> -            return self.host.gpu_devices[self.dut_index]
> -        except IndexError as exc:
> -            logger.error("Invalid VMTB config - device card index = %s not available", self.dut_index)
> -            raise exceptions.VmtbConfigError(f'Device card index = {self.dut_index} not available') from exc
> +        if self.dut is None:
> +            logger.error("Invalid VMTB config - DRM card%s is not bound to %s driver",
> +                         self.dut_index, self.host.drm_driver_name)
> +            raise exceptions.VmtbConfigError(f'Invalid VMTB config - DRM card{self.dut_index} device not supported')
> +
> +        return self.dut
>   
>       @property
>       def get_vm(self):
> diff --git a/tools/vmtb/vmm_flows/test_basic.py b/tools/vmtb/vmm_flows/test_basic.py
> index 100be7652..1d3a68b36 100644
> --- a/tools/vmtb/vmm_flows/test_basic.py
> +++ b/tools/vmtb/vmm_flows/test_basic.py
> @@ -1,5 +1,5 @@
>   # SPDX-License-Identifier: MIT
> -# Copyright © 2024 Intel Corporation
> +# Copyright © 2024-2026 Intel Corporation
>   
>   import logging
>   import time
> @@ -82,7 +82,7 @@ class TestVmWorkload:
>               logger.info("[%s] Verify result of basic WL", igt.target)
>               assert igt_check(igt)
>   
> -        logger.info("[%s] Verify result of basic WL", ts.host)
> +        logger.info("[Host %s] Verify result of basic WL", ts.get_dut())
LGTM,
Reviewed-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
>           igt_run_check(ts.host, IgtType.EXEC_STORE)
>   
>       def test_wsim(self, setup_vms):

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH i-g-t 03/10] tools/vmtb: Fix VM snapshot query handling
  2026-02-24  7:50 ` [PATCH i-g-t 03/10] tools/vmtb: Fix VM snapshot query handling Adam Miszczak
@ 2026-03-10 10:29   ` Bernatowicz, Marcin
  0 siblings, 0 replies; 25+ messages in thread
From: Bernatowicz, Marcin @ 2026-03-10 10:29 UTC (permalink / raw)
  To: Adam Miszczak, igt-dev; +Cc: kamil.konieczny


On 2/24/2026 8:50 AM, Adam Miszczak wrote:
> QMP command 'query-named-block-nodes' is used to select a block device
> for saving VM snapshot (QMP 'snapshot-save').
>
> Add polling for the command's return message in QMP response queue.
> It sporadically happened that unsolicited QMP message like:
> [QMP RSP] <- {"timestamp": {...}, "event": "RTC_CHANGE" ...}
> was falsely taken as a response to previously submitted
> QMP 'query-named-block-nodes' command.
> Hence, no 'block device node' argument is passed to
> 'snapshot-load' command which leads to migration tests fail.
> Also, add a condition to check if a given block node
> is writable (not read-only).
>
> Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
> ---
>   .../machines/virtual/backends/qmp_monitor.py  | 25 ++++++++++---------
>   1 file changed, 13 insertions(+), 12 deletions(-)
>
> diff --git a/tools/vmtb/bench/machines/virtual/backends/qmp_monitor.py b/tools/vmtb/bench/machines/virtual/backends/qmp_monitor.py
> index ef3c8aa1c..d364a5711 100644
> --- a/tools/vmtb/bench/machines/virtual/backends/qmp_monitor.py
> +++ b/tools/vmtb/bench/machines/virtual/backends/qmp_monitor.py
> @@ -1,5 +1,5 @@
>   # SPDX-License-Identifier: MIT
> -# Copyright © 2024 Intel Corporation
> +# Copyright © 2024-2026 Intel Corporation
>   
>   import json
>   import logging
> @@ -123,17 +123,18 @@ class QmpMonitor():
>           ret: typing.Dict = {}
>   
>           qmp_msg = self.qmp_queue.get()
> -        # logger.debug('[QMP RSP Queue] -> %s', qmp_msg)
> -        if 'return' in qmp_msg:
> -            ret = qmp_msg.get('return')
> -            for block in ret:
> -                if block.get('drv') == 'qcow2':
> -                    node_name = block.get('node-name')
> -                    # Get the most recent state snapshot from the snapshots list:
> -                    snapshots = block.get('image').get('snapshots')
> -                    if snapshots:
> -                        snapshot_tag = snapshots[-1].get('name')
> -                    break
> +        while 'return' not in qmp_msg:
> +            qmp_msg = self.qmp_queue.get()
> +
> +        ret = qmp_msg.get('return')
> +        for block in ret:
> +            if block.get('drv') == 'qcow2' and block.get('ro') is False:
> +                node_name = block.get('node-name')
> +                # Get the most recent state snapshot from the snapshots list:
> +                snapshots = block.get('image').get('snapshots')
> +                if snapshots:
> +                    snapshot_tag = snapshots[-1].get('name')
> +                break
LGTM,
Reviewed-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
>   
>           return (node_name, snapshot_tag)
>   

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH i-g-t 04/10] tools/vmtb: Extend IGT and WSIM abstractions
  2026-02-24  7:50 ` [PATCH i-g-t 04/10] tools/vmtb: Extend IGT and WSIM abstractions Adam Miszczak
@ 2026-03-10 10:36   ` Bernatowicz, Marcin
  0 siblings, 0 replies; 25+ messages in thread
From: Bernatowicz, Marcin @ 2026-03-10 10:36 UTC (permalink / raw)
  To: Adam Miszczak, igt-dev; +Cc: kamil.konieczny


On 2/24/2026 8:50 AM, Adam Miszczak wrote:
> Introduce few improvements to IGT and gem_wsim executors:
>
> 1. Add gem_wsim workload descriptor resources config
> In order to place workload files in a common resources directory,
> extend VMTB config with a relevant entry and read the path in a conftest.
>
> Implement capability for device specific workload files in wsim resources
> directory (as different GPU devices may have various sets of engines).
> Wsim device specific path format looks as follows:
> [vmtb_root_path]/vmm_flows/resources/wsim/[device_name_abbr]/[wl_desc].wsim
> e.g.:
> - resources/wsim/ptl/wl.wsim
> - resources/wsim/bmg/wl.wsim
>
> 2. Support gem_wsim workload files on VM
> So far GemWsim was initialized with a simple string workload descriptor
> passed with '-w <workload>' option.
> However, multiple complex workloads are expected for a busy VF migration
> scenarios - therefore it would be handy to define it as workload files.
> Gem_wsim input files will be deployed as VMTB resources on a host,
> whereas we want to execute it on VM as well.
> Hence, content of the wsim workload file is copied to /tmp on a guest/host
> and executed from that location.
> In case of the host, original (resources) location will work
> as a wsim file input, however temp file is still used for simplicity
> and consistency (to avoid instance type checks).
>
> 3. Add IGT and WSIM results check function
> Extend IgtExecutor and GemWsim with new check_results() method to allow
> object-oriented approach for checking IGT/WSIM results and unify interfaces.
> Existing helper - igt_check(IgtExecutor) is still supported,
> but IgtExecutor.check_results() is now preferred.
> Also, implement IgtExecutor's is_running() (similarly to GemWsim)
> and keep the process state (ProcessResult).
>
> Introduced change simplifies supporting both IGT and gem_wsim workloads
> in busy migration tests.
>
> 4. Support IGT tests repeated execution
> Few planned VF busy migration scenarios require executing short IGT tests
> in a longer time slot (in a loop).
> To achieve it, allow IgtExecutor to accept expected number of IGT test
> repeats and reflect it in a testlist passed to the igt_runner
> (multiply requested test entries).
>
> By default, IgtExecutor's 'num_repeats' input parameter is set to 1,
> so in the usual case (single IGT execution) it doesn't need to be
> explicitly provided.
>
> Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
> ---
>   tools/vmtb/bench/configurators/vmtb_config.py |  4 +-
>   tools/vmtb/bench/executors/gem_wsim.py        | 45 +++++++++++++++----
>   tools/vmtb/bench/executors/igt.py             | 36 ++++++++++++---
>   tools/vmtb/bench/machines/physical/device.py  |  2 +-
>   tools/vmtb/vmm_flows/conftest.py              |  8 +++-
>   tools/vmtb/vmtb_config.json                   |  1 +
>   6 files changed, 78 insertions(+), 18 deletions(-)
>
> diff --git a/tools/vmtb/bench/configurators/vmtb_config.py b/tools/vmtb/bench/configurators/vmtb_config.py
> index 49dde4589..8fd2b87d5 100644
> --- a/tools/vmtb/bench/configurators/vmtb_config.py
> +++ b/tools/vmtb/bench/configurators/vmtb_config.py
> @@ -1,5 +1,5 @@
>   # SPDX-License-Identifier: MIT
> -# Copyright © 2024 Intel Corporation
> +# Copyright © 2024-2026 Intel Corporation
>   
>   import json
>   import logging
> @@ -40,6 +40,7 @@ class VmtbConfig:
>       host_config: VmtbHostConfig
>       guest_config: VmtbGuestConfig
>       vgpu_profiles_path: str
> +    wsim_wl_path: str
>       guc_ver_path: str
>       ci_host_dmesg_file: str
>   
> @@ -104,6 +105,7 @@ class VmtbConfigJsonReader:
>               host_config=vmtb_host_config,
>               guest_config=vmtb_guest_config,
>               vgpu_profiles_path=config_json['resources']['vgpu_profiles_path'],
> +            wsim_wl_path=config_json['resources']['wsim_wl_path'],
>               guc_ver_path=config_json['resources']['guc_ver_path'],
>               ci_host_dmesg_file=config_json['ci']['host_dmesg_file'])
>   
> diff --git a/tools/vmtb/bench/executors/gem_wsim.py b/tools/vmtb/bench/executors/gem_wsim.py
> index 46fa2291c..0cdfcc7e4 100644
> --- a/tools/vmtb/bench/executors/gem_wsim.py
> +++ b/tools/vmtb/bench/executors/gem_wsim.py
> @@ -1,9 +1,10 @@
>   # SPDX-License-Identifier: MIT
> -# Copyright © 2024 Intel Corporation
> +# Copyright © 2024-2026 Intel Corporation
>   
>   import logging
>   import re
>   import typing
> +from pathlib import Path
>   
>   from bench import exceptions
>   from bench.executors.shell import ShellExecutor
> @@ -23,13 +24,28 @@ PREEMPT_10MS_WORKLOAD = (f'1.DEFAULT.{int(ONE_CYCLE_DURATION_MS * 1000 / 2)}.0.0
>   NON_PREEMPT_10MS_WORKLOAD = f'X.1.0,X.2.0,{PREEMPT_10MS_WORKLOAD}'
>   
>   class GemWsim(ShellExecutor):
> -    def __init__(self, machine: MachineInterface, num_clients: int = 1, num_repeats: int = 1,
> -                 workload: str = PREEMPT_10MS_WORKLOAD, timeout: int = DEFAULT_TIMEOUT) -> None:
> -        super().__init__(
> -            machine,
> -            f'/usr/local/libexec/igt-gpu-tools/benchmarks/gem_wsim -w {workload} -c {num_clients} -r {num_repeats}',
> -            timeout)
> -        self.machine_id = str(machine)
> +    def __init__(self, target: MachineInterface,
> +                 num_clients: int = 1,
> +                 num_repeats: int = 1,
> +                 workload: str = PREEMPT_10MS_WORKLOAD,
> +                 timeout: int = DEFAULT_TIMEOUT) -> None:
> +
> +        self.machine_id = str(target)
> +        wl_file_path = Path(workload)
> +
> +        if wl_file_path.is_file():
> +            # Copy workload descriptor from the source host file
> +            # to the requested target machine (VM or host)
> +            workload = '/tmp/igt_workload.wsim'
> +            wl_desc = wl_file_path.read_text(encoding='utf-8')
> +            target.write_file_content(workload, wl_desc)
> +
> +            logger.debug("IGT/wsim workload descriptor:\n%s", wl_desc)
> +
> +        wsim_path = Path(target.get_igt_config().test_dir) / 'benchmarks' / 'gem_wsim'
> +        command = f'{wsim_path} -w {workload} -c {num_clients} -r {num_repeats}'
> +
> +        super().__init__(target, command, timeout)
>   
>       def __str__(self) -> str:
>           return f'gem_wsim({self.machine_id}:{self.pid})'
> @@ -49,6 +65,19 @@ class GemWsim(ShellExecutor):
>           raise exceptions.GemWsimError(f'{self}: exit_code: {proc_result.exit_code}'
>                                         f' stdout: {proc_result.stdout} stderr: {proc_result.stderr}')
>   
> +    def check_results(self) -> bool:
> +        """Verify gem_wsim execution results. Return True for workload success, False on fail."""
> +        # TODO: support also checking wsim workload: 'Verify Xe spinner batch completion'
> +        try:
> +            wl_results: GemWsimResult = self.wait_results()
> +        except exceptions.GemWsimError as exc:
> +            logger.error("[%s] WSIM failed: %s", self.target, exc)
> +            return False
> +
> +        logger.debug("[%s] WSIM passed in %ss (%s WL/s)",
> +                      self.target, wl_results.elapsed_sec, wl_results.workloads_per_sec)
> +        return True
> +
>   
>   def gem_wsim_parallel_exec_and_check(vms: typing.List[MachineInterface], workload: str, iterations: int,
>                                        expected: typing.Optional[GemWsimResult] = None) -> GemWsimResult:
> diff --git a/tools/vmtb/bench/executors/igt.py b/tools/vmtb/bench/executors/igt.py
> index 4296464c2..a08f71d54 100644
> --- a/tools/vmtb/bench/executors/igt.py
> +++ b/tools/vmtb/bench/executors/igt.py
> @@ -1,5 +1,5 @@
>   # SPDX-License-Identifier: MIT
> -# Copyright © 2024 Intel Corporation
> +# Copyright © 2024-2026 Intel Corporation
>   
>   import enum
>   import json
> @@ -34,6 +34,7 @@ igt_tests: typing.Dict[IgtType, typing.Tuple[str, str]] = {
>   class IgtExecutor(ExecutorInterface):
>       def __init__(self, target: MachineInterface,
>                    test: typing.Union[str, IgtType],
> +                 num_repeats: int = 1,
>                    timeout: int = DEFAULT_TIMEOUT) -> None:
>           self.igt_config = target.get_igt_config()
>   
> @@ -46,18 +47,25 @@ class IgtExecutor(ExecutorInterface):
>           self.results: typing.Dict[str, typing.Any] = {}
>           self.target: MachineInterface = target
>           self.igt: str = test if isinstance(test, str) else self.select_igt_variant(target.get_drm_driver_name(), test)
> -        self.target.write_file_content(testlist, self.igt)
> -        self.timeout: int = timeout
>   
>           logger.info("[%s] Execute IGT test: %s", target, self.igt)
> +        if num_repeats > 1:
> +            logger.debug("Repeat IGT execution %s times", num_repeats)
> +            self.igt = (self.igt + '\n') * num_repeats
> +
> +        self.target.write_file_content(testlist, self.igt)
> +        self.timeout: int = timeout
> +        self.proc_result = ProcessResult()
>           self.pid: int = self.target.execute(command)
>   
>       # Executor interface implementation
>       def status(self) -> ProcessResult:
> -        return self.target.execute_status(self.pid)
> +        self.proc_result = self.target.execute_status(self.pid)
> +        return self.proc_result
>   
>       def wait(self) -> ProcessResult:
> -        return self.target.execute_wait(self.pid, self.timeout)
> +        self.proc_result = self.target.execute_wait(self.pid, self.timeout)
> +        return self.proc_result
>   
>       def sendsig(self, sig: signal.Signals) -> None:
>           self.target.execute_signal(self.pid, sig)
> @@ -69,9 +77,25 @@ class IgtExecutor(ExecutorInterface):
>           self.sendsig(signal.SIGKILL)
>   
>       # IGT specific methods
> +    def is_running(self) -> bool:
> +        return not self.status().exited
> +
> +    def check_results(self) -> bool:
> +        """Verify IGT test results. Return True for test success, False on fail."""
> +        if not self.proc_result.exited:
> +            self.proc_result = self.wait()
> +
> +        if self.proc_result.exit_code == 0 and self.did_pass():
> +            logger.debug("[%s] IGT passed", self.target)
> +            return True
> +
> +        logger.error("[%s] IGT failed: %s", self.target, self.proc_result)
> +        return False
> +
>       def get_results_log(self) -> typing.Dict:
>           # Results are cached
>           if self.results:
> +            logger.debug("Get available IGT results from cache")
>               return self.results
>           path = posixpath.join(self.igt_config.result_dir, 'results.json')
>           result = self.target.read_file_content(path)
> @@ -95,7 +119,7 @@ class IgtExecutor(ExecutorInterface):
>                   continue
>               fail_case = fail_case + aggregate[key]
>   
> -        logger.debug('Full IGT test results:\n%s', json.dumps(results, indent=4))
> +        logger.debug("[%s] Full IGT test results:\n%s", self.target, json.dumps(results, indent=4))
>   
>           if fail_case > 0:
>               logger.error('Test failed!')
> diff --git a/tools/vmtb/bench/machines/physical/device.py b/tools/vmtb/bench/machines/physical/device.py
> index 887f607e4..a487c0e5f 100644
> --- a/tools/vmtb/bench/machines/physical/device.py
> +++ b/tools/vmtb/bench/machines/physical/device.py
> @@ -45,7 +45,7 @@ class Device(DeviceInterface):
>   
>       def __init__(self, bdf: str, driver: str) -> None:
>           self.pci_info = self.PciInfo(bdf)
> -        self.gpu_model: str = pci.get_gpu_model(self.pci_info.devid)
> +        self.gpu_model = pci.get_gpu_model(self.pci_info.devid)
>           self.driver: DriverInterface = self.instantiate_driver(driver, self.pci_info.minor_number)
>   
>       def __str__(self) -> str:
> diff --git a/tools/vmtb/vmm_flows/conftest.py b/tools/vmtb/vmm_flows/conftest.py
> index 3bfac01c4..28c0b5f00 100644
> --- a/tools/vmtb/vmm_flows/conftest.py
> +++ b/tools/vmtb/vmm_flows/conftest.py
> @@ -79,8 +79,6 @@ class VmmTestingSetup:
>           self.guest_os_image = vmtb_config.get_guest_config().os_image_path if cmdline_config['vm_image'] is None \
>                            else cmdline_config['vm_image']
>   
> -        self.vgpu_profiles_dir = vmtb_config.vmtb_config_file.parent / vmtb_config.config.vgpu_profiles_path
> -
>           self.host.drm_driver_name = vmtb_config.get_host_config().driver
>           self.host.igt_config = vmtb_config.get_host_config().igt_config
>   
> @@ -103,6 +101,12 @@ class VmmTestingSetup:
>                       self.get_dut().driver.get_name(),
>                       vf_migration_support)
>   
> +        vmtb_root_path = vmtb_config.vmtb_config_file.parent
> +        self.vgpu_profiles_dir = vmtb_root_path / vmtb_config.config.vgpu_profiles_path
> +        # Device specific wsim descriptors directory path, e.g.:
> +        # [vmtb_root]/vmm_flows/resources/wsim/ptl (last subdir is lowercase key/name from pci.GpuModel class)
> +        self.wsim_wl_dir = vmtb_root_path / vmtb_config.config.wsim_wl_path / self.get_dut().gpu_model.name.lower()
> +
>           self.vgpu_profile: VgpuProfile = self.get_vgpu_profile()
>   
>           # Start maximum requested number of VMs, but not more than VFs supported by the given vGPU profile
> diff --git a/tools/vmtb/vmtb_config.json b/tools/vmtb/vmtb_config.json
> index 640a64123..2b8fb43f3 100644
> --- a/tools/vmtb/vmtb_config.json
> +++ b/tools/vmtb/vmtb_config.json
> @@ -23,6 +23,7 @@
>       },
>       "resources": {
>           "vgpu_profiles_path": "vmm_flows/resources/vgpu_profiles",
> +        "wsim_wl_path": "vmm_flows/resources/wsim",
LGTM,
Reviewed-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
>           "guc_ver_path": "vmm_flows/resources/guc"
>       },
>       "ci": {

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH i-g-t 05/10] tools/vmtb: VF auto/fair provisioning support
  2026-02-24  7:50 ` [PATCH i-g-t 05/10] tools/vmtb: VF auto/fair provisioning support Adam Miszczak
@ 2026-03-10 10:38   ` Bernatowicz, Marcin
  0 siblings, 0 replies; 25+ messages in thread
From: Bernatowicz, Marcin @ 2026-03-10 10:38 UTC (permalink / raw)
  To: Adam Miszczak, igt-dev; +Cc: kamil.konieczny


On 2/24/2026 8:50 AM, Adam Miszczak wrote:
> Currently test variants allow provisioning with vGPU profiles only,
> however, xe KMD supports also fair resources allocation (auto-provisioning).
> Therefore, the following provisioning modes shall be supported from now:
> - vGPU profile: both PF/VF resources and scheduling (via debugfs)
> - fair/auto provisioning (driver defaults for resources and scheduling)
> - fair/auto resources provisioning with concrete scheduling profile
>
> Test variants are now specified as a list of 3-element tuples:
>     test_variants_N = [(num_of_vfs, VfProvisioningMode.X, VfSchedulingMode.Y), ...]
> Test ID printed in the following format:
>     test_name[NxVF-(P:provisioning_mode S:scheduling_mode)]
>
> Additional changes:
> - align parametrized tests with the new variants format
> - use Device methods: set_resources and set_scheduling
>    for relevant provisioning modes
> - split vGPU profile printing to resources and scheduler part
> - fix PF lmem_spare getter/setter to check for LMEM presence
> - detect standalone media GT for proper VF provisioning
>
> Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
> ---
>   .../vmtb/bench/configurators/vgpu_profile.py  | 37 +++++---
>   .../configurators/vgpu_profile_config.py      |  7 +-
>   tools/vmtb/bench/drivers/driver_interface.py  |  6 +-
>   tools/vmtb/bench/drivers/xe.py                | 16 +++-
>   tools/vmtb/bench/machines/physical/device.py  | 58 +++++++-----
>   tools/vmtb/vmm_flows/conftest.py              | 89 ++++++++++++++-----
>   tools/vmtb/vmm_flows/test_basic.py            | 21 +++--
>   7 files changed, 164 insertions(+), 70 deletions(-)
>
> diff --git a/tools/vmtb/bench/configurators/vgpu_profile.py b/tools/vmtb/bench/configurators/vgpu_profile.py
> index 7c536c1d0..c680fdb83 100644
> --- a/tools/vmtb/bench/configurators/vgpu_profile.py
> +++ b/tools/vmtb/bench/configurators/vgpu_profile.py
> @@ -1,5 +1,5 @@
>   # SPDX-License-Identifier: MIT
> -# Copyright © 2024 Intel Corporation
> +# Copyright © 2024-2026 Intel Corporation
>   
>   import json
>   import logging
> @@ -55,8 +55,19 @@ class VgpuProfile:
>       def print_parameters(self) -> None:
>           logger.info(
>               "\nvGPU Profile:\n"
> -            "   Num VFs = %s\n"
> -            "\nResources:\n"
> +            "   Num VFs = %s\n",
> +            self.num_vfs)
> +        self.print_resources_config()
> +        self.print_scheduler_config()
> +        logger.info(
> +            "\nSecurity:\n"
> +            "   Reset After Vf Switch = %s\n",
> +            self.security.reset_after_vf_switch
> +        )
> +
> +    def print_resources_config(self) -> None:
> +        logger.info(
> +            "\nResources config:\n"
>               "   PF:\n"
>               "\tLMEM = %s B\n"
>               "\tContexts = %s\n"
> @@ -66,24 +77,24 @@ class VgpuProfile:
>               "\tLMEM = %s B\n"
>               "\tContexts = %s\n"
>               "\tDoorbells = %s\n"
> -            "\tGGTT = %s B\n"
> -            "\nScheduling:\n"
> +            "\tGGTT = %s B\n",
> +            self.resources.pfLmem, self.resources.pfContexts, self.resources.pfDoorbells, self.resources.pfGgtt,
> +            self.resources.vfLmem, self.resources.vfContexts, self.resources.vfDoorbells, self.resources.vfGgtt,
> +        )
> +
> +    def print_scheduler_config(self) -> None:
> +        logger.info(
> +            "\nScheduling config:\n"
>               "   Schedule If Idle = %s\n"
>               "   PF:\n"
>               "\tExecution Quanta = %s ms\n"
>               "\tPreemption Timeout = %s us\n"
>               "   VF:\n"
>               "\tExecution Quanta = %s ms\n"
> -            "\tPreemption Timeout = %s us\n"
> -            "\nSecurity:\n"
> -            "   Reset After Vf Switch = %s\n",
> -            self.num_vfs,
> -            self.resources.pfLmem, self.resources.pfContexts, self.resources.pfDoorbells, self.resources.pfGgtt,
> -            self.resources.vfLmem, self.resources.vfContexts, self.resources.vfDoorbells, self.resources.vfGgtt,
> +            "\tPreemption Timeout = %s us\n",
>               self.scheduler.scheduleIfIdle,
>               self.scheduler.pfExecutionQuanta, self.scheduler.pfPreemptionTimeout,
> -            self.scheduler.vfExecutionQuanta, self.scheduler.vfPreemptionTimeout,
> -            self.security.reset_after_vf_switch
> +            self.scheduler.vfExecutionQuanta, self.scheduler.vfPreemptionTimeout
>           )
>   
>   
> diff --git a/tools/vmtb/bench/configurators/vgpu_profile_config.py b/tools/vmtb/bench/configurators/vgpu_profile_config.py
> index 915cfb2b8..4bddb641e 100644
> --- a/tools/vmtb/bench/configurators/vgpu_profile_config.py
> +++ b/tools/vmtb/bench/configurators/vgpu_profile_config.py
> @@ -1,5 +1,5 @@
>   # SPDX-License-Identifier: MIT
> -# Copyright © 2024 Intel Corporation
> +# Copyright © 2024-2026 Intel Corporation
>   
>   import logging
>   from enum import Enum
> @@ -17,6 +17,11 @@ from bench.configurators.vgpu_profile import (VgpuProfile,
>   logger = logging.getLogger('DeviceConfigurator')
>   
>   
> +class VfProvisioningMode(Enum):
> +    VGPU_PROFILE = 0
> +    AUTO = 1
> +
> +
>   class VfSchedulingMode(str, Enum):
>       INFINITE = 'Infinite' # Infinite EQ/PT - HW default
>       DEFAULT_PROFILE = 'Default_Profile' # Default vGPU scheduler profile
> diff --git a/tools/vmtb/bench/drivers/driver_interface.py b/tools/vmtb/bench/drivers/driver_interface.py
> index af2f96837..3026fece7 100644
> --- a/tools/vmtb/bench/drivers/driver_interface.py
> +++ b/tools/vmtb/bench/drivers/driver_interface.py
> @@ -1,5 +1,5 @@
>   # SPDX-License-Identifier: MIT
> -# Copyright © 2024 Intel Corporation
> +# Copyright © 2024-2026 Intel Corporation
>   
>   import abc
>   import enum
> @@ -65,6 +65,10 @@ class DriverInterface(abc.ABC):
>       def has_lmem(self) -> bool:
>           raise NotImplementedError
>   
> +    @abc.abstractmethod
> +    def is_media_gt(self, gt_num: int) -> bool:
> +        raise NotImplementedError
> +
>       @abc.abstractmethod
>       def get_auto_provisioning(self) -> bool:
>           raise NotImplementedError
> diff --git a/tools/vmtb/bench/drivers/xe.py b/tools/vmtb/bench/drivers/xe.py
> index 009cec5be..c2b9643bb 100644
> --- a/tools/vmtb/bench/drivers/xe.py
> +++ b/tools/vmtb/bench/drivers/xe.py
> @@ -1,5 +1,5 @@
>   # SPDX-License-Identifier: MIT
> -# Copyright © 2024 Intel Corporation
> +# Copyright © 2024-2026 Intel Corporation
>   
>   import logging
>   import typing
> @@ -95,11 +95,18 @@ class XeDriver(DriverInterface):
>           path = self.debugfs_path / 'gt0' / 'pf' / 'lmem_spare'
>           return path.exists()
>   
> +    def is_media_gt(self, gt_num: int) -> bool:
> +        # XXX: is lack of PF's ggtt/lmem_spare or VF's ggtt/lmem_quota
> +        # a best way to check for standalone media GT?
> +        path = self.debugfs_path / f'gt{gt_num}' / 'pf' / 'ggtt_spare'
> +        return not path.exists()
> +
>       def get_auto_provisioning(self) -> bool:
>           raise exceptions.NotAvailableError('auto_provisioning attribute not available')
>   
>       def set_auto_provisioning(self, val: bool) -> None:
> -        raise exceptions.NotAvailableError('auto_provisioning attribute not available')
> +        # No-op - xe driver doesn't publish this attribute
> +        pass
>   
>       def cancel_work(self) -> None:
>           # Function to cancel all remaing work on GPU (for test cleanup).
> @@ -129,11 +136,12 @@ class XeDriver(DriverInterface):
>   
>       def get_pf_lmem_spare(self, gt_num: int) -> int:
>           path = self.__helper_create_debugfs_path(0, gt_num, '', 'lmem_spare')
> -        return int(self.__read_debugfs(path))
> +        return int(self.__read_debugfs(path)) if self.has_lmem() else 0
>   
>       def set_pf_lmem_spare(self, gt_num: int, val: int) -> None:
>           path = self.__helper_create_debugfs_path(0, gt_num, '', 'lmem_spare')
> -        self.__write_debugfs(path, str(val))
> +        if self.has_lmem():
> +            self.__write_debugfs(path, str(val))
>   
>       def get_pf_contexts_spare(self, gt_num: int) -> int:
>           path = self.__helper_create_debugfs_path(0, gt_num, '', 'contexts_spare')
> diff --git a/tools/vmtb/bench/machines/physical/device.py b/tools/vmtb/bench/machines/physical/device.py
> index a487c0e5f..250466733 100644
> --- a/tools/vmtb/bench/machines/physical/device.py
> +++ b/tools/vmtb/bench/machines/physical/device.py
> @@ -83,6 +83,9 @@ class Device(DeviceInterface):
>       def has_lmem(self) -> bool:
>           return self.driver.has_lmem()
>   
> +    def is_gt_media_type(self, gt_num: int) -> bool:
> +        return self.driver.is_media_gt(gt_num)
> +
>       def create_vf(self, num: int) -> int:
>           """Enable a requested number of VFs.
>           Disable SRIOV drivers autoprobe to allow VFIO driver override for VFs.
> @@ -156,37 +159,44 @@ class Device(DeviceInterface):
>           bdf_list = [self.get_vf_bdf(vf) for vf in vf_list]
>           return bdf_list
>   
> -    def provision(self, profile: VgpuProfile) -> None:
> -        logger.info("[%s] Provision VFs - set vGPU profile for %s VFs", self.pci_info.bdf, profile.num_vfs)
> +    def __set_provisioning(self, num_vfs: int, profile: VgpuProfile, set_resources: bool) -> None:
> +        """Helper to write provisioning attributes over sysfs/debugfs for PF and requested number of VFs.
> +        If 'set_resources' parameter is True - apply the full vGPU profile (hard resources and scheduling).
> +        Otherwise, set only scheduling profile (e.g. in case of auto resources provisioning).
> +        """
> +        main_gt_nums = [gt_num for gt_num in range(self.get_num_gts()) if not self.is_gt_media_type(gt_num)]
>   
> -        num_vfs = profile.num_vfs
> -        num_gts = self.get_num_gts() # Number of tiles (GTs)
> -        gt_nums = [0] if num_gts == 1 else [0, 1] # Tile (GT) numbers/indexes
> +        logger.info("[%s] Provision %sxVFs on main GT%s", self.pci_info.bdf, num_vfs, main_gt_nums)
>   
> -        for gt_num in gt_nums:
> -            self.driver.set_pf_policy_sched_if_idle(gt_num, int(profile.scheduler.scheduleIfIdle))
> +        for gt_num in main_gt_nums:
> +            if set_resources:
> +                self.set_resources(0, gt_num, profile.resources)
> +            self.set_scheduling(0, gt_num, profile.scheduler)
>               self.driver.set_pf_policy_reset_engine(gt_num, int(profile.security.reset_after_vf_switch))
> -            self.driver.set_exec_quantum_ms(0, gt_num, profile.scheduler.pfExecutionQuanta)
> -            self.driver.set_preempt_timeout_us(0, gt_num, profile.scheduler.pfPreemptionTimeout)
> -            self.driver.set_doorbells_quota(0, gt_num, profile.resources.pfDoorbells)
> -            # PF contexts are currently assigned by the driver and cannot be reprovisioned from sysfs
>   
>           for vf_num in range(1, num_vfs + 1):
> -            if num_gts > 1 and num_vfs > 1:
> +            gt_nums = main_gt_nums
> +            if len(main_gt_nums) > 1 and num_vfs > 1:
>                   # Multi-tile device Mode 2|3 - odd VFs on GT0, even on GT1
> -                gt_nums = [0] if vf_num % 2 else [1]
> +                gt_nums = [main_gt_nums[0] if vf_num % 2 else main_gt_nums[1]]
>   
>               for gt_num in gt_nums:
> -                self.driver.set_lmem_quota(vf_num, gt_num, profile.resources.vfLmem)
> -                self.driver.set_ggtt_quota(vf_num, gt_num, profile.resources.vfGgtt)
> -                self.driver.set_contexts_quota(vf_num, gt_num, profile.resources.vfContexts)
> -                self.driver.set_doorbells_quota(vf_num, gt_num, profile.resources.vfDoorbells)
> -                self.driver.set_exec_quantum_ms(vf_num, gt_num, profile.scheduler.vfExecutionQuanta)
> -                self.driver.set_preempt_timeout_us(vf_num, gt_num, profile.scheduler.vfPreemptionTimeout)
> +                if set_resources:
> +                    self.set_resources(vf_num, gt_num, profile.resources)
> +                self.set_scheduling(vf_num, gt_num, profile.scheduler)
> +
> +    def provision(self, profile: VgpuProfile) -> None:
> +        """Provision PF and VF(s) based on requested vGPU profile."""
> +        self.__set_provisioning(profile.num_vfs, profile, set_resources=True)
> +
> +    def provision_scheduling(self, num_vfs: int, profile: VgpuProfile) -> None:
> +        """Provision PF and VF(s) scheduling based on requested vGPU profile's scheduler config."""
> +        self.__set_provisioning(num_vfs, profile, set_resources=False)
>   
>       # fn_num = 0 for PF, 1..n for VF
>       def set_scheduling(self, fn_num: int, gt_num: int, scheduling_config: VgpuSchedulerConfig) -> None:
> -        logger.info("[%s] Provision scheduling config for PCI Function %s", self.pci_info.bdf, fn_num)
> +        """Write sysfs/debugfs PF/VF scheduling attributes."""
> +        logger.debug("[%s] Set scheduling for PCI Function %s", self.pci_info.bdf, fn_num)
>           if fn_num == 0:
>               self.driver.set_pf_policy_sched_if_idle(gt_num, int(scheduling_config.scheduleIfIdle))
>               self.driver.set_exec_quantum_ms(0, gt_num, scheduling_config.pfExecutionQuanta)
> @@ -196,7 +206,8 @@ class Device(DeviceInterface):
>               self.driver.set_preempt_timeout_us(fn_num, gt_num, scheduling_config.vfPreemptionTimeout)
>   
>       def set_resources(self, fn_num: int, gt_num: int, resources_config: VgpuResourcesConfig) -> None:
> -        logger.info("[%s] Provision resources config for PCI Function %s", self.pci_info.bdf, fn_num)
> +        """Write sysfs/debugfs PF/VF resources attributes."""
> +        logger.debug("[%s] Set resources for PCI Function %s", self.pci_info.bdf, fn_num)
>           if fn_num == 0:
>               self.driver.set_pf_ggtt_spare(gt_num, resources_config.pfGgtt)
>               self.driver.set_pf_lmem_spare(gt_num, resources_config.pfLmem)
> @@ -227,8 +238,9 @@ class Device(DeviceInterface):
>               for vf_num in range(1, num_vfs + 1):
>                   self.driver.set_contexts_quota(vf_num, gt_num, 0)
>                   self.driver.set_doorbells_quota(vf_num, gt_num, 0)
> -                self.driver.set_ggtt_quota(vf_num, gt_num, 0)
> -                self.driver.set_lmem_quota(vf_num, gt_num, 0)
> +                if not self.is_gt_media_type(gt_num):
> +                    self.driver.set_ggtt_quota(vf_num, gt_num, 0)
> +                    self.driver.set_lmem_quota(vf_num, gt_num, 0)
>   
>       def cancel_work(self) -> None:
>           """Drop and reset remaining GPU execution at exit."""
> diff --git a/tools/vmtb/vmm_flows/conftest.py b/tools/vmtb/vmm_flows/conftest.py
> index 28c0b5f00..12726416f 100644
> --- a/tools/vmtb/vmm_flows/conftest.py
> +++ b/tools/vmtb/vmm_flows/conftest.py
> @@ -12,7 +12,8 @@ import pytest
>   
>   from bench import exceptions
>   from bench.configurators.vgpu_profile import VgpuProfile
> -from bench.configurators.vgpu_profile_config import (VfSchedulingMode,
> +from bench.configurators.vgpu_profile_config import (VfProvisioningMode,
> +                                                     VfSchedulingMode,
>                                                        VgpuProfileConfigurator)
>   from bench.configurators.vmtb_config import VmtbConfigurator
>   from bench.helpers.helpers import modprobe_driver, modprobe_driver_check
> @@ -39,6 +40,7 @@ class VmmTestingConfig:
>       Available settings:
>       - num_vfs: requested number of VFs to enable
>       - max_num_vms: maximal number of VMs (the value can be different than enabled number of VFs)
> +    - provisioning_mode: auto (fair resources allocation by a driver) or vGPU profile
>       - scheduling_mode: requested vGPU scheduling profile (infinite maps to default 0's)
>       - auto_poweron_vm: assign VFs and power on VMs automatically in setup fixture
>       - auto_probe_vm_driver: probe guest DRM driver in setup fixture (VM must be powered on)
> @@ -47,6 +49,7 @@ class VmmTestingConfig:
>       """
>       num_vfs: int = 1
>       max_num_vms: int = 2
> +    provisioning_mode: VfProvisioningMode = VfProvisioningMode.AUTO
>       scheduling_mode: VfSchedulingMode = VfSchedulingMode.INFINITE
>   
>       auto_poweron_vm: bool = True
> @@ -56,12 +59,14 @@ class VmmTestingConfig:
>       wa_reduce_vf_lmem: bool = False
>   
>       def __str__(self) -> str:
> -        return f'{self.num_vfs}VF'
> +        test_config_id = f'{self.num_vfs}VF-(P:{self.provisioning_mode.name} S:{self.scheduling_mode.name})'
> +        return test_config_id
>   
>       def __repr__(self) -> str:
>           return (f'\nVmmTestingConfig:'
>                   f'\nNum VFs = {self.num_vfs} / max num VMs = {self.max_num_vms}'
> -                f'\nVF scheduling mode = {self.scheduling_mode}'
> +                f'\nVF provisioning mode = {self.provisioning_mode.name}'
> +                f'\nVF scheduling mode = {self.scheduling_mode.name}'
>                   f'\nSetup flags:'
>                   f'\n\tVM - auto power-on = {self.auto_poweron_vm}'
>                   f'\n\tVM - auto DRM driver probe = {self.auto_probe_vm_driver}'
> @@ -107,7 +112,9 @@ class VmmTestingSetup:
>           # [vmtb_root]/vmm_flows/resources/wsim/ptl (last subdir is lowercase key/name from pci.GpuModel class)
>           self.wsim_wl_dir = vmtb_root_path / vmtb_config.config.wsim_wl_path / self.get_dut().gpu_model.name.lower()
>   
> -        self.vgpu_profile: VgpuProfile = self.get_vgpu_profile()
> +        if (self.testing_config.provisioning_mode is VfProvisioningMode.VGPU_PROFILE
> +            or self.testing_config.scheduling_mode is not VfSchedulingMode.INFINITE):
> +            self.vgpu_profile: VgpuProfile = self.get_vgpu_profile()
>   
>           # Start maximum requested number of VMs, but not more than VFs supported by the given vGPU profile
>           self.vms: typing.List[VirtualMachine] = [
> @@ -115,7 +122,7 @@ class VmmTestingSetup:
>                              vmtb_config.get_guest_config().driver,
>                              vmtb_config.get_guest_config().igt_config,
>                              vf_migration_support)
> -            for vm_idx in range(min(self.vgpu_profile.num_vfs, self.testing_config.max_num_vms))]
> +            for vm_idx in range(min(self.testing_config.num_vfs, self.testing_config.max_num_vms))]
>   
>       def get_vgpu_profile(self) -> VgpuProfile:
>           configurator = VgpuProfileConfigurator(self.vgpu_profiles_dir, self.get_dut().gpu_model)
> @@ -126,8 +133,6 @@ class VmmTestingSetup:
>               logger.error("Suitable vGPU profile not found: %s", exc)
>               raise exceptions.VgpuProfileError('Invalid test setup - vGPU profile not found!')
>   
> -        vgpu_profile.print_parameters()
> -
>           return vgpu_profile
>   
>       def get_dut(self) -> Device:
> @@ -224,20 +229,35 @@ def fixture_setup_vms(get_vmtb_config, get_cmdline_config, get_host, request):
>       ts: VmmTestingSetup = VmmTestingSetup(get_vmtb_config, get_cmdline_config, host, tc)
>   
>       device: Device = ts.get_dut()
> -    num_vfs = ts.vgpu_profile.num_vfs
> +    num_vfs = ts.testing_config.num_vfs
>       num_vms = ts.get_num_vms()
>   
>       logger.info('[Test setup: %sVF-%sVM]', num_vfs, num_vms)
>   
> -    # XXX: VF migration on discrete devices (with LMEM) is currently quite slow.
> -    # As a temporary workaround, reduce size of LMEM assigned to VFs to speed up a state save/load process.
> -    if tc.wa_reduce_vf_lmem and device.has_lmem():
> -        logger.debug("W/A: reduce VFs LMEM quota to accelerate state save/restore")
> -        org_vgpu_profile_vfLmem = ts.vgpu_profile.resources.vfLmem
> -        # Assign max 512 MB to VF
> -        ts.vgpu_profile.resources.vfLmem = min(ts.vgpu_profile.resources.vfLmem // 2, 536870912)
> -
> -    device.provision(ts.vgpu_profile)
> +    if ts.testing_config.provisioning_mode is VfProvisioningMode.VGPU_PROFILE:
> +        # XXX: Double migration is slow on discrete GPUs (with VRAM),
> +        # As a workaround, reduce VRAM size assigned to VFs to speed up a save process.
> +        # This w/a should be removed when a save/restore time improves.
> +        if tc.wa_reduce_vf_lmem and device.has_lmem():
> +            logger.debug("W/A: reduce VFs LMEM quota to accelerate state save")
> +            org_vgpu_profile_vfLmem = ts.vgpu_profile.resources.vfLmem
> +            # Assign max 512 MB to VF
> +            ts.vgpu_profile.resources.vfLmem = min(ts.vgpu_profile.resources.vfLmem // 2, 536870912)
> +
> +        ts.vgpu_profile.print_parameters()
> +        device.provision(ts.vgpu_profile)
> +
> +        # XXX: cleanup counterpart for VFs LMEM quota workaround:
> +        # restore original value after vGPU profile applied
> +        if tc.wa_reduce_vf_lmem and device.has_lmem():
> +            ts.vgpu_profile.resources.vfLmem = org_vgpu_profile_vfLmem
> +
> +    else:
> +        device.driver.set_auto_provisioning(True)
> +        if ts.testing_config.scheduling_mode is not VfSchedulingMode.INFINITE:
> +            # Auto provisioning with concrete scheduling (i.e. different than HW default: infinite)
> +            ts.vgpu_profile.print_scheduler_config()
> +            device.provision_scheduling(num_vfs, ts.vgpu_profile)
>   
>       assert device.create_vf(num_vfs) == num_vfs
>   
> @@ -257,10 +277,39 @@ def fixture_setup_vms(get_vmtb_config, get_cmdline_config, get_host, request):
>       yield ts
>   
>       logger.info('[Test teardown: %sVF-%sVM]', num_vfs, num_vms)
> -    # XXX: cleanup counterpart for VFs LMEM quota workaround - restore original value
> -    if tc.wa_reduce_vf_lmem and device.has_lmem():
> -        ts.vgpu_profile.resources.vfLmem = org_vgpu_profile_vfLmem
> +    ts.teardown()
>   
> +
> +# Obsolete fixtures 'create_Xhost_Yvm' - 'fixture_setup_vms' is preferred
> +@pytest.fixture(scope='function')
> +def create_1host_1vm(get_vmtb_config, get_cmdline_config, get_host):
> +    num_vfs, num_vms = 1, 1
> +    ts: VmmTestingSetup = VmmTestingSetup(get_vmtb_config, get_cmdline_config, get_host,
> +                                          VmmTestingConfig(num_vfs, num_vms))
> +
> +    logger.info('[Test setup: %sVF-%sVM]', num_vfs, num_vms)
> +    logger.debug(repr(ts.testing_config))
> +
> +    logger.info('[Test execution: %sVF-%sVM]', num_vfs, num_vms)
> +    yield ts
> +
> +    logger.info('[Test teardown: %sVF-%sVM]', num_vfs, num_vms)
> +    ts.teardown()
> +
> +
> +@pytest.fixture(scope='function')
> +def create_1host_2vm(get_vmtb_config, get_cmdline_config, get_host):
> +    num_vfs, num_vms = 2, 2
> +    ts: VmmTestingSetup = VmmTestingSetup(get_vmtb_config, get_cmdline_config, get_host,
> +                                          VmmTestingConfig(num_vfs, num_vms))
> +
> +    logger.info('[Test setup: %sVF-%sVM]', num_vfs, num_vms)
> +    logger.debug(repr(ts.testing_config))
> +
> +    logger.info('[Test execution: %sVF-%sVM]', num_vfs, num_vms)
> +    yield ts
> +
> +    logger.info('[Test teardown: %sVF-%sVM]', num_vfs, num_vms)
>       ts.teardown()
>   
>   
> diff --git a/tools/vmtb/vmm_flows/test_basic.py b/tools/vmtb/vmm_flows/test_basic.py
> index 1d3a68b36..9b8731273 100644
> --- a/tools/vmtb/vmm_flows/test_basic.py
> +++ b/tools/vmtb/vmm_flows/test_basic.py
> @@ -7,7 +7,7 @@ from typing import List, Tuple
>   
>   import pytest
>   
> -from bench.configurators.vgpu_profile_config import VfSchedulingMode
> +from bench.configurators.vgpu_profile_config import VfProvisioningMode, VfSchedulingMode
>   from bench.executors.gem_wsim import (ONE_CYCLE_DURATION_MS,
>                                         PREEMPT_10MS_WORKLOAD, GemWsim,
>                                         GemWsimResult,
> @@ -27,20 +27,23 @@ DELAY_FOR_WORKLOAD_SEC = 2 # Waiting gem_wsim to be running [seconds]
>   DELAY_FOR_RELOAD_SEC = 3 # Waiting before driver reloading [seconds]
>   
>   
> -def set_test_config(test_variants: List[Tuple[int, VfSchedulingMode]],
> +def set_test_config(test_variants: List[Tuple[int, VfProvisioningMode, VfSchedulingMode]],
>                       max_vms: int = 2, vf_driver_load: bool = True) -> List[VmmTestingConfig]:
>       """Helper function to provide a parametrized test with a list of test configuration variants."""
>       logger.debug("Init test variants: %s", test_variants)
>       test_configs: List[VmmTestingConfig] = []
>   
>       for config in test_variants:
> -        (num_vfs, scheduling_mode) = config
> -        test_configs.append(VmmTestingConfig(num_vfs, max_vms, scheduling_mode, auto_probe_vm_driver=vf_driver_load))
> +        (num_vfs, provisioning_mode, scheduling_mode) = config
> +        test_configs.append(VmmTestingConfig(num_vfs, max_vms, provisioning_mode, scheduling_mode,
> +                                             auto_probe_vm_driver=vf_driver_load))
>   
>       return test_configs
>   
>   
> -test_variants_1 = [(1, VfSchedulingMode.DEFAULT_PROFILE), (2, VfSchedulingMode.DEFAULT_PROFILE)]
> +test_variants_1 = [(1, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE),
> +                   (2, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE),
> +                   (2, VfProvisioningMode.AUTO, VfSchedulingMode.INFINITE)]
>   
>   @pytest.mark.parametrize('setup_vms', set_test_config(test_variants_1), ids=idfn_test_config, indirect=['setup_vms'])
>   class TestVmSetup:
> @@ -60,8 +63,9 @@ class TestVmSetup:
>               assert driver_check(vm)
>   
>   
> -test_variants_2 = [(1, VfSchedulingMode.DEFAULT_PROFILE), (2, VfSchedulingMode.DEFAULT_PROFILE),
> -                   (4, VfSchedulingMode.DEFAULT_PROFILE)]
> +test_variants_2 = [(1, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE),
> +                   (2, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE),
> +                   (4, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE)]
>   
>   @pytest.mark.parametrize('setup_vms', set_test_config(test_variants_2), ids=idfn_test_config, indirect=['setup_vms'])
>   class TestVmWorkload:
> @@ -102,7 +106,8 @@ class TestVmWorkload:
>           logger.info("Execute wsim parallel on VMs - results: %s", result)
>   
>   
> -test_variants_3 = [(2, VfSchedulingMode.DEFAULT_PROFILE), (4, VfSchedulingMode.DEFAULT_PROFILE)]
> +test_variants_3 = [(2, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE),
> +                   (4, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE)]
LGTM,
Reviewed-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
>   
>   @pytest.mark.parametrize('setup_vms', set_test_config(test_variants=test_variants_3, max_vms=4, vf_driver_load=False),
>                            ids = idfn_test_config, indirect=['setup_vms'])

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH i-g-t 06/10] tools/vmtb: Refactor driver interfaces
  2026-02-24  7:50 ` [PATCH i-g-t 06/10] tools/vmtb: Refactor driver interfaces Adam Miszczak
@ 2026-03-10 10:43   ` Bernatowicz, Marcin
  0 siblings, 0 replies; 25+ messages in thread
From: Bernatowicz, Marcin @ 2026-03-10 10:43 UTC (permalink / raw)
  To: Adam Miszczak, igt-dev; +Cc: kamil.konieczny


On 2/24/2026 8:50 AM, Adam Miszczak wrote:
> Introduce new common driver interface - base class for all DRM drivers.
> DriverInterface exposes basic functions like bind, unbind or reset
> and is extended by specialized classes representing PF and VF drivers.
> Both PF and VF driver classes implement methods to read/write sysfs/debugfs:
> a host uses standard Python's pathlib for filesystem operations,
> guest access it over QEMU Guest-Agent commands.
> Additionally, PfDriverInterface publishes functions to enable
> and provision VFs, configure scheduling etc.
> Concrete implementation of PF driver is provided by Xe driver class.
>
> Additional adjustments for xe provisioning:
> - scheduling configured via sysfs SRIOV admin tree:
>    /sys/bus/pci/drivers/xe/[BDF]/sriov_admin
> - support bulk settings (PF and all VFs) for EQ, PT and scheduling priority
> - align with a new 'sched_priority' file format:
>    low/normal/high strings instead of integers
> - remove 'sched_if_idle' attribute support - enable strict scheduling
>    via 'normal' scheduling priority
> - support new debugfs 'restore_auto_provisioning' attribute
>    to reenable auto-provisioning mode.
> - set LMEM and GGTT quotas exclusively on a root tile
> - in auto resources provisioning mode, setting scheduling parameters
>    should follow VFs enabling
>    (otherwise xe KMD sets custom provisioning mode for resources as well)
> - Device.reset_provisioning() clears (zeroes) provisioning attributes
>    and restores auto-provisioning
>
> Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
> ---
>   tools/vmtb/bench/drivers/driver_interface.py | 179 +++++++++++++---
>   tools/vmtb/bench/drivers/xe.py               | 207 ++++++++-----------
>   tools/vmtb/bench/machines/physical/device.py |  96 +++++----
>   tools/vmtb/vmm_flows/conftest.py             |  14 +-
>   4 files changed, 301 insertions(+), 195 deletions(-)
>
> diff --git a/tools/vmtb/bench/drivers/driver_interface.py b/tools/vmtb/bench/drivers/driver_interface.py
> index 3026fece7..0b0bd5abb 100644
> --- a/tools/vmtb/bench/drivers/driver_interface.py
> +++ b/tools/vmtb/bench/drivers/driver_interface.py
> @@ -3,13 +3,21 @@
>   
>   import abc
>   import enum
> +import logging
>   import typing
> +from pathlib import Path
>   
> +from bench import exceptions
> +from bench.machines.machine_interface import MachineInterface
> +from bench.helpers.log import LogDecorators
>   
> -class SchedulingPriority(enum.Enum):
> -    LOW = 0
> -    NORMAL = 1
> -    HIGH = 2
> +logger = logging.getLogger('DriverInterface')
> +
> +
> +class SchedulingPriority(str, enum.Enum):
> +    LOW = 'low'
> +    NORMAL = 'normal'
> +    HIGH = 'high'
>   
>   
>   class VfControl(str, enum.Enum):
> @@ -23,20 +31,85 @@ class VfControl(str, enum.Enum):
>   
>   
>   class DriverInterface(abc.ABC):
> +    """Base class for DRM drivers (Physical and Virtual).
> +    Provide common operations for all drivers like bind/unbind, reset etc.
> +    """
> +    def __init__(self, bdf: str) -> None:
> +        self.pci_bdf = bdf
> +        self.sysfs_device_path = Path('/sys/bus/pci/devices') / self.pci_bdf
> +        self.sysfs_driver_path = Path('/sys/bus/pci/drivers') / self.get_name()
> +        self.debugfs_path = Path('/sys/kernel/debug/dri') / self.pci_bdf
> +
> +    @abc.abstractmethod
> +    def get_name(self) -> str:
> +        raise NotImplementedError
> +
> +    @abc.abstractmethod
> +    def write_sysfs(self, path: Path, value: str) -> None:
> +        raise NotImplementedError
>   
> -    @staticmethod
>       @abc.abstractmethod
> -    def get_name() -> str:
> +    def read_sysfs(self, path: Path) -> str:
>           raise NotImplementedError
>   
>       @abc.abstractmethod
> -    def bind(self, bdf: str) -> None:
> +    def write_debugfs(self, file: str, value: str) -> None:
>           raise NotImplementedError
>   
>       @abc.abstractmethod
> -    def unbind(self, bdf: str) -> None:
> +    def read_debugfs(self, file: str) -> str:
>           raise NotImplementedError
>   
> +    @LogDecorators.parse_kmsg
> +    def bind(self) -> None:
> +        self.write_sysfs((self.sysfs_driver_path / 'bind'), self.pci_bdf)
> +
> +    @LogDecorators.parse_kmsg
> +    def unbind(self) -> None:
> +        self.write_sysfs((self.sysfs_driver_path / 'unbind'), self.pci_bdf)
> +
> +    @LogDecorators.parse_kmsg
> +    def flr(self) -> None:
> +        self.write_sysfs((self.sysfs_device_path / 'reset'), '1')
> +
> +
> +class PfDriverInterface(DriverInterface, abc.ABC):
> +    """Base class for PF drivers, extends common DriverInterface base class.
> +    Provide operations specific for PF drivers like read/write sysfs on Host,
> +    set number of VFs to enable, set/get provisioning related attributes etc.
> +    """
> +    @LogDecorators.parse_kmsg
> +    def __write_fs(self, path: Path, value: str) -> None:
> +        try:
> +            path.write_text(value)
> +            logger.debug("Write: %s -> %s", value, path)
> +        except Exception as exc:
> +            logger.error("Unable to write %s -> %s", value, path)
> +            raise exceptions.HostError(f'Could not write to {path}. Error: {exc}') from exc
> +
> +    @LogDecorators.parse_kmsg
> +    def __read_fs(self, path: Path) -> str:
> +        try:
> +            ret = path.read_text()
> +        except Exception as exc:
> +            logger.error("Unable to read %s", path)
> +            raise exceptions.HostError(f'Could not read from {path}. Error: {exc}') from exc
> +
> +        logger.debug("Read: %s -> %s", path, ret.strip())
> +        return ret
> +
> +    def write_sysfs(self, path: Path, value: str) -> None:
> +        self.__write_fs(path, value)
> +
> +    def read_sysfs(self, path: Path) -> str:
> +        return str(self.__read_fs(path))
> +
> +    def write_debugfs(self, file: str, value: str) -> None:
> +        self.__write_fs(self.debugfs_path / file, value)
> +
> +    def read_debugfs(self, file: str) -> str:
> +        return str(self.__read_fs(self.debugfs_path / file))
> +
>       @abc.abstractmethod
>       def get_totalvfs(self) -> int:
>           raise NotImplementedError
> @@ -70,17 +143,14 @@ class DriverInterface(abc.ABC):
>           raise NotImplementedError
>   
>       @abc.abstractmethod
> -    def get_auto_provisioning(self) -> bool:
> -        raise NotImplementedError
> -
> -    @abc.abstractmethod
> -    def set_auto_provisioning(self, val: bool) -> None:
> +    def restore_auto_provisioning(self) -> None:
>           raise NotImplementedError
>   
>       @abc.abstractmethod
>       def cancel_work(self) -> None:
>           raise NotImplementedError
>   
> +    # PF provisioning
>       @abc.abstractmethod
>       def get_pf_ggtt_spare(self, gt_num: int) -> int:
>           raise NotImplementedError
> @@ -113,14 +183,6 @@ class DriverInterface(abc.ABC):
>       def set_pf_doorbells_spare(self, gt_num: int, val: int) -> None:
>           raise NotImplementedError
>   
> -    @abc.abstractmethod
> -    def get_pf_sched_priority(self, gt_num: int) -> SchedulingPriority:
> -        raise NotImplementedError
> -
> -    @abc.abstractmethod
> -    def set_pf_sched_priority(self, gt_num: int, val: SchedulingPriority) -> None:
> -        raise NotImplementedError
> -
>       @abc.abstractmethod
>       def get_pf_policy_reset_engine(self, gt_num: int) -> int:
>           raise NotImplementedError
> @@ -137,14 +199,7 @@ class DriverInterface(abc.ABC):
>       def set_pf_policy_sample_period_ms(self, gt_num: int, val: int) -> None:
>           raise NotImplementedError
>   
> -    @abc.abstractmethod
> -    def get_pf_policy_sched_if_idle(self, gt_num: int) -> int:
> -        raise NotImplementedError
> -
> -    @abc.abstractmethod
> -    def set_pf_policy_sched_if_idle(self, gt_num: int, val: int) -> None:
> -        raise NotImplementedError
> -
> +    # VF provisioning
>       @abc.abstractmethod
>       def get_ggtt_quota(self, vf_num: int, gt_num: int) -> int:
>           raise NotImplementedError
> @@ -177,20 +232,53 @@ class DriverInterface(abc.ABC):
>       def set_doorbells_quota(self, vf_num: int, gt_num: int, val: int) -> None:
>           raise NotImplementedError
>   
> +    # Scheduling provisioning
> +    @abc.abstractmethod
> +    def get_exec_quantum_ms(self, fn_num: int) -> int:
> +        "Get execution quantum (ms) for PF/VF (EQ/exec_quantum_ms)."
> +        raise NotImplementedError
> +
> +    @abc.abstractmethod
> +    def set_exec_quantum_ms(self, fn_num: int, val: int) -> None:
> +        "Set execution quantum (ms) for PF/VF (EQ/exec_quantum_ms)."
> +        raise NotImplementedError
> +
> +    @abc.abstractmethod
> +    def set_bulk_exec_quantum_ms(self, val: int) -> None:
> +        "Set execution quantum (ms) for PF and all VFs (EQ/exec_quantum_ms)."
> +        raise NotImplementedError
> +
> +    @abc.abstractmethod
> +    def get_preempt_timeout_us(self, fn_num: int) -> int:
> +        "Get preemption timeout (us) for PF/VF (PT/preempt_timeout_us)."
> +        raise NotImplementedError
> +
> +    @abc.abstractmethod
> +    def set_preempt_timeout_us(self, fn_num: int, val: int) -> None:
> +        "Set preemption timeout (us) for PF/VF (PT/preempt_timeout_us)."
> +        raise NotImplementedError
> +
>       @abc.abstractmethod
> -    def get_exec_quantum_ms(self, vf_num: int, gt_num: int) -> int:
> +    def set_bulk_preempt_timeout_us(self, val: int) -> None:
> +        "Set preemption timeout (us) for PF and all VFs (PT/preempt_timeout_us)."
>           raise NotImplementedError
>   
>       @abc.abstractmethod
> -    def set_exec_quantum_ms(self, vf_num: int, gt_num: int, val: int) -> None:
> +    def get_sched_priority(self, fn_num: int) -> SchedulingPriority:
> +        "Get scheduling priority (sched_priority) of PF/VF: low, normal or high."
>           raise NotImplementedError
>   
>       @abc.abstractmethod
> -    def get_preempt_timeout_us(self, vf_num: int, gt_num: int) -> int:
> +    def set_pf_sched_priority(self, val: SchedulingPriority) -> None:
> +        "Set scheduling priority (sched_priority) for PF only."
> +        # Independent sched_prio setting is available only for PF
>           raise NotImplementedError
>   
>       @abc.abstractmethod
> -    def set_preempt_timeout_us(self, vf_num: int, gt_num: int, val: int) -> None:
> +    def set_bulk_sched_priority(self, val: SchedulingPriority) -> None:
> +        "Set scheduling priority (sched_priority) for PF and all VFs."
> +        # Set sched_prio for PF and all VFs.
> +        # Setting sched_priority for a single VF independently is not supported currently.
>           raise NotImplementedError
>   
>       @abc.abstractmethod
> @@ -200,3 +288,28 @@ class DriverInterface(abc.ABC):
>       @abc.abstractmethod
>       def get_ggtt_available(self, gt_num: int) -> typing.Tuple[int, int]:
>           raise NotImplementedError
> +
> +
> +class VfDriver(DriverInterface):
> +    """Base class for VF drivers, extends common DriverInterface base class.
> +    Provide operations specific for VF drivers like read/write sysfs on Guest/VM.
> +    """
> +    def __init__(self, bdf: str, vm: MachineInterface) -> None:
> +        # VirtualMachine instance is required for VM filesystem access via QEMU Guest-Agent
> +        self.vm: MachineInterface = vm
> +        super().__init__(bdf)
> +
> +    def get_name(self) -> str:
> +        return self.vm.get_drm_driver_name()
> +
> +    def write_sysfs(self, path: Path, value: str) -> None:
> +        self.vm.write_file_content(str(path), value)
> +
> +    def read_sysfs(self, path: Path) -> str:
> +        return self.vm.read_file_content(str(path))
> +
> +    def write_debugfs(self, file: str, value: str) -> None:
> +        self.vm.write_file_content(str(self.debugfs_path / file), value)
> +
> +    def read_debugfs(self, file: str) -> str:
> +        return self.vm.read_file_content(str(self.debugfs_path / file))
> diff --git a/tools/vmtb/bench/drivers/xe.py b/tools/vmtb/bench/drivers/xe.py
> index c2b9643bb..26e4e0a08 100644
> --- a/tools/vmtb/bench/drivers/xe.py
> +++ b/tools/vmtb/bench/drivers/xe.py
> @@ -2,85 +2,42 @@
>   # Copyright © 2024-2026 Intel Corporation
>   
>   import logging
> +import re
>   import typing
>   from pathlib import Path
>   
> -from bench import exceptions
> -from bench.drivers.driver_interface import (DriverInterface,
> +from bench.drivers.driver_interface import (PfDriverInterface,
>                                               SchedulingPriority, VfControl)
> -from bench.helpers.log import LogDecorators
>   
>   logger = logging.getLogger('XeDriver')
>   
>   
> -class XeDriver(DriverInterface):
> -    def __init__(self, card_index: int) -> None:
> -        self.sysfs_card_path = Path(f'/sys/class/drm/card{card_index}')
> -        self.debugfs_path = Path(f'/sys/kernel/debug/dri/{card_index}')
> -
> -    @staticmethod
> -    def get_name() -> str:
> +class XeDriver(PfDriverInterface):
> +    """Xe driver abstraction class, implements PfDriverInterface.
> +    Provide xe specific sysfs/debugfs access and other operations on Host.
> +    """
> +    def get_name(self) -> str:
>           return 'xe'
>   
> -    @LogDecorators.parse_kmsg
> -    def __write_fs(self, base_path: Path, name: str, value: str) -> None:
> -        path = base_path / name
> -        try:
> -            path.write_text(value)
> -            logger.debug("Write: %s -> %s", value, path)
> -        except Exception as exc:
> -            logger.error("Unable to write %s -> %s", value, path)
> -            raise exceptions.HostError(f'Could not write to {path}. Error: {exc}') from exc
> -
> -    @LogDecorators.parse_kmsg
> -    def __read_fs(self,  base_path: Path, name: str) -> str:
> -        path = base_path / name
> -        try:
> -            ret = path.read_text()
> -        except Exception as exc:
> -            logger.error("Unable to read %s", path)
> -            raise exceptions.HostError(f'Could not read from {path}. Error: {exc}') from exc
> -
> -        logger.debug("Read: %s -> %s", path, ret.strip())
> -        return ret
> -
> -    def __write_sysfs(self, name: str, value: str) -> None:
> -        self.__write_fs(self.sysfs_card_path / 'device', name, value)
> -
> -    def __read_sysfs(self, name: str) -> str:
> -        return str(self.__read_fs(self.sysfs_card_path / 'device', name))
> -
> -    def __write_debugfs(self, name: str, value: str) -> None:
> -        self.__write_fs(self.debugfs_path, name, value)
> -
> -    def __read_debugfs(self, name: str) -> str:
> -        return str(self.__read_fs(self.debugfs_path, name))
> -
> -    def bind(self, bdf: str) -> None:
> -        self.__write_sysfs('driver/bind', bdf)
> -
> -    def unbind(self, bdf: str) -> None:
> -        self.__write_sysfs('driver/unbind', bdf)
> -
>       def get_totalvfs(self) -> int:
> -        return int(self.__read_sysfs('sriov_totalvfs'))
> +        return int(self.read_sysfs(self.sysfs_device_path / 'sriov_totalvfs'))
>   
>       def get_numvfs(self) -> int:
> -        return int(self.__read_sysfs('sriov_numvfs'))
> +        return int(self.read_sysfs(self.sysfs_device_path / 'sriov_numvfs'))
>   
>       def set_numvfs(self, val: int) -> None:
> -        self.__write_sysfs('sriov_numvfs', str(val))
> +        self.write_sysfs(self.sysfs_device_path / 'sriov_numvfs', str(val))
>   
>       def get_drivers_autoprobe(self) -> int:
> -        return int(self.__read_sysfs('sriov_drivers_autoprobe'))
> +        return int(self.read_sysfs(self.sysfs_device_path / 'sriov_drivers_autoprobe'))
>   
>       def set_drivers_autoprobe(self, val: int) -> None:
> -        self.__write_sysfs('sriov_drivers_autoprobe', str(val))
> +        self.write_sysfs(self.sysfs_device_path / 'sriov_drivers_autoprobe', str(val))
>   
>       def get_num_gts(self) -> int:
>           gt_num = 0
>           # Fixme: tile0 only at the moment, add support for multiple tiles if needed
> -        path = self.sysfs_card_path / 'device' / 'tile0' / 'gt'
> +        path = self.sysfs_device_path / 'tile0' / 'gt'
>   
>           if path.exists():
>               gt_num = 1
> @@ -101,12 +58,9 @@ class XeDriver(DriverInterface):
>           path = self.debugfs_path / f'gt{gt_num}' / 'pf' / 'ggtt_spare'
>           return not path.exists()
>   
> -    def get_auto_provisioning(self) -> bool:
> -        raise exceptions.NotAvailableError('auto_provisioning attribute not available')
> -
> -    def set_auto_provisioning(self, val: bool) -> None:
> -        # No-op - xe driver doesn't publish this attribute
> -        pass
> +    def restore_auto_provisioning(self) -> None:
> +        path = self.debugfs_path / 'sriov' / 'restore_auto_provisioning'
> +        self.write_debugfs(str(path), str(1))
>   
>       def cancel_work(self) -> None:
>           # Function to cancel all remaing work on GPU (for test cleanup).
> @@ -114,84 +68,77 @@ class XeDriver(DriverInterface):
>           pass
>   
>       # Create debugfs path to given parameter (without a base part):
> -    # gt@gt_num/[pf|vf@vf_num]/@attr
> -    # @vf_num: VF number (1-based) or 0 for PF
> +    # gt@gt_num/[pf|vf@fn_num]/@attr
> +    # @fn_num: VF number (1-based) or 0 for PF
>       # @gt_num: GT instance number
>       # @subdir: subdirectory for attribute or empty string if not exists
>       # @attr: iov parameter name
>       # Returns: iov debugfs path to @attr
> -    def __helper_create_debugfs_path(self, vf_num: int, gt_num: int, subdir: str, attr: str) -> str:
> -        vf_gt_part = f'gt{gt_num}/pf' if vf_num == 0 else f'gt{gt_num}/vf{vf_num}'
> -        return f'{vf_gt_part}/{subdir}/{attr}'
> +    def __helper_create_debugfs_path(self, fn_num: int, gt_num: int, subdir: str, attr: str) -> str:
> +        gt_fn_part = f'gt{gt_num}/pf' if fn_num == 0 else f'gt{gt_num}/vf{fn_num}'
> +        return f'{gt_fn_part}/{subdir}/{attr}'
> +
> +    # Create sysfs sriov_admin path to given scheduling parameter (without a base part):
> +    # sriov_admin/[pf|vf@fn_num]/profile/@attr
> +    # @fn_num: VF number (1-based) or 0 for PF
> +    # @attr: iov parameter name
> +    # Returns: iov sysfs path to @attr
> +    def __helper_create_sriov_admin_path(self, fn_num: int, attr: str) -> str:
> +        fn_part = 'pf' if fn_num == 0 else f'vf{fn_num}'
> +        return f'sriov_admin/{fn_part}/profile/{attr}'
>   
>       # PF spare resources
>       # Debugfs location: [SRIOV debugfs base path]/gtM/pf/xxx_spare
>       def get_pf_ggtt_spare(self, gt_num: int) -> int:
>           path = self.__helper_create_debugfs_path(0, gt_num, '', 'ggtt_spare')
> -        return int(self.__read_debugfs(path))
> +        return int(self.read_debugfs(path))
>   
>       def set_pf_ggtt_spare(self, gt_num: int, val: int) -> None:
>           path = self.__helper_create_debugfs_path(0, gt_num, '',  'ggtt_spare')
> -        self.__write_debugfs(path, str(val))
> +        self.write_debugfs(path, str(val))
>   
>       def get_pf_lmem_spare(self, gt_num: int) -> int:
>           path = self.__helper_create_debugfs_path(0, gt_num, '', 'lmem_spare')
> -        return int(self.__read_debugfs(path)) if self.has_lmem() else 0
> +        return int(self.read_debugfs(path)) if self.has_lmem() else 0
>   
>       def set_pf_lmem_spare(self, gt_num: int, val: int) -> None:
>           path = self.__helper_create_debugfs_path(0, gt_num, '', 'lmem_spare')
>           if self.has_lmem():
> -            self.__write_debugfs(path, str(val))
> +            self.write_debugfs(path, str(val))
>   
>       def get_pf_contexts_spare(self, gt_num: int) -> int:
>           path = self.__helper_create_debugfs_path(0, gt_num, '', 'contexts_spare')
> -        return int(self.__read_debugfs(path))
> +        return int(self.read_debugfs(path))
>   
>       def set_pf_contexts_spare(self, gt_num: int, val: int) -> None:
>           path = self.__helper_create_debugfs_path(0, gt_num, '', 'contexts_spare')
> -        self.__write_debugfs(path, str(val))
> +        self.write_debugfs(path, str(val))
>   
>       def get_pf_doorbells_spare(self, gt_num: int) -> int:
>           path = self.__helper_create_debugfs_path(0, gt_num, '', 'doorbells_spare')
> -        return int(self.__read_debugfs(path))
> +        return int(self.read_debugfs(path))
>   
>       def set_pf_doorbells_spare(self, gt_num: int, val: int) -> None:
>           path = self.__helper_create_debugfs_path(0, gt_num, '', 'doorbells_spare')
> -        self.__write_debugfs(path, str(val))
> +        self.write_debugfs(path, str(val))
>   
>       # PF specific provisioning parameters
>       # Debugfs location: [SRIOV debugfs base path]/gtM/pf
> -    def get_pf_sched_priority(self, gt_num: int) -> SchedulingPriority:
> -        logger.warning("PF sched_priority param not available")
> -        return SchedulingPriority.LOW
> -
> -    def set_pf_sched_priority(self, gt_num: int, val: SchedulingPriority) -> None:
> -        logger.warning("PF sched_priority param not available")
> -
>       def get_pf_policy_reset_engine(self, gt_num: int) -> int:
>           path = self.__helper_create_debugfs_path(0, gt_num, '', 'reset_engine')
> -        return int(self.__read_debugfs(path))
> +        return int(self.read_debugfs(path))
>   
>       def set_pf_policy_reset_engine(self, gt_num: int, val: int) -> None:
>           path = self.__helper_create_debugfs_path(0, gt_num, '', 'reset_engine')
> -        self.__write_debugfs(path, str(val))
> +        self.write_debugfs(path, str(val))
>   
>       def get_pf_policy_sample_period_ms(self, gt_num: int) -> int:
>           path = self.__helper_create_debugfs_path(0, gt_num, '', 'sample_period_ms')
> -        return int(self.__read_debugfs(path))
> +        return int(self.read_debugfs(path))
>   
>       def set_pf_policy_sample_period_ms(self, gt_num: int, val: int) -> None:
>           path = self.__helper_create_debugfs_path(0, gt_num, '', 'sample_period_ms')
> -        self.__write_debugfs(path, str(val))
> -
> -    def get_pf_policy_sched_if_idle(self, gt_num: int) -> int:
> -        path = self.__helper_create_debugfs_path(0, gt_num, '', 'sched_if_idle')
> -        return int(self.__read_debugfs(path))
> -
> -    def set_pf_policy_sched_if_idle(self, gt_num: int, val: int) -> None:
> -        # In order to set strict scheduling policy, PF scheduling priority needs to be default
> -        path = self.__helper_create_debugfs_path(0, gt_num, '', 'sched_if_idle')
> -        self.__write_debugfs(path, str(val))
> +        self.write_debugfs(path, str(val))
>   
>       # VF and PF provisioning parameters
>       # Debugfs location: [SRIOV debugfs base path]/gtM/[pf|vfN]
> @@ -202,7 +149,7 @@ class XeDriver(DriverInterface):
>               return 0
>   
>           path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'ggtt_quota')
> -        return int(self.__read_debugfs(path))
> +        return int(self.read_debugfs(path))
>   
>       def set_ggtt_quota(self, vf_num: int, gt_num: int, val: int) -> None:
>           if vf_num == 0:
> @@ -210,7 +157,7 @@ class XeDriver(DriverInterface):
>               return
>   
>           path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'ggtt_quota')
> -        self.__write_debugfs(path, str(val))
> +        self.write_debugfs(path, str(val))
>   
>       def get_lmem_quota(self, vf_num: int, gt_num: int) -> int:
>           if vf_num == 0:
> @@ -218,7 +165,7 @@ class XeDriver(DriverInterface):
>               return 0
>   
>           path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'lmem_quota')
> -        return int(self.__read_debugfs(path)) if self.has_lmem() else 0
> +        return int(self.read_debugfs(path)) if self.has_lmem() else 0
>   
>       def set_lmem_quota(self, vf_num: int, gt_num: int, val: int) -> None:
>           if vf_num == 0:
> @@ -227,7 +174,7 @@ class XeDriver(DriverInterface):
>   
>           path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'lmem_quota')
>           if self.has_lmem():
> -            self.__write_debugfs(path, str(val))
> +            self.write_debugfs(path, str(val))
>   
>       def get_contexts_quota(self, vf_num: int, gt_num: int) -> int:
>           if vf_num == 0:
> @@ -235,7 +182,7 @@ class XeDriver(DriverInterface):
>               return 0
>   
>           path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'contexts_quota')
> -        return int(self.__read_debugfs(path))
> +        return int(self.read_debugfs(path))
>   
>       def set_contexts_quota(self, vf_num: int, gt_num: int, val: int) -> None:
>           if vf_num == 0:
> @@ -243,7 +190,7 @@ class XeDriver(DriverInterface):
>               return
>   
>           path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'contexts_quota')
> -        self.__write_debugfs(path, str(val))
> +        self.write_debugfs(path, str(val))
>   
>       def get_doorbells_quota(self, vf_num: int, gt_num: int) -> int:
>           if vf_num == 0:
> @@ -251,7 +198,7 @@ class XeDriver(DriverInterface):
>               return 0
>   
>           path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'doorbells_quota')
> -        return int(self.__read_debugfs(path))
> +        return int(self.read_debugfs(path))
>   
>       def set_doorbells_quota(self, vf_num: int, gt_num: int, val: int) -> None:
>           if vf_num == 0:
> @@ -259,23 +206,51 @@ class XeDriver(DriverInterface):
>               return
>   
>           path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'doorbells_quota')
> -        self.__write_debugfs(path, str(val))
> +        self.write_debugfs(path, str(val))
> +
> +    # VF and PF scheduling parameters
> +    # Sysfs location: [SRIOV sysfs base path]/sriov_admin/[pf|vfN]/profile
> +    # @fn_num: VF number (1-based) or 0 for PF
> +    def get_exec_quantum_ms(self, fn_num: int) -> int:
> +        sriov_admin_path = self.__helper_create_sriov_admin_path(fn_num, 'exec_quantum_ms')
> +        return int(self.read_sysfs(self.sysfs_device_path / sriov_admin_path))
> +
> +    def set_exec_quantum_ms(self, fn_num: int, val: int) -> None:
> +        sriov_admin_path = self.__helper_create_sriov_admin_path(fn_num, 'exec_quantum_ms')
> +        self.write_sysfs(self.sysfs_device_path / sriov_admin_path, str(val))
> +
> +    def set_bulk_exec_quantum_ms(self, val: int) -> None:
> +        self.write_sysfs(self.sysfs_device_path / 'sriov_admin/.bulk_profile/exec_quantum_ms', str(val))
> +
> +    def get_preempt_timeout_us(self, fn_num: int) -> int:
> +        sriov_admin_path = self.__helper_create_sriov_admin_path(fn_num, 'preempt_timeout_us')
> +        return int(self.read_sysfs(self.sysfs_device_path / sriov_admin_path))
> +
> +    def set_preempt_timeout_us(self, fn_num: int, val: int) -> None:
> +        sriov_admin_path = self.__helper_create_sriov_admin_path(fn_num, 'preempt_timeout_us')
> +        self.write_sysfs(self.sysfs_device_path / sriov_admin_path, str(val))
> +
> +    def set_bulk_preempt_timeout_us(self, val: int) -> None:
> +        self.write_sysfs(self.sysfs_device_path / 'sriov_admin/.bulk_profile/preempt_timeout_us', str(val))
> +
> +    def get_sched_priority(self, fn_num: int) -> SchedulingPriority:
> +        sriov_admin_path = self.__helper_create_sriov_admin_path(fn_num, 'sched_priority')
> +        ret = self.read_sysfs(self.sysfs_device_path / sriov_admin_path).rstrip()
>   
> -    def get_exec_quantum_ms(self, vf_num: int, gt_num: int) -> int:
> -        path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'exec_quantum_ms')
> -        return int(self.__read_debugfs(path))
> +        match = re.search(r'\[(low|normal|high)\]', ret)
> +        if match:
> +            return SchedulingPriority(match.group(1))
>   
> -    def set_exec_quantum_ms(self, vf_num: int, gt_num: int, val: int) -> None:
> -        path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'exec_quantum_ms')
> -        self.__write_debugfs(path, str(val))
> +        logger.error("Unexpected sched_priority value (must be low/normal/high)")
> +        raise ValueError('Unexpected sched_priority value (must be low/normal/high)')
>   
> -    def get_preempt_timeout_us(self, vf_num: int, gt_num: int) -> int:
> -        path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'preempt_timeout_us')
> -        return int(self.__read_debugfs(path))
> +    def set_pf_sched_priority(self, val: SchedulingPriority) -> None:
> +        # Independent sched_prio setting is available for PF only
> +        sriov_admin_path = self.__helper_create_sriov_admin_path(0, 'sched_priority')
> +        self.write_sysfs(self.sysfs_device_path / sriov_admin_path, val)
>   
> -    def set_preempt_timeout_us(self, vf_num: int, gt_num: int, val: int) -> None:
> -        path = self.__helper_create_debugfs_path(vf_num, gt_num, '', 'preempt_timeout_us')
> -        self.__write_debugfs(path, str(val))
> +    def set_bulk_sched_priority(self, val: SchedulingPriority) -> None:
> +        self.write_sysfs(self.sysfs_device_path / 'sriov_admin/.bulk_profile/sched_priority', val)
>   
>       # Control state of the running VF (WO)
>       # Debugfs location: [SRIOV debugfs base path]/gtM/vfN/control
> @@ -285,7 +260,7 @@ class XeDriver(DriverInterface):
>       # For debug purposes only.
>       def set_vf_control(self, vf_num: int, val: VfControl) -> None:
>           path = self.__helper_create_debugfs_path(vf_num, 0, '', 'control')
> -        self.__write_debugfs(path, val)
> +        self.write_debugfs(path, val)
>   
>       # Read [attribute]_available value from debugfs:
>       # /sys/kernel/debug/dri/[card_index]/gt@gt_num/pf/@attr_available
> diff --git a/tools/vmtb/bench/machines/physical/device.py b/tools/vmtb/bench/machines/physical/device.py
> index 250466733..f1f24c65c 100644
> --- a/tools/vmtb/bench/machines/physical/device.py
> +++ b/tools/vmtb/bench/machines/physical/device.py
> @@ -11,7 +11,7 @@ from bench import exceptions
>   from bench.configurators import pci
>   from bench.configurators.vgpu_profile import (VgpuProfile, VgpuResourcesConfig,
>                                                 VgpuSchedulerConfig)
> -from bench.drivers.driver_interface import DriverInterface, SchedulingPriority
> +from bench.drivers.driver_interface import PfDriverInterface, SchedulingPriority
>   from bench.helpers.log import LogDecorators
>   from bench.machines.device_interface import DeviceInterface
>   
> @@ -46,12 +46,12 @@ class Device(DeviceInterface):
>       def __init__(self, bdf: str, driver: str) -> None:
>           self.pci_info = self.PciInfo(bdf)
>           self.gpu_model = pci.get_gpu_model(self.pci_info.devid)
> -        self.driver: DriverInterface = self.instantiate_driver(driver, self.pci_info.minor_number)
> +        self.driver: PfDriverInterface = self.instantiate_driver(self.pci_info.bdf, driver)
>   
>       def __str__(self) -> str:
>           return f'Dev-{self.pci_info.bdf}'
>   
> -    def instantiate_driver(self, driver_name: str, card_index: int) -> Any:
> +    def instantiate_driver(self, bdf: str, driver_name: str) -> Any:
>           module_name = f'bench.drivers.{driver_name}'
>           class_name = f'{driver_name.capitalize()}Driver'
>   
> @@ -62,7 +62,7 @@ class Device(DeviceInterface):
>               logging.error("Driver module/class is not available: %s", exc)
>               raise exceptions.VmtbConfigError(f'Requested driver module {driver_name} is not available!')
>   
> -        return driver_class(card_index)
> +        return driver_class(bdf)
>   
>       def set_drivers_autoprobe(self, val: bool) -> None:
>           self.driver.set_drivers_autoprobe(int(val))
> @@ -164,26 +164,27 @@ class Device(DeviceInterface):
>           If 'set_resources' parameter is True - apply the full vGPU profile (hard resources and scheduling).
>           Otherwise, set only scheduling profile (e.g. in case of auto resources provisioning).
>           """
> -        main_gt_nums = [gt_num for gt_num in range(self.get_num_gts()) if not self.is_gt_media_type(gt_num)]
> -
> +        all_gt_nums = list(range(self.get_num_gts()))
> +        main_gt_nums = [gt_num for gt_num in all_gt_nums if not self.is_gt_media_type(gt_num)]
>           logger.info("[%s] Provision %sxVFs on main GT%s", self.pci_info.bdf, num_vfs, main_gt_nums)
>   
> -        for gt_num in main_gt_nums:
> +        for gt_num in all_gt_nums:
>               if set_resources:
>                   self.set_resources(0, gt_num, profile.resources)
> -            self.set_scheduling(0, gt_num, profile.scheduler)
>               self.driver.set_pf_policy_reset_engine(gt_num, int(profile.security.reset_after_vf_switch))
>   
> +        self.set_scheduling(0, profile.scheduler)
> +
>           for vf_num in range(1, num_vfs + 1):
> -            gt_nums = main_gt_nums
>               if len(main_gt_nums) > 1 and num_vfs > 1:
>                   # Multi-tile device Mode 2|3 - odd VFs on GT0, even on GT1
> -                gt_nums = [main_gt_nums[0] if vf_num % 2 else main_gt_nums[1]]
> +                all_gt_nums = [main_gt_nums[0] if vf_num % 2 else main_gt_nums[1]]
>   
> -            for gt_num in gt_nums:
> +            for gt_num in all_gt_nums:
>                   if set_resources:
>                       self.set_resources(vf_num, gt_num, profile.resources)
> -                self.set_scheduling(vf_num, gt_num, profile.scheduler)
> +
> +            self.set_scheduling(vf_num, profile.scheduler)
>   
>       def provision(self, profile: VgpuProfile) -> None:
>           """Provision PF and VF(s) based on requested vGPU profile."""
> @@ -194,44 +195,47 @@ class Device(DeviceInterface):
>           self.__set_provisioning(num_vfs, profile, set_resources=False)
>   
>       # fn_num = 0 for PF, 1..n for VF
> -    def set_scheduling(self, fn_num: int, gt_num: int, scheduling_config: VgpuSchedulerConfig) -> None:
> -        """Write sysfs/debugfs PF/VF scheduling attributes."""
> +    def set_scheduling(self, fn_num: int, scheduling_config: VgpuSchedulerConfig) -> None:
> +        """Write sysfs PF/VF scheduling attributes."""
>           logger.debug("[%s] Set scheduling for PCI Function %s", self.pci_info.bdf, fn_num)
> +
>           if fn_num == 0:
> -            self.driver.set_pf_policy_sched_if_idle(gt_num, int(scheduling_config.scheduleIfIdle))
> -            self.driver.set_exec_quantum_ms(0, gt_num, scheduling_config.pfExecutionQuanta)
> -            self.driver.set_preempt_timeout_us(0, gt_num, scheduling_config.pfPreemptionTimeout)
> +            eq, pt = scheduling_config.pfExecutionQuanta, scheduling_config.pfPreemptionTimeout
>           else:
> -            self.driver.set_exec_quantum_ms(fn_num, gt_num, scheduling_config.vfExecutionQuanta)
> -            self.driver.set_preempt_timeout_us(fn_num, gt_num, scheduling_config.vfPreemptionTimeout)
> +            eq, pt = scheduling_config.vfExecutionQuanta, scheduling_config.vfPreemptionTimeout
> +
> +        self.driver.set_exec_quantum_ms(fn_num, eq)
> +        self.driver.set_preempt_timeout_us(fn_num, pt)
> +
> +        if scheduling_config.scheduleIfIdle:
> +            self.driver.set_bulk_sched_priority(SchedulingPriority.NORMAL)
>   
>       def set_resources(self, fn_num: int, gt_num: int, resources_config: VgpuResourcesConfig) -> None:
> -        """Write sysfs/debugfs PF/VF resources attributes."""
> +        """Write debugfs PF/VF resources attributes."""
>           logger.debug("[%s] Set resources for PCI Function %s", self.pci_info.bdf, fn_num)
>           if fn_num == 0:
> -            self.driver.set_pf_ggtt_spare(gt_num, resources_config.pfGgtt)
> -            self.driver.set_pf_lmem_spare(gt_num, resources_config.pfLmem)
> +            if not self.is_gt_media_type(gt_num):
> +                self.driver.set_pf_ggtt_spare(gt_num, resources_config.pfGgtt)
> +                self.driver.set_pf_lmem_spare(gt_num, resources_config.pfLmem)
>               self.driver.set_pf_contexts_spare(gt_num, resources_config.pfContexts)
>               self.driver.set_pf_doorbells_spare(gt_num, resources_config.pfDoorbells)
>           else:
> -            self.driver.set_ggtt_quota(fn_num, gt_num, resources_config.vfGgtt)
> -            self.driver.set_lmem_quota(fn_num, gt_num, resources_config.vfLmem)
> +            if not self.is_gt_media_type(gt_num):
> +                self.driver.set_ggtt_quota(fn_num, gt_num, resources_config.vfGgtt)
> +                self.driver.set_lmem_quota(fn_num, gt_num, resources_config.vfLmem)
>               self.driver.set_contexts_quota(fn_num, gt_num, resources_config.vfContexts)
>               self.driver.set_doorbells_quota(fn_num, gt_num, resources_config.vfDoorbells)
>   
> -    def reset_provisioning(self, num_vfs: int) -> None:
> -        """Clear provisioning config for a requested number of VFs.
> -        Function calls the sysfs control interface to clear VF provisioning settings
> -        and restores the auto provisioning mode.
> -        """
> -        logger.info("[%s] Reset %s VFs provisioning configuration", self.pci_info.bdf, num_vfs)
> +    def clear_provisioning_attributes(self, num_vfs: int) -> None:
> +        """Clear provisioning attributes for a requested number of VFs."""
> +        # Provisioning config are likely wiped out by (xe) debugfs/restore_auto_provisioning,
> +        # but explicit clear shouldn't harm.
> +        self.driver.set_bulk_sched_priority(SchedulingPriority.LOW)
> +        self.driver.set_bulk_exec_quantum_ms(0)
> +        self.driver.set_bulk_preempt_timeout_us(0)
> +
>           for gt_num in range(self.get_num_gts()):
> -            if self.get_scheduling_priority(gt_num) != SchedulingPriority.LOW:
> -                self.set_scheduling_priority(gt_num, SchedulingPriority.LOW)
> -            self.driver.set_pf_policy_sched_if_idle(gt_num, 0)
>               self.driver.set_pf_policy_reset_engine(gt_num, 0)
> -            self.driver.set_exec_quantum_ms(0, gt_num, 0)
> -            self.driver.set_preempt_timeout_us(0, gt_num, 0)
>               self.driver.set_doorbells_quota(0, gt_num, 0)
>               # PF contexts cannot be set from sysfs
>   
> @@ -242,14 +246,24 @@ class Device(DeviceInterface):
>                       self.driver.set_ggtt_quota(vf_num, gt_num, 0)
>                       self.driver.set_lmem_quota(vf_num, gt_num, 0)
>   
> +    def reset_provisioning(self, num_vfs: int) -> None:
> +        """Clear provisioning config for a given number of VFs and restore auto provisioning mode."""
> +        logger.info("[%s] Reset %sxVF provisioning configuration", self.pci_info.bdf, num_vfs)
> +        self.clear_provisioning_attributes(num_vfs)
> +        self.driver.restore_auto_provisioning()
> +
>       def cancel_work(self) -> None:
>           """Drop and reset remaining GPU execution at exit."""
>           self.driver.cancel_work()
>   
> -    def get_scheduling_priority(self, gt_num: int) -> SchedulingPriority:
> -        return self.driver.get_pf_sched_priority(gt_num)
> +    def get_scheduling_priority(self, fn_num: int) -> SchedulingPriority:
> +        """Get scheduling priority for a given VF or PF."""
> +        return self.driver.get_sched_priority(fn_num)
> +
> +    def set_scheduling_priority(self, val: SchedulingPriority) -> None:
> +        """Set scheduling priority for PF and all VFs. Normal priority enables strict scheduling."""
> +        self.driver.set_bulk_sched_priority(val)
>   
> -    def set_scheduling_priority(self, gt_num: int, val: SchedulingPriority) -> None:
> -        # In order to set scheduling priority, strict scheduling policy needs to be default
> -        # self.drm_driver.set_pf_policy_sched_if_idle(gt_num, 0)
> -        self.driver.set_pf_sched_priority(gt_num, val)
> +    def set_pf_scheduling_priority(self, val: SchedulingPriority) -> None:
> +        """Set scheduling priority for PF only. High prioritizes PF execution over VFs."""
> +        self.driver.set_pf_sched_priority(val)
> diff --git a/tools/vmtb/vmm_flows/conftest.py b/tools/vmtb/vmm_flows/conftest.py
> index 12726416f..a2a6b6680 100644
> --- a/tools/vmtb/vmm_flows/conftest.py
> +++ b/tools/vmtb/vmm_flows/conftest.py
> @@ -253,14 +253,18 @@ def fixture_setup_vms(get_vmtb_config, get_cmdline_config, get_host, request):
>               ts.vgpu_profile.resources.vfLmem = org_vgpu_profile_vfLmem
>   
>       else:
> -        device.driver.set_auto_provisioning(True)
> -        if ts.testing_config.scheduling_mode is not VfSchedulingMode.INFINITE:
> -            # Auto provisioning with concrete scheduling (i.e. different than HW default: infinite)
> -            ts.vgpu_profile.print_scheduler_config()
> -            device.provision_scheduling(num_vfs, ts.vgpu_profile)
> +        device.driver.restore_auto_provisioning()
>   
>       assert device.create_vf(num_vfs) == num_vfs
>   
> +    if (ts.testing_config.provisioning_mode is VfProvisioningMode.AUTO and
> +        ts.testing_config.scheduling_mode is not VfSchedulingMode.INFINITE):
> +        # Auto resources provisioning with concrete scheduling (i.e. different than HW default: infinite).
> +        # Scheduler params override must be done after enabling VFs
> +        # to allow hard resources auto provisioning by KMD.
> +        ts.vgpu_profile.print_scheduler_config()
> +        device.provision_scheduling(num_vfs, ts.vgpu_profile)
> +
LGTM,
Reviewed-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
>       if tc.auto_poweron_vm:
>           bdf_list = [device.get_vf_bdf(vf) for vf in range(1, num_vms + 1)]
>           for vm, bdf in zip(ts.get_vm, bdf_list):

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH i-g-t 07/10] tools/vmtb: Introduce VirtualDevice class
  2026-02-24  7:50 ` [PATCH i-g-t 07/10] tools/vmtb: Introduce VirtualDevice class Adam Miszczak
@ 2026-03-10 10:45   ` Bernatowicz, Marcin
  0 siblings, 0 replies; 25+ messages in thread
From: Bernatowicz, Marcin @ 2026-03-10 10:45 UTC (permalink / raw)
  To: Adam Miszczak, igt-dev; +Cc: kamil.konieczny


On 2/24/2026 8:50 AM, Adam Miszczak wrote:
> VirtualDevice represents GPU device enumerated on VM/Guest OS
> (composited into VirtualMachine class).
> Implement methods common of all devices like bind/unbind driver,
> number of GTs as well as VF specific getter of assigned resources
> read from debugfs self_config file.
> Similarly to physical Device, PciInfo instance with PCI BDF,
> Device ID and minor device is embedded as inner class.
>
> VirtualDevice needs to keep a reference to the VirtualMachine
> (and pass it to VfDriver) to access Guest OS via QEMU Guest-Agent
> running on VM level.
>
> Additionally:
> - add dir_list function to a common MachineInterface
>    (used currently by VirtualDevice)
> - remove physical device specific functions:
>    create/remove VF from a base DeviceInterface class.
> - adjust debugfs/self_config reader
>
> Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
> ---
>   tools/vmtb/bench/machines/device_interface.py |  14 +-
>   tools/vmtb/bench/machines/host.py             |   5 +
>   .../vmtb/bench/machines/machine_interface.py  |   6 +-
>   tools/vmtb/bench/machines/virtual/device.py   | 179 ++++++++++++++++++
>   tools/vmtb/bench/machines/virtual/vm.py       |   5 +
>   5 files changed, 198 insertions(+), 11 deletions(-)
>   create mode 100644 tools/vmtb/bench/machines/virtual/device.py
>
> diff --git a/tools/vmtb/bench/machines/device_interface.py b/tools/vmtb/bench/machines/device_interface.py
> index e8d4068e8..0eff493f0 100644
> --- a/tools/vmtb/bench/machines/device_interface.py
> +++ b/tools/vmtb/bench/machines/device_interface.py
> @@ -1,19 +1,13 @@
>   # SPDX-License-Identifier: MIT
> -# Copyright © 2024 Intel Corporation
> +# Copyright © 2024-2026 Intel Corporation
>   
>   import abc
>   
>   
>   class DeviceInterface(abc.ABC):
> -
> -    @abc.abstractmethod
> -    def create_vf(self, num: int) -> int:
> -        raise NotImplementedError
> -
> -    @abc.abstractmethod
> -    def remove_vfs(self) -> int:
> -        raise NotImplementedError
> -
> +    """Base class for devices (Physical and Virtual).
> +    Provide common operations for all devices like bind/unbind driver.
> +    """
>       @abc.abstractmethod
>       def bind_driver(self) -> None:
>           raise NotImplementedError
> diff --git a/tools/vmtb/bench/machines/host.py b/tools/vmtb/bench/machines/host.py
> index aecc7709a..b6cfb62ef 100644
> --- a/tools/vmtb/bench/machines/host.py
> +++ b/tools/vmtb/bench/machines/host.py
> @@ -99,6 +99,11 @@ class Host(MachineInterface):
>       def dir_exists(self, path: str) -> bool:
>           return Path(path).is_dir()
>   
> +    def dir_list(self, path: str) -> typing.List[str]:
> +        # TODO: implement, currently no-op to fulfill MachineInterface requirement
> +        logger.warning("Host.dir_list() is not implemented yet!")
> +        return []
> +
>       def get_drm_driver_name(self) -> str:
>           # Used as a part of MachineInterface for helpers
>           return self.drm_driver_name
> diff --git a/tools/vmtb/bench/machines/machine_interface.py b/tools/vmtb/bench/machines/machine_interface.py
> index 8daa2cda3..d67c3db74 100644
> --- a/tools/vmtb/bench/machines/machine_interface.py
> +++ b/tools/vmtb/bench/machines/machine_interface.py
> @@ -1,5 +1,5 @@
>   # SPDX-License-Identifier: MIT
> -# Copyright © 2024 Intel Corporation
> +# Copyright © 2024-2026 Intel Corporation
>   
>   import abc
>   import enum
> @@ -56,6 +56,10 @@ class MachineInterface(metaclass=abc.ABCMeta):
>       def dir_exists(self, path: str) -> bool:
>           raise NotImplementedError
>   
> +    @abc.abstractmethod
> +    def dir_list(self, path: str) -> typing.List[str]:
> +        raise NotImplementedError
> +
>       @abc.abstractmethod
>       def get_drm_driver_name(self) -> str:
>           raise NotImplementedError
> diff --git a/tools/vmtb/bench/machines/virtual/device.py b/tools/vmtb/bench/machines/virtual/device.py
> new file mode 100644
> index 000000000..c838db59d
> --- /dev/null
> +++ b/tools/vmtb/bench/machines/virtual/device.py
> @@ -0,0 +1,179 @@
> +# SPDX-License-Identifier: MIT
> +# Copyright © 2025-2026 Intel Corporation
> +
> +import logging
> +import re
> +import typing
> +
> +from bench import exceptions
> +from bench.configurators import pci
> +from bench.drivers.driver_interface import DriverInterface, VfDriver
> +from bench.machines.device_interface import DeviceInterface
> +from bench.machines.machine_interface import MachineInterface
> +
> +logger = logging.getLogger('VirtualDevice')
> +
> +
> +class VirtualDevice(DeviceInterface):
> +    class PciInfo:
> +        def __init__(self, bdf: str, vm: MachineInterface) -> None:
> +            self.bdf: str = bdf
> +            self.vm: MachineInterface = vm
> +            self.devid: str = self.get_device_id(self.bdf)
> +            self.minor_number: int = self.get_device_minor_number(self.bdf)
> +
> +        def get_device_minor_number(self, bdf: str) -> int:
> +            drm_dir = f'/sys/bus/pci/devices/{bdf}/drm'
> +
> +            for dir_name in self.vm.dir_list(drm_dir):
> +                if 'card' in dir_name:
> +                    index_match = re.match(r'card(?P<card_index>\d+)', dir_name)
> +                    if index_match:
> +                        return int(index_match.group('card_index'))
> +
> +            logger.error("Could not determine minor number (card index) for device %s", bdf)
> +            raise exceptions.HostError(f'Could not determine minor number (card index) for device {bdf}')
> +
> +        def get_device_id(self, bdf: str) -> str:
> +            device_file = f'/sys/bus/pci/devices/{bdf}/device'
> +            devid = self.vm.read_file_content(device_file)
> +
> +            return devid.strip()[2:] # Strip whitespaces and 0x
> +
> +    def __init__(self, bdf: str, vm: MachineInterface) -> None:
> +        self.pci_info = self.PciInfo(bdf, vm)
> +        self.gpu_model = pci.get_gpu_model(self.pci_info.devid)
> +        # Reference to VirtualMachine - required for Guest-Agent use (e.g. guest file read/write):
> +        self.vm: MachineInterface = vm
> +        self.driver: DriverInterface = VfDriver(self.pci_info.bdf, self.vm)
> +
> +        # Resources provisioned to the VF/VM:
> +        self._lmem_size: typing.Optional[int] = None
> +        self._ggtt_size: typing.Optional[int] = None
> +        self._contexts: typing.Optional[int] = None
> +        self._doorbells: typing.Optional[int] = None
> +        # Tile mask is relevant for multi-tile devices:
> +        self._tile_mask: typing.Optional[int] = None
> +
> +    def __str__(self) -> str:
> +        return f'VirtualDevice-{self.pci_info.bdf}'
> +
> +    def bind_driver(self) -> None:
> +        logger.debug("Bind %s driver to virtual device - PCI BDF: %s",
> +                     self.vm.get_drm_driver_name(), self.pci_info.bdf)
> +        self.driver.bind()
> +
> +    def unbind_driver(self) -> None:
> +        logger.debug("Unbind %s driver from virtual device - PCI BDF: %s",
> +                     self.vm.get_drm_driver_name(), self.pci_info.bdf)
> +        self.driver.unbind()
> +
> +    @property
> +    def lmem_size(self) -> typing.Optional[int]:
> +        if self._lmem_size is None:
> +            self.get_debugfs_selfconfig()
> +
> +        return self._lmem_size
> +
> +    @property
> +    def ggtt_size(self) -> typing.Optional[int]:
> +        if self._ggtt_size is None:
> +            self.get_debugfs_selfconfig()
> +
> +        return self._ggtt_size
> +
> +    @property
> +    def contexts(self) -> typing.Optional[int]:
> +        if self._contexts is None:
> +            self.get_debugfs_selfconfig()
> +
> +        return self._contexts
> +
> +    @property
> +    def doorbells(self) -> typing.Optional[int]:
> +        if self._doorbells is None:
> +            self.get_debugfs_selfconfig()
> +
> +        return self._doorbells
> +
> +    @property
> +    def tile_mask(self) -> typing.Optional[int]:
> +        if self._tile_mask is None:
> +            self.get_debugfs_selfconfig()
> +
> +        return self._tile_mask
> +
> +    def get_num_gts(self) -> int:
> +        """Get number of GTs for a device based on exposed sysfs gt nodes."""
> +        gt_num = 0
> +        # Fixme: tile0 only at the moment, add support for multiple tiles if needed
> +        path = self.driver.sysfs_device_path / 'tile0'
> +
> +        if self.vm.dir_exists(str(path / 'gt')):
> +            gt_num = 1
> +        else:
> +            while self.vm.dir_exists(str(path / f'gt{gt_num}')):
> +                gt_num += 1
> +
> +        return gt_num
> +
> +    # helper_convert_units_to_bytes - convert size with units to bytes
> +    # @size_str: multiple-byte unit size with suffix (K/M/G)
> +    # Returns: size in bytes
> +    # TODO: function perhaps could be moved to some new utils module
> +    # improve - consider regex to handle various formats eg. both M and MB
> +    def helper_convert_units_to_bytes(self, size_str: str) -> int:
> +        size_str = size_str.upper()
> +        size_int = 0
> +
> +        if size_str.endswith('B'):
> +            size_int = int(size_str[0:-1])
> +        elif size_str.endswith('K'):
> +            size_int = int(size_str[0:-1]) * 1024
> +        elif size_str.endswith('M'):
> +            size_int = int(size_str[0:-1]) * 1024**2
> +        elif size_str.endswith('G'):
> +            size_int = int(size_str[0:-1]) * 1024**3
> +
> +        return size_int
> +
> +    # __parse_selfconfig_size - parses size string from debugfs/self_config
> +    # GGTT/LMEM size on xe has the following format:
> +    # GGTT size:      536870912 (512 MiB)
> +    # whereas on i915 (unit suffix):
> +    # GGTT size:     524288K
> +    # @size_str: size string read from self_config file
> +    # (with unit suffix (B/K/M/G) or in bytes (without suffix))
> +    # Returns: size in bytes
> +    def __parse_selfconfig_size(self, size_str: str) -> int:
> +        retval = 0
> +        size_match = re.search(r'(?P<size_units>^\d+[BKMG])|(?P<size_bytes>^\d+)', size_str.strip())
> +        if size_match:
> +            if size_match.group('size_units'):
> +                # i915 specific format (in B/K/M/G units)
> +                retval = self.helper_convert_units_to_bytes(size_match.group('size_units'))
> +            elif size_match.group('size_bytes'):
> +                # Xe specific format (in Bytes)
> +                retval = int(size_match.group('size_bytes'))
> +            else:
> +                logger.warning("Unexpected size pattern match!")
> +
> +        return retval
> +
> +    def get_debugfs_selfconfig(self, gt_num: int = 0) -> None:
> +        """Read hard resources allocated to VF from debugfs selfconfig file."""
> +        out = self.driver.read_debugfs(f'gt{gt_num}/vf/self_config')
> +
> +        for line in out.splitlines():
> +            param, value = line.split(':')
> +
> +            if param == 'GGTT size':
> +                self._ggtt_size = self.__parse_selfconfig_size(value)
> +            elif param == 'LMEM size':
> +                self._lmem_size = self.__parse_selfconfig_size(value)
> +            elif param.find('contexts') != -1:
> +                self._contexts = int(value)
> +            elif param.find('doorbells') != -1:
> +                self._doorbells = int(value)
> +            elif param == 'tile mask':
> +                self._tile_mask = int(value, base=16)
> diff --git a/tools/vmtb/bench/machines/virtual/vm.py b/tools/vmtb/bench/machines/virtual/vm.py
> index 9f4ca1de7..312e87e4b 100644
> --- a/tools/vmtb/bench/machines/virtual/vm.py
> +++ b/tools/vmtb/bench/machines/virtual/vm.py
> @@ -518,6 +518,11 @@ class VirtualMachine(MachineInterface):
>               return False
>           return True
>   
> +    def dir_list(self, path: str) -> typing.List[str]:
> +        # TODO: implement, currently no-op to fulfill MachineInterface requirement
> +        logger.warning("VirtualMachine.dir_list() is not implemented yet!")
> +        return []
> +
LGTM,
Reviewed-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
>       def link_exists(self, path: str) -> bool:
>           pid = self.execute(f'/bin/sh -c "[ -h {path} ]"')
>           status = self.execute_wait(pid)

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH i-g-t 08/10] tools/vmtb: Redesign VirtualMachine class
  2026-02-24  7:50 ` [PATCH i-g-t 08/10] tools/vmtb: Redesign VirtualMachine class Adam Miszczak
@ 2026-03-10 10:47   ` Bernatowicz, Marcin
  0 siblings, 0 replies; 25+ messages in thread
From: Bernatowicz, Marcin @ 2026-03-10 10:47 UTC (permalink / raw)
  To: Adam Miszczak, igt-dev; +Cc: kamil.konieczny


On 2/24/2026 8:50 AM, Adam Miszczak wrote:
> Split original VirtualMachine class into specialized abstractions:
> VirtualMachine, VirtualDevice and VfDriver.
> Extend new VirtualMachine with new functions to load and remove DRM driver
> and discover devices on Guest OS.
>
> Redesigned abstractions have the following responsibilities:
> - VirtualMachine supports operations like start/stop VM, load/unload driver,
>    enumerate virtual devices, execute process on guest,
>    power states handling, save/load state etc.
> - VirtualDevice represents GPU device visible on a guest OS
>    (resources allocated to VF, local PCI BDF, Device ID)
> - VfDriver handles low-level functions of virtual device
>    as sysfs/debugfs access
>
> New implementation provides placeholders for multiple VFs passed to VM,
> but currently only single VF (one virtual GPU per VM) is supported.
>
> Additionally, create separate VM/Guest kernel log files,
> located in a root VMTB directory.
> VM dmesg is also propagated to logfile.log as previously.
>
> Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
> ---
>   tools/vmtb/bench/machines/virtual/vm.py | 252 +++++++++++-------------
>   tools/vmtb/vmm_flows/conftest.py        |   7 +-
>   2 files changed, 116 insertions(+), 143 deletions(-)
>
> diff --git a/tools/vmtb/bench/machines/virtual/vm.py b/tools/vmtb/bench/machines/virtual/vm.py
> index 312e87e4b..2469af965 100644
> --- a/tools/vmtb/bench/machines/virtual/vm.py
> +++ b/tools/vmtb/bench/machines/virtual/vm.py
> @@ -4,14 +4,14 @@
>   import base64
>   import json
>   import logging
> -import os
> -import posixpath
> +import re
>   import shlex
>   import signal
>   import subprocess
>   import threading
>   import time
>   import typing
> +from pathlib import Path
>   from types import FrameType
>   
>   from bench import exceptions
> @@ -21,6 +21,7 @@ from bench.machines.machine_interface import (DEFAULT_TIMEOUT,
>                                                 SuspendMode)
>   from bench.machines.virtual.backends.guestagent import GuestAgentBackend
>   from bench.machines.virtual.backends.qmp_monitor import QmpMonitor
> +from bench.machines.virtual.device import VirtualDevice
>   
>   logger = logging.getLogger('VirtualMachine')
>   
> @@ -60,40 +61,34 @@ class VirtualMachine(MachineInterface):
>   
>       def __init__(self, vm_number: int, backing_image: str, driver: str,
>                    igt_config: VmtbIgtConfig, vf_migration_support: bool) -> None:
> -        self.vf_bdf: typing.Optional[str] = None
> -        self.process: typing.Optional[subprocess.Popen] = None
>           self.vmnum: int = vm_number
> -        self.card_num: int = 0
> -        self.sysfs_prefix_path = posixpath.join('/sys/class/drm/', f'card{str(self.card_num)}')
> -        self.questagent_sockpath = posixpath.join('/tmp', f'qga{self.vmnum}.sock')
> -        self.qmp_sockpath = posixpath.join('/tmp', f'mon{self.vmnum}.sock')
>           self.drm_driver_name: str = driver
>           self.igt_config: VmtbIgtConfig = igt_config
>           self.vf_migration: bool = vf_migration_support
>   
> -        if not posixpath.exists(backing_image):
> +        # Passed VFs and VirtualDevices list - placeholder for multiple VFs passed to single VM:
> +        # currently only one VF/VirtualDevice per VM supported (ie. passed_vf_bdfs[0]).
> +        # TODO: add support for multiple VFs/VirtualDevices per VM
> +        self.passed_vf_bdfs: typing.List[str] = []
> +        self.gpu_devices: typing.List[VirtualDevice] = []
> +        self.process: typing.Optional[subprocess.Popen] = None
> +
> +        self.questagent_sockpath = Path('/tmp') / f'qga{self.vmnum}.sock'
> +        self.qmp_sockpath = Path('/tmp') / f'mon{self.vmnum}.sock'
> +
> +        if not Path(backing_image).exists():
>               logger.error('No image for VM%s', self.vmnum)
>               raise exceptions.GuestError(f'No image for VM{self.vmnum}')
> +
>           self.image: str = self.__create_qemu_image(backing_image)
> +
>           self.migrate_source_image: typing.Optional[str] = None
>           self.migrate_destination_vm: bool = False
>   
> -        # Resources provisioned to the VF/VM:
> -        self._lmem_size: typing.Optional[int] = None
> -        self._ggtt_size: typing.Optional[int] = None
> -        self._contexts: typing.Optional[int] = None
> -        self._doorbells: typing.Optional[int] = None
> -
> -        # GT number and tile is relevant mainly for multi-tile devices
> -        # List of all GTs used by a given VF:
> -        # - for single-tile: only root [0]
> -        # - for multi-tile Mode 2/3: either root [0] or remote [1]
> -        # - for multi-tile Mode 1: spans on both tiles [0, 1]
> -        self._gt_nums: typing.List[int] = []
> -        self._tile_mask: typing.Optional[int] = None
> +        self.dmesg_logger = self.__setup_dmesg_logger()
>   
>       def __str__(self) -> str:
> -        return f'VM{self.vmnum}_{self.vf_bdf}'
> +        return f'VM{self.vmnum}-VF:{self.passed_vf_bdfs[0] if self.passed_vf_bdfs else 'N/A'}'
>   
>       def __del__(self) -> None:
>           if not self.is_running():
> @@ -112,6 +107,18 @@ class VirtualMachine(MachineInterface):
>               print('QEMU did not terminate, killing it')
>               self.process.kill()
>   
> +    def __setup_dmesg_logger(self) -> logging.Logger:
> +        """Configure VM dmesg logger.
> +        Logs are directed to dedicated vm[NUM]_dmesg.log and propagated to logfile.log.
> +        """
> +        dmesg_logger = logging.getLogger(f'VM{self.vmnum}-kmsg')
> +        # Remove any existing logger handlers to avoid duplicated prints for parametrized tests
> +        dmesg_logger.handlers.clear()
> +        dmesg_log_handler = logging.FileHandler(f'vm{self.vmnum}_dmesg.log')
> +        dmesg_logger.addHandler(dmesg_log_handler)
> +
> +        return dmesg_logger
> +
>       def __get_backing_file_format(self, backing_file: str) -> typing.Any:
>           """Get the format of the backing image file using qemu-img info."""
>           command = ['qemu-img', 'info', '--output=json', backing_file]
> @@ -143,14 +150,13 @@ class VirtualMachine(MachineInterface):
>           return output_image
>   
>       def __log_qemu_output(self, out: typing.TextIO) -> None:
> -        stdoutlog = logging.getLogger(f'VM{self.vmnum}-kmsg')
>           for line in iter(out.readline, ''):
> -            stdoutlog.debug(line.strip())
> +            self.dmesg_logger.debug(line.strip())
>   
>       def __sockets_exists(self) -> bool:
> -        return os.path.exists(self.questagent_sockpath) and os.path.exists(self.qmp_sockpath)
> +        return self.questagent_sockpath.exists() and self.qmp_sockpath.exists()
>   
> -    def __get_popen_command(self) -> typing.List[str]:
> +    def __prepare_qemu_command(self) -> typing.List[str]:
>           command = ['qemu-system-x86_64',
>                      '-vnc', f':{self.vmnum}',
>                      '-serial', 'stdio',
> @@ -165,8 +171,8 @@ class VirtualMachine(MachineInterface):
>                      '-chardev', f'socket,id=mon{self.vmnum},path=/tmp/mon{self.vmnum}.sock,server=on,wait=off',
>                      '-mon', f'chardev=mon{self.vmnum},mode=control']
>   
> -        if self.vf_bdf:
> -            command.extend(['-enable-kvm', '-cpu', 'host', '-device', f'vfio-pci,host={self.vf_bdf}'])
> +        if self.passed_vf_bdfs:
> +            command.extend(['-enable-kvm', '-cpu', 'host', '-device', f'vfio-pci,host={self.passed_vf_bdfs[0]}'])
>               if self.vf_migration:
>                   command[-1] += ',enable-migration=on'
>   
> @@ -185,77 +191,82 @@ class VirtualMachine(MachineInterface):
>               cur = cur[key]
>           return cur
>   
> -    @property
> -    def get_vm_num(self) -> int:
> -        return self.vmnum
> -
>       def assign_vf(self, vf_bdf: str) -> None:
> -        self.vf_bdf = vf_bdf
> +        """Pass VFs to VM - required to run QEMU (prior to VM power on)"""
> +        self.passed_vf_bdfs.append(vf_bdf)
>   
>       def set_migration_source(self, src_image: str) -> None:
>           self.migrate_source_image = src_image
>           self.migrate_destination_vm = True
>   
> -    @property
> -    def lmem_size(self) -> typing.Optional[int]:
> -        if self._lmem_size is None:
> -            self.helper_get_debugfs_selfconfig()
> -
> -        return self._lmem_size
> -
> -    @property
> -    def ggtt_size(self) -> typing.Optional[int]:
> -        if self._ggtt_size is None:
> -            self.helper_get_debugfs_selfconfig()
> -
> -        return self._ggtt_size
> -
> -    @property
> -    def contexts(self) -> typing.Optional[int]:
> -        if self._contexts is None:
> -            self.helper_get_debugfs_selfconfig()
> -
> -        return self._contexts
> -
> -    @property
> -    def doorbells(self) -> typing.Optional[int]:
> -        if self._doorbells is None:
> -            self.helper_get_debugfs_selfconfig()
> -
> -        return self._doorbells
> -
> -    @property
> -    def tile_mask(self) -> typing.Optional[int]:
> -        if self._tile_mask is None:
> -            self.helper_get_debugfs_selfconfig()
> -
> -        return self._tile_mask
> -
> -    @property
> -    def gt_nums(self) -> typing.List[int]:
> -        self._gt_nums = self.get_gt_num_from_sysfs()
> -        if not self._gt_nums:
> -            logger.warning("VM sysfs: missing GT index")
> -            self._gt_nums = [0]
> -
> -        return self._gt_nums
> -
> -    def get_gt_num_from_sysfs(self) -> typing.List[int]:
> -        # Get GT number of VF passed to a VM, based on an exisitng a sysfs path
> -        vm_gt_num = []
> -        if self.dir_exists(posixpath.join(self.sysfs_prefix_path, 'gt/gt0')):
> -            vm_gt_num.append(0)
> -        if self.dir_exists(posixpath.join(self.sysfs_prefix_path, 'gt/gt1')):
> -            vm_gt_num.append(1)
> -
> -        return vm_gt_num
> -
>       def get_drm_driver_name(self) -> str:
>           return self.drm_driver_name
>   
>       def get_igt_config(self) -> VmtbIgtConfig:
>           return self.igt_config
>   
> +    def get_dut(self) -> VirtualDevice:
> +        # Currently only one first enumerated device is supported (virtual card0)
> +        return self.gpu_devices[0]
> +
> +    def is_drm_driver_loaded(self) -> bool:
> +        return self.dir_exists(f'/sys/bus/pci/drivers/{self.drm_driver_name}')
> +
> +    def load_drm_driver(self) -> None:
> +        """Load (modprobe) guest DRM driver."""
> +        if not self.is_drm_driver_loaded():
> +            logger.debug("VirtualMachine - load DRM driver")
> +            drv_probe_pid = self.execute(f'modprobe {self.drm_driver_name}')
> +            if self.execute_wait(drv_probe_pid).exit_code != 0:
> +                logger.error("%s driver probe failed on guest!", self.drm_driver_name)
> +                raise exceptions.GuestError(f'{self.drm_driver_name} driver probe failed on guest!')
> +
> +    def unload_drm_driver(self) -> None:
> +        """Unload (remove) guest DRM driver."""
> +        logger.debug("VirtualMachine - unload DRM driver")
> +        for device in self.gpu_devices:
> +            logger.debug("Unbind %s from virtual device %s", self.drm_driver_name, device.pci_info.bdf)
> +            device.unbind_driver()
> +
> +        rmmod_pid = self.execute(f'modprobe -rf {self.drm_driver_name}')
> +        if self.execute_wait(rmmod_pid).exit_code != 0:
> +            logger.error("DRM driver remove failed!")
> +            raise exceptions.HostError('DRM driver remove failed!')
> +
> +        logger.debug("%s successfully removed", self.drm_driver_name)
> +
> +    def discover_devices(self) -> None:
> +        """Detect all (virtual) PCI GPU devices on the guest and initialize VirtualDevice list."""
> +        if not self.is_drm_driver_loaded():
> +            logger.error("Unable to discover devices on guest - %s driver is not loaded!", self.drm_driver_name)
> +            raise exceptions.HostError(
> +                f'Unable to discover devices on guest - {self.drm_driver_name} driver is not loaded!')
> +
> +        detected_devices: typing.List[VirtualDevice] = []
> +        drv_path = Path('/sys/bus/pci/drivers/') / self.drm_driver_name
> +
> +        dev_dir_ls = self.dir_list(str(drv_path))
> +
> +        # Look for a directory name with a PCI BDF (e.g. 0000:1a:00.0)
> +        for bdf in dev_dir_ls:
> +            match = re.match(r'\d{4}(?::[0-9a-z-A-Z]{2}){2}.[0-7]', bdf)
> +            if match:
> +                device = VirtualDevice(bdf, self)
> +                detected_devices.append(device)
> +
> +        # Output list of detected devices sorted by an ascending card index (device minor number)
> +        self.gpu_devices = sorted(detected_devices, key=lambda dev: dev.pci_info.minor_number)
> +
> +        if not self.gpu_devices:
> +            logger.error("Virtualized GPU PCI device (bound to %s driver) not detected!", self.drm_driver_name)
> +            raise exceptions.GuestError(
> +                f'Virtualized GPU PCI device (bound to {self.drm_driver_name} driver) not detected!')
> +
> +        logger.debug("Detected virtualized GPU PCI device(s):")
> +        for dev in self.gpu_devices:
> +            logger.debug("[virtual card%s] PCI BDF: %s / DevID: %s (%s)",
> +                          dev.pci_info.minor_number, dev.pci_info.bdf, dev.pci_info.devid, dev.gpu_model)
> +
>       @Decorators.timeout_signal
>       def poweron(self) -> None:
>           logger.debug('Powering on VM%s', self.vmnum)
> @@ -263,7 +274,7 @@ class VirtualMachine(MachineInterface):
>               logger.warning('VM%s already running', self.vmnum)
>               return
>   
> -        command = self.__get_popen_command()
> +        command = self.__prepare_qemu_command()
>           # We don't want to kill the process created here (like 'with' would do) so disable the following linter issue:
>           # R1732: consider-using-with (Consider using 'with' for resource-allocating operations)
>           # pylint: disable=R1732
> @@ -292,8 +303,8 @@ class VirtualMachine(MachineInterface):
>                   logger.info('waiting for socket')
>                   time.sleep(1)
>               # Passing five minutes timeout for every command
> -            self.ga = GuestAgentBackend(self.questagent_sockpath, 300)
> -            self.qm = QmpMonitor(self.qmp_sockpath, 300)
> +            self.ga = GuestAgentBackend(str(self.questagent_sockpath), 300)
> +            self.qm = QmpMonitor(str(self.qmp_sockpath), 300)
>               vm_status = self.qm.query_status()
>   
>               if not self.migrate_destination_vm and vm_status != 'running':
> @@ -317,6 +328,7 @@ class VirtualMachine(MachineInterface):
>   
>       @Decorators.timeout_signal
>       def poweroff(self) -> None:
> +        """Power off VM via the Guest-Agent guest-shutdown(powerdown) command."""
>           logger.debug('Powering off VM%s', self.vmnum)
>           assert self.process
>           if not self.is_running():
> @@ -338,8 +350,9 @@ class VirtualMachine(MachineInterface):
>   
>               if self.__sockets_exists():
>                   # Remove leftovers and notify about unclear qemu shutdown
> -                os.remove(self.questagent_sockpath)
> -                os.remove(self.qmp_sockpath)
> +                self.questagent_sockpath.unlink()
> +                self.qmp_sockpath.unlink()
> +                logger.error('VM%s was not gracefully powered off - sockets exist', self.vmnum)
>                   raise exceptions.GuestError(f'VM{self.vmnum} was not gracefully powered off - sockets exist')
>   
>       def reboot(self) -> None:
> @@ -441,7 +454,7 @@ class VirtualMachine(MachineInterface):
>           ret = execout.get('return')
>           if ret:
>               pid: int = ret.get('pid')
> -            logger.debug('Running %s on VM%s with pid %s', command, self.vmnum, pid)
> +            logger.debug("Run command on VM%s: %s (PID: %s)", self.vmnum, command, pid)
>               return pid
>   
>           logger.error('Command %s did not return pid', command)
> @@ -519,9 +532,12 @@ class VirtualMachine(MachineInterface):
>           return True
>   
>       def dir_list(self, path: str) -> typing.List[str]:
> -        # TODO: implement, currently no-op to fulfill MachineInterface requirement
> -        logger.warning("VirtualMachine.dir_list() is not implemented yet!")
> -        return []
> +        pid = self.execute(f'/bin/sh -c "ls {path}"')
> +        status: ProcessResult = self.execute_wait(pid)
> +        if status.exit_code:
> +            raise exceptions.GuestError(f'VM ls failed - error: {status.exit_code}')
> +
> +        return status.stdout.split()
>   
>       def link_exists(self, path: str) -> bool:
>           pid = self.execute(f'/bin/sh -c "[ -h {path} ]"')
> @@ -571,45 +587,3 @@ class VirtualMachine(MachineInterface):
>               raise exceptions.GuestError(f'VM{self.vmnum} state load error: {job_error}')
>   
>           logger.debug('VM state load finished successfully')
> -
> -    # helper_convert_units_to_bytes - convert size with units to bytes
> -    # @size_str: multiple-byte unit size with suffix (K/M/G)
> -    # Returns: size in bytes
> -    # TODO: function perhaps could be moved to some new utils module
> -    # improve - consider regex to handle various formats eg. both M and MB
> -    def helper_convert_units_to_bytes(self, size_str: str) -> int:
> -        size_str = size_str.upper()
> -        size_int = 0
> -
> -        if size_str.endswith('B'):
> -            size_int = int(size_str[0:-1])
> -        elif size_str.endswith('K'):
> -            size_int = int(size_str[0:-1]) * 1024
> -        elif size_str.endswith('M'):
> -            size_int = int(size_str[0:-1]) * 1024**2
> -        elif size_str.endswith('G'):
> -            size_int = int(size_str[0:-1]) * 1024**3
> -
> -        return size_int
> -
> -    # helper_get_debugfs_selfconfig - read resources allocated to VF from debugfs:
> -    # /sys/kernel/debug/dri/@card/gt@gt_num/iov/self_config
> -    # @card: card number
> -    # @gt_num: GT instance number
> -    def helper_get_debugfs_selfconfig(self, card: int = 0, gt_num: int = 0) -> None:
> -        path = posixpath.join(f'/sys/kernel/debug/dri/{card}/gt{gt_num}/iov/self_config')
> -        out = self.read_file_content(path)
> -
> -        for line in out.splitlines():
> -            param, value = line.split(':')
> -
> -            if param == 'GGTT size':
> -                self._ggtt_size = self.helper_convert_units_to_bytes(value)
> -            elif param == 'LMEM size':
> -                self._lmem_size = self.helper_convert_units_to_bytes(value)
> -            elif param == 'contexts':
> -                self._contexts = int(value)
> -            elif param == 'doorbells':
> -                self._doorbells = int(value)
> -            elif param == 'tile mask':
> -                self._tile_mask = int(value, base=16)
> diff --git a/tools/vmtb/vmm_flows/conftest.py b/tools/vmtb/vmm_flows/conftest.py
> index a2a6b6680..ae149d652 100644
> --- a/tools/vmtb/vmm_flows/conftest.py
> +++ b/tools/vmtb/vmm_flows/conftest.py
> @@ -16,7 +16,6 @@ from bench.configurators.vgpu_profile_config import (VfProvisioningMode,
>                                                        VfSchedulingMode,
>                                                        VgpuProfileConfigurator)
>   from bench.configurators.vmtb_config import VmtbConfigurator
> -from bench.helpers.helpers import modprobe_driver, modprobe_driver_check
>   from bench.helpers.log import HOST_DMESG_FILE
>   from bench.machines.host import Device, Host
>   from bench.machines.virtual.vm import VirtualMachine
> @@ -273,9 +272,9 @@ def fixture_setup_vms(get_vmtb_config, get_cmdline_config, get_host, request):
>           ts.poweron_vms()
>   
>           if tc.auto_probe_vm_driver:
> -            modprobe_cmds = [modprobe_driver(vm) for vm in ts.get_vm]
> -            for i, cmd in enumerate(modprobe_cmds):
> -                assert modprobe_driver_check(ts.get_vm[i], cmd), f'modprobe failed on VM{i}'
> +            for vm in ts.get_vm:
> +                vm.load_drm_driver()
> +                vm.discover_devices()
LGTM,
Reviewed-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
>   
>       logger.info('[Test execution: %sVF-%sVM]', num_vfs, num_vms)
>       yield ts

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH i-g-t 09/10] tools/vmtb: Support max VFs configuration
  2026-02-24  7:50 ` [PATCH i-g-t 09/10] tools/vmtb: Support max VFs configuration Adam Miszczak
@ 2026-03-10 10:52   ` Bernatowicz, Marcin
  0 siblings, 0 replies; 25+ messages in thread
From: Bernatowicz, Marcin @ 2026-03-10 10:52 UTC (permalink / raw)
  To: Adam Miszczak, igt-dev; +Cc: kamil.konieczny


On 2/24/2026 8:50 AM, Adam Miszczak wrote:
> Enable maximum VFs test configuration variant, for both:
> auto-provisioning and vGPU profiles.
> Max VFs is device-specific value read via sysfs.
> For auto-provisioning, max VFs always equals sysfs/sriov_totalvfs,
> but the highest supported number of VFs defined by vGPU profiles
> may differ from the hardware max value.
>
> Max VFs test config variant can be requested by passing MAX_VFS label
> to VmmTestingConfig structure (num_vfs) or convenience tuple, for example:
> test_variants = [(MAX_VFS, VfProvisioningMode.AUTO, VfSchedulingMode.INFINITE),
>                   (MAX_VFS, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE)]
>
> Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
> ---
>   tools/vmtb/vmm_flows/conftest.py | 29 ++++++++++++++++++++++++++---
>   1 file changed, 26 insertions(+), 3 deletions(-)
>
> diff --git a/tools/vmtb/vmm_flows/conftest.py b/tools/vmtb/vmm_flows/conftest.py
> index ae149d652..02c297f93 100644
> --- a/tools/vmtb/vmm_flows/conftest.py
> +++ b/tools/vmtb/vmm_flows/conftest.py
> @@ -32,6 +32,10 @@ def pytest_addoption(parser):
>                        help='Device card index for test execution')
>   
>   
> +# Label indicating Max VFs configurarion variant, intended for pass to VmmTestingConfig.
> +MAX_VFS = "Max"
> +
> +
>   @dataclass
>   class VmmTestingConfig:
>       """Structure represents test configuration used by a setup fixture.
> @@ -54,16 +58,23 @@ class VmmTestingConfig:
>       auto_poweron_vm: bool = True
>       auto_probe_vm_driver: bool = True
>       unload_host_drivers_on_teardown: bool = False
> +    enable_max_vfs: bool = False
>       # Temporary W/A: reduce size of LMEM assigned to VFs to speed up a VF state save-restore process
>       wa_reduce_vf_lmem: bool = False
>   
> +    def __post_init__(self):
> +        if self.num_vfs is MAX_VFS:
> +            self.enable_max_vfs = True
> +            self.num_vfs = 0 # Actual value set in VmmTestingSetup
> +
>       def __str__(self) -> str:
> -        test_config_id = f'{self.num_vfs}VF-(P:{self.provisioning_mode.name} S:{self.scheduling_mode.name})'
> +        test_config_id = (f'{self.num_vfs if not self.enable_max_vfs else "Max"}VF'
> +                          + f'-(P:{self.provisioning_mode.name} S:{self.scheduling_mode.name})')
>           return test_config_id
>   
>       def __repr__(self) -> str:
>           return (f'\nVmmTestingConfig:'
> -                f'\nNum VFs = {self.num_vfs} / max num VMs = {self.max_num_vms}'
> +                f'\nNum VFs = {self.num_vfs if not self.enable_max_vfs else "Max"} / max num VMs = {self.max_num_vms}'
>                   f'\nVF provisioning mode = {self.provisioning_mode.name}'
>                   f'\nVF scheduling mode = {self.scheduling_mode.name}'
>                   f'\nSetup flags:'
> @@ -89,6 +100,7 @@ class VmmTestingSetup:
>           self.host.load_drivers()
>           self.host.discover_devices()
>           self.dut: Device = self.host.get_device(self.dut_index)
> +        self.total_vfs: int = self.get_dut().driver.get_totalvfs()
>   
>           # VF migration requires vendor specific VFIO driver (e.g. xe-vfio-pci)
>           vf_migration_support: bool = self.host.is_driver_loaded(f'{self.host.drm_driver_name}-vfio-pci')
> @@ -98,11 +110,13 @@ class VmmTestingSetup:
>                       "\n\tPCI BDF: %s "
>                       "\n\tDevice ID: %s (%s)"
>                       "\n\tHost DRM driver: %s"
> -                    "\n\tVF migration support: %s",
> +                    "\n\tMax VFs supported: %s"
> +                    "\n\tVF migration supported: %s",
>                       self.dut_index,
>                       self.get_dut().pci_info.bdf,
>                       self.get_dut().pci_info.devid, self.get_dut().gpu_model,
>                       self.get_dut().driver.get_name(),
> +                    self.total_vfs,
>                       vf_migration_support)
>   
>           vmtb_root_path = vmtb_config.vmtb_config_file.parent
> @@ -115,6 +129,9 @@ class VmmTestingSetup:
>               or self.testing_config.scheduling_mode is not VfSchedulingMode.INFINITE):
>               self.vgpu_profile: VgpuProfile = self.get_vgpu_profile()
>   
> +        if self.testing_config.provisioning_mode is VfProvisioningMode.AUTO and self.testing_config.enable_max_vfs:
> +            self.testing_config.num_vfs = self.total_vfs
> +
>           # Start maximum requested number of VMs, but not more than VFs supported by the given vGPU profile
>           self.vms: typing.List[VirtualMachine] = [
>               VirtualMachine(vm_idx, self.guest_os_image,
> @@ -125,6 +142,12 @@ class VmmTestingSetup:
>   
>       def get_vgpu_profile(self) -> VgpuProfile:
>           configurator = VgpuProfileConfigurator(self.vgpu_profiles_dir, self.get_dut().gpu_model)
> +        if self.testing_config.enable_max_vfs:
> +            # Get a vGPU profile with the most VFs (not necessarily equal to sysfs/sriov_totalvfs)
> +            self.testing_config.num_vfs = max(configurator.supported_vgpu_profiles.vf_resources,
> +                                              key=lambda profile: profile.vf_count).vf_count
> +            logger.debug("Max VFs supported by vGPU profiles: %s", self.testing_config.num_vfs)
> +
LGTM,
Reviewed-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
>           try:
>               vgpu_profile = configurator.get_vgpu_profile(self.testing_config.num_vfs,
>                                                            self.testing_config.scheduling_mode)

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH i-g-t 10/10] tools/vmtb: Platform enabling: PTL and BMG support
  2026-02-24  7:50 ` [PATCH i-g-t 10/10] tools/vmtb: Platform enabling: PTL and BMG support Adam Miszczak
@ 2026-03-10 10:52   ` Bernatowicz, Marcin
  0 siblings, 0 replies; 25+ messages in thread
From: Bernatowicz, Marcin @ 2026-03-10 10:52 UTC (permalink / raw)
  To: Adam Miszczak, igt-dev; +Cc: kamil.konieczny


On 2/24/2026 8:50 AM, Adam Miszczak wrote:
> Add PCI Device IDs and example vGPU profiles for
> Panther Lake (PTL) and Battlemage (BMG).
> Remove unused ATS-M references.
>
> Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
> ---
>   tools/vmtb/bench/configurators/pci.py         | 43 +++++---
>   .../{Flex170.json => Bmg_g21_12.json}         | 58 +++++------
>   .../resources/vgpu_profiles/Ptl.json          | 97 +++++++++++++++++++
>   3 files changed, 154 insertions(+), 44 deletions(-)
>   rename tools/vmtb/vmm_flows/resources/vgpu_profiles/{Flex170.json => Bmg_g21_12.json} (73%)
>   create mode 100644 tools/vmtb/vmm_flows/resources/vgpu_profiles/Ptl.json
>
> diff --git a/tools/vmtb/bench/configurators/pci.py b/tools/vmtb/bench/configurators/pci.py
> index 8e8afb138..0b524d3c2 100644
> --- a/tools/vmtb/bench/configurators/pci.py
> +++ b/tools/vmtb/bench/configurators/pci.py
> @@ -1,13 +1,13 @@
>   # SPDX-License-Identifier: MIT
> -# Copyright © 2024 Intel Corporation
> +# Copyright © 2024-2026 Intel Corporation
>   
>   import enum
>   import typing
>   
>   
>   class GpuModel(str, enum.Enum):
> -    ATSM150 = 'Arctic Sound M150 (ATS-M1)'
> -    ATSM75 = 'Arctic Sound M75 (ATS-M3)'
> +    PTL = 'Panther Lake (PTL)'
> +    BMG = 'Battlemage (BMG)'
>       Unknown = 'Unknown'
>   
>       def __str__(self) -> str:
> @@ -21,28 +21,41 @@ def get_gpu_model(pci_id: str) -> GpuModel:
>   
>   def get_vgpu_profiles_file(gpu_model: GpuModel) -> str:
>       """Return vGPU profile definition JSON file for a given GPU model."""
> -    if gpu_model == GpuModel.ATSM150:
> -        vgpu_device_file = 'Flex170.json'
> -    elif gpu_model == GpuModel.ATSM75:
> -        vgpu_device_file = 'Flex140.json'
> +    if gpu_model == GpuModel.PTL:
> +        vgpu_device_file = 'Ptl.json'
> +    elif gpu_model == GpuModel.BMG:
> +        vgpu_device_file = 'Bmg_g21_12.json'
>       else: # GpuModel.Unknown
>           vgpu_device_file = 'N/A'
>   
>       return vgpu_device_file
>   
>   
> -# PCI Device IDs: ATS-M150 (M1)
> -_atsm150_pci_ids = {
> -    '56C0': GpuModel.ATSM150,
> -    '56C2': GpuModel.ATSM150
> +# PCI Device IDs: PTL
> +_ptl_pci_ids = {
> +    'B080': GpuModel.PTL,
> +    'B081': GpuModel.PTL,
> +    'B082': GpuModel.PTL,
> +    'B083': GpuModel.PTL,
> +    'B084': GpuModel.PTL,
> +    'B085': GpuModel.PTL,
> +    'B086': GpuModel.PTL,
> +    'B087': GpuModel.PTL,
> +    'B08F': GpuModel.PTL,
> +    'B090': GpuModel.PTL,
> +    'B0A0': GpuModel.PTL,
> +    'B0B0': GpuModel.PTL,
> +    'FD80': GpuModel.PTL,
> +    'FD81': GpuModel.PTL
>   }
>   
>   
> -# PCI Device IDs: ATS-M75 (M3)
> -_atsm75_pci_ids = {
> -    '56C1': GpuModel.ATSM75
> +# PCI Device IDs: BMG (G21 - VRAM: 12GB / other)
> +_bmg_pci_ids = {
> +    'E20B': GpuModel.BMG # B36 / 12GB
>   }
>   
>   
>   # All PCI Device IDs to GPU Device Names mapping
> -pci_ids: typing.Dict[str, GpuModel] = {**_atsm150_pci_ids, **_atsm75_pci_ids}
> +pci_ids: typing.Dict[str, GpuModel] = {**_ptl_pci_ids,
> +                                       **_bmg_pci_ids}
> diff --git a/tools/vmtb/vmm_flows/resources/vgpu_profiles/Flex170.json b/tools/vmtb/vmm_flows/resources/vgpu_profiles/Bmg_g21_12.json
> similarity index 73%
> rename from tools/vmtb/vmm_flows/resources/vgpu_profiles/Flex170.json
> rename to tools/vmtb/vmm_flows/resources/vgpu_profiles/Bmg_g21_12.json
> index ff1fa7e20..75ca907ab 100644
> --- a/tools/vmtb/vmm_flows/resources/vgpu_profiles/Flex170.json
> +++ b/tools/vmtb/vmm_flows/resources/vgpu_profiles/Bmg_g21_12.json
> @@ -1,58 +1,58 @@
>   {
> -    "version": "1.1",
> +    "version": "1.2",
>       "PFResources": {
>           "Default": "MinimumPFResources",
>           "Profile": {
>               "MinimumPFResources": {
> -                "LocalMemoryEccOn": 402653184,
> -                "LocalMemoryEccOff": 402653184,
> -                "Contexts": 1024,
> +                "LocalMemoryEccOn": 134217728,
> +                "LocalMemoryEccOff": 134217728,
> +                "Contexts": 256,
>                   "Doorbells": 16,
> -                "GGTTSize": 268435456
> +                "GGTTSize": 67108864
>               }
>           }
>       },
>       "vGPUResources": {
>           "Default": null,
>           "Profile": {
> -            "Flex170_16": {
> +            "Bmg_12": {
>                   "VFCount": 1,
> -                "LocalMemoryEccOff": 16777216000,
> -                "LocalMemoryEccOn": 2147483648,
> +                "LocalMemoryEccOff": 12717129728,
> +                "LocalMemoryEccOn": 12717129728,
>                   "Contexts": 1024,
>                   "Doorbells": 240,
>                   "GGTTSize": 4026531840
>               },
> -            "Flex170_8": {
> +            "Bmg_6": {
>                   "VFCount": 2,
> -                "LocalMemoryEccOff": 8388608000,
> -                "LocalMemoryEccOn": 2147483648,
> +                "LocalMemoryEccOff": 6341787648,
> +                "LocalMemoryEccOn": 6341787648,
>                   "Contexts": 1024,
>                   "Doorbells": 120,
>                   "GGTTSize": 2013265920
>               },
> -            "Flex170_4": {
> -                "VFCount": 4,
> -                "LocalMemoryEccOff": 4194304000,
> -                "LocalMemoryEccOn": 2147483648,
> +            "Bmg_4": {
> +                "VFCount": 3,
> +                "LocalMemoryEccOff": 4211081216,
> +                "LocalMemoryEccOn": 4211081216,
>                   "Contexts": 1024,
> -                "Doorbells": 60,
> -                "GGTTSize": 1006632960
> +                "Doorbells": 80,
> +                "GGTTSize": 1342177280
>               },
> -            "Flex170_2": {
> -                "VFCount": 8,
> -                "LocalMemoryEccOff": 2097152000,
> -                "LocalMemoryEccOn": 1073741824,
> +            "Bmg_2": {
> +                "VFCount": 6,
> +                "LocalMemoryEccOff": 2080374784,
> +                "LocalMemoryEccOn": 2080374784,
>                   "Contexts": 1024,
> -                "Doorbells": 30,
> -                "GGTTSize": 503316480
> +                "Doorbells": 40,
> +                "GGTTSize": 671088640
>               },
> -            "Flex170_1": {
> -                "VFCount": 16,
> -                "LocalMemoryEccOff": 1048576000,
> -                "LocalMemoryEccOn": 536870912,
> +            "Bmg_1": {
> +                "VFCount": 12,
> +                "LocalMemoryEccOff": 1023410176,
> +                "LocalMemoryEccOn": 1023410176,
>                   "Contexts": 1024,
> -                "Doorbells": 15,
> +                "Doorbells": 20,
>                   "GGTTSize": 251658240
>               }
>           }
> @@ -110,4 +110,4 @@
>               }
>           }
>       }
> -}
> \ No newline at end of file
> +}
> diff --git a/tools/vmtb/vmm_flows/resources/vgpu_profiles/Ptl.json b/tools/vmtb/vmm_flows/resources/vgpu_profiles/Ptl.json
> new file mode 100644
> index 000000000..efc61bce1
> --- /dev/null
> +++ b/tools/vmtb/vmm_flows/resources/vgpu_profiles/Ptl.json
> @@ -0,0 +1,97 @@
> +{
> +    "version": "0.1",
> +    "PFResources": {
> +        "Default": "MinimumPFResources",
> +        "Profile": {
> +            "MinimumPFResources": {
> +                "LocalMemoryEccOn": 0,
> +                "LocalMemoryEccOff": 0,
> +                "Contexts": 256,
> +                "Doorbells": 16,
> +                "GGTTSize": 67108864
> +            }
> +        }
> +    },
> +    "vGPUResources": {
> +        "Default": null,
> +        "Profile": {
> +            "Ptl_1": {
> +                "VFCount": 1,
> +                "LocalMemoryEccOff": 0,
> +                "LocalMemoryEccOn": 0,
> +                "Contexts": 1024,
> +                "Doorbells": 240,
> +                "GGTTSize": 4026531840
> +            },
> +            "Ptl_2": {
> +                "VFCount": 2,
> +                "LocalMemoryEccOff": 0,
> +                "LocalMemoryEccOn": 0,
> +                "Contexts": 1024,
> +                "Doorbells": 120,
> +                "GGTTSize": 2013265920
> +            },
> +            "Ptl_4": {
> +                "VFCount": 4,
> +                "LocalMemoryEccOff": 0,
> +                "LocalMemoryEccOn": 0,
> +                "Contexts": 1024,
> +                "Doorbells": 60,
> +                "GGTTSize": 1006632960
> +            }
> +        }
> +    },
> +    "vGPUScheduler": {
> +        "Default": "Flexible_30fps_GPUTimeSlicing",
> +        "Profile": {
> +            "Flexible_30fps_GPUTimeSlicing": {
> +                "GPUTimeSlicing": {
> +                    "ScheduleIfIdle": false,
> +                    "PFExecutionQuantum": 20,
> +                    "PFPreemptionTimeout": 20000,
> +                    "VFAttributes": {
> +                        "VFExecutionQuantum": "lambda VFCount : max( 32 // VFCount, 1)",
> +                        "VFPreemptionTimeout": "lambda VFCount : 128000 if (VFCount == 1) else max( 64000 // VFCount, 16000)"
> +                    }
> +                }
> +            },
> +            "Fixed_30fps_GPUTimeSlicing": {
> +                "GPUTimeSlicing": {
> +                    "ScheduleIfIdle": true,
> +                    "PFExecutionQuantum": 20,
> +                    "PFPreemptionTimeout": 20000,
> +                    "VFAttributes": {
> +                        "VFExecutionQuantum": "lambda VFCount : max( 32 // VFCount, 1)",
> +                        "VFPreemptionTimeout": "lambda VFCount : 128000 if (VFCount == 1) else max( 64000 // VFCount, 16000)"
> +                    }
> +                }
> +            },
> +            "Flexible_BurstableQoS_GPUTimeSlicing": {
> +                "GPUTimeSlicing": {
> +                    "ScheduleIfIdle": false,
> +                    "PFExecutionQuantum": 20,
> +                    "PFPreemptionTimeout": 20000,
> +                    "VFAttributes": {
> +                        "VFExecutionQuantum": "lambda VFCount : min((2000 // max(VFCount-1,1)*0.5, 50))",
> +                        "VFPreemptionTimeout": "lambda VFCount : (2000 // max(VFCount-1,1) - min((2000 // max(VFCount-1,1))*0.5, 50))*1000"
> +                    }
> +                }
> +            }
> +        }
> +    },
> +    "vGPUSecurity": {
> +        "Default": "Disabled",
> +        "Profile": {
> +            "Disabled": {
> +                "ResetAfterVfSwitch": false,
> +                "GuCSamplingPeriod": 0,
> +                "GuCThresholdCATError": 0,
> +                "GuCThresholdPageFault": 0,
> +                "GuCThresholdH2GStorm": 0,
> +                "GuCThresholdDbStorm": 0,
> +                "GuCThresholdGTIrqStorm": 0,
> +                "GuCThresholdEngineReset": 0
> +            }
> +        }
> +    }
> +}
> \ No newline at end of file
LGTM,
Reviewed-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2026-03-10 10:53 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-24  7:50 [PATCH i-g-t 00/10] vmtb: Modernize SR-IOV VM Test Bench core Adam Miszczak
2026-02-24  7:50 ` [PATCH i-g-t 01/10] tools/vmtb: Update QEMU parameters Adam Miszczak
2026-03-10 10:22   ` Bernatowicz, Marcin
2026-02-24  7:50 ` [PATCH i-g-t 02/10] tools/vmtb: Fix DUT selection based on card index Adam Miszczak
2026-03-10 10:26   ` Bernatowicz, Marcin
2026-02-24  7:50 ` [PATCH i-g-t 03/10] tools/vmtb: Fix VM snapshot query handling Adam Miszczak
2026-03-10 10:29   ` Bernatowicz, Marcin
2026-02-24  7:50 ` [PATCH i-g-t 04/10] tools/vmtb: Extend IGT and WSIM abstractions Adam Miszczak
2026-03-10 10:36   ` Bernatowicz, Marcin
2026-02-24  7:50 ` [PATCH i-g-t 05/10] tools/vmtb: VF auto/fair provisioning support Adam Miszczak
2026-03-10 10:38   ` Bernatowicz, Marcin
2026-02-24  7:50 ` [PATCH i-g-t 06/10] tools/vmtb: Refactor driver interfaces Adam Miszczak
2026-03-10 10:43   ` Bernatowicz, Marcin
2026-02-24  7:50 ` [PATCH i-g-t 07/10] tools/vmtb: Introduce VirtualDevice class Adam Miszczak
2026-03-10 10:45   ` Bernatowicz, Marcin
2026-02-24  7:50 ` [PATCH i-g-t 08/10] tools/vmtb: Redesign VirtualMachine class Adam Miszczak
2026-03-10 10:47   ` Bernatowicz, Marcin
2026-02-24  7:50 ` [PATCH i-g-t 09/10] tools/vmtb: Support max VFs configuration Adam Miszczak
2026-03-10 10:52   ` Bernatowicz, Marcin
2026-02-24  7:50 ` [PATCH i-g-t 10/10] tools/vmtb: Platform enabling: PTL and BMG support Adam Miszczak
2026-03-10 10:52   ` Bernatowicz, Marcin
2026-02-24 11:49 ` ✓ Xe.CI.BAT: success for vmtb: Modernize SR-IOV VM Test Bench core Patchwork
2026-02-24 12:43 ` ✓ i915.CI.BAT: " Patchwork
2026-02-24 16:27 ` ✗ i915.CI.Full: failure " Patchwork
2026-02-24 20:21 ` ✗ Xe.CI.FULL: " Patchwork

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox