-
Couldn't load subscription status.
- Fork 2.1k
[virtio-mem] Dynamic slots and performance tests #5490
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
base: feature/virtio-mem
Are you sure you want to change the base?
[virtio-mem] Dynamic slots and performance tests #5490
Conversation
Add a slot_cnt parameter to next_kvm_slot. This will be used to allocate multiple slots for a slotted hotpluggable region. Signed-off-by: Riccardo Mancini <mancio@amazon.com>
To avoid boilerplate code in multiple places, let's just define it once and use it everywhere. Signed-off-by: Riccardo Mancini <mancio@amazon.com>
In preparation to adding support for multiple memory slots, refactor the mincore_bitmap function to accept a pointer and length rather than an entire memory region object. Signed-off-by: Riccardo Mancini <mancio@amazon.com>
a94732d to
418d9be
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## feature/virtio-mem #5490 +/- ##
======================================================
+ Coverage 83.23% 83.30% +0.07%
======================================================
Files 276 276
Lines 28666 28836 +170
======================================================
+ Hits 23861 24023 +162
- Misses 4805 4813 +8
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
A single GuestMemoryRegion can be split into multiple KVM slots. This is used for Hotplug type regions where we can dynamically remove access to the region from the guest. Signed-off-by: Riccardo Mancini <mancio@amazon.com>
Dynamically plug/unplug KVM slots when any/all of the blocks are plugged/unplugged. This prevents the guest from accessing unplugged memory. However, this doesn't yet prevent the device emulation from accessing the slots. Signed-off-by: Riccardo Mancini <mancio@amazon.com>
418d9be to
9f5740e
Compare
Add a performance test that measures the latency to hot(un)plug different amounts of memory. Signed-off-by: Riccardo Mancini <mancio@amazon.com>
Add the memory hotplug tests to buildkite. Signed-off-by: Riccardo Mancini <mancio@amazon.com>
9f5740e to
84671d9
Compare
This prevents the device emulation to be tricked into accessing unplugged memory ranges. If a malicious driver tries to do so, the VMM will crash with a memory error. Signed-off-by: Riccardo Mancini <mancio@amazon.com>
These two functions were doing a similar thing. Let's extend the build_from_snapshot to support uffd and drop the newly introduced clone_vm. Signed-off-by: Riccardo Mancini <mancio@amazon.com>
Extend the tests to also check that everything works with diff snapshots (dirty page tracking and mincore). Signed-off-by: Riccardo Mancini <mancio@amazon.com>
Add a test that verifies that incremental snapshots work as expected. Each generation will plug more memory and verify that the contents in memory from previous generations are persisted. Signed-off-by: Riccardo Mancini <mancio@amazon.com>
84671d9 to
25fa432
Compare
| /// Obtain the next free kvm slot id | ||
| pub fn next_kvm_slot(&self) -> Option<u32> { | ||
| let next = self.common.next_kvm_slot.fetch_add(1, Ordering::Relaxed); | ||
| pub fn next_kvm_slot(&self, slot_cnt: u32) -> Option<u32> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'd be worth explaining what the new argument does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack
| pub slot_from: u32, | ||
| /// the size of the slots of this region | ||
| pub slot_size: usize, | ||
| /// a bitvec indicating whether region i is plugged into KVM (1) or not (0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whether slot i is plugged?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct, will fix
| pub plugged: Mutex<BitVec>, | ||
| } | ||
|
|
||
| /// A snapshot of the state of a memory slot |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does "snapshot of the state" mean here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean that it's a point-in-time view of the state of the memory slot. Maybe it'd be less confusing "The current state of a memory slot"
| slot_cnt: usize, | ||
| ) -> Self { | ||
| // Caller should pass a valid slot size and count for this region | ||
| assert!(slot_size * slot_cnt == u64_to_usize(region.len())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can we infer slot_size or slot_cnt instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could recompute the slot_cnt that is computed in the caller already. I agree it's cleaner.
| "type": "dword", | ||
| "op": "eq", | ||
| "val": 1075883590, | ||
| "comment": "KVM_SET_USER_MEMORY_REGION" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can explain why we need it here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack
| .guest_memory() | ||
| .iter() | ||
| .find(|r| r.region_type == GuestRegionType::Hotpluggable) | ||
| .expect("there should be one and only one hotpluggable region"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how do we verify it's the only one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not verified, if there are multiple it's gonna return the first one. I specified it in the same sentence because I didn't want to leave a separate comment.
| } | ||
|
|
||
| impl<'a> GuestMemorySlot<'a> { | ||
| pub(crate) fn protect(&self, accessible: bool) -> Result<(), MemoryError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: the reverse logic of the boolean may read more smoothly: protect(true) would mean "protection enabled".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed
Changes
mprotectto protect unplugged slots from the VMM device emulation.Reason
virtio-mem feature work.
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
tools/devtool checkbuild --allto verify that the PR passesbuild checks on all supported architectures.
tools/devtool checkstyleto verify that the PR passes theautomated style checks.
how they are solving the problem in a clear and encompassing way.
in the PR.
CHANGELOG.md.Runbook for Firecracker API changes.
integration tests.
TODO.rust-vmm.