From 473ae270d0e7b80046471826ffe2d75068605305 Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Wed, 30 May 2018 18:09:59 -0700 Subject: 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 Reviewed-on: https://chromium-review.googlesource.com/1089719 Reviewed-by: Sonny Rao --- Cargo.lock | 1 + resources/Cargo.toml | 1 + resources/src/lib.rs | 4 ++ resources/src/system_allocator.rs | 130 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 resources/src/system_allocator.rs diff --git a/Cargo.lock b/Cargo.lock index 562afbc..48e93e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -304,6 +304,7 @@ name = "resources" version = "0.1.0" dependencies = [ "data_model 0.1.0", + "sys_util 0.1.0", ] [[package]] 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 { + 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 { + 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 { + 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 { + 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 { + 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, + io_size: Option, + mmio_base: Option, + mmio_size: Option, + device_base: Option, + device_size: Option, +} + +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::new(self.io_base?, self.io_size?, + self.device_base?, self.device_size?, + self.mmio_base?, self.mmio_size?, + first_irq) + } +} -- cgit 1.4.1