Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 52 additions & 5 deletions kernel-hal-bare/src/arch/x86_64/interrupt.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,32 @@
#![allow(dead_code)]
#![allow(non_upper_case_globals)]

use alloc::sync::Arc;
use alloc::vec::Vec;
use spin::Mutex;
use trapframe::TrapFrame;

pub type InterruptHandle = Arc<dyn Fn() + Send + Sync>;
lazy_static! {
static ref IRQ_TABLE: Mutex<Vec<Option<InterruptHandle>>> = Default::default();
}

pub fn init() {
init_irq_table();
irq_add_handle(Timer, Arc::new(timer));
irq_add_handle(COM1, Arc::new(com1));
irq_add_handle(Keyboard, Arc::new(keyboard));
super::irq_enable(Keyboard);
super::irq_enable(COM1);
}

fn init_irq_table() {
let mut table = IRQ_TABLE.lock();
for _ in 0..64 {
table.push(None);
}
}

#[no_mangle]
pub extern "C" fn trap_handler(tf: &mut TrapFrame) {
trace!("Interrupt: {:#x} @ CPU{}", tf.trap_num, 0); // TODO 0 should replace in multi-core case
Expand All @@ -24,11 +44,38 @@ pub fn irq_handle(irq: u8) {
use super::{phys_to_virt, LocalApic, XApic, LAPIC_ADDR};
let mut lapic = unsafe { XApic::new(phys_to_virt(LAPIC_ADDR)) };
lapic.eoi();
match irq {
Timer => timer(),
COM1 => com1(),
Keyboard => keyboard(),
_ => panic!("unhandled external IRQ number: {}", irq),
let table = IRQ_TABLE.lock();
match &table[irq as usize] {
Some(f) => f(),
None => panic!("unhandled external IRQ number: {}", irq),
}
}

#[export_name = "hal_irq_add_handle"]
pub fn irq_add_handle(irq: u8, handle: InterruptHandle) -> bool {
info!("IRQ add handle {}", irq);
let irq = irq as usize;
let mut table = IRQ_TABLE.lock();
match table[irq] {
Some(_) => false,
None => {
table[irq] = Some(handle);
true
}
}
}

#[export_name = "hal_irq_remove_handle"]
pub fn irq_remove_handle(irq: u8) -> bool {
info!("IRQ remove handle {}", irq);
let irq = irq as usize;
let mut table = IRQ_TABLE.lock();
match table[irq] {
Some(_) => {
table[irq] = None;
false
}
None => true,
}
}

Expand Down
8 changes: 7 additions & 1 deletion kernel-hal-bare/src/arch/x86_64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,12 +310,18 @@ fn timer_init() {
lapic.cpu_init();
}

#[inline(always)]
#[export_name = "hal_irq_enable"]
pub fn irq_enable(irq: u8) {
let mut ioapic = unsafe { IoApic::new(phys_to_virt(IOAPIC_ADDR)) };
ioapic.enable(irq, 0);
}

#[export_name = "hal_irq_disable"]
pub fn irq_disable(irq: u8) {
let mut ioapic = unsafe { IoApic::new(phys_to_virt(IOAPIC_ADDR)) };
ioapic.disable(irq);
}

const LAPIC_ADDR: usize = 0xfee0_0000;
const IOAPIC_ADDR: usize = 0xfec0_0000;

Expand Down
29 changes: 29 additions & 0 deletions kernel-hal/src/dummy.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::*;
use crate::vdso::VdsoConstants;
use alloc::boxed::Box;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::future::Future;
use core::ops::FnOnce;
Expand Down Expand Up @@ -265,6 +266,34 @@ pub fn irq_handle(_irq: u8) {
unimplemented!()
}

/// Add an interrupt handle to an irq
#[linkage = "weak"]
#[export_name = "hal_irq_add_handle"]
pub fn irq_add_handle(_irq: u8, _handle: Arc<dyn Fn() + Send + Sync>) -> bool {
unimplemented!()
}

/// Remove the interrupt handle of an irq
#[linkage = "weak"]
#[export_name = "hal_irq_remove_handle"]
pub fn irq_remove_handle(_irq: u8) -> bool {
unimplemented!()
}

/// Enable IRQ.
#[linkage = "weak"]
#[export_name = "hal_irq_enable"]
pub fn irq_enable(_irq: u8) {
unimplemented!()
}

/// Disable IRQ.
#[linkage = "weak"]
#[export_name = "hal_irq_disable"]
pub fn irq_disable(_irq: u8) {
unimplemented!()
}

/// Get platform specific information.
#[linkage = "weak"]
#[export_name = "hal_vdso_constants"]
Expand Down
57 changes: 57 additions & 0 deletions zircon-object/src/dev/interrupt/event_interrupt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use {super::*, alloc::sync::Arc, spin::Mutex};

pub struct EventInterrupt {
vector: u8,
inner: Mutex<EventInterruptInner>,
}

#[derive(Default)]
struct EventInterruptInner {
register: bool,
}

impl EventInterrupt {
pub fn new(vector: usize) -> Arc<Self> {
// TODO check vector is a vaild IRQ number
Arc::new(EventInterrupt {
vector: vector as u8,
inner: Default::default(),
})
}
}

impl InterruptTrait for EventInterrupt {
fn mask_interrupt_locked(&self) {
kernel_hal::irq_disable(self.vector as u8);
}

fn unmask_interrupt_locked(&self) {
kernel_hal::irq_enable(self.vector as u8);
}

fn register_interrupt_handler(&self, handle: Arc<dyn Fn() + Send + Sync>) -> ZxResult {
let mut inner = self.inner.lock();
if inner.register {
return Err(ZxError::ALREADY_BOUND);
}
if kernel_hal::irq_add_handle(self.vector, handle) {
inner.register = true;
Ok(())
} else {
Err(ZxError::ALREADY_BOUND)
}
}

fn unregister_interrupt_handler(&self) -> ZxResult {
let mut inner = self.inner.lock();
if !inner.register {
return Ok(());
}
if kernel_hal::irq_remove_handle(self.vector) {
inner.register = false;
Ok(())
} else {
Err(ZxError::ALREADY_BOUND)
} // maybe a better error code?
}
}
Loading