mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-02 01:45: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;
|
extern crate vm_memory;
|
||||||
|
|
||||||
mod address;
|
mod address;
|
||||||
|
mod gsi;
|
||||||
mod system;
|
mod system;
|
||||||
|
|
||||||
pub use crate::address::AddressAllocator;
|
pub use crate::address::AddressAllocator;
|
||||||
|
pub use crate::gsi::{GsiAllocator, GsiApic};
|
||||||
pub use crate::system::SystemAllocator;
|
pub use crate::system::SystemAllocator;
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
use vm_memory::{GuestAddress, GuestUsize};
|
use vm_memory::{GuestAddress, GuestUsize};
|
||||||
|
|
||||||
use crate::address::AddressAllocator;
|
use crate::address::AddressAllocator;
|
||||||
|
use crate::gsi::{GsiAllocator, GsiApic};
|
||||||
|
|
||||||
use libc::{sysconf, _SC_PAGESIZE};
|
use libc::{sysconf, _SC_PAGESIZE};
|
||||||
|
|
||||||
@ -25,12 +26,12 @@ fn pagesize() -> usize {
|
|||||||
/// # Example - Use the `SystemAddress` builder.
|
/// # Example - Use the `SystemAddress` builder.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use vm_allocator::SystemAllocator;
|
/// # use vm_allocator::{GsiApic, SystemAllocator};
|
||||||
/// # use vm_memory::{Address, GuestAddress, GuestUsize};
|
/// # use vm_memory::{Address, GuestAddress, GuestUsize};
|
||||||
/// let mut allocator = SystemAllocator::new(
|
/// let mut allocator = SystemAllocator::new(
|
||||||
/// GuestAddress(0x1000), 0x10000,
|
/// GuestAddress(0x1000), 0x10000,
|
||||||
/// GuestAddress(0x10000000), 0x10000000,
|
/// GuestAddress(0x10000000), 0x10000000,
|
||||||
/// 5).unwrap();
|
/// vec![GsiApic::new(5, 19)]).unwrap();
|
||||||
/// assert_eq!(allocator.allocate_irq(), Some(5));
|
/// assert_eq!(allocator.allocate_irq(), Some(5));
|
||||||
/// assert_eq!(allocator.allocate_irq(), Some(6));
|
/// assert_eq!(allocator.allocate_irq(), Some(6));
|
||||||
/// assert_eq!(allocator.allocate_mmio_addresses(None, 0x1000, Some(0x1000)), Some(GuestAddress(0x1fffe000)));
|
/// assert_eq!(allocator.allocate_mmio_addresses(None, 0x1000, Some(0x1000)), Some(GuestAddress(0x1fffe000)));
|
||||||
@ -39,7 +40,7 @@ fn pagesize() -> usize {
|
|||||||
pub struct SystemAllocator {
|
pub struct SystemAllocator {
|
||||||
io_address_space: AddressAllocator,
|
io_address_space: AddressAllocator,
|
||||||
mmio_address_space: AddressAllocator,
|
mmio_address_space: AddressAllocator,
|
||||||
next_irq: u32,
|
gsi_allocator: GsiAllocator,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SystemAllocator {
|
impl SystemAllocator {
|
||||||
@ -56,23 +57,23 @@ impl SystemAllocator {
|
|||||||
io_size: GuestUsize,
|
io_size: GuestUsize,
|
||||||
mmio_base: GuestAddress,
|
mmio_base: GuestAddress,
|
||||||
mmio_size: GuestUsize,
|
mmio_size: GuestUsize,
|
||||||
first_irq: u32,
|
apics: Vec<GsiApic>,
|
||||||
) -> Option<Self> {
|
) -> Option<Self> {
|
||||||
Some(SystemAllocator {
|
Some(SystemAllocator {
|
||||||
io_address_space: AddressAllocator::new(io_base, io_size)?,
|
io_address_space: AddressAllocator::new(io_base, io_size)?,
|
||||||
mmio_address_space: AddressAllocator::new(mmio_base, mmio_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.
|
/// Reserves the next available system irq number.
|
||||||
pub fn allocate_irq(&mut self) -> Option<u32> {
|
pub fn allocate_irq(&mut self) -> Option<u32> {
|
||||||
if let Some(irq_num) = self.next_irq.checked_add(1) {
|
self.gsi_allocator.allocate_irq().ok()
|
||||||
self.next_irq = irq_num;
|
}
|
||||||
Some(irq_num - 1)
|
|
||||||
} else {
|
/// Reserves the next available GSI.
|
||||||
None
|
pub fn allocate_gsi(&mut self) -> Option<u32> {
|
||||||
}
|
self.gsi_allocator.allocate_gsi().ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reserves a section of `size` bytes of IO address space.
|
/// 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::ptr::null_mut;
|
||||||
use std::sync::{Arc, Barrier, Mutex};
|
use std::sync::{Arc, Barrier, Mutex};
|
||||||
use std::{result, str, thread};
|
use std::{result, str, thread};
|
||||||
use vm_allocator::SystemAllocator;
|
use vm_allocator::{GsiApic, SystemAllocator};
|
||||||
use vm_memory::guest_memory::FileOffset;
|
use vm_memory::guest_memory::FileOffset;
|
||||||
use vm_memory::{
|
use vm_memory::{
|
||||||
Address, Bytes, Error as MmapError, GuestAddress, GuestMemory, GuestMemoryMmap,
|
Address, Bytes, Error as MmapError, GuestAddress, GuestMemory, GuestMemoryMmap,
|
||||||
@ -1066,13 +1066,18 @@ impl<'a> Vm<'a> {
|
|||||||
|
|
||||||
CpuidPatch::patch_cpuid(&mut cpuid, cpuid_patches);
|
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's allocate 64 GiB of addressable MMIO space, starting at 0.
|
||||||
let mut allocator = SystemAllocator::new(
|
let mut allocator = SystemAllocator::new(
|
||||||
GuestAddress(0),
|
GuestAddress(0),
|
||||||
1 << 16 as GuestUsize,
|
1 << 16 as GuestUsize,
|
||||||
GuestAddress(0),
|
GuestAddress(0),
|
||||||
1 << 36 as GuestUsize,
|
1 << 36 as GuestUsize,
|
||||||
X86_64_IRQ_BASE,
|
vec![ioapic],
|
||||||
)
|
)
|
||||||
.ok_or(Error::CreateSystemAllocator)?;
|
.ok_or(Error::CreateSystemAllocator)?;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user