public inbox for igt-dev@lists.freedesktop.org
 help / color / mirror / Atom feed
From: "Bernatowicz, Marcin" <marcin.bernatowicz@linux.intel.com>
To: Adam Miszczak <adam.miszczak@linux.intel.com>,
	igt-dev@lists.freedesktop.org
Cc: kamil.konieczny@linux.intel.com
Subject: Re: [PATCH i-g-t 04/10] tools/vmtb: Extend IGT and WSIM abstractions
Date: Tue, 10 Mar 2026 11:36:28 +0100	[thread overview]
Message-ID: <a084c2e6-adf6-4282-bc95-d31b77877a71@linux.intel.com> (raw)
In-Reply-To: <20260224075027.2409675-5-adam.miszczak@linux.intel.com>


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": {

  reply	other threads:[~2026-03-10 10:36 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=a084c2e6-adf6-4282-bc95-d31b77877a71@linux.intel.com \
    --to=marcin.bernatowicz@linux.intel.com \
    --cc=adam.miszczak@linux.intel.com \
    --cc=igt-dev@lists.freedesktop.org \
    --cc=kamil.konieczny@linux.intel.com \
    /path/to/YOUR_REPLY

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

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