Skip to content

Commit 7233f05

Browse files
committed
pci: add tests for PCIe root bus
Add an integration test that checks that `lspci` correctly locates the PCIe root complex if PCI is enabled for the microVM. Also, add a negative test that checks that PCIe root complex doesn't exist when PCI is not enabled. Also, extend coverage of, at least some of, the tests to ensure that they run with and without PCI configuration enabled. Do that by extending the `uvm_any*` fixtures to yield both variants. Signed-off-by: Babis Chalios <[email protected]>
1 parent 2dedce1 commit 7233f05

File tree

6 files changed

+126
-15
lines changed

6 files changed

+126
-15
lines changed

tests/conftest.py

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -534,22 +534,38 @@ def mem_size_mib():
534534
return 256
535535

536536

537+
@pytest.fixture(params=[True, False])
538+
def pci_enabled(request):
539+
"""Fixture that allows configuring whether a microVM will have PCI enabled or not"""
540+
yield request.param
541+
542+
537543
def uvm_booted(
538-
microvm_factory, guest_kernel, rootfs, cpu_template, vcpu_count=2, mem_size_mib=256
544+
microvm_factory,
545+
guest_kernel,
546+
rootfs,
547+
cpu_template,
548+
pci_enabled,
549+
vcpu_count=2,
550+
mem_size_mib=256,
539551
):
540552
"""Return a booted uvm"""
541553
uvm = microvm_factory.build(guest_kernel, rootfs)
542-
uvm.spawn()
554+
uvm.spawn(pci=pci_enabled)
543555
uvm.basic_config(vcpu_count=vcpu_count, mem_size_mib=mem_size_mib)
544556
uvm.set_cpu_template(cpu_template)
545557
uvm.add_net_iface()
546558
uvm.start()
547559
return uvm
548560

549561

550-
def uvm_restored(microvm_factory, guest_kernel, rootfs, cpu_template, **kwargs):
562+
def uvm_restored(
563+
microvm_factory, guest_kernel, rootfs, cpu_template, pci_enabled, **kwargs
564+
):
551565
"""Return a restored uvm"""
552-
uvm = uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template, **kwargs)
566+
uvm = uvm_booted(
567+
microvm_factory, guest_kernel, rootfs, cpu_template, pci_enabled, **kwargs
568+
)
553569
snapshot = uvm.snapshot_full()
554570
uvm.kill()
555571
uvm2 = microvm_factory.build_from_snapshot(snapshot)
@@ -570,6 +586,7 @@ def uvm_any(
570586
guest_kernel,
571587
rootfs,
572588
cpu_template_any,
589+
pci_enabled,
573590
vcpu_count,
574591
mem_size_mib,
575592
):
@@ -579,21 +596,73 @@ def uvm_any(
579596
guest_kernel,
580597
rootfs,
581598
cpu_template_any,
599+
pci_enabled,
582600
vcpu_count=vcpu_count,
583601
mem_size_mib=mem_size_mib,
584602
)
585603

586604

587605
@pytest.fixture
588606
def uvm_any_booted(
589-
microvm_factory, guest_kernel, rootfs, cpu_template_any, vcpu_count, mem_size_mib
607+
microvm_factory,
608+
guest_kernel,
609+
rootfs,
610+
cpu_template_any,
611+
pci_enabled,
612+
vcpu_count,
613+
mem_size_mib,
590614
):
591615
"""Return booted uvms"""
592616
return uvm_booted(
593617
microvm_factory,
594618
guest_kernel,
595619
rootfs,
596620
cpu_template_any,
621+
pci_enabled,
622+
vcpu_count=vcpu_count,
623+
mem_size_mib=mem_size_mib,
624+
)
625+
626+
627+
@pytest.fixture
628+
def uvm_any_with_pci(
629+
uvm_ctor,
630+
microvm_factory,
631+
guest_kernel_acpi,
632+
rootfs,
633+
cpu_template_any,
634+
vcpu_count,
635+
mem_size_mib,
636+
):
637+
"""Return booted uvms with PCI enabled"""
638+
return uvm_ctor(
639+
microvm_factory,
640+
guest_kernel_acpi,
641+
rootfs,
642+
cpu_template_any,
643+
True,
644+
vcpu_count=vcpu_count,
645+
mem_size_mib=mem_size_mib,
646+
)
647+
648+
649+
@pytest.fixture
650+
def uvm_any_without_pci(
651+
uvm_ctor,
652+
microvm_factory,
653+
guest_kernel,
654+
rootfs,
655+
cpu_template_any,
656+
vcpu_count,
657+
mem_size_mib,
658+
):
659+
"""Return booted uvms with PCI disabled"""
660+
return uvm_ctor(
661+
microvm_factory,
662+
guest_kernel,
663+
rootfs,
664+
cpu_template_any,
665+
False,
597666
vcpu_count=vcpu_count,
598667
mem_size_mib=mem_size_mib,
599668
)

