Skip to content

Conversation

bchalios
Copy link
Contributor

@bchalios bchalios commented Sep 25, 2025

Changes

This is a follow up to #5426.

This time around, we mainly:

  1. Move the implementation of the PCI emulation inside the Firecracker vmm crate since it is quite opinionated and not necessarily re-usable by other hypervisors. The pci crate now only holds enum definitions that are Rust representations of various PCI specification values
  2. Make creating/restoring logic of various types more Firecracker-idiomatic
  3. Re-work MSI-X implementation to avoid needless indirections and duplication of MSI-X state in various types.
  4. Move the bus-related types into a module inside vmm and get rid of the vm-device vended crate.

Reason

A lot of this implementation is hypervisor specific and it fits much better in the Firecracker's binary target rather than a generic PCI crate. This way we can remove a lot of dead code and reduce indirection (dynamic dispatch) as well as improve error handling.

License Acceptance

By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache 2.0 license. For more information on following Developer
Certificate of Origin and signing off your commits, please check
CONTRIBUTING.md.

PR Checklist

  • I have read and understand CONTRIBUTING.md.
  • I have run tools/devtool checkbuild --all to verify that the PR passes
    build checks on all supported architectures.
  • I have run tools/devtool checkstyle to verify that the PR passes the
    automated style checks.
  • I have described what is done in these changes, why they are needed, and
    how they are solving the problem in a clear and encompassing way.
  • I have updated any relevant documentation (both in code and in the docs)
    in the PR.
  • I have mentioned all user-facing changes in CHANGELOG.md.
  • If a specific issue led to this PR, this PR closes the issue.
  • When making API changes, I have followed the
    Runbook for Firecracker API changes.
  • I have tested all new and changed functionalities in unit tests and/or
    integration tests.
  • I have linked an issue to every new TODO.

  • This functionality cannot be added in rust-vmm.

Copy link

codecov bot commented Sep 25, 2025

Codecov Report

❌ Patch coverage is 66.18357% with 140 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.79%. Comparing base (d93f562) to head (65d293a).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
src/pci/src/lib.rs 20.00% 80 Missing ⚠️
src/vmm/src/devices/virtio/transport/pci/device.rs 60.00% 20 Missing ⚠️
src/vmm/src/pci/bus.rs 67.64% 11 Missing ⚠️
src/vmm/src/pci/configuration.rs 77.08% 11 Missing ⚠️
src/vmm/src/pci/msix.rs 78.84% 11 Missing ⚠️
src/vmm/src/vstate/vm.rs 70.00% 3 Missing ⚠️
src/vmm/src/device_manager/pci_mngr.rs 91.66% 1 Missing ⚠️
src/vmm/src/devices/virtio/transport/mod.rs 0.00% 1 Missing ⚠️
src/vmm/src/pci/mod.rs 0.00% 1 Missing ⚠️
src/vmm/src/vstate/bus.rs 87.50% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5453      +/-   ##
==========================================
+ Coverage   82.75%   82.79%   +0.04%     
==========================================
  Files         263      263              
  Lines       27307    27226      -81     
==========================================
- Hits        22597    22541      -56     
+ Misses       4710     4685      -25     
Flag Coverage Δ
5.10-m5n.metal 82.97% <66.18%> (+0.04%) ⬆️
5.10-m6a.metal 82.22% <66.18%> (+0.04%) ⬆️
5.10-m6g.metal 79.57% <66.01%> (+0.03%) ⬆️
5.10-m6i.metal 82.97% <66.18%> (+0.05%) ⬆️
5.10-m7a.metal-48xl 82.21% <66.18%> (+0.03%) ⬆️
5.10-m7g.metal 79.57% <66.01%> (+0.03%) ⬆️
5.10-m7i.metal-24xl 82.94% <66.18%> (+0.04%) ⬆️
5.10-m7i.metal-48xl 82.94% <66.18%> (+0.04%) ⬆️
5.10-m8g.metal-24xl 79.57% <66.01%> (+0.03%) ⬆️
5.10-m8g.metal-48xl 79.57% <66.01%> (+0.03%) ⬆️
6.1-m5n.metal 83.00% <66.18%> (+0.04%) ⬆️
6.1-m6a.metal 82.26% <66.18%> (+0.04%) ⬆️
6.1-m6g.metal 79.57% <66.01%> (+0.03%) ⬆️
6.1-m6i.metal 83.00% <66.18%> (+0.04%) ⬆️
6.1-m7a.metal-48xl 82.24% <66.18%> (+0.04%) ⬆️
6.1-m7g.metal 79.57% <66.01%> (+0.04%) ⬆️
6.1-m7i.metal-24xl 83.01% <66.18%> (+0.04%) ⬆️
6.1-m7i.metal-48xl 83.01% <66.18%> (+0.04%) ⬆️
6.1-m8g.metal-24xl 79.57% <66.01%> (+0.03%) ⬆️
6.1-m8g.metal-48xl 79.57% <66.01%> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bchalios bchalios force-pushed the pci_cleanup branch 2 times, most recently from 72b76f8 to 3ff2084 Compare September 29, 2025 11:42
@bchalios bchalios changed the title Pci cleanup PCI cleanup & MSI-X refactoring Sep 29, 2025
@bchalios bchalios force-pushed the pci_cleanup branch 4 times, most recently from 06d8d72 to 51180ec Compare September 30, 2025 09:02
@bchalios bchalios marked this pull request as ready for review September 30, 2025 09:21
@bchalios bchalios added the Status: Awaiting review Indicates that a pull request is ready to be reviewed label Sep 30, 2025
We don't really use the programming interface field of the PCI header.
It's always zero for the devices we support. Don't expose it as an
argument for constructing PciConfiguration objects.

