vm-allocator: Expand the IRQ allocation API to support GSI

GSI (Global System Interrupt) is an extension of just a linear array of
IRQs. It takes IOAPICs into account for example.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
Samuel Ortiz
2019-07-11 11:48:14 +02:00
committed by Sebastien Boeuf
parent 96fb38a5aa
commit 0a04a950a1
4 changed files with 105 additions and 13 deletions

View File

@@ -10,6 +10,7 @@
use vm_memory::{GuestAddress, GuestUsize};
use crate::address::AddressAllocator;
use crate::gsi::{GsiAllocator, GsiApic};
use libc::{sysconf, _SC_PAGESIZE};
@@ -25,12 +26,12 @@ fn pagesize() -> usize {
/// # Example - Use the `SystemAddress` builder.
///
/// ```
/// # use vm_allocator::SystemAllocator;
/// # use vm_allocator::{GsiApic, SystemAllocator};
/// # use vm_memory::{Address, GuestAddress, GuestUsize};
/// let mut allocator = SystemAllocator::new(
/// GuestAddress(0x1000), 0x10000,
/// GuestAddress(0x10000000), 0x10000000,
/// 5).unwrap();
/// vec![GsiApic::new(5, 19)]).unwrap();
/// assert_eq!(allocator.allocate_irq(), Some(5));
/// assert_eq!(allocator.allocate_irq(), Some(6));
/// assert_eq!(allocator.allocate_mmio_addresses(None, 0x1000, Some(0x1000)), Some(GuestAddress(0x1fffe000)));
@@ -39,7 +40,7 @@ fn pagesize() -> usize {
pub struct SystemAllocator {
io_address_space: AddressAllocator,
mmio_address_space: AddressAllocator,
next_irq: u32,
gsi_allocator: GsiAllocator,
}
impl SystemAllocator {
@@ -56,23 +57,23 @@ impl SystemAllocator {
io_size: GuestUsize,
mmio_base: GuestAddress,
mmio_size: GuestUsize,
first_irq: u32,
apics: Vec<GsiApic>,
) -> Option<Self> {
Some(SystemAllocator {
io_address_space: AddressAllocator::new(io_base, io_size)?,
mmio_address_space: AddressAllocator::new(mmio_base, mmio_size)?,
next_irq: first_irq,
gsi_allocator: GsiAllocator::new(apics),
})
}
/// 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
}
self.gsi_allocator.allocate_irq().ok()
}
/// Reserves the next available GSI.
pub fn allocate_gsi(&mut self) -> Option<u32> {
self.gsi_allocator.allocate_gsi().ok()
}
/// Reserves a section of `size` bytes of IO address space.