tests/framework/microvm.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@ def spawn(
600600
log_show_origin=False,
601601
metrics_path="fc.ndjson",
602602
emit_metrics: bool = False,
603+
pci: bool = False,
603604
):
604605
"""Start a microVM as a daemon or in a screen session."""
605606
# pylint: disable=subprocess-run-check
@@ -640,6 +641,9 @@ def spawn(
640641
# Checking the timings requires DEBUG level log messages
641642
self.time_api_requests = False
642643

644+
if pci:
645+
self.jailer.extra_args["enable-pci"] = None
646+
643647
cmd = [
644648
*self._pre_cmd,
645649
str(self.jailer_binary_path),

tests/integration_tests/functional/test_net.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@ def test_multi_queue_unsupported(uvm_plain):
8585

8686

8787
@pytest.fixture
88-
def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs):
88+
def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs, pci_enabled):
8989
"""Return booted and restored uvm with no CPU templates"""
90-
return uvm_ctor(microvm_factory, guest_kernel, rootfs, None)
90+
return uvm_ctor(microvm_factory, guest_kernel, rootfs, None, pci_enabled)
9191

9292

9393
def test_tap_offload(uvm_any):
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""Tests for the PCI devices"""
4+
5+
6+
def test_pci_root_present(uvm_any_with_pci):
7+
"""
8+
Test that a guest with PCI enabled has a PCI root device.
9+
"""
10+
11+
vm = uvm_any_with_pci
12+
devices = vm.ssh.run("lspci").stdout.strip().split("\n")
13+
print(devices)
14+
assert devices[0].startswith(
15+
"00:00.0 Host bridge: Intel Corporation Device"
16+
), "PCI root not found in guest"
17+
18+
19+
def test_pci_disabled(uvm_any_without_pci):
20+
"""
21+
Test that a guest with PCI disabled does not have a PCI root device but still works.
22+
"""
23+
24+
vm = uvm_any_without_pci
25+
_, stdout, _ = vm.ssh.run("lspci")
26+
assert (
27+
"00:00.0 Host bridge: Intel Corporation Device" not in stdout
28+
), "PCI root not found in guest"

tests/integration_tests/functional/test_rng.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
from host_tools.network import SSHConnection
99

1010

11-
def uvm_with_rng_booted(microvm_factory, guest_kernel, rootfs, rate_limiter):
11+
def uvm_with_rng_booted(
12+
microvm_factory, guest_kernel, rootfs, rate_limiter, pci_enabled
13+
):
1214
"""Return a booted microvm with virtio-rng configured"""
1315
uvm = microvm_factory.build(guest_kernel, rootfs)
14-
uvm.spawn(log_level="INFO")
16+
uvm.spawn(log_level="INFO", pci=pci_enabled)
1517
uvm.basic_config(vcpu_count=2, mem_size_mib=256)
1618
uvm.add_net_iface()
1719
uvm.api.entropy.put(rate_limiter=rate_limiter)
@@ -21,9 +23,13 @@ def uvm_with_rng_booted(microvm_factory, guest_kernel, rootfs, rate_limiter):
2123
return uvm
2224

2325

24-
def uvm_with_rng_restored(microvm_factory, guest_kernel, rootfs, rate_limiter):
26+
def uvm_with_rng_restored(
27+
microvm_factory, guest_kernel, rootfs, rate_limiter, pci_enabled
28+
):
2529
"""Return a restored uvm with virtio-rng configured"""
26-
uvm = uvm_with_rng_booted(microvm_factory, guest_kernel, rootfs, rate_limiter)
30+
uvm = uvm_with_rng_booted(
31+
microvm_factory, guest_kernel, rootfs, rate_limiter, pci_enabled
32+
)
2733
snapshot = uvm.snapshot_full()
2834
uvm.kill()
2935
uvm2 = microvm_factory.build_from_snapshot(snapshot)
@@ -44,9 +50,9 @@ def rate_limiter(request):
4450

4551

4652
@pytest.fixture
47-
def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs, rate_limiter):
53+
def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs, rate_limiter, pci_enabled):
4854
"""Return booted and restored uvms"""
49-
return uvm_ctor(microvm_factory, guest_kernel, rootfs, rate_limiter)
55+
return uvm_ctor(microvm_factory, guest_kernel, rootfs, rate_limiter, pci_enabled)
5056

5157

5258
def list_rng_available(ssh_connection: SSHConnection) -> list[str]:

tests/integration_tests/security/test_vulnerabilities.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,13 +216,17 @@ def microvm_factory_a(record_property):
216216

217217

218218
@pytest.fixture
219-
def uvm_any_a(microvm_factory_a, uvm_ctor, guest_kernel, rootfs, cpu_template_any):
219+
def uvm_any_a(
220+
microvm_factory_a, uvm_ctor, guest_kernel, rootfs, cpu_template_any, pci_enabled
221+
):
220222
"""Return uvm with revision A firecracker
221223
222224
Since pytest caches fixtures, this guarantees uvm_any_a will match a vm from uvm_any.
223225
See https://docs.pytest.org/en/stable/how-to/fixtures.html#fixtures-can-be-requested-more-than-once-per-test-return-values-are-cached
224226
"""
225-
return uvm_ctor(microvm_factory_a, guest_kernel, rootfs, cpu_template_any)
227+
return uvm_ctor(
228+
microvm_factory_a, guest_kernel, rootfs, cpu_template_any, pci_enabled
229+
)
226230

227231

228232
def test_check_vulnerability_files_ab(request, uvm_any):

0 commit comments

Comments
 (0)