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
16 changes: 5 additions & 11 deletions src/arch/aarch64/kernel/interrupts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,7 @@ use crate::arch::aarch64::kernel::core_local::{core_id, core_scheduler, incremen
use crate::arch::aarch64::kernel::scheduler::State;
use crate::arch::aarch64::kernel::serial::handle_uart_interrupt;
use crate::arch::aarch64::mm::paging::{self, BasePageSize, PageSize, PageTableEntryFlags};
#[cfg(not(feature = "pci"))]
use crate::drivers::mmio::get_interrupt_handlers;
#[cfg(feature = "pci")]
use crate::drivers::pci::get_interrupt_handlers;
use crate::drivers::{InterruptHandlerQueue, InterruptLine};
use crate::drivers::InterruptHandlerMap;
use crate::env;
use crate::mm::{PageAlloc, PageRangeAllocator};
use crate::scheduler::{self, CoreId, timer_interrupts};
Expand All @@ -40,8 +36,7 @@ static mut TIMER_INTERRUPT: u32 = 0;
/// Number of the UART interrupt
static mut UART_INTERRUPT: u32 = 0;
/// Possible interrupt handlers
static INTERRUPT_HANDLERS: OnceCell<HashMap<u8, InterruptHandlerQueue, RandomState>> =
OnceCell::new();
static INTERRUPT_HANDLERS: OnceCell<InterruptHandlerMap> = OnceCell::new();
/// Driver for the Arm Generic Interrupt Controller version 3 (or 4).
pub(crate) static GIC: SpinMutex<Option<GicV3<'_>>> = SpinMutex::new(None);

Expand Down Expand Up @@ -87,16 +82,15 @@ pub fn disable() {
dmb(ISH);
}

pub(crate) fn install_handlers() {
let mut handlers: HashMap<InterruptLine, InterruptHandlerQueue, RandomState> =
pub(crate) fn install_handlers(old_handlers: InterruptHandlerMap) {
let mut handlers: InterruptHandlerMap =
HashMap::with_hasher(RandomState::with_seeds(0, 0, 0, 0));

fn timer_handler() {
debug!("Handle timer interrupt");
timer_interrupts::clear_active_and_set_next();
}

for (key, value) in get_interrupt_handlers().into_iter() {
for (key, value) in old_handlers.into_iter() {
handlers.insert(key + SPI_START, value);
}

Expand Down
18 changes: 10 additions & 8 deletions src/arch/aarch64/kernel/mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use crate::arch::aarch64::kernel::interrupts::GIC;
use crate::arch::aarch64::mm::paging::{self, PageSize};
#[cfg(feature = "virtio-console")]
use crate::console::IoDevice;
use crate::drivers::InterruptHandlerMap;
#[cfg(feature = "virtio-console")]
use crate::drivers::console::VirtioConsoleDriver;
#[cfg(feature = "virtio-console")]
Expand Down Expand Up @@ -117,7 +118,7 @@ pub(crate) fn get_vsock_driver() -> Option<&'static InterruptTicketMutex<VirtioV
.find_map(|drv| drv.get_vsock_driver())
}

pub fn init_drivers() {
pub fn init_drivers(handlers: &mut InterruptHandlerMap) {
without_interrupts(|| {
let Some(fdt) = crate::env::fdt() else {
error!("No device tree found, cannot initialize MMIO drivers");
Expand Down Expand Up @@ -191,13 +192,14 @@ pub fn init_drivers() {
"Found {id:?} card at {mmio:p}, irq: {irq}, type: {irqtype}, flags: {irqflags}"
);

let drv = match mmio_virtio::init_device(mmio, irq.try_into().unwrap()) {
Ok(drv) => drv,
Err(err) => {
error!("{err}");
continue;
}
};
let drv =
match mmio_virtio::init_device(mmio, irq.try_into().unwrap(), handlers) {
Ok(drv) => drv,
Err(err) => {
error!("{err}");
continue;
}
};

let mut gic = GIC.lock();
let Some(gic) = gic.as_mut() else {
Expand Down
10 changes: 8 additions & 2 deletions src/arch/riscv64/kernel/devicetree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::arch::riscv64::kernel::mmio::MmioDriver;
use crate::arch::riscv64::mm::paging::{self, PageSize};
#[cfg(feature = "virtio-console")]
use crate::console::IoDevice;
use crate::drivers::InterruptHandlerMap;
#[cfg(feature = "virtio-console")]
use crate::drivers::console::VirtioUART;
#[cfg(all(feature = "virtio-console", not(feature = "pci")))]
Expand Down Expand Up @@ -97,9 +98,13 @@ pub fn init() {
info!("Model: {model}");
}

#[cfg_attr(
any(not(any(feature = "gem-net", feature = "virtio")), feature = "pci"),
expect(unused_variables)
)]
/// Inits drivers based on the device tree
/// This function should only be called once
pub fn init_drivers() {
pub fn init_drivers(handlers: &mut InterruptHandlerMap) {
// TODO: Implement devicetree correctly
if let Some(fdt) = env::fdt() {
debug!("Init drivers using devicetree");
Expand Down Expand Up @@ -184,6 +189,7 @@ pub fn init_drivers() {
irq.try_into().unwrap(),
phy_addr,
<[u8; 6]>::try_from(mac).expect("MAC with invalid length"),
handlers,
) {
Ok(drv) => *NETWORK_DEVICE.lock() = Some(drv),
Err(err) => error!("Could not initialize GEM driver: {err}"),
Expand Down Expand Up @@ -252,7 +258,7 @@ pub fn init_drivers() {

debug!("Found virtio {id:?} at {mmio:p}");

match mmio_virtio::init_device(mmio, irq.try_into().unwrap()) {
match mmio_virtio::init_device(mmio, irq.try_into().unwrap(), handlers) {
#[cfg(feature = "virtio-console")]
Ok(VirtioDriver::Console(drv)) => {
register_driver(MmioDriver::VirtioConsole(
Expand Down
13 changes: 3 additions & 10 deletions src/arch/riscv64/kernel/interrupts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@ use riscv::interrupt::{Exception, Interrupt, Trap};
use riscv::register::{scause, sie, sip, sstatus, stval};
use trapframe::TrapFrame;

use crate::drivers::InterruptHandlerQueue;
#[cfg(not(feature = "pci"))]
use crate::drivers::mmio::get_interrupt_handlers;
#[cfg(feature = "pci")]
use crate::drivers::pci::get_interrupt_handlers;
use crate::drivers::InterruptHandlerMap;
use crate::scheduler;

/// Base address of the PLIC, only one access at the same time is allowed
Expand All @@ -25,8 +21,7 @@ static PLIC_CONTEXT: SpinMutex<u16> = SpinMutex::new(0x0);
/// PLIC context for new interrupt handlers
static CURRENT_INTERRUPTS: SpinMutex<Vec<u32>> = SpinMutex::new(Vec::new());

static INTERRUPT_HANDLERS: OnceCell<HashMap<u8, InterruptHandlerQueue, RandomState>> =
OnceCell::new();
static INTERRUPT_HANDLERS: OnceCell<InterruptHandlerMap> = OnceCell::new();

/// Init Interrupts
pub(crate) fn install() {
Expand Down Expand Up @@ -119,9 +114,7 @@ pub(crate) fn disable() {
}

/// Currently not needed because we use the trapframe crate
pub(crate) fn install_handlers() {
let handlers = get_interrupt_handlers();

pub(crate) fn install_handlers(handlers: InterruptHandlerMap) {
for irq_number in handlers.keys() {
unsafe {
let base_ptr = PLIC_BASE.lock();
Expand Down
12 changes: 4 additions & 8 deletions src/arch/x86_64/kernel/interrupts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,10 @@ use crate::arch::x86_64::kernel::core_local::{core_scheduler, increment_irq_coun
use crate::arch::x86_64::kernel::{apic, processor};
use crate::arch::x86_64::mm::paging::{BasePageSize, PageSize, page_fault_handler};
use crate::arch::x86_64::swapgs;
use crate::drivers::InterruptHandlerQueue;
#[cfg(not(feature = "pci"))]
use crate::drivers::mmio::get_interrupt_handlers;
#[cfg(feature = "pci")]
use crate::drivers::pci::get_interrupt_handlers;
use crate::drivers::InterruptHandlerMap;
use crate::scheduler::{self, CoreId};

static IRQ_HANDLERS: OnceCell<HashMap<u8, InterruptHandlerQueue, RandomState>> = OnceCell::new();
static IRQ_HANDLERS: OnceCell<InterruptHandlerMap> = OnceCell::new();
static IRQ_NAMES: InterruptTicketMutex<HashMap<u8, &'static str, RandomState>> =
InterruptTicketMutex::new(HashMap::with_hasher(RandomState::with_seeds(0, 0, 0, 0)));

Expand Down Expand Up @@ -161,8 +157,8 @@ pub(crate) fn install() {
IRQ_NAMES.lock().insert(7, "FPU");
}

pub(crate) fn install_handlers() {
IRQ_HANDLERS.set(get_interrupt_handlers()).unwrap();
pub(crate) fn install_handlers(handlers: InterruptHandlerMap) {
IRQ_HANDLERS.set(handlers).unwrap();
}

fn handle_interrupt(stack_frame: ExceptionStackFrame, index: u8, _error_code: Option<u64>) {
Expand Down
15 changes: 10 additions & 5 deletions src/arch/x86_64/kernel/mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::arch::x86_64::mm::paging;
use crate::arch::x86_64::mm::paging::{
BasePageSize, PageSize, PageTableEntryFlags, PageTableEntryFlagsExt,
};
use crate::drivers::InterruptHandlerMap;
#[cfg(feature = "virtio-console")]
use crate::drivers::console::VirtioConsoleDriver;
#[cfg(feature = "virtio-fs")]
Expand Down Expand Up @@ -217,8 +218,12 @@ pub(crate) fn get_vsock_driver() -> Option<&'static InterruptTicketMutex<VirtioV
.find_map(|drv| drv.get_vsock_driver())
}

fn register_mmio(mmio: VolatileRef<'static, DeviceRegisters>, irq: u8) {
match mmio_virtio::init_device(mmio, irq) {
fn register_mmio(
mmio: VolatileRef<'static, DeviceRegisters>,
irq: u8,
handlers: &mut InterruptHandlerMap,
) {
match mmio_virtio::init_device(mmio, irq, handlers) {
#[cfg(feature = "virtio-console")]
Ok(VirtioDriver::Console(drv)) => {
register_driver(MmioDriver::VirtioConsole(InterruptTicketMutex::new(*drv)));
Expand All @@ -239,7 +244,7 @@ fn register_mmio(mmio: VolatileRef<'static, DeviceRegisters>, irq: u8) {
}
}

pub(crate) fn init_drivers() {
pub(crate) fn init_drivers(handlers: &mut InterruptHandlerMap) {
without_interrupts(|| {
let layout = PageLayout::from_size(BasePageSize::SIZE as usize).unwrap();
let page_range = PageBox::new(layout).unwrap();
Expand All @@ -249,11 +254,11 @@ pub(crate) fn init_drivers() {

if linux_mmio.is_empty() {
for (mmio, irq) in guess_device(virtual_address) {
register_mmio(mmio, irq);
register_mmio(mmio, irq, handlers);
}
} else {
for (mmio, irq) in check_linux_args(linux_mmio, virtual_address) {
register_mmio(mmio, irq);
register_mmio(mmio, irq, handlers);
}
}

Expand Down
33 changes: 17 additions & 16 deletions src/arch/x86_64/kernel/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ use uart_16550::backend::PioBackend;
use uart_16550::{Config, Uart16550};

#[cfg(feature = "pci")]
use crate::arch::x86_64::kernel::interrupts;
#[cfg(feature = "pci")]
use crate::drivers::InterruptLine;
use crate::drivers::InterruptHandlerMap;
use crate::errno::Errno;

#[cfg(feature = "pci")]
Expand Down Expand Up @@ -79,21 +77,24 @@ impl Write for SerialDevice {
}

#[cfg(feature = "pci")]
pub(crate) fn get_serial_handler() -> (InterruptLine, fn()) {
fn serial_handler() {
let mut guard = UART_DEVICE.lock();

while guard.uart.read_ready().unwrap() {
let mut buf = [0; 256];
let n = guard.uart.read(&mut buf).unwrap();
guard.buffer.write_all(&buf[..n]).unwrap();
}
pub(crate) fn handle_interrupt() {
let mut guard = UART_DEVICE.lock();

drop(guard);
crate::console::CONSOLE_WAKER.lock().wake();
while guard.uart.read_ready().unwrap() {
let mut buf = [0; 256];
let n = guard.uart.read(&mut buf).unwrap();
guard.buffer.write_all(&buf[..n]).unwrap();
}

interrupts::add_irq_name(SERIAL_IRQ, "COM1");
drop(guard);
crate::console::CONSOLE_WAKER.lock().wake();
}

(SERIAL_IRQ, serial_handler)
#[cfg(feature = "pci")]
pub(crate) fn register_handler(handlers: &mut InterruptHandlerMap) {
super::interrupts::add_irq_name(SERIAL_IRQ, "COM1");
handlers
.entry(SERIAL_IRQ)
.or_default()
.push_back(handle_interrupt);
}
10 changes: 5 additions & 5 deletions src/drivers/console/mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@ use virtio::console::Config;
use virtio::mmio::{DeviceRegisters, DeviceRegistersVolatileFieldAccess};
use volatile::VolatileRef;

use crate::drivers::InterruptLine;
use crate::drivers::console::{ConsoleDevCfg, RxQueue, TxQueue, VirtioConsoleDriver};
use crate::drivers::virtio::error::VirtioError;
use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg};
use crate::drivers::{InterruptHandlerMap, InterruptLine};

// Backend-dependent interface for Virtio console driver
impl VirtioConsoleDriver {
pub fn new(
dev_id: u16,
mut registers: VolatileRef<'static, DeviceRegisters>,
irq: InterruptLine,
) -> Result<VirtioConsoleDriver, VirtioError> {
let dev_cfg_raw: &'static Config = unsafe {
&*registers
Expand All @@ -37,7 +36,6 @@ impl VirtioConsoleDriver {
com_cfg: ComCfg::new(registers),
isr_stat,
notif_cfg,
irq,
recv_vq: RxQueue::new(),
send_vq: TxQueue::new(),
})
Expand All @@ -52,9 +50,11 @@ impl VirtioConsoleDriver {
dev_id: u16,
registers: VolatileRef<'static, DeviceRegisters>,
irq: InterruptLine,
handlers: &mut InterruptHandlerMap,
) -> Result<VirtioConsoleDriver, VirtioError> {
let mut drv = VirtioConsoleDriver::new(dev_id, registers, irq)?;
drv.init_dev().map_err(VirtioError::ConsoleDriver)?;
let mut drv = VirtioConsoleDriver::new(dev_id, registers)?;
drv.init_dev(handlers, Some(irq))
.map_err(VirtioError::ConsoleDriver)?;
drv.com_cfg.print_information();
Ok(drv)
}
Expand Down
19 changes: 12 additions & 7 deletions src/drivers/console/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ use crate::drivers::virtio::virtqueue::split::SplitVq;
use crate::drivers::virtio::virtqueue::{
AvailBufferToken, BufferElem, BufferType, UsedBufferToken, VirtQueue, Virtq,
};
use crate::drivers::{Driver, InterruptLine};
use crate::drivers::{Driver, InterruptHandlerMap, InterruptLine};
use crate::errno::Errno;
use crate::mm::device_alloc::DeviceAlloc;

Expand Down Expand Up @@ -262,17 +262,12 @@ pub(crate) struct VirtioConsoleDriver {
pub(super) com_cfg: ComCfg,
pub(super) isr_stat: IsrStatus,
pub(super) notif_cfg: NotifCfg,
pub(super) irq: InterruptLine,

pub(super) recv_vq: RxQueue,
pub(super) send_vq: TxQueue,
}

impl Driver for VirtioConsoleDriver {
fn get_interrupt_number(&self) -> InterruptLine {
self.irq
}

fn get_name(&self) -> &'static str {
"virtio"
}
Expand Down Expand Up @@ -304,7 +299,11 @@ impl VirtioConsoleDriver {
self.com_cfg.set_failed();
}

pub fn init_dev(&mut self) -> Result<(), VirtioConsoleError> {
pub fn init_dev(
&mut self,
handlers: &mut InterruptHandlerMap,
irq: Option<InterruptLine>,
) -> Result<(), VirtioConsoleError> {
// Reset
self.com_cfg.reset_dev();

Expand Down Expand Up @@ -369,6 +368,12 @@ impl VirtioConsoleDriver {
// Interrupt for communicating that a sent packet left, is not needed
self.send_vq.disable_notifs();

handlers.entry(irq.unwrap()).or_default().push_back(|| {
if let Some(driver) = get_console_driver() {
driver.lock().handle_interrupt();
};
});

// At this point the device is "live"
self.com_cfg.drv_ok();

Expand Down
Loading
Loading