mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-21 20:15:21 +00:00
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:
parent
96fb38a5aa
commit
0a04a950a1
84
vm-allocator/src/gsi.rs
Normal file
84
vm-allocator/src/gsi.rs
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright © 2019 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
|
||||
|
||||
use std::collections::btree_map::BTreeMap;
|
||||
use std::result;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Overflow,
|
||||
}
|
||||
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
/// GsiApic
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct GsiApic {
|
||||
base: u32,
|
||||
irqs: u32,
|
||||
}
|
||||
|
||||
impl GsiApic {
|
||||
/// New GSI APIC
|
||||
pub fn new(base: u32, irqs: u32) -> Self {
|
||||
GsiApic { base, irqs }
|
||||
}
|
||||
}
|
||||
|
||||
/// GsiAllocator
|
||||
pub struct GsiAllocator {
|
||||
apics: BTreeMap<u32, u32>,
|
||||
next_irq: u32,
|
||||
next_gsi: u32,
|
||||
}
|
||||
|
||||
impl GsiAllocator {
|
||||
/// New GSI allocator
|
||||
pub fn new(apics: Vec<GsiApic>) -> Self {
|
||||
let mut allocator = GsiAllocator {
|
||||
apics: BTreeMap::new(),
|
||||
next_irq: 0xffff_ffff,
|
||||
next_gsi: 0,
|
||||
};
|
||||
|
||||
for apic in &apics {
|
||||
if apic.base < allocator.next_irq {
|
||||
allocator.next_irq = apic.base;
|
||||
}
|
||||
|
||||
if apic.base + apic.irqs > allocator.next_gsi {
|
||||
allocator.next_gsi = apic.base + apic.irqs;
|
||||
}
|
||||
|
||||
allocator.apics.insert(apic.base, apic.irqs);
|
||||
}
|
||||
|
||||
allocator
|
||||
}
|
||||
|
||||
/// Allocate a GSI
|
||||
pub fn allocate_gsi(&mut self) -> Result<u32> {
|
||||
self.next_gsi = self.next_gsi.checked_add(1).ok_or(Error::Overflow)?;
|
||||
|
||||
Ok(self.next_gsi - 1)
|
||||
}
|
||||
|
||||
/// Allocate an IRQ
|
||||
pub fn allocate_irq(&mut self) -> Result<u32> {
|
||||
let mut irq: u32 = 0;
|
||||
for (base, irqs) in self.apics.iter() {
|
||||
// HACKHACK - This only works with 1 single IOAPIC...
|
||||
if self.next_irq >= *base && self.next_irq < *base + *irqs {
|
||||
irq = self.next_irq;
|
||||
self.next_irq += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if irq == 0 {
|
||||
return Err(Error::Overflow);
|
||||
}
|
||||
|
||||
Ok(irq)
|
||||
}
|
||||
}
|
@ -14,7 +14,9 @@ extern crate libc;
|
||||
extern crate vm_memory;
|
||||
|
||||
mod address;
|
||||
mod gsi;
|
||||
mod system;
|
||||
|
||||
pub use crate::address::AddressAllocator;
|
||||
pub use crate::gsi::{GsiAllocator, GsiApic};
|
||||
pub use crate::system::SystemAllocator;
|
||||
|
@ -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.
|
||||
|
@ -44,7 +44,7 @@ use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::ptr::null_mut;
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use std::{result, str, thread};
|
||||
use vm_allocator::SystemAllocator;
|
||||
use vm_allocator::{GsiApic, SystemAllocator};
|
||||
use vm_memory::guest_memory::FileOffset;
|
||||
use vm_memory::{
|
||||
Address, Bytes, Error as MmapError, GuestAddress, GuestMemory, GuestMemoryMmap,
|
||||
@ -1066,13 +1066,18 @@ impl<'a> Vm<'a> {
|
||||
|
||||
CpuidPatch::patch_cpuid(&mut cpuid, cpuid_patches);
|
||||
|
||||
let ioapic = GsiApic::new(
|
||||
X86_64_IRQ_BASE,
|
||||
ioapic::NUM_IOAPIC_PINS as u32 - X86_64_IRQ_BASE,
|
||||
);
|
||||
|
||||
// Let's allocate 64 GiB of addressable MMIO space, starting at 0.
|
||||
let mut allocator = SystemAllocator::new(
|
||||
GuestAddress(0),
|
||||
1 << 16 as GuestUsize,
|
||||
GuestAddress(0),
|
||||
1 << 36 as GuestUsize,
|
||||
X86_64_IRQ_BASE,
|
||||
vec![ioapic],
|
||||
)
|
||||
.ok_or(Error::CreateSystemAllocator)?;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user