Skip to content

refactor: de-duplicate virtio queue validation logic #5276

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

roypat
Copy link
Contributor

@roypat roypat commented Jun 20, 2025

As part of #5260 we noticed that parts of our virtio queue validation logic was duplicated between Queue::is_valid and Queue::initialize, resulting in most queue invariants being checked twice needlessly. This PR fixed this by merging the two functions, and having all validation happen right before activation (refusing to activate the device if validation of any of its queues fails).

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 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.

roypat added 4 commits June 20, 2025 16:44
Just call initialize() again. It does some needless alignment checking,
but that's not really harmful.

Signed-off-by: Patrick Roy <roypat@amazon.co.uk>
Factor out the alignment checks on the vring components into
get_slice_ptr, instead of writing them out 3 times in initialize().
While we're at it, also explain why its okay to only alignment check the
GPA and not the HVAs as well.

Signed-off-by: Patrick Roy <roypat@amazon.co.uk>
Vring validation was a bit awkwardly split across two functions which
did overlapping sets of checks: Queue::initialize verified alignment and
memory accesses, while Queue::is_valid additionally checked Queue::ready
and Queue::size. However, on the activation path, both were called,
meanign we checked alignment twice (.initialize() is called in
.activate(), but we only call .activate() if .is_valid() returned true).
This is confusing at best, and at worst made us potentially virtio spec
incompliant: If the quest tried to activate a virtio device, but
this failed because some vring was not valid (in terms of
Queue::is_valid), then Firecracker would silently ignore the activation
request. Now, it instead marks the device as needing reset, and notifies
the guest of its failure to properly configure the vrings.

While we're at it, also remove some duplicated checks from the vring
restoration code: .initialize() is called for activated devices, so
there's no need to later validate the size specifically again, and also
no need for the additional call to is_valid().

Signed-off-by: Patrick Roy <roypat@amazon.co.uk>
verify_size only had assertions about our mocks, which is not very
useful (in fact, the second assertion was trivially true, no matter what
we did). So let's just remove it.

Signed-off-by: Patrick Roy <roypat@amazon.co.uk>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant