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 2/7] tools/vmtb: Rework VF scheduler provisioning
Date: Thu, 8 Oct 2026 15:54:20 +0200 [thread overview]
Message-ID: <f3951eff-b985-4069-8aaa-ad880bff6564@linux.intel.com> (raw)
In-Reply-To: <20260928072600.426902-3-adam.miszczak@linux.intel.com>
LGTM,
Reviewed-by: Marcin Bernatowicz <marcin.bernatowicz@linux.intel.com>
On 9/28/2026 9:25 AM, Adam Miszczak wrote:
> Align default VF scheduling setup with the current xe KMD behavior.
> Scheduling settings: execution quanta (EQ) and preemption-timeout (PT)
> are set to 16ms by default (instead of infinite/0), therefore:
> - rename VfSchedulingMode.INFINITE → AUTO
> - update VmmTestingConfig default from INFINITE to AUTO
>
> Fix scheduler-only manual provisioning - support VF config variants
> where only the scheduler setup is needed (auto resources provisioning
> with a concrete scheduling mode). In this case load scheduler profile
> even when no matching resources profile exists.
>
> In addition, fix max VFs handling, improve assertions for creating VFs
> and skip unsupported test configs instead of failing.
>
> Signed-off-by: Adam Miszczak <adam.miszczak@linux.intel.com>
> ---
> .../configurators/vgpu_profile_config.py | 20 +++++---
> tools/vmtb/bench/exceptions.py | 4 ++
> tools/vmtb/bench/machines/physical/device.py | 9 ++--
> tools/vmtb/vmm_flows/conftest.py | 46 +++++++++++--------
> tools/vmtb/vmm_flows/test_basic.py | 2 +-
> 5 files changed, 52 insertions(+), 29 deletions(-)
>
> diff --git a/tools/vmtb/bench/configurators/vgpu_profile_config.py b/tools/vmtb/bench/configurators/vgpu_profile_config.py
> index 4bddb641e..35a8a8835 100644
> --- a/tools/vmtb/bench/configurators/vgpu_profile_config.py
> +++ b/tools/vmtb/bench/configurators/vgpu_profile_config.py
> @@ -23,7 +23,7 @@ class VfProvisioningMode(Enum):
>
>
> class VfSchedulingMode(str, Enum):
> - INFINITE = 'Infinite' # Infinite EQ/PT - HW default
> + AUTO = 'Auto' # Default EQ/PT (set by xe KMD automatically)
> DEFAULT_PROFILE = 'Default_Profile' # Default vGPU scheduler profile
> FLEXIBLE_30FPS = 'Flexible_30fps_GPUTimeSlicing'
> FIXED_30FPS = 'Fixed_30fps_GPUTimeSlicing'
> @@ -87,8 +87,8 @@ class VgpuProfileConfigurator:
> break
>
> if not is_vf_resource_found:
> - logger.error("vGPU VF resources profile %sxVF not found!", requested_num_vfs)
> - raise exceptions.VgpuProfileError(f'vGPU VF resources profile {requested_num_vfs}xVF not found!')
> + logger.warning("vGPU resources profile (%sxVF) not found!", requested_num_vfs)
> + raise exceptions.VgpuProfileNotFound(f'vGPU resources profile ({requested_num_vfs}xVF) not found!')
>
> return vgpu_resources_config
>
> @@ -99,7 +99,7 @@ class VgpuProfileConfigurator:
> # pylint: disable=W0123
> vgpu_scheduler_config = VgpuSchedulerConfig()
>
> - if requested_scheduler is VfSchedulingMode.INFINITE:
> + if requested_scheduler is VfSchedulingMode.AUTO:
> return vgpu_scheduler_config
>
> for scheduler in self.supported_vgpu_profiles.scheduler_configs:
> @@ -136,13 +136,19 @@ class VgpuProfileConfigurator:
>
> return vgpu_security_config
>
> - def get_vgpu_profile(self, requested_num_vfs: int, requested_scheduler: VfSchedulingMode) -> VgpuProfile:
> - """Get vGPU profile for requested number of VFs, scheduler and security modes."""
> + def get_vgpu_profile(self, requested_num_vfs: int, requested_scheduler: VfSchedulingMode,
> + require_resources: bool = True) -> VgpuProfile:
> + """Get vGPU profile for requested number of VFs, scheduler and security modes.
> + If require_resources is False, skip VF resources lookup
> + (e.g. for auto provisioning where only the scheduler config is needed).
> + """
> logger.info("Requested vGPU profile: %s VFs / scheduling: %s", requested_num_vfs, requested_scheduler)
>
> vgpu_profile: VgpuProfile = VgpuProfile()
> vgpu_profile.num_vfs = requested_num_vfs
> - vgpu_profile.resources = self.select_vgpu_resources_profile(requested_num_vfs)
> +
> + if require_resources:
> + vgpu_profile.resources = self.select_vgpu_resources_profile(requested_num_vfs)
>
> if requested_scheduler is VfSchedulingMode.DEFAULT_PROFILE:
> requested_scheduler = VfSchedulingMode(self.supported_vgpu_profiles.scheduler_config_default)
> diff --git a/tools/vmtb/bench/exceptions.py b/tools/vmtb/bench/exceptions.py
> index 1c151669a..557b44142 100644
> --- a/tools/vmtb/bench/exceptions.py
> +++ b/tools/vmtb/bench/exceptions.py
> @@ -40,6 +40,10 @@ class VgpuProfileError(BenchError):
> pass
>
>
> +class VgpuProfileNotFound(VgpuProfileError):
> + pass
> +
> +
> class NotAvailableError(BenchError):
> pass
>
> diff --git a/tools/vmtb/bench/machines/physical/device.py b/tools/vmtb/bench/machines/physical/device.py
> index f1f24c65c..6c0dc4ff9 100644
> --- a/tools/vmtb/bench/machines/physical/device.py
> +++ b/tools/vmtb/bench/machines/physical/device.py
> @@ -59,7 +59,7 @@ class Device(DeviceInterface):
> driver_module = importlib.import_module(module_name)
> driver_class = getattr(driver_module, class_name)
> except (ImportError, AttributeError) as exc:
> - logging.error("Driver module/class is not available: %s", exc)
> + logger.error("Driver module/class is not available: %s", exc)
> raise exceptions.VmtbConfigError(f'Requested driver module {driver_name} is not available!')
>
> return driver_class(bdf)
> @@ -102,7 +102,9 @@ class Device(DeviceInterface):
>
> self.driver.set_numvfs(num)
> ret = self.driver.get_numvfs()
> - assert ret == num
> + if ret != num:
> + logger.error("Failed to create requested number of VFs - expected: %s, got: %s", num, ret)
> + raise exceptions.HostError(f'Failed to create requested number of VFs ({num})')
>
> return ret
>
> @@ -114,7 +116,8 @@ class Device(DeviceInterface):
> self.driver.set_numvfs(0)
> ret = self.driver.get_numvfs()
> if ret != 0:
> - raise exceptions.HostError('VFs not disabled after 0 write')
> + logger.error("Failed to disable VFs - expected 0, got: %s", ret)
> + raise exceptions.HostError('Failed to disable all VFs')
>
> logger.debug("[%s] Enable drivers autoprobe", self.pci_info.bdf)
> self.set_drivers_autoprobe(True)
> diff --git a/tools/vmtb/vmm_flows/conftest.py b/tools/vmtb/vmm_flows/conftest.py
> index 02c297f93..ba6487c84 100644
> --- a/tools/vmtb/vmm_flows/conftest.py
> +++ b/tools/vmtb/vmm_flows/conftest.py
> @@ -44,7 +44,7 @@ class VmmTestingConfig:
> - 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)
> + - scheduling_mode: requested vGPU scheduling profile (auto maps to default EQ=16ms and PT=16000us)
> - 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)
> - unload_host_drivers_on_teardown: unload host DRM drivers in teardown fixture
> @@ -53,7 +53,7 @@ class VmmTestingConfig:
> num_vfs: int = 1
> max_num_vms: int = 2
> provisioning_mode: VfProvisioningMode = VfProvisioningMode.AUTO
> - scheduling_mode: VfSchedulingMode = VfSchedulingMode.INFINITE
> + scheduling_mode: VfSchedulingMode = VfSchedulingMode.AUTO
>
> auto_poweron_vm: bool = True
> auto_probe_vm_driver: bool = True
> @@ -68,8 +68,11 @@ class VmmTestingConfig:
> self.num_vfs = 0 # Actual value set in VmmTestingSetup
>
> def __str__(self) -> str:
> - 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})')
> + test_config_id = (f'{self.num_vfs if not self.enable_max_vfs else "Max"}VF')
> +
> + if self.provisioning_mode is not VfProvisioningMode.AUTO or self.scheduling_mode is not VfSchedulingMode.AUTO:
> + test_config_id += f'-(P:{self.provisioning_mode.name} S:{self.scheduling_mode.name})'
> +
> return test_config_id
>
> def __repr__(self) -> str:
> @@ -126,10 +129,11 @@ class VmmTestingSetup:
> self.wsim_wl_dir = vmtb_root_path / vmtb_config.config.wsim_wl_path / self.get_dut().gpu_model.name.lower()
>
> if (self.testing_config.provisioning_mode is VfProvisioningMode.VGPU_PROFILE
> - or self.testing_config.scheduling_mode is not VfSchedulingMode.INFINITE):
> + or self.testing_config.scheduling_mode is not VfSchedulingMode.AUTO):
> + # vGPU profile or auto resources provisioning with concrete scheduling
> self.vgpu_profile: VgpuProfile = self.get_vgpu_profile()
> -
> - if self.testing_config.provisioning_mode is VfProvisioningMode.AUTO and self.testing_config.enable_max_vfs:
> + elif self.testing_config.enable_max_vfs:
> + # Auto provisioning (with default/auto scheduling) for max VFs (HW limit)
> 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
> @@ -143,17 +147,22 @@ 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)
> + if self.testing_config.provisioning_mode is VfProvisioningMode.VGPU_PROFILE:
> + # 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)
> + else:
> + # Use HW VFs limit (sysfs/sriov_totalvfs) with auto resources provisioning and concrete scheduling
> + self.testing_config.num_vfs = self.total_vfs
>
> try:
> + require_resources = self.testing_config.provisioning_mode is VfProvisioningMode.VGPU_PROFILE
> vgpu_profile = configurator.get_vgpu_profile(self.testing_config.num_vfs,
> - self.testing_config.scheduling_mode)
> - except exceptions.VgpuProfileError as exc:
> - logger.error("Suitable vGPU profile not found: %s", exc)
> - raise exceptions.VgpuProfileError('Invalid test setup - vGPU profile not found!')
> + self.testing_config.scheduling_mode,
> + require_resources)
> + except exceptions.VgpuProfileNotFound as exc:
> + pytest.skip(f'Test config not supported: {exc}')
>
> return vgpu_profile
>
> @@ -277,11 +286,12 @@ def fixture_setup_vms(get_vmtb_config, get_cmdline_config, get_host, request):
> else:
> device.driver.restore_auto_provisioning()
>
> - assert device.create_vf(num_vfs) == num_vfs
> + assert num_vfs <= ts.total_vfs, f'Requested number of VFs ({num_vfs}) exceeds total VFs ({ts.total_vfs})'
> + device.create_vf(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).
> + ts.testing_config.scheduling_mode is not VfSchedulingMode.AUTO):
> + # Auto resources provisioning with scheduling override (i.e. different than default/auto).
> # Scheduler params override must be done after enabling VFs
> # to allow hard resources auto provisioning by KMD.
> ts.vgpu_profile.print_scheduler_config()
> diff --git a/tools/vmtb/vmm_flows/test_basic.py b/tools/vmtb/vmm_flows/test_basic.py
> index 9b8731273..597ebbb68 100644
> --- a/tools/vmtb/vmm_flows/test_basic.py
> +++ b/tools/vmtb/vmm_flows/test_basic.py
> @@ -43,7 +43,7 @@ def set_test_config(test_variants: List[Tuple[int, VfProvisioningMode, VfSchedul
>
> test_variants_1 = [(1, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE),
> (2, VfProvisioningMode.VGPU_PROFILE, VfSchedulingMode.DEFAULT_PROFILE),
> - (2, VfProvisioningMode.AUTO, VfSchedulingMode.INFINITE)]
> + (2, VfProvisioningMode.AUTO, VfSchedulingMode.AUTO)]
>
> @pytest.mark.parametrize('setup_vms', set_test_config(test_variants_1), ids=idfn_test_config, indirect=['setup_vms'])
> class TestVmSetup:
next prev parent reply other threads:[~2026-10-08 13:55 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 7:25 [PATCH i-g-t 0/7] tools/vmtb: Sync VM Test Bench core with current xe SR-IOV Adam Miszczak
2026-09-28 7:25 ` [PATCH i-g-t 1/7] tools/vmtb: Introduce asynchronous VM state save/load functions Adam Miszczak
2026-10-08 13:53 ` Bernatowicz, Marcin
2026-09-28 7:25 ` [PATCH i-g-t 2/7] tools/vmtb: Rework VF scheduler provisioning Adam Miszczak
2026-10-08 13:54 ` Bernatowicz, Marcin [this message]
2026-09-28 7:25 ` [PATCH i-g-t 3/7] tools/vmtb: Align driver/device layer with current xe SR-IOV interfaces Adam Miszczak
2026-10-08 13:54 ` Bernatowicz, Marcin
2026-09-28 7:25 ` [PATCH i-g-t 4/7] tools/vmtb: Fix guest timeout handling and PCI BDF matching Adam Miszczak
2026-10-08 13:55 ` Bernatowicz, Marcin
2026-09-28 7:25 ` [PATCH i-g-t 5/7] tools/vmtb: Add pre-test environment cleanup Adam Miszczak
2026-10-08 13:55 ` Bernatowicz, Marcin
2026-09-28 7:25 ` [PATCH i-g-t 6/7] tools/vmtb: Add VM dmesg wait support Adam Miszczak
2026-10-08 13:56 ` Bernatowicz, Marcin
2026-09-28 7:26 ` [PATCH i-g-t 7/7] tools/vmtb: Extend IGT and WSIM executors Adam Miszczak
2026-10-08 12:59 ` Bernatowicz, Marcin
2026-09-28 20:28 ` ✓ i915.CI.BAT: success for tools/vmtb: Sync VM Test Bench core with current xe SR-IOV Patchwork
2026-09-28 20:47 ` ✓ Xe.CI.BAT: " Patchwork
2026-09-29 2:19 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-09-29 4:08 ` ✗ i915.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=f3951eff-b985-4069-8aaa-ad880bff6564@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.