kernel/interrupt/
controllers.rs

1//! Interrupt controller trait definitions
2//!
3//! This module defines the basic traits for local and external interrupt controllers.
4
5use crate::interrupt::InterruptError;
6
7use super::{CpuId, InterruptId, InterruptResult, Priority};
8use alloc::boxed::Box;
9
10/// Trait for local interrupt controllers (like CLINT)
11///
12/// Local interrupt controllers manage CPU-local interrupts such as timer interrupts
13/// and software interrupts.
14pub trait LocalInterruptController: Send + Sync {
15    /// Initialize the local interrupt controller for a specific CPU
16    fn init(&mut self, cpu_id: CpuId) -> InterruptResult<()>;
17
18    /// Enable a specific local interrupt type for a CPU
19    fn enable_interrupt(
20        &mut self,
21        cpu_id: CpuId,
22        interrupt_type: LocalInterruptType,
23    ) -> InterruptResult<()>;
24
25    /// Disable a specific local interrupt type for a CPU
26    fn disable_interrupt(
27        &mut self,
28        cpu_id: CpuId,
29        interrupt_type: LocalInterruptType,
30    ) -> InterruptResult<()>;
31
32    /// Check if a specific local interrupt type is pending for a CPU
33    fn is_pending(&self, cpu_id: CpuId, interrupt_type: LocalInterruptType) -> bool;
34
35    /// Clear a pending local interrupt for a CPU
36    fn clear_interrupt(
37        &mut self,
38        cpu_id: CpuId,
39        interrupt_type: LocalInterruptType,
40    ) -> InterruptResult<()>;
41
42    /// Send a software interrupt to a specific CPU
43    fn send_software_interrupt(&mut self, target_cpu: CpuId) -> InterruptResult<()>;
44
45    /// Clear a software interrupt for a specific CPU
46    fn clear_software_interrupt(&mut self, cpu_id: CpuId) -> InterruptResult<()>;
47
48    /// Set timer interrupt for a specific CPU
49    fn set_timer(&mut self, cpu_id: CpuId, time: u64) -> InterruptResult<()>;
50
51    /// Get current timer value
52    fn get_time(&self) -> u64;
53
54    /// Returns the timer clock frequency in Hz
55    fn get_timer_frequency_hz(&self) -> u64;
56}
57
58/// Trait for external interrupt controllers (like PLIC)
59///
60/// External interrupt controllers manage interrupts from external devices
61/// and can route them to different CPUs with priority support.
62pub trait ExternalInterruptController: Send + Sync {
63    /// Initialize the external interrupt controller
64    fn init(&mut self) -> InterruptResult<()>;
65
66    /// Enable a specific interrupt for a CPU
67    fn enable_interrupt(&mut self, interrupt_id: InterruptId, cpu_id: CpuId)
68    -> InterruptResult<()>;
69
70    /// Disable a specific interrupt for a CPU
71    fn disable_interrupt(
72        &mut self,
73        interrupt_id: InterruptId,
74        cpu_id: CpuId,
75    ) -> InterruptResult<()>;
76
77    /// Set priority for a specific interrupt
78    fn set_priority(
79        &mut self,
80        interrupt_id: InterruptId,
81        priority: Priority,
82    ) -> InterruptResult<()>;
83
84    /// Get priority for a specific interrupt
85    fn get_priority(&self, interrupt_id: InterruptId) -> InterruptResult<Priority>;
86
87    /// Set priority threshold for a CPU
88    fn set_threshold(&mut self, cpu_id: CpuId, threshold: Priority) -> InterruptResult<()>;
89
90    /// Get priority threshold for a CPU
91    fn get_threshold(&self, cpu_id: CpuId) -> InterruptResult<Priority>;
92
93    /// Claim an interrupt (acknowledge and get the interrupt ID)
94    fn claim_interrupt(&mut self, cpu_id: CpuId) -> InterruptResult<Option<InterruptId>>;
95
96    /// Complete an interrupt (signal that handling is finished)
97    fn complete_interrupt(
98        &mut self,
99        cpu_id: CpuId,
100        interrupt_id: InterruptId,
101    ) -> InterruptResult<()>;
102
103    /// Check if a specific interrupt is pending
104    fn is_pending(&self, interrupt_id: InterruptId) -> bool;
105
106    /// Get the maximum number of interrupts supported
107    fn max_interrupts(&self) -> InterruptId;
108
109    /// Get the number of CPUs supported
110    fn max_cpus(&self) -> CpuId;
111}
112
113/// Types of local interrupts
114#[derive(Debug, Clone, Copy, PartialEq, Eq)]
115pub enum LocalInterruptType {
116    /// Timer interrupt
117    Timer,
118    /// Software interrupt
119    Software,
120    /// External interrupt (from PLIC)
121    External,
122}
123
124/// Interrupt controller registry
125///
126/// This struct maintains references to the active interrupt controllers
127/// and provides a unified interface for interrupt management.
128/// Supports multiple local interrupt controllers for different CPU groups.
129pub struct InterruptControllers {
130    local_controllers: alloc::vec::Vec<Box<dyn LocalInterruptController>>,
131    external_controller: Option<Box<dyn ExternalInterruptController>>,
132    cpu_to_local_controller: alloc::collections::BTreeMap<CpuId, usize>, // CPU ID -> controller index
133}
134
135unsafe impl Send for InterruptControllers {}
136unsafe impl Sync for InterruptControllers {}
137
138impl InterruptControllers {
139    /// Create a new interrupt controller registry
140    pub fn new() -> Self {
141        Self {
142            local_controllers: alloc::vec::Vec::new(),
143            external_controller: None,
144            cpu_to_local_controller: alloc::collections::BTreeMap::new(),
145        }
146    }
147
148    /// Register a local interrupt controller for specific CPUs
149    /// Returns the controller index
150    pub fn register_local_controller(
151        &mut self,
152        controller: Box<dyn LocalInterruptController>,
153        cpu_ids: &[CpuId],
154    ) -> usize {
155        let controller_index = self.local_controllers.len();
156        self.local_controllers.push(controller);
157
158        // Map CPUs to this controller
159        for &cpu_id in cpu_ids {
160            self.cpu_to_local_controller
161                .insert(cpu_id, controller_index);
162        }
163
164        controller_index
165    }
166
167    /// Register a local interrupt controller for a single CPU
168    /// Returns the controller index
169    pub fn register_local_controller_for_cpu(
170        &mut self,
171        controller: Box<dyn LocalInterruptController>,
172        cpu_id: CpuId,
173    ) -> usize {
174        self.register_local_controller(controller, &[cpu_id])
175    }
176
177    /// Register a local interrupt controller for a CPU range (convenience function)
178    /// Returns the controller index
179    pub fn register_local_controller_for_range(
180        &mut self,
181        controller: Box<dyn LocalInterruptController>,
182        cpu_range: core::ops::Range<CpuId>,
183    ) -> usize {
184        let cpu_ids: alloc::vec::Vec<CpuId> = cpu_range.collect();
185        self.register_local_controller(controller, &cpu_ids)
186    }
187
188    /// Register an external interrupt controller
189    pub fn register_external_controller(
190        &mut self,
191        controller: Box<dyn ExternalInterruptController>,
192    ) {
193        self.external_controller = Some(controller);
194    }
195
196    /// Get a reference to the local interrupt controller for a specific CPU
197    pub fn local_controller_for_cpu(
198        &self,
199        cpu_id: CpuId,
200    ) -> Option<&Box<dyn LocalInterruptController>> {
201        let controller_index = self.cpu_to_local_controller.get(&cpu_id)?;
202        self.local_controllers.get(*controller_index)
203    }
204
205    /// Get a reference to a specific local interrupt controller by index
206    pub fn local_controller(&self, index: usize) -> Option<&Box<dyn LocalInterruptController>> {
207        self.local_controllers.get(index)
208    }
209
210    /// Get a mutable reference to the local interrupt controller for a specific CPU
211    pub fn local_controller_mut_for_cpu(
212        &mut self,
213        cpu_id: CpuId,
214    ) -> Option<&mut Box<dyn LocalInterruptController>> {
215        let controller_index = self.cpu_to_local_controller.get(&cpu_id)?;
216        self.local_controllers.get_mut(*controller_index)
217    }
218
219    /// Get a mutable reference to a specific local interrupt controller by index
220    pub fn local_controller_mut(
221        &mut self,
222        index: usize,
223    ) -> Option<&mut Box<dyn LocalInterruptController>> {
224        self.local_controllers.get_mut(index)
225    }
226
227    /// Get a mutable reference to the external interrupt controller
228    pub fn external_controller_mut(&mut self) -> Option<&mut Box<dyn ExternalInterruptController>> {
229        self.external_controller.as_mut()
230    }
231
232    /// Initialize all local controllers for their respective CPUs
233    pub fn init_local_controllers(&mut self) -> InterruptResult<()> {
234        for (cpu_id, &controller_index) in &self.cpu_to_local_controller {
235            if let Some(controller) = self.local_controllers.get_mut(controller_index) {
236                controller.init(*cpu_id)?;
237            } else {
238                return Err(InterruptError::ControllerNotFound);
239            }
240        }
241        Ok(())
242    }
243
244    /// Initialize the external controller
245    pub fn init_external_controller(&mut self) -> InterruptResult<()> {
246        if let Some(controller) = self.external_controller.as_mut() {
247            crate::early_println!(
248                "[interrupt] init_external_controller: calling controller.init()"
249            );
250            controller.init()?;
251            crate::early_println!(
252                "[interrupt] init_external_controller: controller.init() returned"
253            );
254            Ok(())
255        } else {
256            crate::early_println!(
257                "[interrupt] init_external_controller: no external controller registered"
258            );
259            Err(InterruptError::ControllerNotFound)
260        }
261    }
262
263    /// Check if local controller is available for a specific CPU
264    pub fn has_local_controller_for_cpu(&self, cpu_id: CpuId) -> bool {
265        self.cpu_to_local_controller.contains_key(&cpu_id)
266    }
267
268    /// Check if any local controller is available
269    pub fn has_local_controller(&self) -> bool {
270        !self.local_controllers.is_empty()
271    }
272
273    /// Check if external controller is available
274    pub fn has_external_controller(&self) -> bool {
275        self.external_controller.is_some()
276    }
277
278    /// Get the number of registered local controllers
279    pub fn local_controller_count(&self) -> usize {
280        self.local_controllers.len()
281    }
282
283    /// Get CPU IDs managed by a specific local controller
284    pub fn cpus_for_controller(&self, controller_index: usize) -> alloc::vec::Vec<CpuId> {
285        self.cpu_to_local_controller
286            .iter()
287            .filter_map(|(cpu_id, &index)| {
288                if index == controller_index {
289                    Some(*cpu_id)
290                } else {
291                    None
292                }
293            })
294            .collect()
295    }
296}