Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use interrupt_controller in interrupts::aarch64 #972

Merged
merged 11 commits into from
Aug 1, 2023
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion kernel/arm_boards/src/boards/qemu_virt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const fn redist(aff0: usize) -> PhysicalAddress {
pub const NUM_CPUS: usize = 4;
pub const NUM_PL011_UARTS: usize = 1;

pub static BOARD_CONFIG: BoardConfig = BoardConfig {
pub const BOARD_CONFIG: BoardConfig = BoardConfig {
cpu_ids: [
cpu_id(0),
cpu_id(1),
Expand All @@ -36,4 +36,6 @@ pub static BOARD_CONFIG: BoardConfig = BoardConfig {
],
}),
pl011_base_addresses: [ PhysicalAddress::new_canonical(0x09000000) ],
pl011_rx_spi: 33,
cpu_local_timer_ppi: 30,
};
10 changes: 10 additions & 0 deletions kernel/arm_boards/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ pub struct BoardConfig {
pub cpu_ids: [mpidr::DefinedMpidrValue; NUM_CPUS],
pub interrupt_controller: InterruptControllerConfig,
pub pl011_base_addresses: [PhysicalAddress; NUM_PL011_UARTS],

/// The IRQ number reserved for the PL011 Single-Serial-Port Controller
/// which Theseus currently uses for logging and UART console.
pub pl011_rx_spi: u8,

/// The IRQ number reserved for CPU-local timer interrupts,
/// which Theseus currently uses for preemptive task switching.
//
// aarch64 manuals define the default timer IRQ number to be 30.
pub cpu_local_timer_ppi: u8,
}

// by default & on x86_64, the default.rs file is used
Expand Down
1 change: 1 addition & 0 deletions kernel/captain/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ log = "0.4.8"

irq_safety = { git = "https://github.com/theseus-os/irq_safety" }
dfqueue = { path = "../../libs/dfqueue", version = "0.1.0" }
interrupt_controller = { path = "../interrupt_controller" }
multicore_bringup = { path = "../multicore_bringup" }
device_manager = { path = "../device_manager" }
early_printer = { path = "../early_printer" }
Expand Down
6 changes: 6 additions & 0 deletions kernel/captain/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ pub fn init(
// arch-gate: the IDT & special stacks are x86_64 specific
#[cfg(target_arch = "x86_64")]
let idt = {
// does nothing at the moment on x86_64
interrupt_controller::init()?;

let (double_fault_stack, privilege_stack) = {
let mut kernel_mmi = kernel_mmi_ref.lock();
(
Expand All @@ -116,6 +119,9 @@ pub fn init(
};

#[cfg(target_arch = "aarch64")] {
// Initialize the GIC
interrupt_controller::init()?;

interrupts::init()?;

// register BSP CpuId
Expand Down
207 changes: 114 additions & 93 deletions kernel/interrupt_controller/src/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,6 @@ pub struct SystemInterruptControllerVersion(pub u8);
pub struct SystemInterruptControllerId(pub u8);
#[derive(Debug, Copy, Clone)]
pub struct LocalInterruptControllerId(pub u16);
#[derive(Debug, Copy, Clone)]
pub struct SystemInterruptNumber(pub(crate) gic::InterruptNumber);
#[derive(Debug, Copy, Clone)]
pub struct LocalInterruptNumber(pub(crate) gic::InterruptNumber);

impl SystemInterruptNumber {
/// Constructor
///
/// On aarch64, shared-peripheral interrupt numbers must lie
/// between 32 & 1019 (inclusive)
pub const fn new(raw_num: u32) -> Self {
match raw_num {
32..=1019 => Self(raw_num),
_ => panic!("Invalid SystemInterruptNumber (must lie in 32..1020)"),
}
}
}

impl LocalInterruptNumber {
/// Constructor
///
/// On aarch64, shared-peripheral interrupt numbers must lie
/// between 0 & 31 (inclusive)
pub const fn new(raw_num: u32) -> Self {
match raw_num {
0..=31 => Self(raw_num),
_ => panic!("Invalid LocalInterruptNumber (must lie in 0..32)"),
}
}
}

/// The private global Generic Interrupt Controller singleton
pub(crate) static INTERRUPT_CONTROLLER: IrqSafeMutex<Option<ArmGic>> = IrqSafeMutex::new(None);
Expand Down Expand Up @@ -89,52 +59,43 @@ pub struct SystemInterruptController;
/// On aarch64 w/ GIC, this corresponds to a Redistributor & CPU interface.
pub struct LocalInterruptController;

// 1st variant: get system controller
// 2nd variant: get local controller
macro_rules! get_int_ctlr {
($name:ident, $func:ident, $this:expr) => {
let mut $name = INTERRUPT_CONTROLLER.lock();
let $name = $name.as_mut().expect(concat!("BUG: ", stringify!($func), "(): INTERRUPT_CONTROLLER was uninitialized"));
};
($name:ident, $func:ident) => ( get_int_ctlr!($name, $func, ()) );
}

impl SystemInterruptControllerApi for SystemInterruptController {
fn id(&self) -> SystemInterruptControllerId {
get_int_ctlr!(int_ctlr, id, self);
let mut int_ctlr = INTERRUPT_CONTROLLER.lock();
let int_ctlr = int_ctlr
.as_ref()
.expect("BUG: id(): INTERRUPT_CONTROLLER was uninitialized");

SystemInterruptControllerId(int_ctlr.implementer().product_id)
}

fn version(&self) -> SystemInterruptControllerVersion {
get_int_ctlr!(int_ctlr, version, self);
let mut int_ctlr = INTERRUPT_CONTROLLER.lock();
let int_ctlr = int_ctlr
.as_ref()
.expect("BUG: version(): INTERRUPT_CONTROLLER was uninitialized");

SystemInterruptControllerVersion(int_ctlr.implementer().version)
}

fn get_destination(
&self,
interrupt_num: SystemInterruptNumber,
) -> Result<(Vec<InterruptDestination>, Priority), &'static str> {
get_int_ctlr!(int_ctlr, get_destination, self);

let priority = int_ctlr.get_interrupt_priority(interrupt_num.0);
let local_number = LocalInterruptNumber(interrupt_num.0);

let vec = match int_ctlr.get_spi_target(interrupt_num.0)?.canonicalize() {
SpiDestination::Specific(cpu) => [InterruptDestination {
cpu,
local_number,
}].to_vec(),
SpiDestination::AnyCpuAvailable => BOARD_CONFIG.cpu_ids.map(|mpidr| InterruptDestination {
cpu: mpidr.into(),
local_number,
}).to_vec(),
interrupt_num: InterruptNumber,
) -> Result<(Vec<CpuId>, Priority), &'static str> {
assert!(interrupt_num >= 32, "shared peripheral interrupts have a number >= 32");
let mut int_ctlr = INTERRUPT_CONTROLLER.lock();
let int_ctlr = int_ctlr
.as_ref()
.expect("BUG: get_destination(): INTERRUPT_CONTROLLER was uninitialized");

let priority = int_ctlr.get_interrupt_priority(interrupt_num as _);
let vec = match int_ctlr.get_spi_target(interrupt_num as _)?.canonicalize() {
SpiDestination::Specific(cpu) => [cpu].to_vec(),
SpiDestination::AnyCpuAvailable => BOARD_CONFIG.cpu_ids.map(|mpidr| mpidr.into()).to_vec(),
SpiDestination::GICv2TargetList(list) => {
let mut vec = Vec::with_capacity(8);
for result in list.iter() {
vec.push(InterruptDestination {
cpu: result?,
local_number,
});
vec.push(result?);
}
vec
}
Expand All @@ -145,71 +106,131 @@ impl SystemInterruptControllerApi for SystemInterruptController {

fn set_destination(
&self,
sys_int_num: SystemInterruptNumber,
destination: InterruptDestination,
sys_int_num: InterruptNumber,
destination: CpuId,
priority: Priority,
) -> Result<(), &'static str> {
get_int_ctlr!(int_ctlr, set_destination, self);
assert_eq!(sys_int_num.0, destination.local_number.0, "Local & System Interrupt Numbers cannot be different with GIC");
assert!(sys_int_num >= 32, "shared peripheral interrupts have a number >= 32");
let mut int_ctlr = INTERRUPT_CONTROLLER.lock();
let int_ctlr = int_ctlr
.as_mut()
.expect("BUG: set_destination(): INTERRUPT_CONTROLLER was uninitialized");

int_ctlr.set_spi_target(sys_int_num.0, SpiDestination::Specific(destination.cpu));
int_ctlr.set_interrupt_priority(sys_int_num.0, priority);
int_ctlr.set_spi_target(sys_int_num as _, SpiDestination::Specific(destination));
int_ctlr.set_interrupt_priority(sys_int_num as _, priority);

Ok(())
}
}

impl LocalInterruptControllerApi for LocalInterruptController {
fn init_secondary_cpu_interface(&self) {
let mut int_ctlr = INTERRUPT_CONTROLLER.lock();
let int_ctlr = int_ctlr
.as_mut()
.expect("BUG: init_secondary_cpu_interface(): INTERRUPT_CONTROLLER was uninitialized");

int_ctlr.init_secondary_cpu_interface();
}

fn id(&self) -> LocalInterruptControllerId {
get_int_ctlr!(int_ctlr, id);
let mut int_ctlr = INTERRUPT_CONTROLLER.lock();
let int_ctlr = int_ctlr
.as_ref()
.expect("BUG: id(): INTERRUPT_CONTROLLER was uninitialized");

LocalInterruptControllerId(int_ctlr.get_cpu_interface_id())
}

fn get_local_interrupt_priority(&self, num: LocalInterruptNumber) -> Priority {
get_int_ctlr!(int_ctlr, get_local_interrupt_priority);
int_ctlr.get_interrupt_priority(num.0)
fn get_local_interrupt_priority(&self, num: InterruptNumber) -> Priority {
assert!(num < 32, "local interrupts have a number < 32");
let mut int_ctlr = INTERRUPT_CONTROLLER.lock();
let int_ctlr = int_ctlr
.as_ref()
.expect("BUG: get_local_interrupt_priority(): INTERRUPT_CONTROLLER was uninitialized");

int_ctlr.get_interrupt_priority(num as _)
}

fn set_local_interrupt_priority(&self, num: LocalInterruptNumber, priority: Priority) {
get_int_ctlr!(int_ctlr, set_local_interrupt_priority);
int_ctlr.set_interrupt_priority(num.0, priority);
fn set_local_interrupt_priority(&self, num: InterruptNumber, priority: Priority) {
assert!(num < 32, "local interrupts have a number < 32");
let mut int_ctlr = INTERRUPT_CONTROLLER.lock();
let int_ctlr = int_ctlr
.as_mut()
.expect("BUG: set_local_interrupt_priority(): INTERRUPT_CONTROLLER was uninitialized");

int_ctlr.set_interrupt_priority(num as _, priority);
}

fn is_local_interrupt_enabled(&self, num: LocalInterruptNumber) -> bool {
get_int_ctlr!(int_ctlr, is_local_interrupt_enabled);
int_ctlr.get_interrupt_state(num.0)
fn is_local_interrupt_enabled(&self, num: InterruptNumber) -> bool {
assert!(num < 32, "local interrupts have a number < 32");
let mut int_ctlr = INTERRUPT_CONTROLLER.lock();
let int_ctlr = int_ctlr
.as_ref()
.expect("BUG: is_local_interrupt_enabled(): INTERRUPT_CONTROLLER was uninitialized");

int_ctlr.get_interrupt_state(num as _)
}

fn enable_local_interrupt(&self, num: LocalInterruptNumber, enabled: bool) {
get_int_ctlr!(int_ctlr, enable_local_interrupt);
int_ctlr.set_interrupt_state(num.0, enabled);
fn enable_local_interrupt(&self, num: InterruptNumber, enabled: bool) {
assert!(num < 32, "local interrupts have a number < 32");
let mut int_ctlr = INTERRUPT_CONTROLLER.lock();
let int_ctlr = int_ctlr
.as_mut()
.expect("BUG: enable_local_interrupt(): INTERRUPT_CONTROLLER was uninitialized");

int_ctlr.set_interrupt_state(num as _, enabled);
}

fn send_ipi(&self, destination: InterruptDestination) {
get_int_ctlr!(int_ctlr, send_ipi);
int_ctlr.send_ipi(destination.local_number.0, IpiTargetCpu::Specific(destination.cpu));
fn send_ipi(&self, num: InterruptNumber, dest: InterruptDestination) {
use InterruptDestination::*;
assert!(num < 16, "IPIs have a number < 16");

let mut int_ctlr = INTERRUPT_CONTROLLER.lock();
let int_ctlr = int_ctlr
.as_mut()
.expect("BUG: send_ipi(): INTERRUPT_CONTROLLER was uninitialized");

int_ctlr.send_ipi(num as _, match dest {
SpecificCpu(cpu) => IpiTargetCpu::Specific(cpu),
AllOtherCpus => IpiTargetCpu::AllOtherCpus,
});
}

fn get_minimum_priority(&self) -> Priority {
get_int_ctlr!(int_ctlr, get_minimum_priority);
let mut int_ctlr = INTERRUPT_CONTROLLER.lock();
let int_ctlr = int_ctlr
.as_ref()
.expect("BUG: get_minimum_priority(): INTERRUPT_CONTROLLER was uninitialized");

int_ctlr.get_minimum_priority()
}

fn set_minimum_priority(&self, priority: Priority) {
get_int_ctlr!(int_ctlr, set_minimum_priority);
let mut int_ctlr = INTERRUPT_CONTROLLER.lock();
let int_ctlr = int_ctlr
.as_mut()
.expect("BUG: set_minimum_priority(): INTERRUPT_CONTROLLER was uninitialized");

int_ctlr.set_minimum_priority(priority)
}

fn acknowledge_interrupt(&self) -> (LocalInterruptNumber, Priority) {
get_int_ctlr!(int_ctlr, acknowledge_interrupt);
fn acknowledge_interrupt(&self) -> (InterruptNumber, Priority) {
let mut int_ctlr = INTERRUPT_CONTROLLER.lock();
let int_ctlr = int_ctlr
.as_mut()
.expect("BUG: acknowledge_interrupt(): INTERRUPT_CONTROLLER was uninitialized");

let (num, prio) = int_ctlr.acknowledge_interrupt();

(LocalInterruptNumber(num), prio)
(num as _, prio)
}

fn end_of_interrupt(&self, number: LocalInterruptNumber) {
get_int_ctlr!(int_ctlr, end_of_interrupt);
int_ctlr.end_of_interrupt(number.0)
fn end_of_interrupt(&self, number: InterruptNumber) {
let mut int_ctlr = INTERRUPT_CONTROLLER.lock();
let int_ctlr = int_ctlr
.as_mut()
.expect("BUG: end_of_interrupt(): INTERRUPT_CONTROLLER was uninitialized");

int_ctlr.end_of_interrupt(number as _)
}
}
Loading