diff options
author | Zach Reizner <zachr@google.com> | 2017-06-23 20:19:05 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-06-27 10:55:46 -0700 |
commit | b3fba4535c322ebbd4f53c69ec9b7153f9bb04d6 (patch) | |
tree | 5ca61d7071d53f5661b78cc799702c9e65d74490 | |
parent | 34959d42c145cf5bb00bb429fee698df3c06a401 (diff) | |
download | crosvm-b3fba4535c322ebbd4f53c69ec9b7153f9bb04d6.tar crosvm-b3fba4535c322ebbd4f53c69ec9b7153f9bb04d6.tar.gz crosvm-b3fba4535c322ebbd4f53c69ec9b7153f9bb04d6.tar.bz2 crosvm-b3fba4535c322ebbd4f53c69ec9b7153f9bb04d6.tar.lz crosvm-b3fba4535c322ebbd4f53c69ec9b7153f9bb04d6.tar.xz crosvm-b3fba4535c322ebbd4f53c69ec9b7153f9bb04d6.tar.zst crosvm-b3fba4535c322ebbd4f53c69ec9b7153f9bb04d6.zip |
sys_util: implement VolatileMemory for Mmap and GuestMemory
Mmap and GuestMemory are the intended targets for the VolatileMemory trait. TEST=cargo test BUG=None Change-Id: Ie228b5daef691a6dcb80841be1c3dddb4b19ffc4 Reviewed-on: https://chromium-review.googlesource.com/547335 Commit-Ready: Zach Reizner <zachr@chromium.org> Tested-by: Zach Reizner <zachr@chromium.org> Reviewed-by: Zach Reizner <zachr@chromium.org>
-rw-r--r-- | sys_util/src/guest_memory.rs | 50 | ||||
-rw-r--r-- | sys_util/src/mmap.rs | 57 |
2 files changed, 106 insertions, 1 deletions
diff --git a/sys_util/src/guest_memory.rs b/sys_util/src/guest_memory.rs index f7ad298..ae96ead 100644 --- a/sys_util/src/guest_memory.rs +++ b/sys_util/src/guest_memory.rs @@ -9,6 +9,7 @@ use std::result; use std::sync::Arc; use data_model::DataInit; +use data_model::volatile_memory::*; use guest_address::GuestAddress; use mmap::MemoryMapping; @@ -56,7 +57,8 @@ impl GuestMemory { } } - let mapping = MemoryMapping::new(range.1).map_err(|_| Error::MemoryMappingFailed)?; + let mapping = MemoryMapping::new(range.1) + .map_err(|_| Error::MemoryMappingFailed)?; regions.push(MemoryRegion { mapping: mapping, guest_base: range.0, @@ -282,6 +284,19 @@ impl GuestMemory { } } +impl VolatileMemory for GuestMemory { + fn get_slice(&self, offset: usize, count: usize) -> VolatileMemoryResult<VolatileSlice> { + for region in self.regions.iter() { + if offset >= region.guest_base.0 && offset < region_end(region).0 { + return region + .mapping + .get_slice(offset - region.guest_base.0, count); + } + } + Err(VolatileMemoryError::OutOfBounds { addr: offset }) + } +} + #[cfg(test)] mod tests { use super::*; @@ -316,4 +331,37 @@ mod tests { assert_eq!(val1, num1); assert_eq!(val2, num2); } + + #[test] + fn test_ref_load_u64() { + let start_addr1 = GuestAddress(0x0); + let start_addr2 = GuestAddress(0x1000); + let gm = GuestMemory::new(&vec![(start_addr1, 0x1000), (start_addr2, 0x1000)]).unwrap(); + + let val1: u64 = 0xaa55aa55aa55aa55; + let val2: u64 = 0x55aa55aa55aa55aa; + gm.write_obj_at_addr(val1, GuestAddress(0x500)).unwrap(); + gm.write_obj_at_addr(val2, GuestAddress(0x1000 + 32)) + .unwrap(); + let num1: u64 = gm.get_ref(0x500).unwrap().load(); + let num2: u64 = gm.get_ref(0x1000 + 32).unwrap().load(); + assert_eq!(val1, num1); + assert_eq!(val2, num2); + } + + #[test] + fn test_ref_store_u64() { + let start_addr1 = GuestAddress(0x0); + let start_addr2 = GuestAddress(0x1000); + let gm = GuestMemory::new(&vec![(start_addr1, 0x1000), (start_addr2, 0x1000)]).unwrap(); + + let val1: u64 = 0xaa55aa55aa55aa55; + let val2: u64 = 0x55aa55aa55aa55aa; + gm.get_ref(0x500).unwrap().store(val1); + gm.get_ref(0x1000 + 32).unwrap().store(val2); + let num1: u64 = gm.read_obj_from_addr(GuestAddress(0x500)).unwrap(); + let num2: u64 = gm.read_obj_from_addr(GuestAddress(0x1000 + 32)).unwrap(); + assert_eq!(val1, num1); + assert_eq!(val2, num2); + } } diff --git a/sys_util/src/mmap.rs b/sys_util/src/mmap.rs index edd2a00..57627f8 100644 --- a/sys_util/src/mmap.rs +++ b/sys_util/src/mmap.rs @@ -11,8 +11,10 @@ use std::ptr::null_mut; use std::os::unix::io::AsRawFd; use libc; + use errno; +use data_model::volatile_memory::*; use data_model::DataInit; #[derive(Debug)] @@ -281,6 +283,19 @@ impl MemoryMapping { } } +impl VolatileMemory for MemoryMapping { + fn get_slice(&self, offset: usize, count: usize) -> VolatileMemoryResult<VolatileSlice> { + let mem_end = calc_offset(offset, count)?; + if mem_end > self.size { + return Err(VolatileMemoryError::OutOfBounds { addr: mem_end }); + } + + // Safe because we checked that offset + count was within our range and we only ever hand + // out volatile accessors. + Ok(unsafe { VolatileSlice::new((self.addr as usize + offset) as *mut _, count) }) + } +} + impl Drop for MemoryMapping { fn drop(&mut self) { // This is safe because we mmap the area at addr ourselves, and nobody @@ -294,6 +309,7 @@ impl Drop for MemoryMapping { #[cfg(test)] mod tests { use super::*; + use data_model::{VolatileMemory, VolatileMemoryError}; #[test] fn basic_map() { @@ -308,4 +324,45 @@ mod tests { assert!(res.is_ok()); assert_eq!(res.unwrap(), 5); } + + #[test] + fn slice_size() { + let m = MemoryMapping::new(5).unwrap(); + let s = m.get_slice(2, 3).unwrap(); + assert_eq!(s.size(), 3); + } + + #[test] + fn slice_addr() { + let m = MemoryMapping::new(5).unwrap(); + let s = m.get_slice(2, 3).unwrap(); + assert_eq!(s.as_ptr(), unsafe { m.as_ptr().offset(2) }); + } + + #[test] + fn slice_store() { + let m = MemoryMapping::new(5).unwrap(); + let r = m.get_ref(2).unwrap(); + r.store(9u16); + assert_eq!(m.read_obj::<u16>(2).unwrap(), 9); + } + + #[test] + fn slice_overflow_error() { + use std::usize; + let m = MemoryMapping::new(5).unwrap(); + let res = m.get_slice(usize::MAX, 3).unwrap_err(); + assert_eq!(res, + VolatileMemoryError::Overflow { + base: usize::MAX, + offset: 3, + }); + + } + #[test] + fn slice_oob_error() { + let m = MemoryMapping::new(5).unwrap(); + let res = m.get_slice(3, 3).unwrap_err(); + assert_eq!(res, VolatileMemoryError::OutOfBounds { addr: 6 }); + } } |