mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
allocator: Add a basic resource allocation crate
This is based on the crosvm resource allocator from commit 107edb3e. We only have PIO and MMIO address space to handle, and don't have a GPU specific path and space. Also, we support allocating a range at a specified address. This is mostly useful for PIO, but might be also necessary for MMIO. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
102
vm-allocator/src/system.rs
Executable file
102
vm-allocator/src/system.rs
Executable file
@@ -0,0 +1,102 @@
|
||||
// Copyright 2018 The Chromium OS Authors. All rights reserved.
|
||||
// Copyright © 2019 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
//
|
||||
// Portions Copyright 2017 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 THIRD-PARTY file.
|
||||
|
||||
use vm_memory::{GuestAddress, GuestUsize};
|
||||
|
||||
use crate::address::AddressAllocator;
|
||||
|
||||
use libc::{sysconf, _SC_PAGESIZE};
|
||||
|
||||
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
|
||||
#[inline(always)]
|
||||
fn pagesize() -> usize {
|
||||
// Trivially safe
|
||||
unsafe { sysconf(_SC_PAGESIZE) as usize }
|
||||
}
|
||||
|
||||
/// Manages allocating system resources such as address space and interrupt numbers.
|
||||
///
|
||||
/// # Example - Use the `SystemAddress` builder.
|
||||
///
|
||||
/// ```
|
||||
/// # use vm_allocator::SystemAllocator;
|
||||
/// # use vm_memory::{Address, GuestAddress, GuestUsize};
|
||||
/// let mut allocator = SystemAllocator::new(
|
||||
/// Some(GuestAddress(0x1000)), Some(0x10000),
|
||||
/// GuestAddress(0x10000000), 0x10000000,
|
||||
/// 5).unwrap();
|
||||
/// assert_eq!(allocator.allocate_irq(), Some(5));
|
||||
/// assert_eq!(allocator.allocate_irq(), Some(6));
|
||||
/// assert_eq!(allocator.allocate_mmio_addresses(None, 0x1000), Some(GuestAddress(0x1fffe000)));
|
||||
///
|
||||
/// ```
|
||||
pub struct SystemAllocator {
|
||||
io_address_space: Option<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.
|
||||
/// * `mmio_base` - The starting address of MMIO memory.
|
||||
/// * `mmio_size` - The size of MMIO memory.
|
||||
/// * `first_irq` - The first irq number to give out.
|
||||
pub fn new(
|
||||
io_base: Option<GuestAddress>,
|
||||
io_size: Option<GuestUsize>,
|
||||
mmio_base: GuestAddress,
|
||||
mmio_size: GuestUsize,
|
||||
first_irq: u32,
|
||||
) -> Option<Self> {
|
||||
let page_size = pagesize() as u64;
|
||||
Some(SystemAllocator {
|
||||
io_address_space: if let (Some(b), Some(s)) = (io_base, io_size) {
|
||||
Some(AddressAllocator::new(b, s, Some(0x400))?)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
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,
|
||||
address: GuestAddress,
|
||||
size: GuestUsize,
|
||||
) -> Option<GuestAddress> {
|
||||
self.io_address_space
|
||||
.as_mut()?
|
||||
.allocate(Some(address), size)
|
||||
}
|
||||
|
||||
/// Reserves a section of `size` bytes of MMIO address space.
|
||||
pub fn allocate_mmio_addresses(
|
||||
&mut self,
|
||||
address: Option<GuestAddress>,
|
||||
size: GuestUsize,
|
||||
) -> Option<GuestAddress> {
|
||||
self.mmio_address_space.allocate(address, size)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user