summary refs log tree commit diff
path: root/resources
diff options
context:
space:
mode:
authorJakub Staron <jstaron@google.com>2019-04-24 10:55:25 -0700
committerCommit Bot <commit-bot@chromium.org>2019-06-05 07:28:54 +0000
commita3411eaac1ad3d51d5282d1462d6764ad539ce13 (patch)
tree7a9898280f1cd8c78dcdfac6893189ed42419d76 /resources
parent127453d7eccdb6a903d0855fabb8f0935be90882 (diff)
downloadcrosvm-a3411eaac1ad3d51d5282d1462d6764ad539ce13.tar
crosvm-a3411eaac1ad3d51d5282d1462d6764ad539ce13.tar.gz
crosvm-a3411eaac1ad3d51d5282d1462d6764ad539ce13.tar.bz2
crosvm-a3411eaac1ad3d51d5282d1462d6764ad539ce13.tar.lz
crosvm-a3411eaac1ad3d51d5282d1462d6764ad539ce13.tar.xz
crosvm-a3411eaac1ad3d51d5282d1462d6764ad539ce13.tar.zst
crosvm-a3411eaac1ad3d51d5282d1462d6764ad539ce13.zip
crosvm: virtio-pmem device
Adds support for virtio-pmem device as an alternative for virtio-blk.

Exposing disk image to guest as virtio-blk device results in both guest
and host independently caching the disk I/O. Using virtio-pmem device
allows to mount disk image as direct access (DAX) in the guest and thus
bypass the guest cache. This will reduce memory foodprint of the VMs.

BUG=None
TEST=cargo test
TEST=Boot patched termina kernel in crosvm; mount virtio-pmem device as
DAX and run xfstests.

Change-Id: I935fc8fc7527f79e5169f07ec7927e4ea4fa6027
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1605517
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Zach Reizner <zachr@chromium.org>
Commit-Queue: Jakub StaroĊ„ <jstaron@google.com>
Diffstat (limited to 'resources')
-rw-r--r--resources/src/address_allocator.rs75
-rw-r--r--resources/src/lib.rs2
2 files changed, 71 insertions, 6 deletions
diff --git a/resources/src/address_allocator.rs b/resources/src/address_allocator.rs
index 45927e0..11978ee 100644
--- a/resources/src/address_allocator.rs
+++ b/resources/src/address_allocator.rs
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+use std::cmp;
 use std::collections::HashMap;
 
 use crate::{Alloc, Error, Result};
@@ -63,18 +64,29 @@ impl AddressAllocator {
         })
     }
 
-    /// Allocates a range of addresses from the managed region with an optional tag.
-    /// Returns allocated_address. (allocated_address, size, tag) can be retrieved
-    /// through the `get` method.
-    pub fn allocate(&mut self, size: u64, alloc: Alloc, tag: String) -> Result<u64> {
+    /// Allocates a range of addresses from the managed region with an optional tag
+    /// and minimal alignment. Returns allocated_address. (allocated_address, size, tag)
+    /// can be retrieved through the `get` method.
+    pub fn allocate_with_align(
+        &mut self,
+        size: u64,
+        alloc: Alloc,
+        tag: String,
+        alignment: u64,
+    ) -> Result<u64> {
+        let alignment = cmp::max(self.alignment, alignment);
+
         if self.allocs.contains_key(&alloc) {
             return Err(Error::ExistingAlloc(alloc));
         }
         if size == 0 {
             return Err(Error::AllocSizeZero);
         }
-        let align_adjust = if self.next_addr % self.alignment != 0 {
-            self.alignment - (self.next_addr % self.alignment)
+        if !alignment.is_power_of_two() {
+            return Err(Error::BadAlignment);
+        }
+        let align_adjust = if self.next_addr % alignment != 0 {
+            alignment - (self.next_addr % alignment)
         } else {
             0
         };
@@ -95,6 +107,10 @@ impl AddressAllocator {
         Ok(addr)
     }
 
+    pub fn allocate(&mut self, size: u64, alloc: Alloc, tag: String) -> Result<u64> {
+        self.allocate_with_align(size, alloc, tag, self.alignment)
+    }
+
     /// Returns allocation associated with `alloc`, or None if no such allocation exists.
     pub fn get(&self, alloc: &Alloc) -> Option<&(u64, u64, String)> {
         self.allocs.get(alloc)
@@ -180,4 +196,51 @@ mod tests {
             Some(&(0x1000, 0x110, String::from("bar0")))
         );
     }
+
+    #[test]
+    fn allocate_with_alignment_allocator_alignment() {
+        let mut pool = AddressAllocator::new(0x1000, 0x10000, Some(0x100)).unwrap();
+        assert_eq!(
+            pool.allocate_with_align(0x110, Alloc::Anon(0), String::from("bar0"), 0x1),
+            Ok(0x1000)
+        );
+        assert_eq!(
+            pool.allocate_with_align(0x100, Alloc::Anon(1), String::from("bar1"), 0x1),
+            Ok(0x1200)
+        );
+    }
+
+    #[test]
+    fn allocate_with_alignment_custom_alignment() {
+        let mut pool = AddressAllocator::new(0x1000, 0x10000, Some(0x4)).unwrap();
+        assert_eq!(
+            pool.allocate_with_align(0x110, Alloc::Anon(0), String::from("bar0"), 0x100),
+            Ok(0x1000)
+        );
+        assert_eq!(
+            pool.allocate_with_align(0x100, Alloc::Anon(1), String::from("bar1"), 0x100),
+            Ok(0x1200)
+        );
+    }
+
+    #[test]
+    fn allocate_with_alignment_no_allocator_alignment() {
+        let mut pool = AddressAllocator::new(0x1000, 0x10000, None).unwrap();
+        assert_eq!(
+            pool.allocate_with_align(0x110, Alloc::Anon(0), String::from("bar0"), 0x100),
+            Ok(0x1000)
+        );
+        assert_eq!(
+            pool.allocate_with_align(0x100, Alloc::Anon(1), String::from("bar1"), 0x100),
+            Ok(0x1200)
+        );
+    }
+
+    #[test]
+    fn allocate_with_alignment_alignment_non_power_of_two() {
+        let mut pool = AddressAllocator::new(0x1000, 0x10000, None).unwrap();
+        assert!(pool
+            .allocate_with_align(0x110, Alloc::Anon(0), String::from("bar0"), 200)
+            .is_err());
+    }
 }
diff --git a/resources/src/lib.rs b/resources/src/lib.rs
index a49f998..c10608e 100644
--- a/resources/src/lib.rs
+++ b/resources/src/lib.rs
@@ -33,6 +33,8 @@ pub enum Alloc {
     PciBar { bus: u8, dev: u8, bar: u8 },
     /// GPU render node region.
     GpuRenderNode,
+    /// Pmem device region with associated device index.
+    PmemDevice(usize),
 }
 
 #[derive(Debug, Eq, PartialEq)]