Signed-off-by: Babis Chalios <[email protected]>
Drop PciBarConfiguration type which wasn't used anywhere any more.

Signed-off-by: Babis Chalios <[email protected]>
The implementation of the PCI emulation components is heavily
Firecracker opinionated. Move those inside a module of `vmm` crate and
leave in the `pci` module only type definitions which can easily be
reused across VMMs.

We also take advantage of this refactoring to remove in various places
the usage of `std::io::Error` as error types returned by emulation
logic.

Signed-off-by: Babis Chalios <[email protected]>
The code we inherited from Cloud Hypervisor was using a single `new`
method for creating objects both for booted and snapshot resumed VMs.
The `new` method had an optional `state` argument. When this argument
was `Some(state)` the construction of the object happened through
copying values from `state`.

Split this functionality, for various types, in two distinct methods
`new` & `from_state` which are only called for booted and snapshotted
microVMs respectively. This is similar to the pattern we're using
throughout Firecracker, reduces if/else branches, as well as the
arguments of distinct methods.

Signed-off-by: Babis Chalios <[email protected]>
Our implementation of MSI-X was taken from the equivalent
Cloud Hypervisor one. Cloud Hypervisor supports non-KVM hypervisors,
hence they introduced a few abstractions to cater for that. More
specifically, they are using a trait (`InterruptSourceGroup`) to
describe the underlying hypervisor-specific mechanism used to drive
MSI-X interrupts from the device to the guest.

Moreover, they use a couple of types to distinguish between MSI, MSI-X
and legacy IRQ interrupts and how these can be configured. This is
especially useful for MSI/MSI-X interrupts where the interrupt
configuration is provided by the guest over PCI bus MMIO accesses.
Finally, in order to allow for transparent error handling, `Result`
types returned by related trait methods was returning `std::io::Error`
types as the error type, which is not very intuitive.

We don't need all of that. We clearly distinguish between legacy
interrupts and MSI-X (we don't use at all MSI), so we can simply plug in
all the definitions directly where we need them without any dynamic
dispatch indirection.

Moreover, various MSI-X components were stored all over the place
creating a lot of unnecessary duplication.

This commit refactors our implementation to get rid of the unnecessary
bit of dynamic dispatch. We still keep the `VirtioInterrupt` trait which
we use to abstract the actual interrupt type (IRQ or MSI-X) from VirtIO
devices. Moreover, it removes the duplication of MSI-X related types
across various types. We only duplicate the MSI-X configuration type
(which is behind an Arc) in a few places to avoid needing to
unnecessarily take a lock(). Moreover, we introduce a single interrupt
related error type and get rid of the `std::io::Error` usage.

Finally, it introduces a couple of metrics for interrupts that are
useful information by themselves, but also help us maintain some unit
testing assertions for which we were relying on a mock type that
implemented `InterruptSourceGroup`.

Signed-off-by: Babis Chalios <[email protected]>
We are only using the Bus-related definitions from there now. Move those
in a module under `vmm` and drop the dependency to `vm-device`.

Signed-off-by: Babis Chalios <[email protected]>
Copy link
Contributor

@ShadowCurse ShadowCurse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM

@bchalios bchalios enabled auto-merge (rebase) October 3, 2025 09:49
@bchalios bchalios merged commit 2dab5e8 into firecracker-microvm:main Oct 3, 2025
5 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Awaiting review Indicates that a pull request is ready to be reviewed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants