Skip to content

Commit 9b80100

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 0d18c9b commit 9b80100

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
@@ -545,22 +545,38 @@ def mem_size_mib():
545545
return 256
546546

547547

548+
@pytest.fixture(params=[True, False])
549+
def pci_enabled(request):
550+
"""Fixture that allows configuring whether a microVM will have PCI enabled or not"""
551+
yield request.param
552+
553+
548554
def uvm_booted(
549-
microvm_factory, guest_kernel, rootfs, cpu_template, vcpu_count=2, mem_size_mib=256
555+
microvm_factory,
556+
guest_kernel,
557+
rootfs,
558+
cpu_template,
559+
pci_enabled,
560+
vcpu_count=2,
561+
mem_size_mib=256,
550562
):
551563
"""Return a booted uvm"""
552564
uvm = microvm_factory.build(guest_kernel, rootfs)
553-
uvm.spawn()
565+
uvm.spawn(pci=pci_enabled)
554566
uvm.basic_config(vcpu_count=vcpu_count, mem_size_mib=mem_size_mib)
555567
uvm.set_cpu_template(cpu_template)
556568
uvm.add_net_iface()
557569
uvm.start()
558570
return uvm
559571

560572

561-
def uvm_restored(microvm_factory, guest_kernel, rootfs, cpu_template, **kwargs):
573+
def uvm_restored(
574+
microvm_factory, guest_kernel, rootfs, cpu_template, pci_enabled, **kwargs
575+
):
562576
"""Return a restored uvm"""
563-
uvm = uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template, **kwargs)
577+
uvm = uvm_booted(
578+
microvm_factory, guest_kernel, rootfs, cpu_template, pci_enabled, **kwargs
579+
)
564580
snapshot = uvm.snapshot_full()
565581
uvm.kill()
566582
uvm2 = microvm_factory.build_from_snapshot(snapshot)
@@ -581,6 +597,7 @@ def uvm_any(
581597
guest_kernel,
582598
rootfs,
583599
cpu_template_any,
600+
pci_enabled,
584601
vcpu_count,
585602
mem_size_mib,
586603
):
@@ -590,21 +607,73 @@ def uvm_any(
590607
guest_kernel,
591608
rootfs,
592609
cpu_template_any,
610+
pci_enabled,
593611
vcpu_count=vcpu_count,
594612
mem_size_mib=mem_size_mib,
595613
)
596614

597615

598616
@pytest.fixture
599617
def uvm_any_booted(
600-
microvm_factory, guest_kernel, rootfs, cpu_template_any, vcpu_count, mem_size_mib
618+
microvm_factory,
619+
guest_kernel,
620+
rootfs,
621+
cpu_template_any,
622+
pci_enabled,
623+
vcpu_count,
624+
mem_size_mib,
601625
):
602626
"""Return booted uvms"""
603627
return uvm_booted(
604628
microvm_factory,
605629
guest_kernel,
606630
rootfs,
607631
cpu_template_any,
632+
pci_enabled,
633+
vcpu_count=vcpu_count,
634+
mem_size_mib=mem_size_mib,
635+
)
636+
637+
638+
@pytest.fixture
639+
def uvm_any_with_pci(
640+
uvm_ctor,
641+
microvm_factory,
642+
guest_kernel_acpi,
643+
rootfs,
644+
cpu_template_any,
645+
vcpu_count,
646+
mem_size_mib,
647+
):
648+
"""Return booted uvms with PCI enabled"""
649+
return uvm_ctor(
650+
microvm_factory,
651+
guest_kernel_acpi,
652+
rootfs,
653+
cpu_template_any,
654+
True,
655+
vcpu_count=vcpu_count,
656+
mem_size_mib=mem_size_mib,
657+
)
658+
659+
660+
@pytest.fixture
661+
def uvm_any_without_pci(
662+
uvm_ctor,
663+
microvm_factory,
664+
guest_kernel,
665+
rootfs,
666+
cpu_template_any,
667+
vcpu_count,
668+
mem_size_mib,
669+
):
670+
"""Return booted uvms with PCI disabled"""
671+
return uvm_ctor(
672+
microvm_factory,
673+
guest_kernel,
674+
rootfs,
675+
cpu_template_any,
676+
False,
608677
vcpu_count=vcpu_count,
609678
mem_size_mib=mem_size_mib,
610679
)

tests/framework/microvm.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,7 @@ def spawn(
610610
log_show_origin=False,
611611
metrics_path="fc.ndjson",
612612
emit_metrics: bool = False,
613+
pci: bool = False,
613614
):
614615
"""Start a microVM as a daemon or in a screen session."""
615616
# pylint: disable=subprocess-run-check
@@ -655,6 +656,9 @@ def spawn(
655656
# Checking the timings requires DEBUG level log messages
656657
self.time_api_requests = False
657658

659+
if pci:
660+
self.jailer.extra_args["enable-pci"] = None
661+
658662
cmd = [
659663
*self._pre_cmd,
660664
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)