summary refs log tree commit diff
diff options
context:
space:
mode:
authorFletcher Woodruff <fletcherw@chromium.org>2020-01-22 16:58:28 -0700
committerCommit Bot <commit-bot@chromium.org>2020-01-23 16:23:21 +0000
commit42bff13009bfa0361ad1572997aba5f457cf38f3 (patch)
treea17514da0e0018870672984d5eaa30924c57a804
parentf9fc42376a68c17985e2b2d68c077d66f18e3feb (diff)
downloadcrosvm-42bff13009bfa0361ad1572997aba5f457cf38f3.tar
crosvm-42bff13009bfa0361ad1572997aba5f457cf38f3.tar.gz
crosvm-42bff13009bfa0361ad1572997aba5f457cf38f3.tar.bz2
crosvm-42bff13009bfa0361ad1572997aba5f457cf38f3.tar.lz
crosvm-42bff13009bfa0361ad1572997aba5f457cf38f3.tar.xz
crosvm-42bff13009bfa0361ad1572997aba5f457cf38f3.tar.zst
crosvm-42bff13009bfa0361ad1572997aba5f457cf38f3.zip
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>
-rw-r--r--sys_util/src/guest_memory.rs32
1 files changed, 32 insertions, 0 deletions
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<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 {