2019-07-11 09:48:14 +00:00
|
|
|
// Copyright © 2019 Intel Corporation
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
|
|
|
|
|
2020-06-09 04:04:40 +00:00
|
|
|
#[cfg(target_arch = "x86_64")]
|
2019-07-11 09:48:14 +00:00
|
|
|
use std::collections::btree_map::BTreeMap;
|
|
|
|
use std::result;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum Error {
|
|
|
|
Overflow,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub type Result<T> = result::Result<T, Error>;
|
|
|
|
|
|
|
|
/// GsiApic
|
2020-06-09 04:04:40 +00:00
|
|
|
#[cfg(target_arch = "x86_64")]
|
2019-07-11 09:48:14 +00:00
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
pub struct GsiApic {
|
|
|
|
base: u32,
|
|
|
|
irqs: u32,
|
|
|
|
}
|
|
|
|
|
2020-06-09 04:04:40 +00:00
|
|
|
#[cfg(target_arch = "x86_64")]
|
2019-07-11 09:48:14 +00:00
|
|
|
impl GsiApic {
|
|
|
|
/// New GSI APIC
|
|
|
|
pub fn new(base: u32, irqs: u32) -> Self {
|
|
|
|
GsiApic { base, irqs }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// GsiAllocator
|
|
|
|
pub struct GsiAllocator {
|
2020-06-09 04:04:40 +00:00
|
|
|
#[cfg(target_arch = "x86_64")]
|
2019-07-11 09:48:14 +00:00
|
|
|
apics: BTreeMap<u32, u32>,
|
|
|
|
next_irq: u32,
|
|
|
|
next_gsi: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl GsiAllocator {
|
2020-06-09 04:04:40 +00:00
|
|
|
#[cfg(target_arch = "x86_64")]
|
2019-07-11 09:48:14 +00:00
|
|
|
/// 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
|
|
|
|
}
|
|
|
|
|
2020-06-09 04:04:40 +00:00
|
|
|
#[cfg(target_arch = "aarch64")]
|
2020-08-23 07:45:44 +00:00
|
|
|
#[allow(clippy::new_without_default)]
|
2020-06-09 04:04:40 +00:00
|
|
|
/// New GSI allocator
|
|
|
|
pub fn new() -> Self {
|
|
|
|
GsiAllocator {
|
|
|
|
next_irq: arch::IRQ_BASE,
|
|
|
|
next_gsi: arch::IRQ_BASE,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-11 09:48:14 +00:00
|
|
|
/// Allocate a GSI
|
|
|
|
pub fn allocate_gsi(&mut self) -> Result<u32> {
|
2020-06-09 04:04:40 +00:00
|
|
|
let gsi = self.next_gsi;
|
2019-07-11 09:48:14 +00:00
|
|
|
self.next_gsi = self.next_gsi.checked_add(1).ok_or(Error::Overflow)?;
|
2020-06-09 04:04:40 +00:00
|
|
|
Ok(gsi)
|
2019-07-11 09:48:14 +00:00
|
|
|
}
|
|
|
|
|
2020-06-09 04:04:40 +00:00
|
|
|
#[cfg(target_arch = "x86_64")]
|
2019-07-11 09:48:14 +00:00
|
|
|
/// 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)
|
|
|
|
}
|
2020-06-09 04:04:40 +00:00
|
|
|
|
|
|
|
#[cfg(target_arch = "aarch64")]
|
|
|
|
/// Allocate an IRQ
|
|
|
|
pub fn allocate_irq(&mut self) -> Result<u32> {
|
|
|
|
let irq = self.next_irq;
|
|
|
|
self.next_irq = self.next_irq.checked_add(1).ok_or(Error::Overflow)?;
|
|
|
|
Ok(irq)
|
|
|
|
}
|
2019-07-11 09:48:14 +00:00
|
|
|
}
|