diff --git a/src/arch/aarch64/kernel/interrupts.rs b/src/arch/aarch64/kernel/interrupts.rs index ede0f8d8be..b4527817e6 100644 --- a/src/arch/aarch64/kernel/interrupts.rs +++ b/src/arch/aarch64/kernel/interrupts.rs @@ -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}; @@ -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> = - OnceCell::new(); +static INTERRUPT_HANDLERS: OnceCell = OnceCell::new(); /// Driver for the Arm Generic Interrupt Controller version 3 (or 4). pub(crate) static GIC: SpinMutex>> = SpinMutex::new(None); @@ -87,16 +82,15 @@ pub fn disable() { dmb(ISH); } -pub(crate) fn install_handlers() { - let mut handlers: HashMap = +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); } diff --git a/src/arch/aarch64/kernel/mmio.rs b/src/arch/aarch64/kernel/mmio.rs index faa4900b04..4c6730ffe8 100644 --- a/src/arch/aarch64/kernel/mmio.rs +++ b/src/arch/aarch64/kernel/mmio.rs @@ -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")] @@ -117,7 +118,7 @@ pub(crate) fn get_vsock_driver() -> Option<&'static InterruptTicketMutex 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 { diff --git a/src/arch/riscv64/kernel/devicetree.rs b/src/arch/riscv64/kernel/devicetree.rs index c418b27e16..92e1697175 100644 --- a/src/arch/riscv64/kernel/devicetree.rs +++ b/src/arch/riscv64/kernel/devicetree.rs @@ -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")))] @@ -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"); @@ -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}"), @@ -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( diff --git a/src/arch/riscv64/kernel/interrupts.rs b/src/arch/riscv64/kernel/interrupts.rs index 42e06114e9..b346753ab9 100644 --- a/src/arch/riscv64/kernel/interrupts.rs +++ b/src/arch/riscv64/kernel/interrupts.rs @@ -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 @@ -25,8 +21,7 @@ static PLIC_CONTEXT: SpinMutex = SpinMutex::new(0x0); /// PLIC context for new interrupt handlers static CURRENT_INTERRUPTS: SpinMutex> = SpinMutex::new(Vec::new()); -static INTERRUPT_HANDLERS: OnceCell> = - OnceCell::new(); +static INTERRUPT_HANDLERS: OnceCell = OnceCell::new(); /// Init Interrupts pub(crate) fn install() { @@ -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(); diff --git a/src/arch/x86_64/kernel/interrupts.rs b/src/arch/x86_64/kernel/interrupts.rs index fb07fb6d9b..3ed4572acb 100644 --- a/src/arch/x86_64/kernel/interrupts.rs +++ b/src/arch/x86_64/kernel/interrupts.rs @@ -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> = OnceCell::new(); +static IRQ_HANDLERS: OnceCell = OnceCell::new(); static IRQ_NAMES: InterruptTicketMutex> = InterruptTicketMutex::new(HashMap::with_hasher(RandomState::with_seeds(0, 0, 0, 0))); @@ -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) { diff --git a/src/arch/x86_64/kernel/mmio.rs b/src/arch/x86_64/kernel/mmio.rs index db17b31098..50bc6871fb 100644 --- a/src/arch/x86_64/kernel/mmio.rs +++ b/src/arch/x86_64/kernel/mmio.rs @@ -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")] @@ -217,8 +218,12 @@ pub(crate) fn get_vsock_driver() -> Option<&'static InterruptTicketMutex, 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))); @@ -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(); @@ -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); } } diff --git a/src/arch/x86_64/kernel/serial.rs b/src/arch/x86_64/kernel/serial.rs index 7d26526cd0..0e6eea22e4 100644 --- a/src/arch/x86_64/kernel/serial.rs +++ b/src/arch/x86_64/kernel/serial.rs @@ -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")] @@ -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); } diff --git a/src/drivers/console/mmio.rs b/src/drivers/console/mmio.rs index 7bef82ea95..d6eb885026 100644 --- a/src/drivers/console/mmio.rs +++ b/src/drivers/console/mmio.rs @@ -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 { let dev_cfg_raw: &'static Config = unsafe { &*registers @@ -37,7 +36,6 @@ impl VirtioConsoleDriver { com_cfg: ComCfg::new(registers), isr_stat, notif_cfg, - irq, recv_vq: RxQueue::new(), send_vq: TxQueue::new(), }) @@ -52,9 +50,11 @@ impl VirtioConsoleDriver { dev_id: u16, registers: VolatileRef<'static, DeviceRegisters>, irq: InterruptLine, + handlers: &mut InterruptHandlerMap, ) -> Result { - 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) } diff --git a/src/drivers/console/mod.rs b/src/drivers/console/mod.rs index 3bf4e2f0c2..c46fddd7e0 100644 --- a/src/drivers/console/mod.rs +++ b/src/drivers/console/mod.rs @@ -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; @@ -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" } @@ -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, + ) -> Result<(), VirtioConsoleError> { // Reset self.com_cfg.reset_dev(); @@ -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(); diff --git a/src/drivers/console/pci.rs b/src/drivers/console/pci.rs index 640c474502..b8f611648a 100644 --- a/src/drivers/console/pci.rs +++ b/src/drivers/console/pci.rs @@ -3,6 +3,7 @@ use virtio::console::Config; use volatile::VolatileRef; use crate::arch::kernel::pci::PciConfigRegion; +use crate::drivers::InterruptHandlerMap; use crate::drivers::console::{ConsoleDevCfg, RxQueue, TxQueue, VirtioConsoleDriver}; use crate::drivers::pci::PciDevice; use crate::drivers::virtio::error::{self, VirtioError}; @@ -47,7 +48,6 @@ impl VirtioConsoleDriver { com_cfg, isr_stat: isr_cfg, notif_cfg, - irq: device.get_irq().unwrap(), recv_vq: RxQueue::new(), send_vq: TxQueue::new(), }) @@ -58,6 +58,7 @@ impl VirtioConsoleDriver { /// Returns a driver instance of VirtioConsoleDriver. pub(crate) fn init( device: &PciDevice, + handlers: &mut InterruptHandlerMap, ) -> Result { // enable bus master mode device.set_command(CommandRegister::BUS_MASTER_ENABLE); @@ -76,7 +77,7 @@ impl VirtioConsoleDriver { } }; - match drv.init_dev() { + match drv.init_dev(handlers, device.get_irq()) { Ok(()) => { info!( "Console device with id {:x}, has been initialized by driver!", diff --git a/src/drivers/fs/mmio.rs b/src/drivers/fs/mmio.rs index 3ae8b2db2a..83afe9f119 100644 --- a/src/drivers/fs/mmio.rs +++ b/src/drivers/fs/mmio.rs @@ -4,17 +4,16 @@ use virtio::fs::Config; use virtio::mmio::{DeviceRegisters, DeviceRegistersVolatileFieldAccess}; use volatile::VolatileRef; -use crate::drivers::InterruptLine; use crate::drivers::fs::{FsDevCfg, VirtioFsDriver}; 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 fs driver impl VirtioFsDriver { pub fn new( dev_id: u16, mut registers: VolatileRef<'static, DeviceRegisters>, - irq: InterruptLine, ) -> Result { let dev_cfg_raw: &'static Config = unsafe { &*registers @@ -40,7 +39,6 @@ impl VirtioFsDriver { isr_stat, notif_cfg, vqueues: Vec::new(), - irq, }) } @@ -53,9 +51,11 @@ impl VirtioFsDriver { dev_id: u16, registers: VolatileRef<'static, DeviceRegisters>, irq: InterruptLine, + handlers: &mut InterruptHandlerMap, ) -> Result { - let mut drv = VirtioFsDriver::new(dev_id, registers, irq)?; - drv.init_dev().map_err(VirtioError::FsDriver)?; + let mut drv = VirtioFsDriver::new(dev_id, registers)?; + drv.init_dev(handlers, Some(irq)) + .map_err(VirtioError::FsDriver)?; drv.com_cfg.print_information(); Ok(drv) } diff --git a/src/drivers/fs/mod.rs b/src/drivers/fs/mod.rs index 435fae9f1d..ddb5e506e0 100644 --- a/src/drivers/fs/mod.rs +++ b/src/drivers/fs/mod.rs @@ -30,7 +30,10 @@ use volatile::VolatileRef; use volatile::access::ReadOnly; use crate::config::VIRTIO_MAX_QUEUE_SIZE; -use crate::drivers::Driver; +#[cfg(not(feature = "pci"))] +use crate::drivers::mmio::get_filesystem_driver; +#[cfg(feature = "pci")] +use crate::drivers::pci::get_filesystem_driver; use crate::drivers::virtio::ControlRegisters; use crate::drivers::virtio::error::VirtioFsInitError; #[cfg(not(feature = "pci"))] @@ -42,6 +45,7 @@ use crate::drivers::virtio::virtqueue::split::SplitVq; use crate::drivers::virtio::virtqueue::{ AvailBufferToken, BufferElem, BufferType, VirtQueue, Virtq, }; +use crate::drivers::{Driver, InterruptHandlerMap}; use crate::errno::Errno; use crate::fs::virtio_fs::{self, Rsp, RspHeader, VirtioFsError, VirtioFsInterface}; use crate::mm::device_alloc::DeviceAlloc; @@ -66,7 +70,6 @@ pub(crate) struct VirtioFsDriver { pub(super) isr_stat: IsrStatus, pub(super) notif_cfg: NotifCfg, pub(super) vqueues: Vec, - pub(super) irq: InterruptLine, } // Backend-independent interface for Virtio network driver @@ -86,7 +89,11 @@ impl VirtioFsDriver { /// /// See Virtio specification v1.1. - 3.1.1. /// and v1.1. - 5.11.5 - pub(crate) fn init_dev(&mut self) -> Result<(), VirtioFsInitError> { + pub(crate) fn init_dev( + &mut self, + handlers: &mut InterruptHandlerMap, + irq: Option, + ) -> Result<(), VirtioFsInitError> { // Reset self.com_cfg.reset_dev(); @@ -152,6 +159,12 @@ impl VirtioFsDriver { self.vqueues.push(vq); } + handlers.entry(irq.unwrap()).or_default().push_back(|| { + if let Some(driver) = get_filesystem_driver() { + driver.lock().handle_interrupt(); + }; + }); + // At this point the device is "live" self.com_cfg.drv_ok(); @@ -260,10 +273,6 @@ impl VirtioFsInterface for VirtioFsDriver { } impl Driver for VirtioFsDriver { - fn get_interrupt_number(&self) -> InterruptLine { - self.irq - } - fn get_name(&self) -> &'static str { "virtio" } diff --git a/src/drivers/fs/pci.rs b/src/drivers/fs/pci.rs index 98c5046644..0605e111b9 100644 --- a/src/drivers/fs/pci.rs +++ b/src/drivers/fs/pci.rs @@ -3,6 +3,7 @@ use alloc::vec::Vec; use volatile::VolatileRef; use crate::arch::kernel::pci::PciConfigRegion; +use crate::drivers::InterruptHandlerMap; use crate::drivers::fs::{FsDevCfg, VirtioFsDriver}; use crate::drivers::pci::PciDevice; use crate::drivers::virtio::error::{self, VirtioError}; @@ -49,12 +50,14 @@ impl VirtioFsDriver { isr_stat: isr_cfg, notif_cfg, vqueues: Vec::new(), - irq: device.get_irq().unwrap(), }) } /// Initializes virtio filesystem device - pub fn init(device: &PciDevice) -> Result { + pub fn init( + device: &PciDevice, + handlers: &mut InterruptHandlerMap, + ) -> Result { let mut drv = match pci::map_caps(device) { Ok(caps) => match VirtioFsDriver::new(caps, device) { Ok(driver) => driver, @@ -69,7 +72,7 @@ impl VirtioFsDriver { } }; - match drv.init_dev() { + match drv.init_dev(handlers, device.get_irq()) { Ok(()) => info!( "Filesystem device with id {:x}, has been initialized by driver!", drv.get_dev_id() diff --git a/src/drivers/mmio.rs b/src/drivers/mmio.rs index 24cee0c67a..fca912fb82 100644 --- a/src/drivers/mmio.rs +++ b/src/drivers/mmio.rs @@ -1,95 +1,6 @@ -use ahash::RandomState; -use hashbrown::HashMap; - #[cfg(feature = "virtio-console")] pub(crate) use crate::arch::kernel::mmio::get_console_driver; #[cfg(feature = "virtio-fs")] pub(crate) use crate::arch::kernel::mmio::get_filesystem_driver; #[cfg(feature = "virtio-vsock")] pub(crate) use crate::arch::kernel::mmio::get_vsock_driver; -#[cfg(any( - feature = "virtio-console", - all(target_arch = "riscv64", feature = "gem-net", not(feature = "pci")), - feature = "virtio-net", - feature = "virtio-fs", - feature = "virtio-vsock", -))] -use crate::drivers::Driver; -use crate::drivers::{InterruptHandlerQueue, InterruptLine}; -#[cfg(any( - all(target_arch = "riscv64", feature = "gem-net", not(feature = "pci")), - feature = "virtio-net", -))] -use crate::executor::device::NETWORK_DEVICE; - -pub(crate) fn get_interrupt_handlers() -> HashMap -{ - #[allow(unused_mut)] - let mut handlers: HashMap = - HashMap::with_hasher(RandomState::with_seeds(0, 0, 0, 0)); - - #[cfg(any( - all(target_arch = "riscv64", feature = "gem-net", not(feature = "pci")), - feature = "virtio-net", - ))] - if let Some(device) = NETWORK_DEVICE.lock().as_ref() { - handlers - .entry(device.get_interrupt_number()) - .or_default() - .push_back(crate::executor::network::network_handler); - } - - #[cfg(feature = "virtio-console")] - if let Some(drv) = get_console_driver() { - fn console_handler() { - let Some(driver) = get_console_driver() else { - return; - }; - - driver.lock().handle_interrupt(); - } - - let irq_number = drv.lock().get_interrupt_number(); - handlers - .entry(irq_number) - .or_default() - .push_back(console_handler); - } - - #[cfg(feature = "virtio-fs")] - if let Some(drv) = get_filesystem_driver() { - fn virtio_fs_handler() { - let Some(driver) = get_filesystem_driver() else { - return; - }; - - driver.lock().handle_interrupt(); - } - - let irq_number = drv.lock().get_interrupt_number(); - - handlers - .entry(irq_number) - .or_default() - .push_back(virtio_fs_handler); - } - - #[cfg(feature = "virtio-vsock")] - if let Some(drv) = get_vsock_driver() { - fn vsock_handler() { - let Some(driver) = get_vsock_driver() else { - return; - }; - - driver.lock().handle_interrupt(); - } - - let irq_number = drv.lock().get_interrupt_number(); - handlers - .entry(irq_number) - .or_default() - .push_back(vsock_handler); - } - - handlers -} diff --git a/src/drivers/mod.rs b/src/drivers/mod.rs index ee74b0c634..63277722e3 100644 --- a/src/drivers/mod.rs +++ b/src/drivers/mod.rs @@ -17,12 +17,14 @@ pub mod vsock; use alloc::collections::VecDeque; +use ahash::RandomState; +use hashbrown::HashMap; #[cfg(feature = "pci")] pub(crate) use pci_types::InterruptLine; #[cfg(not(feature = "pci"))] pub(crate) type InterruptLine = u8; -pub(crate) type InterruptHandlerQueue = VecDeque; +pub(crate) type InterruptHandlerMap = HashMap, RandomState>; /// A common error module for drivers. /// [DriverError](error::DriverError) values will be @@ -66,24 +68,34 @@ pub mod error { /// A trait to determine general driver information #[allow(dead_code)] pub(crate) trait Driver { - /// Returns the interrupt number of the device - fn get_interrupt_number(&self) -> InterruptLine; - /// Returns the device driver name fn get_name(&self) -> &'static str; } pub(crate) fn init() { + #[cfg_attr( + all( + not(feature = "pci"), + not(target_arch = "riscv64"), + not(feature = "virtio") + ), + expect(unused_mut) + )] + let mut handlers = HashMap::with_hasher(RandomState::with_seeds(0, 0, 0, 0)); + // Initialize PCI Drivers #[cfg(feature = "pci")] - pci::init(); + pci::init(&mut handlers); + #[cfg(all(feature = "pci", target_arch = "x86_64"))] + crate::arch::kernel::serial::register_handler(&mut handlers); + #[cfg(all(not(feature = "pci"), feature = "virtio", target_arch = "x86_64"))] - crate::arch::kernel::mmio::init_drivers(); + crate::arch::kernel::mmio::init_drivers(&mut handlers); #[cfg(all(not(feature = "pci"), feature = "virtio", target_arch = "aarch64"))] - crate::arch::kernel::mmio::init_drivers(); + crate::arch::kernel::mmio::init_drivers(&mut handlers); #[cfg(target_arch = "riscv64")] - crate::arch::kernel::init_drivers(); + crate::arch::kernel::init_drivers(&mut handlers); - crate::arch::kernel::interrupts::install_handlers(); + crate::arch::kernel::interrupts::install_handlers(handlers); } diff --git a/src/drivers/net/gem.rs b/src/drivers/net/gem.rs index a1ae9ae3af..fb0edc5b67 100644 --- a/src/drivers/net/gem.rs +++ b/src/drivers/net/gem.rs @@ -18,7 +18,7 @@ use tock_registers::{register_bitfields, register_structs}; use crate::drivers::error::DriverError; use crate::drivers::net::{NetworkDriver, mtu}; -use crate::drivers::{Driver, InterruptLine}; +use crate::drivers::{Driver, InterruptHandlerMap}; use crate::executor::network::wake_network_waker; use crate::mm::device_alloc::DeviceAlloc; @@ -207,7 +207,6 @@ pub enum GEMError { /// the device itself. pub struct GEMDriver { mtu: u16, - irq: u8, mac: [u8; 6], rx_counter: u32, rx_fields: RxFields, @@ -316,10 +315,6 @@ impl TxFields { } impl Driver for GEMDriver { - fn get_interrupt_number(&self) -> InterruptLine { - self.irq - } - fn get_name(&self) -> &'static str { "gem" } @@ -574,6 +569,7 @@ pub fn init_device( irq: u8, phy_addr: u32, mac: [u8; 6], + handlers: &mut InterruptHandlerMap, ) -> Result { debug!("Init GEM at {gem_base:p}"); @@ -806,9 +802,13 @@ pub fn init_device( mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] ); + handlers + .entry(irq) + .or_default() + .push_back(crate::executor::network::network_handler); + Ok(GEMDriver { mtu: mtu(), - irq, mac, rx_counter: 0, rx_fields: RxFields { diff --git a/src/drivers/net/loopback.rs b/src/drivers/net/loopback.rs index 85d814c13a..3dd794add4 100644 --- a/src/drivers/net/loopback.rs +++ b/src/drivers/net/loopback.rs @@ -6,8 +6,8 @@ use hermit_sync::SpinMutex; use smoltcp::phy; use smoltcp::time::Instant; +use crate::drivers::Driver; use crate::drivers::net::NetworkDriver; -use crate::drivers::{Driver, InterruptLine}; use crate::executor::network::wake_network_waker; use crate::mm::device_alloc::DeviceAlloc; @@ -26,12 +26,6 @@ impl LoopbackDriver { } impl Driver for LoopbackDriver { - fn get_interrupt_number(&self) -> InterruptLine { - // This is called by mmio / pci specific code, this driver - // is using neither. - unimplemented!() - } - fn get_name(&self) -> &'static str { "loopback" } diff --git a/src/drivers/net/rtl8139.rs b/src/drivers/net/rtl8139.rs index b8b483d13d..6964b0cf95 100644 --- a/src/drivers/net/rtl8139.rs +++ b/src/drivers/net/rtl8139.rs @@ -9,7 +9,7 @@ use core::mem::ManuallyDrop; use core::ptr::NonNull; use endian_num::{le16, le32, le64}; -use pci_types::{Bar, CommandRegister, InterruptLine, MAX_BARS}; +use pci_types::{Bar, CommandRegister, MAX_BARS}; use smoltcp::phy::DeviceCapabilities; use thiserror::Error; use volatile::access::{NoAccess, ReadOnly, ReadWrite}; @@ -17,10 +17,10 @@ use volatile::{VolatileFieldAccess, VolatilePtr, VolatileRef, map_field}; use crate::arch::kernel::interrupts::*; use crate::arch::kernel::pci::PciConfigRegion; -use crate::drivers::Driver; use crate::drivers::error::DriverError; use crate::drivers::net::{NetworkDriver, mtu}; use crate::drivers::pci::PciDevice; +use crate::drivers::{Driver, InterruptHandlerMap}; use crate::executor::network::wake_network_waker; use crate::mm::device_alloc::DeviceAlloc; @@ -480,7 +480,6 @@ struct TxFields { pub(crate) struct RTL8139Driver { regs: VolatileRef<'static, Regs>, mtu: u16, - irq: InterruptLine, mac: [u8; 6], rx_fields: RxFields, tx_fields: TxFields, @@ -698,10 +697,6 @@ impl NetworkDriver for RTL8139Driver { } impl Driver for RTL8139Driver { - fn get_interrupt_number(&self) -> InterruptLine { - self.irq - } - fn get_name(&self) -> &'static str { "rtl8139" } @@ -748,6 +743,7 @@ impl Drop for RTL8139Driver { pub(crate) fn init_device( device: &PciDevice, + handlers: &mut InterruptHandlerMap, ) -> Result { let irq = device.get_irq().unwrap(); let mut regs = None; @@ -889,12 +885,15 @@ pub(crate) fn init_device( ); info!("RTL8139 use interrupt line {irq}"); + handlers + .entry(irq) + .or_default() + .push_back(crate::executor::network::network_handler); add_irq_name(irq, "rtl8139"); Ok(RTL8139Driver { regs, mtu: mtu(), - irq, mac, rx_fields: RxFields { rxbuffer, diff --git a/src/drivers/net/virtio/mmio.rs b/src/drivers/net/virtio/mmio.rs index ea21245e3c..ceb6b7c41b 100644 --- a/src/drivers/net/virtio/mmio.rs +++ b/src/drivers/net/virtio/mmio.rs @@ -2,17 +2,16 @@ use smoltcp::phy::ChecksumCapabilities; use virtio::mmio::{DeviceRegisters, DeviceRegistersVolatileFieldAccess}; use volatile::VolatileRef; -use crate::drivers::InterruptLine; use crate::drivers::net::virtio::{Init, NetDevCfg, Uninit, VirtioNetDriver}; 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 network driver impl VirtioNetDriver { pub fn new( dev_id: u16, mut registers: VolatileRef<'static, DeviceRegisters>, - irq: InterruptLine, ) -> Result { let dev_cfg_raw: &'static virtio::net::Config = unsafe { &*registers @@ -39,7 +38,6 @@ impl VirtioNetDriver { notif_cfg, inner: Uninit, num_vqs: 0, - irq, checksums: ChecksumCapabilities::default(), }) } @@ -53,9 +51,12 @@ impl VirtioNetDriver { dev_id: u16, registers: VolatileRef<'static, DeviceRegisters>, irq: InterruptLine, + handlers: &mut InterruptHandlerMap, ) -> Result, VirtioError> { - let drv = VirtioNetDriver::new(dev_id, registers, irq)?; - let mut drv = drv.init_dev().map_err(VirtioError::NetDriver)?; + let drv = VirtioNetDriver::new(dev_id, registers)?; + let mut drv = drv + .init_dev(handlers, Some(irq)) + .map_err(VirtioError::NetDriver)?; drv.print_information(); Ok(drv) } diff --git a/src/drivers/net/virtio/mod.rs b/src/drivers/net/virtio/mod.rs index 3faf4d2fe6..3d43ae375c 100644 --- a/src/drivers/net/virtio/mod.rs +++ b/src/drivers/net/virtio/mod.rs @@ -46,7 +46,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::executor::network::wake_network_waker; use crate::mm::device_alloc::DeviceAlloc; @@ -248,7 +248,6 @@ pub(crate) struct VirtioNetDriver { pub(super) inner: T, pub(super) num_vqs: u16, - pub(super) irq: InterruptLine, /// Describes for what protocols and in which directions, if any, the checksum /// should be calculated in software. It is the complement of what is offloaded /// to the hardware. @@ -595,10 +594,6 @@ impl smoltcp::phy::Device for VirtioNetDriver { } impl Driver for VirtioNetDriver { - fn get_interrupt_number(&self) -> InterruptLine { - self.irq - } - fn get_name(&self) -> &'static str { "virtio" } @@ -754,7 +749,11 @@ impl VirtioNetDriver { /// /// See Virtio specification v1.1. - 3.1.1. /// and v1.1. - 5.1.5 - pub fn init_dev(mut self) -> Result, VirtioNetError> { + pub fn init_dev( + mut self, + handlers: &mut InterruptHandlerMap, + irq: Option, + ) -> Result, VirtioNetError> { // Reset self.com_cfg.reset_dev(); @@ -837,6 +836,11 @@ impl VirtioNetDriver { self.dev_cfg.dev_id ); + handlers + .entry(irq.unwrap()) + .or_default() + .push_back(crate::executor::network::network_handler); + // At this point the device is "live" self.com_cfg.drv_ok(); @@ -861,7 +865,6 @@ impl VirtioNetDriver { notif_cfg: self.notif_cfg, inner, num_vqs: self.num_vqs, - irq: self.irq, checksums: self.checksums, }) } diff --git a/src/drivers/net/virtio/pci.rs b/src/drivers/net/virtio/pci.rs index 83cf8a0094..f2b217438e 100644 --- a/src/drivers/net/virtio/pci.rs +++ b/src/drivers/net/virtio/pci.rs @@ -4,6 +4,7 @@ use volatile::VolatileRef; use super::{Init, Uninit}; use crate::arch::kernel::pci::PciConfigRegion; +use crate::drivers::InterruptHandlerMap; use crate::drivers::net::virtio::{NetDevCfg, VirtioNetDriver}; use crate::drivers::pci::PciDevice; use crate::drivers::virtio::error::{self, VirtioError}; @@ -51,7 +52,6 @@ impl VirtioNetDriver { notif_cfg, inner: Uninit, num_vqs: 0, - irq: device.get_irq().unwrap(), checksums: ChecksumCapabilities::default(), }) } @@ -66,6 +66,7 @@ impl VirtioNetDriver { /// [VirtioNetDriver](structs.virtionetdriver.html) or an [VirtioError](enums.virtioerror.html). pub(crate) fn init( device: &PciDevice, + handlers: &mut InterruptHandlerMap, ) -> Result, VirtioError> { // enable bus master mode device.set_command(CommandRegister::BUS_MASTER_ENABLE); @@ -84,7 +85,7 @@ impl VirtioNetDriver { } }; - let initialized_drv = match drv.init_dev() { + let initialized_drv = match drv.init_dev(handlers, device.get_irq()) { Ok(initialized_drv) => { info!( "Network device with id {:x}, has been initialized by driver!", diff --git a/src/drivers/pci.rs b/src/drivers/pci.rs index b131965ec6..f2a93221c9 100644 --- a/src/drivers/pci.rs +++ b/src/drivers/pci.rs @@ -3,8 +3,6 @@ use alloc::vec::Vec; use core::fmt; -use ahash::RandomState; -use hashbrown::HashMap; #[cfg(any( feature = "virtio-fs", feature = "virtio-vsock", @@ -22,6 +20,9 @@ use pci_types::{ use crate::arch::kernel::pci::PciConfigRegion; #[cfg(feature = "virtio-console")] use crate::console::IoDevice; +#[allow(unused_imports)] +use crate::drivers::Driver; +use crate::drivers::InterruptHandlerMap; #[cfg(feature = "virtio-console")] use crate::drivers::console::{VirtioConsoleDriver, VirtioUART}; #[cfg(feature = "virtio-fs")] @@ -37,8 +38,6 @@ use crate::drivers::virtio::transport::pci as pci_virtio; use crate::drivers::virtio::transport::pci::VirtioDriver; #[cfg(feature = "virtio-vsock")] use crate::drivers::vsock::VirtioVsockDriver; -#[allow(unused_imports)] -use crate::drivers::{Driver, InterruptHandlerQueue}; #[cfg(any(feature = "rtl8139", feature = "virtio-net"))] use crate::executor::device::NETWORK_DEVICE; use crate::init_cell::InitCell; @@ -365,90 +364,12 @@ impl PciDriver { _ => None, } } - - fn get_interrupt_handler(&self) -> (InterruptLine, fn()) { - #[allow(unreachable_patterns)] - match self { - #[cfg(feature = "virtio-vsock")] - Self::VirtioVsock(drv) => { - fn vsock_handler() { - let Some(driver) = get_vsock_driver() else { - return; - }; - - driver.lock().handle_interrupt(); - } - - let irq_number = drv.lock().get_interrupt_number(); - - (irq_number, vsock_handler) - } - #[cfg(feature = "virtio-fs")] - Self::VirtioFs(drv) => { - fn virtio_fs_handler() { - let Some(driver) = get_filesystem_driver() else { - return; - }; - - driver.lock().handle_interrupt(); - } - - let irq_number = drv.lock().get_interrupt_number(); - - (irq_number, virtio_fs_handler) - } - #[cfg(feature = "virtio-console")] - Self::VirtioConsole(drv) => { - fn console_handler() { - let Some(driver) = get_console_driver() else { - return; - }; - - driver.lock().handle_interrupt(); - } - - let irq_number = drv.lock().get_interrupt_number(); - (irq_number, console_handler) - } - _ => todo!(), - } - } } pub(crate) fn register_driver(drv: PciDriver) { PCI_DRIVERS.with(|pci_drivers| pci_drivers.unwrap().push(drv)); } -pub(crate) fn get_interrupt_handlers() -> HashMap -{ - let mut handlers: HashMap = - HashMap::with_hasher(RandomState::with_seeds(0, 0, 0, 0)); - - for drv in PCI_DRIVERS.finalize().iter() { - let (irq_number, handler) = drv.get_interrupt_handler(); - - handlers.entry(irq_number).or_default().push_back(handler); - } - - #[cfg(target_arch = "x86_64")] - { - use crate::arch::kernel::serial::get_serial_handler; - let (irq_number, handler) = get_serial_handler(); - - handlers.entry(irq_number).or_default().push_back(handler); - } - - #[cfg(any(feature = "rtl8139", feature = "virtio-net"))] - if let Some(device) = NETWORK_DEVICE.lock().as_ref() { - handlers - .entry(device.get_interrupt_number()) - .or_default() - .push_back(crate::executor::network::network_handler); - } - - handlers -} - #[cfg(all(not(feature = "rtl8139"), feature = "virtio-net"))] pub(crate) type NetworkDevice = VirtioNetDriver; @@ -479,7 +400,11 @@ pub(crate) fn get_filesystem_driver() -> Option<&'static InterruptTicketMutex { register_driver(PciDriver::VirtioConsole(InterruptTicketMutex::new(*drv))); @@ -529,11 +454,12 @@ pub(crate) fn init() { adapter.device_id() ); - match rtl8139::init_device(adapter) { + match rtl8139::init_device(adapter, handlers) { Ok(drv) => *NETWORK_DEVICE.lock() = Some(drv), Err(err) => error!("Could not initialize rtl8139 device: {err}"), } } + PCI_DRIVERS.finalize(); }); } diff --git a/src/drivers/virtio/transport/mmio.rs b/src/drivers/virtio/transport/mmio.rs index 9c31233cc3..3a5737ff30 100644 --- a/src/drivers/virtio/transport/mmio.rs +++ b/src/drivers/virtio/transport/mmio.rs @@ -16,7 +16,6 @@ use virtio::{DeviceStatus, le32}; use volatile::access::ReadOnly; use volatile::{VolatilePtr, VolatileRef}; -use crate::drivers::InterruptLine; #[cfg(feature = "virtio-console")] use crate::drivers::console::VirtioConsoleDriver; use crate::drivers::error::DriverError; @@ -28,6 +27,7 @@ use crate::drivers::virtio::error::VirtioError; use crate::drivers::virtio::{ControlRegisters, VirtioIdExt}; #[cfg(feature = "virtio-vsock")] use crate::drivers::vsock::VirtioVsockDriver; +use crate::drivers::{InterruptHandlerMap, InterruptLine}; pub struct VqCfgHandler<'a> { vq_index: u16, @@ -335,6 +335,7 @@ pub(crate) enum VirtioDriver { pub(crate) fn init_device( registers: VolatileRef<'static, DeviceRegisters>, irq_no: InterruptLine, + handlers: &mut InterruptHandlerMap, ) -> Result { let dev_id: u16 = 0; @@ -348,7 +349,7 @@ pub(crate) fn init_device( // Verify the device-ID to find the network card match registers.as_ptr().device_id().read() { #[cfg(feature = "virtio-console")] - virtio::Id::Console => match VirtioConsoleDriver::init(dev_id, registers, irq_no) { + virtio::Id::Console => match VirtioConsoleDriver::init(dev_id, registers, irq_no, handlers) { Ok(virt_console_drv) => { info!("Virtio console driver initialized."); @@ -368,7 +369,7 @@ pub(crate) fn init_device( virtio::Id::Fs => { // TODO: check subclass // TODO: proper error handling on driver creation fail - match VirtioFsDriver::init(dev_id, registers, irq_no) { + match VirtioFsDriver::init(dev_id, registers, irq_no, handlers) { Ok(virt_fs_drv) => { info!("Virtio filesystem driver initialized."); crate::arch::kernel::interrupts::add_irq_name(irq_no, "virtio"); @@ -381,7 +382,7 @@ pub(crate) fn init_device( } } #[cfg(feature = "virtio-net")] - virtio::Id::Net => match VirtioNetDriver::init(dev_id, registers, irq_no) { + virtio::Id::Net => match VirtioNetDriver::init(dev_id, registers, irq_no, handlers) { Ok(virt_net_drv) => { info!("Virtio network driver initialized."); @@ -396,7 +397,7 @@ pub(crate) fn init_device( } }, #[cfg(feature = "virtio-vsock")] - virtio::Id::Vsock => match VirtioVsockDriver::init(dev_id, registers, irq_no) { + virtio::Id::Vsock => match VirtioVsockDriver::init(dev_id, registers, irq_no, handlers) { Ok(virt_vsock_drv) => { info!("Virtio sock driver initialized."); diff --git a/src/drivers/virtio/transport/pci.rs b/src/drivers/virtio/transport/pci.rs index 661a68281e..4fc90bc5d6 100644 --- a/src/drivers/virtio/transport/pci.rs +++ b/src/drivers/virtio/transport/pci.rs @@ -19,6 +19,7 @@ use volatile::access::ReadOnly; use volatile::{VolatilePtr, VolatileRef}; use crate::arch::kernel::pci::PciConfigRegion; +use crate::drivers::InterruptHandlerMap; #[cfg(feature = "virtio-console")] use crate::drivers::console::VirtioConsoleDriver; use crate::drivers::error::DriverError; @@ -629,8 +630,22 @@ pub(crate) fn map_caps(device: &PciDevice) -> Result`] reference, allowing access to the capabilities /// list of the given device through [map_caps]. +#[cfg_attr( + not(any( + feature = "virtio-console", + feature = "virtio-fs", + all( + not(all(target_arch = "riscv64", feature = "gem-net", not(feature = "pci"))), + not(feature = "rtl8139"), + feature = "virtio-net", + ), + feature = "virtio-vsock" + )), + expect(unused_variables) +)] pub(crate) fn init_device( device: &PciDevice, + handlers: &mut InterruptHandlerMap, ) -> Result { let device_id = device.device_id(); @@ -649,7 +664,7 @@ pub(crate) fn init_device( match id { #[cfg(feature = "virtio-console")] - virtio::Id::Console => match VirtioConsoleDriver::init(device) { + virtio::Id::Console => match VirtioConsoleDriver::init(device, handlers) { Ok(virt_console_drv) => { info!("Virtio console driver initialized."); @@ -670,7 +685,7 @@ pub(crate) fn init_device( virtio::Id::Fs => { // TODO: check subclass // TODO: proper error handling on driver creation fail - match VirtioFsDriver::init(device) { + match VirtioFsDriver::init(device, handlers) { Ok(virt_fs_drv) => { info!("Virtio filesystem driver initialized."); let irq = device.get_irq().unwrap(); @@ -690,7 +705,7 @@ pub(crate) fn init_device( not(feature = "rtl8139"), feature = "virtio-net", ))] - virtio::Id::Net => match VirtioNetDriver::init(device) { + virtio::Id::Net => match VirtioNetDriver::init(device, handlers) { Ok(virt_net_drv) => { info!("Virtio network driver initialized."); @@ -708,7 +723,7 @@ pub(crate) fn init_device( } }, #[cfg(feature = "virtio-vsock")] - virtio::Id::Vsock => match VirtioVsockDriver::init(device) { + virtio::Id::Vsock => match VirtioVsockDriver::init(device, handlers) { Ok(virt_sock_drv) => { info!("Virtio sock driver initialized."); diff --git a/src/drivers/vsock/mmio.rs b/src/drivers/vsock/mmio.rs index f017d517b8..02980e35c5 100644 --- a/src/drivers/vsock/mmio.rs +++ b/src/drivers/vsock/mmio.rs @@ -2,17 +2,16 @@ use virtio::mmio::{DeviceRegisters, DeviceRegistersVolatileFieldAccess}; use virtio::vsock::Config; use volatile::VolatileRef; -use crate::drivers::InterruptLine; use crate::drivers::virtio::error::VirtioError; use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg}; use crate::drivers::vsock::{EventQueue, RxQueue, TxQueue, VirtioVsockDriver, VsockDevCfg}; +use crate::drivers::{InterruptHandlerMap, InterruptLine}; // Backend-dependent interface for Virtio vsock driver impl VirtioVsockDriver { pub fn new( dev_id: u16, mut registers: VolatileRef<'static, DeviceRegisters>, - irq: InterruptLine, ) -> Result { let dev_cfg_raw: &'static Config = unsafe { &*registers @@ -37,7 +36,6 @@ impl VirtioVsockDriver { com_cfg: ComCfg::new(registers), isr_stat, notif_cfg, - irq, event_vq: EventQueue::new(), recv_vq: RxQueue::new(), send_vq: TxQueue::new(), @@ -53,9 +51,11 @@ impl VirtioVsockDriver { dev_id: u16, registers: VolatileRef<'static, DeviceRegisters>, irq: InterruptLine, + handlers: &mut InterruptHandlerMap, ) -> Result { - let mut drv = VirtioVsockDriver::new(dev_id, registers, irq)?; - drv.init_dev().map_err(VirtioError::VsockDriver)?; + let mut drv = VirtioVsockDriver::new(dev_id, registers)?; + drv.init_dev(handlers, Some(irq)) + .map_err(VirtioError::VsockDriver)?; drv.com_cfg.print_information(); Ok(drv) } diff --git a/src/drivers/vsock/mod.rs b/src/drivers/vsock/mod.rs index 88fafd16cd..49a4c075c7 100644 --- a/src/drivers/vsock/mod.rs +++ b/src/drivers/vsock/mod.rs @@ -20,7 +20,10 @@ use volatile::access::ReadOnly; use super::virtio::virtqueue::VirtQueue; use crate::config::{VIRTIO_MAX_QUEUE_SIZE, VSOCK_PACKET_SIZE}; -use crate::drivers::Driver; +#[cfg(not(feature = "pci"))] +use crate::drivers::mmio::get_vsock_driver; +#[cfg(feature = "pci")] +use crate::drivers::pci::get_vsock_driver; use crate::drivers::virtio::ControlRegisters; use crate::drivers::virtio::error::VirtioVsockError; #[cfg(not(feature = "pci"))] @@ -31,6 +34,7 @@ use crate::drivers::virtio::virtqueue::split::SplitVq; use crate::drivers::virtio::virtqueue::{ AvailBufferToken, BufferElem, BufferType, UsedBufferToken, Virtq, }; +use crate::drivers::{Driver, InterruptHandlerMap}; use crate::mm::device_alloc::DeviceAlloc; fn fill_queue(vq: &mut VirtQueue, num_packets: u16, packet_size: u32) { @@ -260,7 +264,6 @@ pub(crate) struct VirtioVsockDriver { pub(super) com_cfg: ComCfg, pub(super) isr_stat: IsrStatus, pub(super) notif_cfg: NotifCfg, - pub(super) irq: InterruptLine, pub(super) event_vq: EventQueue, pub(super) recv_vq: RxQueue, @@ -268,10 +271,6 @@ pub(crate) struct VirtioVsockDriver { } impl Driver for VirtioVsockDriver { - fn get_interrupt_number(&self) -> InterruptLine { - self.irq - } - fn get_name(&self) -> &'static str { "virtio" } @@ -323,7 +322,11 @@ impl VirtioVsockDriver { /// /// See Virtio specification v1.1. - 3.1.1. /// and v1.1. - 5.10.6 - pub fn init_dev(&mut self) -> Result<(), VirtioVsockError> { + pub fn init_dev( + &mut self, + handlers: &mut InterruptHandlerMap, + irq: Option, + ) -> Result<(), VirtioVsockError> { // Reset self.com_cfg.reset_dev(); @@ -399,6 +402,13 @@ impl VirtioVsockDriver { ) .unwrap(), )); + + handlers.entry(irq.unwrap()).or_default().push_back(|| { + if let Some(driver) = get_vsock_driver() { + driver.lock().handle_interrupt(); + }; + }); + // Interrupt for event packets is wanted self.event_vq.enable_notifs(); diff --git a/src/drivers/vsock/pci.rs b/src/drivers/vsock/pci.rs index 7b1ad9c33f..143075c397 100644 --- a/src/drivers/vsock/pci.rs +++ b/src/drivers/vsock/pci.rs @@ -1,6 +1,7 @@ use volatile::VolatileRef; use crate::arch::kernel::pci::PciConfigRegion; +use crate::drivers::InterruptHandlerMap; use crate::drivers::pci::PciDevice; use crate::drivers::virtio::error::{self, VirtioError}; use crate::drivers::virtio::transport::pci; @@ -46,7 +47,6 @@ impl VirtioVsockDriver { com_cfg, isr_stat: isr_cfg, notif_cfg, - irq: device.get_irq().unwrap(), event_vq: EventQueue::new(), recv_vq: RxQueue::new(), send_vq: TxQueue::new(), @@ -58,6 +58,7 @@ impl VirtioVsockDriver { /// Returns a driver instance of VirtioVsockDriver. pub(crate) fn init( device: &PciDevice, + handlers: &mut InterruptHandlerMap, ) -> Result { let mut drv = match pci::map_caps(device) { Ok(caps) => match VirtioVsockDriver::new(caps, device) { @@ -73,7 +74,7 @@ impl VirtioVsockDriver { } }; - match drv.init_dev() { + match drv.init_dev(handlers, device.get_irq()) { Ok(()) => { let cid = drv.get_cid(); info!("Socket device with cid {cid:x}, has been initialized by driver!");