guest_memory: add fn to get memfd offset of addr

Add a function offset_from_base() which, given a GuestAddress, determines
the offset of that address within the backing memfd of the GuestMemory.

In other words, this lets you convert a GuestAddress into an offset that
can be understood by another process which has mapped the the memfd and
would like to read from that address.

BUG=chromium:968724
TEST=cargo test

Change-Id: I5b033ad29dd38090f74577c068cc62ee9c6effb6
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2015835
Tested-by: Fletcher Woodruff <fletcherw@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Commit-Queue: Fletcher Woodruff <fletcherw@chromium.org>
This commit is contained in:
Fletcher Woodruff 2020-01-22 16:58:28 -07:00 committed by Commit Bot
parent f9fc42376a
commit 42bff13009

View file

@ -553,6 +553,38 @@ impl GuestMemory {
}
Err(Error::InvalidGuestAddress(guest_addr))
}
/// Convert a GuestAddress into an offset within self.memfd.
///
/// Due to potential gaps within GuestMemory, it is helpful to know the
/// offset within the memfd where a given address is found. This offset
/// can then be passed to another process mapping the memfd to read data
/// starting at that address.
///
/// # Arguments
/// * `guest_addr` - Guest address to convert.
///
/// # Examples
///
/// ```
/// # use sys_util::{GuestAddress, GuestMemory};
/// let addr_a = GuestAddress(0x1000);
/// let addr_b = GuestAddress(0x8000);
/// let mut gm = GuestMemory::new(&vec![
/// (addr_a, 0x2000),
/// (addr_b, 0x3000)]).expect("failed to create GuestMemory");
/// let offset = gm.offset_from_base(GuestAddress(0x9500))
/// .expect("failed to get offset");
/// assert_eq!(offset, 0x3500);
/// ```
pub fn offset_from_base(&self, guest_addr: GuestAddress) -> Result<usize> {
for region in self.regions.iter() {
if guest_addr >= region.guest_base && guest_addr < region_end(region) {
return Ok(region.memfd_offset + guest_addr.offset_from(region.guest_base) as usize);
}
}
Err(Error::InvalidGuestAddress(guest_addr))
}
}
impl VolatileMemory for GuestMemory {