diff --git a/jobs.py b/jobs.py index 50713dfb6..a157b20df 100755 --- a/jobs.py +++ b/jobs.py @@ -332,6 +332,16 @@ "nb_pools": 1, "params": {}, "paths": ["tests/xo"], + }, + "pci-passthrough": { + "description": "Testing PCI passthrough functionalities", + "requirements": [ + "A XCP-ng host >= 8.3 with a PGPU and a PCI to passthrough.", + "The host will be rebooted by the tests." + ], + "nb_pools": 1, + "params": {}, + "paths": ["tests/pci_passthrough"], } } diff --git a/tests/pci_passthrough/conftest.py b/tests/pci_passthrough/conftest.py new file mode 100644 index 000000000..8cee20a26 --- /dev/null +++ b/tests/pci_passthrough/conftest.py @@ -0,0 +1,50 @@ +import logging +import pytest + +from lib.common import safe_split + +@pytest.fixture(scope="session") +def enabled_pci_uuid(host): + pci_uuids = safe_split(host.xe("pci-list", {"host-uuid": host.uuid}, minimal=True), ',') + + pci_uuid = None + for uuid in pci_uuids: + dom0_access = host.xe("pci-get-dom0-access-status", {"uuid": uuid}) + if dom0_access == "enabled": + pci_uuid = uuid + break + + if pci_uuid is None: + pytest.skip("This test requires a PCI to hide from dom0") + + yield pci_uuid + + # Put PCI back in initial state + if host.xe("pci-get-dom0-access-status", {"uuid": pci_uuid}) != "enabled": + host.xe("pci-enable-dom0-access", {"uuid": pci_uuid}) + if host.xe("pci-get-dom0-access-status", {"uuid": pci_uuid}) != "enabled": + host.reboot(verify=True) + +@pytest.fixture(scope="session") +def enabled_pgpu_uuid(host): + pgpu_uuids = safe_split(host.xe("pgpu-list", {"host-uuid": host.uuid}, minimal=True), ',') + + pgpu_uuid = None + for uuid in pgpu_uuids: + pci_uuid = host.xe("pgpu-param-get", {"uuid": uuid, "param-name": "pci-uuid"}) + dom0_access = host.xe("pci-get-dom0-access-status", {"uuid": pci_uuid}) + if dom0_access == "enabled": + pgpu_uuid = uuid + break + + if pgpu_uuid is None: + pytest.skip("This test requires a PGPU to hide from dom0") + + yield pgpu_uuid + + # Put PGPU back in initial state + pci_uuid = host.xe("pgpu-param-get", {"uuid": pgpu_uuid, "param-name": "pci-uuid"}) + if host.xe("pci-get-dom0-access-status", {"uuid": pci_uuid}) != "enabled": + host.xe("pci-enable-dom0-access", {"uuid": pci_uuid}) + if host.xe("pci-get-dom0-access-status", {"uuid": pci_uuid}) != "enabled": + host.reboot(verify=True) diff --git a/tests/pci_passthrough/test_pci_passthrough.py b/tests/pci_passthrough/test_pci_passthrough.py new file mode 100644 index 000000000..2d32e5cb0 --- /dev/null +++ b/tests/pci_passthrough/test_pci_passthrough.py @@ -0,0 +1,79 @@ +import pytest +import logging + +# Requirements: +# - an XCP-ng host (--hosts) >= 8.3 with a PGPU to hide from dom0 + +XEN_CMDLINE = '/opt/xensource/libexec/xen-cmdline' + +@pytest.mark.reboot # reboots the host +@pytest.mark.usefixtures("host_at_least_8_3") +class TestPCIPassthrough: + def test_pci_dom0_access(self, host, enabled_pci_uuid): + host.xe("pci-disable-dom0-access", {"uuid": enabled_pci_uuid}) + assert host.xe("pci-get-dom0-access-status", {"uuid": enabled_pci_uuid}) == "disable_on_reboot" + host.reboot(verify=True) + assert host.xe("pci-get-dom0-access-status", {"uuid": enabled_pci_uuid}) == "disabled" + + host.xe("pci-enable-dom0-access", {"uuid": enabled_pci_uuid}) + assert host.xe("pci-get-dom0-access-status", {"uuid": enabled_pci_uuid}) == "enable_on_reboot" + host.reboot(verify=True) + assert host.xe("pci-get-dom0-access-status", {"uuid": enabled_pci_uuid}) == "enabled" + + def test_access_status_manual_modification(self, host, enabled_pci_uuid): + device_id = host.xe("pci-param-get", {"uuid": enabled_pci_uuid, "param-name": "pci-id"}) + hidden_devices = host.ssh([XEN_CMDLINE, '--get-dom0', '"xen-pciback.hide"']) + if hidden_devices == "": + hidden_devices = "xen-pciback.hide=" + devices = hidden_devices + f"({device_id})" + + host.ssh([XEN_CMDLINE, '--set-dom0', f'"{devices}"']) + assert host.xe("pci-get-dom0-access-status", {"uuid": enabled_pci_uuid}) == "disable_on_reboot" + host.reboot(verify=True) + assert host.xe("pci-get-dom0-access-status", {"uuid": enabled_pci_uuid}) == "disabled" + + host.ssh([XEN_CMDLINE, '--set-dom0', f'"{hidden_devices}"']) + assert host.xe("pci-get-dom0-access-status", {"uuid": enabled_pci_uuid}) == "enable_on_reboot" + host.reboot(verify=True) + assert host.xe("pci-get-dom0-access-status", {"uuid": enabled_pci_uuid}) == "enabled" + +@pytest.mark.reboot # reboots the host +@pytest.mark.usefixtures("host_at_least_8_3") +class TestPGPUPCIDom0AccessInheritance: + def test_pci_sync_dom0_access(self, host, enabled_pgpu_uuid): + pci_uuid = host.xe("pgpu-param-get", {"uuid": enabled_pgpu_uuid, "param-name": "pci-uuid"}) + host.xe("pci-disable-dom0-access", {"uuid": pci_uuid}) + assert host.xe( + "pgpu-param-get", {"uuid": enabled_pgpu_uuid, "param-name": "dom0-access"} + ) == "disable_on_reboot" + + host.reboot(verify=True) + assert host.xe("pgpu-param-get", {"uuid": enabled_pgpu_uuid, "param-name": "dom0-access"}) == "disabled" + + pci_uuid = host.xe("pgpu-param-get", {"uuid": enabled_pgpu_uuid, "param-name": "pci-uuid"}) + host.xe("pci-enable-dom0-access", {"uuid": pci_uuid}) + assert host.xe("pgpu-param-get", {"uuid": enabled_pgpu_uuid, "param-name": "dom0-access"}) == "enable_on_reboot" + + host.reboot(verify=True) + assert host.xe("pgpu-param-get", {"uuid": enabled_pgpu_uuid, "param-name": "dom0-access"}) == "enabled" + + def test_pgpu_sync_dom0_access(self, host, enabled_pgpu_uuid): + pci_uuid = host.xe("pgpu-param-get", {"uuid": enabled_pgpu_uuid, "param-name": "pci-uuid"}) + host.xe("pgpu-disable-dom0-access", {"uuid": enabled_pgpu_uuid}) + assert host.xe( + "pgpu-param-get", {"uuid": enabled_pgpu_uuid, "param-name": "dom0-access"} + ) == "disable_on_reboot" + assert host.xe("pci-get-dom0-access-status", {"uuid": pci_uuid}) == "disable_on_reboot" + + host.reboot(verify=True) + assert host.xe("pgpu-param-get", {"uuid": enabled_pgpu_uuid, "param-name": "dom0-access"}) == "disabled" + assert host.xe("pci-get-dom0-access-status", {"uuid": pci_uuid}) == "disabled" + + pci_uuid = host.xe("pgpu-param-get", {"uuid": enabled_pgpu_uuid, "param-name": "pci-uuid"}) + host.xe("pgpu-enable-dom0-access", {"uuid": enabled_pgpu_uuid}) + assert host.xe("pgpu-param-get", {"uuid": enabled_pgpu_uuid, "param-name": "dom0-access"}) == "enable_on_reboot" + assert host.xe("pci-get-dom0-access-status", {"uuid": pci_uuid}) == "enable_on_reboot" + + host.reboot(verify=True) + assert host.xe("pgpu-param-get", {"uuid": enabled_pgpu_uuid, "param-name": "dom0-access"}) == "enabled" + assert host.xe("pci-get-dom0-access-status", {"uuid": pci_uuid}) == "enabled"