From 42bff13009bfa0361ad1572997aba5f457cf38f3 Mon Sep 17 00:00:00 2001 From: Fletcher Woodruff Date: Wed, 22 Jan 2020 16:58:28 -0700 Subject: 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 Tested-by: kokoro Reviewed-by: Dylan Reid Commit-Queue: Fletcher Woodruff --- sys_util/src/guest_memory.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/sys_util/src/guest_memory.rs b/sys_util/src/guest_memory.rs index 9e23278..6399f8c 100644 --- a/sys_util/src/guest_memory.rs +++ b/sys_util/src/guest_memory.rs @@ -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 { + 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 { -- cgit 1.4.1