summary refs log tree commit diff
path: root/resources
diff options
context:
space:
mode:
authorDylan Reid <dgreid@chromium.org>2018-05-30 18:09:59 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-06-29 01:08:56 -0700
commit473ae270d0e7b80046471826ffe2d75068605305 (patch)
tree9b1fa61ca51429bf392acc619c1820f24759c199 /resources
parentdea77cef92ffb64551451b133bd3d1f0f50e001e (diff)
downloadcrosvm-473ae270d0e7b80046471826ffe2d75068605305.tar
crosvm-473ae270d0e7b80046471826ffe2d75068605305.tar.gz
crosvm-473ae270d0e7b80046471826ffe2d75068605305.tar.bz2
crosvm-473ae270d0e7b80046471826ffe2d75068605305.tar.lz
crosvm-473ae270d0e7b80046471826ffe2d75068605305.tar.xz
crosvm-473ae270d0e7b80046471826ffe2d75068605305.tar.zst
crosvm-473ae270d0e7b80046471826ffe2d75068605305.zip
resources: Add system resource allocator
Start a system resource allocator that will be able to manage the
resources specific to each architecture.

Change-Id: I98cf35c280fefd7b0000801eb7405a236373b753
Signed-off-by: Dylan Reid <dgreid@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1089719
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
Diffstat (limited to 'resources')
-rw-r--r--resources/Cargo.toml1
-rw-r--r--resources/src/lib.rs4
-rw-r--r--resources/src/system_allocator.rs130
3 files changed, 135 insertions, 0 deletions
diff --git a/resources/Cargo.toml b/resources/Cargo.toml
index 74f0c35..2569f9d 100644
--- a/resources/Cargo.toml
+++ b/resources/Cargo.toml
@@ -5,3 +5,4 @@ authors = ["The Chromium OS Authors"]
 
 [dependencies]
 data_model = { path = "../data_model" }
+sys_util = { path = "../sys_util" }
diff --git a/resources/src/lib.rs b/resources/src/lib.rs
index de87db6..11cc905 100644
--- a/resources/src/lib.rs
+++ b/resources/src/lib.rs
@@ -4,6 +4,10 @@
 
 //! Manages system resources that can be allocated to VMs and their devices.
 
+extern crate sys_util;
+
 mod address_allocator;
+mod system_allocator;
 
 pub use address_allocator::AddressAllocator;
+pub use system_allocator::{AddressRanges, SystemAllocator};
diff --git a/resources/src/system_allocator.rs b/resources/src/system_allocator.rs
new file mode 100644
index 0000000..e03f8c2
--- /dev/null
+++ b/resources/src/system_allocator.rs
@@ -0,0 +1,130 @@
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+use address_allocator::AddressAllocator;
+use sys_util::pagesize;
+
+/// Manages allocating system resources such as address space and interrupt numbers.
+///
+/// # Example - Use the `SystemAddress` builder.
+///
+/// ```
+/// # use sys_util::AddressRanges;
+///   if let Some(mut a) = AddressRanges::new()
+///           .add_io_addresses(0x1000, 0x10000)
+///           .add_device_addresses(0x10000000, 0x10000000)
+///           .add_mmio_addresses(0x30000000, 0x10000)
+///           .create_allocator(5) {
+///       assert_eq!(a.allocate_irq(), Some(5));
+///       assert_eq!(a.allocate_irq(), Some(6));
+///       assert_eq!(a.allocate_device_addresses(0x100), Some(0x10000000));
+///   }
+/// ```
+#[derive(Debug, Eq, PartialEq)]
+pub struct SystemAllocator {
+    io_address_space: AddressAllocator,
+    device_address_space: AddressAllocator,
+    mmio_address_space: AddressAllocator,
+    next_irq: u32,
+}
+
+impl SystemAllocator {
+    /// Creates a new `SystemAllocator` for managing addresses and irq numvers.
+    /// Can return `None` if `base` + `size` overflows a u64 or if alignment isn't a power
+    /// of two.
+    ///
+    /// * `io_base` - The starting address of IO memory.
+    /// * `io_size` - The size of IO memory.
+    /// * `dev_base` - The starting address of device memory.
+    /// * `dev_size` - The size of device memory.
+    /// * `mmio_base` - The starting address of MMIO space.
+    /// * `mmio_size` - The size of MMIO space.
+    /// * `first_irq` - The first irq number to give out.
+    fn new(io_base: u64, io_size: u64,
+               dev_base: u64, dev_size: u64,
+               mmio_base: u64, mmio_size: u64,
+               first_irq: u32)
+            -> Option<Self> {
+        let page_size = pagesize() as u64;
+        Some(SystemAllocator {
+            io_address_space: AddressAllocator::new(io_base, io_size, Some(0x400))?,
+            device_address_space: AddressAllocator::new(dev_base, dev_size, Some(page_size))?,
+            mmio_address_space: AddressAllocator::new(mmio_base, mmio_size, Some(page_size))?,
+            next_irq: first_irq,
+        })
+    }
+
+    /// Reserves the next available system irq number.
+    pub fn allocate_irq(&mut self) -> Option<u32> {
+        if let Some(irq_num) = self.next_irq.checked_add(1) {
+            self.next_irq = irq_num;
+            Some(irq_num - 1)
+        } else {
+            None
+        }
+    }
+
+    /// Reserves a section of `size` bytes of IO address space.
+    pub fn allocate_io_addresses(&mut self, size: u64) -> Option<u64> {
+        self.io_address_space.allocate(size)
+    }
+
+    /// Reserves a section of `size` bytes of device address space.
+    pub fn allocate_device_addresses(&mut self, size: u64) -> Option<u64> {
+        self.device_address_space.allocate(size)
+    }
+
+    /// Reserves a section of `size` bytes of device address space.
+    pub fn allocate_mmio_addresses(&mut self, size: u64) -> Option<u64> {
+        self.mmio_address_space.allocate(size)
+    }
+}
+
+/// Used to build a system address map for use in creating a `SystemAllocator`.
+pub struct AddressRanges {
+    io_base: Option<u64>,
+    io_size: Option<u64>,
+    mmio_base: Option<u64>,
+    mmio_size: Option<u64>,
+    device_base: Option<u64>,
+    device_size: Option<u64>,
+}
+
+impl AddressRanges {
+    pub fn new() -> Self {
+        AddressRanges {
+            io_base: None,
+            io_size: None,
+            mmio_base: None,
+            mmio_size: None,
+            device_base: None,
+            device_size: None,
+        }
+    }
+
+    pub fn add_io_addresses(mut self, base: u64, size: u64) -> Self {
+        self.io_base = Some(base);
+        self.io_size = Some(size);
+        self
+    }
+
+    pub fn add_mmio_addresses(mut self, base: u64, size: u64) -> Self {
+        self.mmio_base = Some(base);
+        self.mmio_size = Some(size);
+        self
+    }
+
+    pub fn add_device_addresses(mut self, base: u64, size: u64) -> Self {
+        self.device_base = Some(base);
+        self.device_size = Some(size);
+        self
+    }
+
+    pub fn create_allocator(&self, first_irq: u32) -> Option<SystemAllocator> {
+        SystemAllocator::new(self.io_base?, self.io_size?,
+                             self.device_base?, self.device_size?,
+                             self.mmio_base?, self.mmio_size?,
+                             first_irq)
+    }
+}