Skip to content

Commit ade928d

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 f48b922 commit ade928d

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
@@ -527,22 +527,38 @@ def mem_size_mib():
527527
return 256
528528

529529

530+
@pytest.fixture(params=[True, False])
531+
def pci_enabled(request):
532+
"""Fixture that allows configuring whether a microVM will have PCI enabled or not"""
533+
yield request.param
534+
535+
530536
def uvm_booted(
531-
microvm_factory, guest_kernel, rootfs, cpu_template, vcpu_count=2, mem_size_mib=256
537+
microvm_factory,
538+
guest_kernel,
539+
rootfs,
540+
cpu_template,
541+
pci_enabled,
542+
vcpu_count=2,
543+
mem_size_mib=256,
532544
):
533545
"""Return a booted uvm"""
534546
uvm = microvm_factory.build(guest_kernel, rootfs)
535-
uvm.spawn()
547+
uvm.spawn(pci=pci_enabled)
536548
uvm.basic_config(vcpu_count=vcpu_count, mem_size_mib=mem_size_mib)
537549
uvm.set_cpu_template(cpu_template)
538550
uvm.add_net_iface()
539551
uvm.start()
540552
return uvm
541553

542554

543-
def uvm_restored(microvm_factory, guest_kernel, rootfs, cpu_template, **kwargs):
555+
def uvm_restored(
556+
microvm_factory, guest_kernel, rootfs, cpu_template, pci_enabled, **kwargs
557+
):
544558
"""Return a restored uvm"""
545-
uvm = uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template, **kwargs)
559+
uvm = uvm_booted(
560+
microvm_factory, guest_kernel, rootfs, cpu_template, pci_enabled, **kwargs
561+
)
546562
snapshot = uvm.snapshot_full()
547563
uvm.kill()
548564
uvm2 = microvm_factory.build_from_snapshot(snapshot)
@@ -563,6 +579,7 @@ def uvm_any(
563579
guest_kernel,
564580
rootfs,
565581
cpu_template_any,
582+
pci_enabled,
566583
vcpu_count,
567584
mem_size_mib,
568585
):
@@ -572,21 +589,73 @@ def uvm_any(
572589
guest_kernel,
573590
rootfs,
574591
cpu_template_any,
592+
pci_enabled,
575593
vcpu_count=vcpu_count,
576594
mem_size_mib=mem_size_mib,
577595
)
578596

579597

580598
@pytest.fixture
581599
def uvm_any_booted(
582-
microvm_factory, guest_kernel, rootfs, cpu_template_any, vcpu_count, mem_size_mib
600+
microvm_factory,
601+
guest_kernel,
602+
rootfs,
603+
cpu_template_any,
604+
pci_enabled,
605+
vcpu_count,
606+
mem_size_mib,
583607
):
584608
"""Return booted uvms"""
585609
return uvm_booted(
586610
microvm_factory,
587611
guest_kernel,
588612
rootfs,
589613
cpu_template_any,
614+
pci_enabled,
615+
vcpu_count=vcpu_count,
616+
mem_size_mib=mem_size_mib,
617+
)
618+
619+
620+
@pytest.fixture
621+
def uvm_any_with_pci(
622+
uvm_ctor,
623+
microvm_factory,
624+
guest_kernel_acpi,
625+
rootfs,
626+
cpu_template_any,
627+
vcpu_count,
628+
mem_size_mib,
629+
):
630+
"""Return booted uvms with PCI enabled"""
631+
return uvm_ctor(
632+
microvm_factory,
633+
guest_kernel_acpi,
634+
rootfs,
635+
cpu_template_any,
636+
True,
637+
vcpu_count=vcpu_count,
638+
mem_size_mib=mem_size_mib,
639+
)
640+
641+
642+
@pytest.fixture
643+
def uvm_any_without_pci(
644+
uvm_ctor,
645+
microvm_factory,
646+
guest_kernel,
647+
rootfs,
648+
cpu_template_any,
649+
vcpu_count,
650+
mem_size_mib,
651+
):
652+
"""Return booted uvms with PCI disabled"""
653+
return uvm_ctor(
654+
microvm_factory,
655+
guest_kernel,
656+
rootfs,
657+
cpu_template_any,
658+
False,
590659
vcpu_count=vcpu_count,
591660
mem_size_mib=mem_size_mib,
592661
)

tests/framework/microvm.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,7 @@ def spawn(
597597
log_show_origin=False,
598598
metrics_path="fc.ndjson",
599599
emit_metrics: bool = False,
600+
pci: bool = False,
600601
):
601602
"""Start a microVM as a daemon or in a screen session."""
602603
# pylint: disable=subprocess-run-check
@@ -637,6 +638,9 @@ def spawn(
637638
# Checking the timings requires DEBUG level log messages
638639
self.time_api_requests = False
639640

641+
if pci:
642+
self.jailer.extra_args["enable-pci"] = None
643+
640644
cmd = [
641645
*self._pre_cmd,
642646
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
@@ -89,9 +89,9 @@ def test_multi_queue_unsupported(uvm_plain):
8989

9090

9191
@pytest.fixture
92-
def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs):
92+
def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs, pci_enabled):
9393
"""Return booted and restored uvm with no CPU templates"""
94-
return uvm_ctor(microvm_factory, guest_kernel, rootfs, None)
94+
return uvm_ctor(microvm_factory, guest_kernel, rootfs, None, pci_enabled)
9595

9696

9797
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)