Skip to content
Open
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
11 changes: 4 additions & 7 deletions src/arch/aarch64/kernel/interrupts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ use memory_addresses::{PhysAddr, VirtAddr};
use crate::arch::aarch64::kernel::core_local::increment_irq_counter;
use crate::arch::aarch64::kernel::scheduler::State;
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::kernel::serial::handle_uart_interrupt;
use crate::mm::{PageAlloc, PageRangeAllocator};
Expand Down Expand Up @@ -87,16 +83,17 @@ pub fn disable() {
dmb(ISH);
}

pub(crate) fn install_handlers() {
pub(crate) fn install_handlers(
old_handlers: HashMap<InterruptLine, InterruptHandlerQueue, RandomState>,
) {
let mut handlers: HashMap<InterruptLine, InterruptHandlerQueue, RandomState> =
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
44 changes: 28 additions & 16 deletions src/arch/aarch64/kernel/mmio.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use alloc::vec::Vec;
use core::ptr::NonNull;

use ahash::RandomState;
use align_address::Align;
use arm_gic::{IntId, Trigger};
use hashbrown::HashMap;
#[cfg(any(
feature = "virtio-console",
feature = "virtio-fs",
Expand Down Expand Up @@ -35,6 +37,7 @@ use crate::drivers::virtio::transport::mmio as mmio_virtio;
use crate::drivers::virtio::transport::mmio::VirtioDriver;
#[cfg(feature = "virtio-vsock")]
use crate::drivers::vsock::VirtioVsockDriver;
use crate::drivers::{InterruptHandlerQueue, InterruptLine};
#[cfg(feature = "virtio-net")]
use crate::executor::device::NETWORK_DEVICE;
use crate::init_cell::InitCell;
Expand Down Expand Up @@ -81,7 +84,11 @@ impl MmioDriver {
}
}

#[cfg(any(feature = "virtio-console", feature = "virtio-fs", feature = "virtio-vsock"))]
#[cfg(any(
feature = "virtio-console",
feature = "virtio-fs",
feature = "virtio-vsock"
))]
pub(crate) fn register_driver(drv: MmioDriver) {
MMIO_DRIVERS.with(|mmio_drivers| mmio_drivers.unwrap().push(drv));
}
Expand Down Expand Up @@ -113,7 +120,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 HashMap<InterruptLine, InterruptHandlerQueue, RandomState>) {
without_interrupts(|| {
let Some(fdt) = crate::env::fdt() else {
error!("No device tree found, cannot initialize MMIO drivers");
Expand Down Expand Up @@ -187,13 +194,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 All @@ -209,25 +217,29 @@ pub fn init_drivers() {
} else {
panic!("Invalid interrupt type");
};
gic.set_interrupt_priority(virtio_irqid, Some(cpu_id), 0x00).unwrap();
gic.set_interrupt_priority(virtio_irqid, Some(cpu_id), 0x00)
.unwrap();
if (irqflags & 0xf) == 4 || (irqflags & 0xf) == 8 {
gic.set_trigger(virtio_irqid, Some(cpu_id), Trigger::Level).unwrap();
gic.set_trigger(virtio_irqid, Some(cpu_id), Trigger::Level)
.unwrap();
} else if (irqflags & 0xf) == 2 || (irqflags & 0xf) == 1 {
gic.set_trigger(virtio_irqid, Some(cpu_id), Trigger::Edge).unwrap();
gic.set_trigger(virtio_irqid, Some(cpu_id), Trigger::Edge)
.unwrap();
} else {
panic!("Invalid interrupt level!");
}
gic.enable_interrupt(virtio_irqid, Some(cpu_id), true).unwrap();
gic.enable_interrupt(virtio_irqid, Some(cpu_id), true)
.unwrap();

match drv {
#[cfg(feature = "virtio-console")]
VirtioDriver::Console(drv) => register_driver(MmioDriver::VirtioConsole(
InterruptTicketMutex::new(*drv),
)),
#[cfg(feature = "virtio-fs")]
VirtioDriver::Fs(drv) => register_driver(MmioDriver::VirtioFs(
InterruptTicketMutex::new(*drv),
)),
VirtioDriver::Fs(drv) => {
register_driver(MmioDriver::VirtioFs(InterruptTicketMutex::new(*drv)));
}
#[cfg(feature = "virtio-net")]
VirtioDriver::Net(drv) => *NETWORK_DEVICE.lock() = Some(*drv),
#[cfg(feature = "virtio-vsock")]
Expand Down
10 changes: 8 additions & 2 deletions src/arch/riscv64/kernel/devicetree.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#[cfg(all(feature = "virtio", not(feature = "pci")))]
use core::ptr::NonNull;

use ahash::RandomState;
use hashbrown::HashMap;
use memory_addresses::PhysAddr;
#[cfg(all(feature = "gem-net", not(feature = "pci")))]
use memory_addresses::VirtAddr;
Expand Down Expand Up @@ -42,6 +44,7 @@ use crate::drivers::virtio::transport::mmio as mmio_virtio;
not(feature = "pci"),
))]
use crate::drivers::virtio::transport::mmio::VirtioDriver;
use crate::drivers::{InterruptHandlerQueue, InterruptLine};
use crate::env;
#[cfg(all(any(feature = "gem-net", feature = "virtio-net"), not(feature = "pci")))]
use crate::executor::device::NETWORK_DEVICE;
Expand Down Expand Up @@ -99,7 +102,9 @@ pub fn init() {

/// Inits drivers based on the device tree
/// This function should only be called once
pub fn init_drivers() {
pub fn init_drivers(
#[allow(unused)] handlers: &mut HashMap<InterruptLine, InterruptHandlerQueue, RandomState>,
) {
// 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
12 changes: 4 additions & 8 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::{InterruptHandlerQueue, InterruptLine};
use crate::scheduler;

/// Base address of the PLIC, only one access at the same time is allowed
Expand Down Expand Up @@ -119,9 +115,9 @@ 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: HashMap<InterruptLine, InterruptHandlerQueue, RandomState>,
) {
for irq_number in handlers.keys() {
unsafe {
let base_ptr = PLIC_BASE.lock();
Expand Down
26 changes: 19 additions & 7 deletions src/arch/x86_64/kernel/interrupts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ 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::{InterruptHandlerQueue, InterruptLine};
use crate::scheduler::{self, CoreId};

static IRQ_HANDLERS: OnceCell<HashMap<u8, InterruptHandlerQueue, RandomState>> = OnceCell::new();
Expand Down Expand Up @@ -163,8 +159,24 @@ 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(
#[cfg_attr(not(feature = "pci"), expect(unused_mut))] mut handlers: HashMap<
InterruptLine,
InterruptHandlerQueue,
RandomState,
>,
) {
#[cfg(feature = "pci")]
{
use crate::kernel::serial;
add_irq_name(serial::SERIAL_IRQ, "COM1");
handlers
.entry(serial::SERIAL_IRQ)
.or_default()
.push_back(serial::handle_interrupt);
}

IRQ_HANDLERS.set(handlers).unwrap();
}

fn handle_interrupt(stack_frame: ExceptionStackFrame, index: u8, _error_code: Option<u64>) {
Expand Down
19 changes: 14 additions & 5 deletions src/arch/x86_64/kernel/mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ use alloc::vec::Vec;
use core::ptr::NonNull;
use core::{ptr, str};

use ahash::RandomState;
use align_address::Align;
use free_list::{PageLayout, PageRange};
use hashbrown::HashMap;
#[cfg(any(
feature = "virtio-console",
feature = "virtio-fs",
Expand Down Expand Up @@ -36,6 +38,7 @@ use crate::drivers::virtio::transport::mmio as mmio_virtio;
use crate::drivers::virtio::transport::mmio::VirtioDriver;
#[cfg(feature = "virtio-vsock")]
use crate::drivers::vsock::VirtioVsockDriver;
use crate::drivers::{InterruptHandlerQueue, InterruptLine};
use crate::env;
#[cfg(any(feature = "rtl8139", feature = "virtio-net"))]
use crate::executor::device::NETWORK_DEVICE;
Expand Down Expand Up @@ -217,8 +220,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 HashMap<InterruptLine, InterruptHandlerQueue, RandomState>,
) {
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 +246,9 @@ fn register_mmio(mmio: VolatileRef<'static, DeviceRegisters>, irq: u8) {
}
}

pub(crate) fn init_drivers() {
pub(crate) fn init_drivers(
handlers: &mut HashMap<InterruptLine, InterruptHandlerQueue, RandomState>,
) {
without_interrupts(|| {
let layout = PageLayout::from_size(BasePageSize::SIZE as usize).unwrap();
let page_range = PageBox::new(layout).unwrap();
Expand All @@ -249,11 +258,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
28 changes: 9 additions & 19 deletions src/arch/x86_64/kernel/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,10 @@ use hermit_sync::{InterruptTicketMutex, Lazy};
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::errno::Errno;

#[cfg(feature = "pci")]
const SERIAL_IRQ: u8 = 4;
pub(crate) const SERIAL_IRQ: u8 = 4;

static UART_DEVICE: Lazy<InterruptTicketMutex<UartDevice>> =
Lazy::new(|| unsafe { InterruptTicketMutex::new(UartDevice::new()) });
Expand Down Expand Up @@ -79,21 +75,15 @@ impl Write for SerialDevice {
}

#[cfg(feature = "pci")]
pub(crate) fn get_serial_handler() -> (InterruptLine, fn()) {
fn serial_handler() {
let mut guard = UART_DEVICE.lock();
pub(crate) fn handle_interrupt() {
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();
}

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");

(SERIAL_IRQ, serial_handler)
drop(guard);
crate::console::CONSOLE_WAKER.lock().wake();
}
12 changes: 7 additions & 5 deletions src/drivers/console/mmio.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
use ahash::RandomState;
use hashbrown::HashMap;
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::{InterruptHandlerQueue, 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 +38,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 +52,11 @@ impl VirtioConsoleDriver {
dev_id: u16,
registers: VolatileRef<'static, DeviceRegisters>,
irq: InterruptLine,
handlers: &mut HashMap<InterruptLine, InterruptHandlerQueue, RandomState>,
) -> 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
Loading
Loading