kernel/interrupt/
mod.rs

1//! Interrupt management system
2//!
3//! This module provides a comprehensive interrupt management system for the Scarlet kernel.
4//! It supports both local interrupts (via CLINT) and external interrupts (via PLIC) on RISC-V architecture.
5
6use core::fmt;
7use hashbrown::HashMap;
8
9use crate::arch::{self, interrupt::enable_external_interrupts};
10
11pub mod controllers;
12
13/// Interrupt ID type
14pub type InterruptId = u32;
15
16/// CPU ID type
17pub type CpuId = u32;
18
19/// Priority level for interrupts
20pub type Priority = u32;
21
22/// Handle for managing interrupt processing
23///
24/// This provides a safe interface for interrupt handlers to interact with
25/// the interrupt controller without direct access.
26pub struct InterruptHandle<'a> {
27    interrupt_id: InterruptId,
28    cpu_id: CpuId,
29    completed: bool,
30    manager: &'a mut InterruptManager,
31}
32
33impl<'a> InterruptHandle<'a> {
34    /// Create a new interrupt handle
35    pub fn new(
36        interrupt_id: InterruptId,
37        cpu_id: CpuId,
38        manager: &'a mut InterruptManager,
39    ) -> Self {
40        Self {
41            interrupt_id,
42            cpu_id,
43            completed: false,
44            manager,
45        }
46    }
47
48    /// Get the interrupt ID
49    pub fn interrupt_id(&self) -> InterruptId {
50        self.interrupt_id
51    }
52
53    /// Get the CPU ID
54    pub fn cpu_id(&self) -> CpuId {
55        self.cpu_id
56    }
57
58    /// Mark the interrupt as completed
59    ///
60    /// This should be called when the handler has finished processing the interrupt.
61    pub fn complete(&mut self) -> InterruptResult<()> {
62        if self.completed {
63            return Err(InterruptError::InvalidOperation);
64        }
65
66        self.manager
67            .complete_external_interrupt(self.cpu_id, self.interrupt_id)?;
68        self.completed = true;
69        Ok(())
70    }
71
72    /// Check if the interrupt has been completed
73    pub fn is_completed(&self) -> bool {
74        self.completed
75    }
76
77    /// Enable another interrupt
78    pub fn enable_interrupt(&mut self, target_interrupt: InterruptId) -> InterruptResult<()> {
79        self.manager
80            .enable_external_interrupt(target_interrupt, self.cpu_id)
81    }
82
83    /// Disable another interrupt
84    pub fn disable_interrupt(&mut self, target_interrupt: InterruptId) -> InterruptResult<()> {
85        self.manager
86            .disable_external_interrupt(target_interrupt, self.cpu_id)
87    }
88}
89
90impl<'a> Drop for InterruptHandle<'a> {
91    fn drop(&mut self) {
92        if !self.completed {
93            // Auto-complete if not manually completed
94            let _ = self.complete();
95        }
96    }
97}
98
99/// Result type for interrupt operations
100pub type InterruptResult<T = ()> = Result<T, InterruptError>;
101
102/// Errors that can occur during interrupt management
103#[derive(Debug, Clone, Copy, PartialEq, Eq)]
104pub enum InterruptError {
105    /// Invalid interrupt ID
106    InvalidInterruptId,
107    /// Invalid CPU ID
108    InvalidCpuId,
109    /// Controller not found
110    ControllerNotFound,
111    /// Handler already registered
112    HandlerAlreadyRegistered,
113    /// Handler not found
114    HandlerNotFound,
115    /// Invalid priority
116    InvalidPriority,
117    /// Operation not supported
118    NotSupported,
119    /// Hardware error
120    HardwareError,
121    /// Invalid operation
122    InvalidOperation,
123}
124
125impl fmt::Display for InterruptError {
126    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127        match self {
128            InterruptError::InvalidInterruptId => write!(f, "Invalid interrupt ID"),
129            InterruptError::InvalidCpuId => write!(f, "Invalid CPU ID"),
130            InterruptError::ControllerNotFound => write!(f, "Controller not found"),
131            InterruptError::HandlerAlreadyRegistered => write!(f, "Handler already registered"),
132            InterruptError::HandlerNotFound => write!(f, "Handler not found"),
133            InterruptError::InvalidPriority => write!(f, "Invalid priority"),
134            InterruptError::NotSupported => write!(f, "Operation not supported"),
135            InterruptError::HardwareError => write!(f, "Hardware error"),
136            InterruptError::InvalidOperation => write!(f, "Invalid operation"),
137        }
138    }
139}
140
141/// Enable interrupts globally
142pub fn enable_interrupts() {
143    arch::interrupt::enable_interrupts();
144}
145
146/// Disable interrupts globally
147pub fn disable_interrupts() {
148    arch::interrupt::disable_interrupts();
149}
150
151/// Execute a closure with interrupts disabled
152pub fn with_interrupts_disabled<F, R>(f: F) -> R
153where
154    F: FnOnce() -> R,
155{
156    arch::interrupt::with_interrupts_disabled(f)
157}
158
159/// Check if interrupts are currently enabled
160pub fn are_interrupts_enabled() -> bool {
161    arch::interrupt::are_interrupts_enabled()
162}
163
164/// Unified interrupt manager
165///
166/// This manages both local and external interrupts in a single structure.
167pub struct InterruptManager {
168    controllers: controllers::InterruptControllers,
169    external_handlers: spin::Mutex<HashMap<InterruptId, ExternalInterruptHandler>>,
170    interrupt_devices: spin::Mutex<
171        HashMap<InterruptId, alloc::sync::Arc<dyn crate::device::events::InterruptCapableDevice>>,
172    >,
173}
174
175impl InterruptManager {
176    /// Create a new interrupt manager
177    pub fn new() -> Self {
178        Self {
179            controllers: controllers::InterruptControllers::new(),
180            external_handlers: spin::Mutex::new(HashMap::new()),
181            interrupt_devices: spin::Mutex::new(HashMap::new()),
182        }
183    }
184
185    /// Get a reference to the global interrupt manager
186    pub fn global() -> &'static spin::Mutex<InterruptManager> {
187        static INTERRUPT_MANAGER: spin::Once<spin::Mutex<InterruptManager>> = spin::Once::new();
188        INTERRUPT_MANAGER.call_once(|| spin::Mutex::new(InterruptManager::new()))
189    }
190
191    /// Get a mutable reference to the global interrupt manager (convenience method)
192    ///
193    /// This method locks the global manager and returns a guard.
194    /// Use this when you need to perform multiple operations atomically.
195    pub fn get_manager() -> spin::MutexGuard<'static, InterruptManager> {
196        Self::global().lock()
197    }
198
199    /// Execute a closure with mutable access to the global interrupt manager
200    ///
201    /// This is a convenience method that automatically handles locking and unlocking.
202    pub fn with_manager<F, R>(f: F) -> R
203    where
204        F: FnOnce(&mut InterruptManager) -> R,
205    {
206        f(&mut Self::global().lock())
207    }
208
209    /// Initialize interrupt controllers only (stage 1).
210    ///
211    /// This is intended to run after interrupt controller drivers (e.g., CLINT/PLIC)
212    /// are discovered/registered, but before other device drivers start enabling
213    /// per-device interrupts.
214    pub fn init_controllers(&mut self) {
215        // Disable interrupts during initialization
216        disable_interrupts();
217        crate::early_println!("[interrupt] init: local controllers...");
218
219        // Initialize local controllers (e.g., CLINT)
220        match self.controllers.init_local_controllers() {
221            Ok(()) => {}
222            Err(e) => {
223                crate::early_println!("Failed to initialize local controllers: {}", e);
224            }
225        }
226
227        crate::early_println!("[interrupt] init: local controllers done");
228
229        crate::early_println!("[interrupt] init: external controller...");
230        // Initialize external controller (e.g., PLIC)
231        match self.controllers.init_external_controller() {
232            Ok(()) => {}
233            Err(e) => {
234                crate::early_println!("Failed to initialize external controller: {}", e);
235            }
236        }
237        crate::early_println!("[interrupt] init: external controller done");
238    }
239
240    /// Enable CPU interrupt reception (stage 2).
241    ///
242    /// This should run after device drivers have registered their handlers and
243    /// enabled the desired interrupt lines in the controller.
244    pub fn enable_cpu_interrupts(&mut self) {
245        enable_external_interrupts(); // Enable external interrupts
246        // Timer interrupts are disabled by default, enable them if needed by scheduler or other components
247    }
248
249    // Note: We intentionally do not provide a one-shot `init()` here.
250    // The kernel boot sequence uses a strict two-stage bring-up to avoid
251    // device drivers enabling interrupts before controllers are initialized.
252
253    /// Handle an external interrupt
254    pub fn handle_external_interrupt(
255        &mut self,
256        interrupt_id: InterruptId,
257        cpu_id: CpuId,
258    ) -> InterruptResult<()> {
259        // First, check for device-based handlers
260        let device = {
261            let devices = self.interrupt_devices.lock();
262            devices.get(&interrupt_id).cloned()
263        };
264
265        if let Some(device) = device {
266            // Call device's interrupt handler
267            device.handle_interrupt()?;
268            self.complete_external_interrupt(cpu_id, interrupt_id)
269        } else {
270            // Fall back to function-based handlers
271            let handler = {
272                let handlers = self.external_handlers.lock();
273                handlers.get(&interrupt_id).copied()
274            };
275
276            if let Some(handler_fn) = handler {
277                let mut handle = InterruptHandle::new(interrupt_id, cpu_id, self);
278                handler_fn(&mut handle)
279            } else {
280                // No handler registered - just complete the interrupt
281                self.complete_external_interrupt(cpu_id, interrupt_id)
282            }
283        }
284    }
285
286    /// Claim and handle the next pending external interrupt
287    pub fn claim_and_handle_external_interrupt(
288        &mut self,
289        cpu_id: CpuId,
290    ) -> InterruptResult<Option<InterruptId>> {
291        let interrupt_id =
292            if let Some(ref mut controller) = self.controllers.external_controller_mut() {
293                controller.claim_interrupt(cpu_id)?
294            } else {
295                return Err(InterruptError::ControllerNotFound);
296            };
297
298        if let Some(id) = interrupt_id {
299            self.handle_external_interrupt(id, cpu_id)?;
300            Ok(Some(id))
301        } else {
302            Ok(None)
303        }
304    }
305
306    /// Enable a local interrupt type for a CPU
307    pub fn enable_local_interrupt(
308        &mut self,
309        cpu_id: CpuId,
310        interrupt_type: controllers::LocalInterruptType,
311    ) -> InterruptResult<()> {
312        if let Some(ref mut controller) = self.controllers.local_controller_mut_for_cpu(cpu_id) {
313            controller.enable_interrupt(cpu_id, interrupt_type)
314        } else {
315            Err(InterruptError::ControllerNotFound)
316        }
317    }
318
319    /// Disable a local interrupt type for a CPU
320    pub fn disable_local_interrupt(
321        &mut self,
322        cpu_id: CpuId,
323        interrupt_type: controllers::LocalInterruptType,
324    ) -> InterruptResult<()> {
325        if let Some(ref mut controller) = self.controllers.local_controller_mut_for_cpu(cpu_id) {
326            controller.disable_interrupt(cpu_id, interrupt_type)
327        } else {
328            Err(InterruptError::ControllerNotFound)
329        }
330    }
331
332    /// Send a software interrupt to a specific CPU
333    pub fn send_software_interrupt(&mut self, target_cpu: CpuId) -> InterruptResult<()> {
334        if let Some(ref mut controller) = self.controllers.local_controller_mut_for_cpu(target_cpu)
335        {
336            controller.send_software_interrupt(target_cpu)
337        } else {
338            Err(InterruptError::ControllerNotFound)
339        }
340    }
341
342    /// Set timer interrupt for a specific CPU
343    pub fn set_timer(&mut self, cpu_id: CpuId, time: u64) -> InterruptResult<()> {
344        if let Some(ref mut controller) = self.controllers.local_controller_mut_for_cpu(cpu_id) {
345            controller.set_timer(cpu_id, time)
346        } else {
347            Err(InterruptError::ControllerNotFound)
348        }
349    }
350
351    pub fn get_time(&self, cpu_id: CpuId) -> InterruptResult<u64> {
352        if let Some(ref controller) = self.controllers.local_controller_for_cpu(cpu_id) {
353            Ok(controller.get_time())
354        } else {
355            Err(InterruptError::ControllerNotFound)
356        }
357    }
358
359    /// Get timer frequency (Hz) for a specific CPU
360    pub fn get_timer_frequency_hz(&self, cpu_id: CpuId) -> InterruptResult<u64> {
361        if let Some(controller) = self.controllers.local_controller_for_cpu(cpu_id) {
362            Ok(controller.get_timer_frequency_hz())
363        } else {
364            Err(InterruptError::ControllerNotFound)
365        }
366    }
367
368    /// Register a local interrupt controller (e.g., CLINT) for specific CPUs
369    pub fn register_local_controller(
370        &mut self,
371        controller: alloc::boxed::Box<dyn controllers::LocalInterruptController>,
372        cpu_ids: &[CpuId],
373    ) -> InterruptResult<usize> {
374        Ok(self
375            .controllers
376            .register_local_controller(controller, cpu_ids))
377    }
378
379    /// Register a local interrupt controller for a CPU range
380    pub fn register_local_controller_for_range(
381        &mut self,
382        controller: alloc::boxed::Box<dyn controllers::LocalInterruptController>,
383        cpu_range: core::ops::Range<CpuId>,
384    ) -> InterruptResult<usize> {
385        Ok(self
386            .controllers
387            .register_local_controller_for_range(controller, cpu_range))
388    }
389
390    /// Register a local interrupt controller for a single CPU
391    pub fn register_local_controller_for_cpu(
392        &mut self,
393        controller: alloc::boxed::Box<dyn controllers::LocalInterruptController>,
394        cpu_id: CpuId,
395    ) -> InterruptResult<usize> {
396        Ok(self
397            .controllers
398            .register_local_controller_for_cpu(controller, cpu_id))
399    }
400
401    /// Register an external interrupt controller (e.g., PLIC)
402    pub fn register_external_controller(
403        &mut self,
404        controller: alloc::boxed::Box<dyn controllers::ExternalInterruptController>,
405    ) -> InterruptResult<()> {
406        if self.controllers.has_external_controller() {
407            return Err(InterruptError::HardwareError);
408        }
409        self.controllers.register_external_controller(controller);
410        Ok(())
411    }
412
413    /// Register a handler for a specific external interrupt
414    pub fn register_external_handler(
415        &mut self,
416        interrupt_id: InterruptId,
417        handler: ExternalInterruptHandler,
418    ) -> InterruptResult<()> {
419        let mut handlers = self.external_handlers.lock();
420        if handlers.contains_key(&interrupt_id) {
421            return Err(InterruptError::HandlerAlreadyRegistered);
422        }
423        handlers.insert(interrupt_id, handler);
424        Ok(())
425    }
426
427    /// Register a device-based handler for a specific external interrupt
428    pub fn register_interrupt_device(
429        &mut self,
430        interrupt_id: InterruptId,
431        device: alloc::sync::Arc<dyn crate::device::events::InterruptCapableDevice>,
432    ) -> InterruptResult<()> {
433        let mut devices = self.interrupt_devices.lock();
434        if devices.contains_key(&interrupt_id) {
435            return Err(InterruptError::HandlerAlreadyRegistered);
436        }
437        devices.insert(interrupt_id, device);
438        Ok(())
439    }
440
441    /// Complete an external interrupt
442    pub fn complete_external_interrupt(
443        &mut self,
444        cpu_id: CpuId,
445        interrupt_id: InterruptId,
446    ) -> InterruptResult<()> {
447        if let Some(ref mut controller) = self.controllers.external_controller_mut() {
448            controller.complete_interrupt(cpu_id, interrupt_id)
449        } else {
450            Err(InterruptError::ControllerNotFound)
451        }
452    }
453
454    /// Enable an external interrupt for a specific CPU
455    pub fn enable_external_interrupt(
456        &mut self,
457        interrupt_id: InterruptId,
458        cpu_id: CpuId,
459    ) -> InterruptResult<()> {
460        if let Some(ref mut controller) = self.controllers.external_controller_mut() {
461            controller.enable_interrupt(interrupt_id, cpu_id)
462        } else {
463            Err(InterruptError::ControllerNotFound)
464        }
465    }
466
467    /// Disable an external interrupt for a specific CPU
468    pub fn disable_external_interrupt(
469        &mut self,
470        interrupt_id: InterruptId,
471        cpu_id: CpuId,
472    ) -> InterruptResult<()> {
473        if let Some(ref mut controller) = self.controllers.external_controller_mut() {
474            controller.disable_interrupt(interrupt_id, cpu_id)
475        } else {
476            Err(InterruptError::ControllerNotFound)
477        }
478    }
479
480    /// Check if local interrupt controller is registered
481    pub fn has_local_controller(&self) -> bool {
482        self.controllers.has_local_controller()
483    }
484
485    /// Check if external interrupt controller is registered
486    pub fn has_external_controller(&self) -> bool {
487        self.controllers.has_external_controller()
488    }
489}
490
491/// Handler function type for external interrupts
492pub type ExternalInterruptHandler = fn(&mut InterruptHandle) -> InterruptResult<()>;
493
494/// Handler function type for local interrupts (timer, software)
495pub type LocalInterruptHandler =
496    fn(cpu_id: CpuId, interrupt_type: controllers::LocalInterruptType) -> InterruptResult<()>;