File: test_basic.py

package info (click to toggle)
intel-gpu-tools 2.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 63,360 kB
  • sloc: xml: 781,458; ansic: 360,567; python: 8,336; yacc: 2,781; perl: 1,196; sh: 1,177; lex: 487; asm: 227; lisp: 35; makefile: 30
file content (160 lines) | stat: -rw-r--r-- 6,909 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# SPDX-License-Identifier: MIT
# Copyright © 2024 Intel Corporation

import logging
import time
from typing import List, Tuple

import pytest

from bench.configurators.vgpu_profile_config import VfSchedulingMode
from bench.executors.gem_wsim import (ONE_CYCLE_DURATION_MS,
                                      PREEMPT_10MS_WORKLOAD, GemWsim,
                                      GemWsimResult,
                                      gem_wsim_parallel_exec_and_check)
from bench.executors.igt import IgtExecutor, IgtType
from bench.helpers.helpers import (driver_check, igt_check, igt_run_check,
                                   modprobe_driver_run_check)
from vmm_flows.conftest import (VmmTestingConfig, VmmTestingSetup,
                                idfn_test_config)

logger = logging.getLogger(__name__)

WL_ITERATIONS_10S = 1000
WL_ITERATIONS_30S = 3000
MS_IN_SEC = 1000
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]],
                    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))

    return test_configs


test_variants_1 = [(1, VfSchedulingMode.DEFAULT_PROFILE), (2, VfSchedulingMode.DEFAULT_PROFILE)]

@pytest.mark.parametrize('setup_vms', set_test_config(test_variants_1), ids=idfn_test_config, indirect=['setup_vms'])
class TestVmSetup:
    """Verify basic virtualization setup:
    - probe PF and VFIO drivers (host)
    - enable and provision VFs (automatic or manual with vGPU profile)
    - power on VMs with assigned VFs
    - probe VF driver (guest)
    - shutdown VMs, reset provisioning and disable VFs
    """
    def test_vm_boot(self, setup_vms):
        logger.info("Test VM boot: power on VM and probe VF driver")
        ts: VmmTestingSetup = setup_vms

        for vm in ts.vms:
            logger.info("[%s] Verify VF DRM driver is loaded in a guest OS", vm)
            assert driver_check(vm)


test_variants_2 = [(1, VfSchedulingMode.DEFAULT_PROFILE), (2, VfSchedulingMode.DEFAULT_PROFILE),
                   (4, VfSchedulingMode.DEFAULT_PROFILE)]

@pytest.mark.parametrize('setup_vms', set_test_config(test_variants_2), ids=idfn_test_config, indirect=['setup_vms'])
class TestVmWorkload:
    """Verify basic IGT workload execution a VM(s):
    - exec_store: basic store submissions on single/multiple VMs
    - gem_wsim: workload simulator running in parallel on multiple VMs
    """
    def test_store(self, setup_vms):
        logger.info("Test VM execution: exec_store")
        ts: VmmTestingSetup = setup_vms
        igt_worklads: List[IgtExecutor] = []

        for vm in ts.vms:
            logger.info("[%s] Execute basic WL", vm)
            igt_worklads.append(IgtExecutor(vm, IgtType.EXEC_STORE))

        for igt in igt_worklads:
            logger.info("[%s] Verify result of basic WL", igt.target)
            assert igt_check(igt)

        logger.info("[%s] Verify result of basic WL", ts.host)
        igt_run_check(ts.host, IgtType.EXEC_STORE)

    def test_wsim(self, setup_vms):
        logger.info("Test VM execution: gem_wsim")
        ts: VmmTestingSetup = setup_vms

        if ts.get_num_vms() < 2:
            pytest.skip("Test scenario not supported for 1xVM setup ")

        # Single workload takes 10ms GPU time, multiplied by 1000 iterations
        # gives the expected 10s duration and 100 workloads/sec
        expected = GemWsimResult(ONE_CYCLE_DURATION_MS * WL_ITERATIONS_10S * len(ts.vms) / MS_IN_SEC,
                                 MS_IN_SEC/ONE_CYCLE_DURATION_MS / len(ts.vms))

        # Check preemptible workload
        result = gem_wsim_parallel_exec_and_check(ts.vms, PREEMPT_10MS_WORKLOAD, WL_ITERATIONS_10S, expected)
        logger.info("Execute wsim parallel on VMs - results: %s", result)


test_variants_3 = [(2, VfSchedulingMode.DEFAULT_PROFILE), (4, 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'])
class TestVfDriverLoadRemove:
    """Verify VF (guest) driver load or remove doesn't affect execution on the other VM:
    - probe VF driver on the last VM while the first VM is running workload
    - remove VF driver on the first VM while the last VM is running workload
    - reload previously removed VF driver on the same VM
    """
    def test_load(self, setup_vms):
        logger.info("Test VM driver load: VF driver probe while other VM executes workload")
        ts: VmmTestingSetup = setup_vms

        vm_first = ts.vms[0]
        vm_last = ts.vms[-1]

        logger.info("[%s] Load VF driver and run basic WL - first VM", vm_first)
        assert modprobe_driver_run_check(vm_first)

        expected_elapsed_sec = ONE_CYCLE_DURATION_MS * WL_ITERATIONS_30S / MS_IN_SEC
        gem_wsim = GemWsim(vm_first, 1, WL_ITERATIONS_30S, PREEMPT_10MS_WORKLOAD)
        time.sleep(DELAY_FOR_WORKLOAD_SEC)
        assert gem_wsim.is_running()

        logger.info("[%s] Load VF driver - last VM", vm_last)
        assert modprobe_driver_run_check(vm_last)

        result = gem_wsim.wait_results()
        assert expected_elapsed_sec * 0.8 < result.elapsed_sec < expected_elapsed_sec * 1.2

    def test_reload(self, setup_vms):
        logger.info("Test VM driver reload: VF driver remove is followed by probe while other VM executes workload")
        ts: VmmTestingSetup = setup_vms

        vm_first = ts.vms[0]
        vm_last = ts.vms[-1]

        logger.info("[%s] Run basic WL - last VM", vm_last)
        expected_elapsed_sec = ONE_CYCLE_DURATION_MS * WL_ITERATIONS_30S / MS_IN_SEC
        gem_wsim = GemWsim(vm_last, 1, WL_ITERATIONS_30S, PREEMPT_10MS_WORKLOAD)
        time.sleep(DELAY_FOR_WORKLOAD_SEC)
        assert gem_wsim.is_running()

        logger.info("[%s] Remove VF driver - first VM", vm_first)
        rmmod_pid = vm_first.execute(f'modprobe -rf {vm_first.get_drm_driver_name()}')
        assert vm_first.execute_wait(rmmod_pid).exit_code == 0

        time.sleep(DELAY_FOR_RELOAD_SEC)

        logger.info("[%s] Reload VF driver and run basic WL - first VM", vm_first)
        assert modprobe_driver_run_check(vm_first)
        assert igt_run_check(vm_first, IgtType.EXEC_STORE)

        result = gem_wsim.wait_results()
        assert expected_elapsed_sec * 0.8 < result.elapsed_sec < expected_elapsed_sec * 1.2