-
Notifications
You must be signed in to change notification settings - Fork 110
Preliminary virtual memory work #339
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: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ | |
Change return type of `GuestRegionMmap::new` from `Result` to `Option`. | ||
- \[#324](https:////github.com/rust-vmm/vm-memory/pull/324)\] `GuestMemoryRegion::bitmap()` now returns a `BitmapSlice`. Accessing the full bitmap is now possible only if the type of the memory region is know, for example with `MmapRegion::bitmap()`. | ||
- \[[#339](https://github.com/rust-vmm/vm-memory/pull/339)\] Fix `Bytes::read()` and `Bytes::write()` not to ignore `try_access()`'s `count` parameter | ||
- \[[#339](https://github.com/rust-vmm/vm-memory/pull/339)\] Implement `Bytes::load()` and `Bytes::store()` with `try_access()` instead of `to_region_addr()` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should also specify that it's only relevant for the blanket impl |
||
|
||
### Removed | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,6 +44,7 @@ | |
use std::convert::From; | ||
use std::fs::File; | ||
use std::io; | ||
use std::mem::size_of; | ||
use std::ops::{BitAnd, BitOr, Deref}; | ||
use std::rc::Rc; | ||
use std::sync::atomic::Ordering; | ||
|
@@ -678,17 +679,62 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T { | |
} | ||
|
||
fn store<O: AtomicAccess>(&self, val: O, addr: GuestAddress, order: Ordering) -> Result<()> { | ||
// `find_region` should really do what `to_region_addr` is doing right now, except | ||
// it should keep returning a `Result`. | ||
self.to_region_addr(addr) | ||
.ok_or(Error::InvalidGuestAddress(addr)) | ||
.and_then(|(region, region_addr)| region.store(val, region_addr, order)) | ||
let expected = size_of::<O>(); | ||
|
||
let completed = self.try_access( | ||
expected, | ||
addr, | ||
|offset, len, region_addr, region| -> Result<usize> { | ||
assert_eq!(offset, 0); | ||
if len < expected { | ||
return Err(Error::PartialBuffer { | ||
expected, | ||
completed: 0, | ||
}); | ||
} | ||
region.store(val, region_addr, order).map(|()| expected) | ||
}, | ||
)?; | ||
|
||
if completed < expected { | ||
Err(Error::PartialBuffer { | ||
expected, | ||
completed, | ||
}) | ||
} else { | ||
Ok(()) | ||
} | ||
Comment on lines
+682
to
+706
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this one (and the one below) would be a bit simpler in terms of let iter = self.get_slices(addr, size_of::<O>());
let vslice = iter.next()?;
if iter.next().is_some() {
return Err(PartialBuffer {0})
}
vslice.store(val) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. heh, or just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, OK. If There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does! In fact, GuestMemoryRegion::store() just defers to Btw, this function is exactly what made me go "mh, maybe there is a use for get_slice() after all". Because atomic loads/stores that cross region boundaries cannot work, and not something that is an implementation TODO that can be solved somehow (e.g. if the guest gives us a virt queue where an atomic goes across region boundaries, then best we can do is fail the device activation). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That’s indeed true and a very good point; for atomic accesses, the reason why they shouldn’t go across boundaries is that they should be naturally aligned, which automatically prevents them from crossing e.g. page boundaries. Then again, specifically for atomic accesses, I think users outside of vm-memory shouldn’t need to implement them and instead use what I still think it could be beneficial to force users to deal with an iterator even when they only expect a single slice because it might encourage them to write a comment why this is OK. Making |
||
} | ||
|
||
fn load<O: AtomicAccess>(&self, addr: GuestAddress, order: Ordering) -> Result<O> { | ||
self.to_region_addr(addr) | ||
.ok_or(Error::InvalidGuestAddress(addr)) | ||
.and_then(|(region, region_addr)| region.load(region_addr, order)) | ||
let expected = size_of::<O>(); | ||
let mut result = None::<O>; | ||
|
||
let completed = self.try_access( | ||
expected, | ||
addr, | ||
|offset, len, region_addr, region| -> Result<usize> { | ||
assert_eq!(offset, 0); | ||
if len < expected { | ||
return Err(Error::PartialBuffer { | ||
expected, | ||
completed: 0, | ||
}); | ||
} | ||
result = Some(region.load(region_addr, order)?); | ||
Ok(expected) | ||
}, | ||
)?; | ||
|
||
if completed < expected { | ||
Err(Error::PartialBuffer { | ||
expected, | ||
completed, | ||
}) | ||
} else { | ||
// Must be set because `completed == expected` | ||
Ok(result.unwrap()) | ||
} | ||
} | ||
} | ||
|
||
|
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.
This should probably go into a
Fixed
section. Also, let's specify that this only applies to the blanket impl provided forT: GuestMemory
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.
OK, right!