kernel/interrupt/
controllers.rs1use crate::interrupt::InterruptError;
6
7use super::{CpuId, InterruptId, InterruptResult, Priority};
8use alloc::boxed::Box;
9
10pub trait LocalInterruptController: Send + Sync {
15 fn init(&mut self, cpu_id: CpuId) -> InterruptResult<()>;
17
18 fn enable_interrupt(
20 &mut self,
21 cpu_id: CpuId,
22 interrupt_type: LocalInterruptType,
23 ) -> InterruptResult<()>;
24
25 fn disable_interrupt(
27 &mut self,
28 cpu_id: CpuId,
29 interrupt_type: LocalInterruptType,
30 ) -> InterruptResult<()>;
31
32 fn is_pending(&self, cpu_id: CpuId, interrupt_type: LocalInterruptType) -> bool;
34
35 fn clear_interrupt(
37 &mut self,
38 cpu_id: CpuId,
39 interrupt_type: LocalInterruptType,
40 ) -> InterruptResult<()>;
41
42 fn send_software_interrupt(&mut self, target_cpu: CpuId) -> InterruptResult<()>;
44
45 fn clear_software_interrupt(&mut self, cpu_id: CpuId) -> InterruptResult<()>;
47
48 fn set_timer(&mut self, cpu_id: CpuId, time: u64) -> InterruptResult<()>;
50
51 fn get_time(&self) -> u64;
53
54 fn get_timer_frequency_hz(&self) -> u64;
56}
57
58pub trait ExternalInterruptController: Send + Sync {
63 fn init(&mut self) -> InterruptResult<()>;
65
66 fn enable_interrupt(&mut self, interrupt_id: InterruptId, cpu_id: CpuId)
68 -> InterruptResult<()>;
69
70 fn disable_interrupt(
72 &mut self,
73 interrupt_id: InterruptId,
74 cpu_id: CpuId,
75 ) -> InterruptResult<()>;
76
77 fn set_priority(
79 &mut self,
80 interrupt_id: InterruptId,
81 priority: Priority,
82 ) -> InterruptResult<()>;
83
84 fn get_priority(&self, interrupt_id: InterruptId) -> InterruptResult<Priority>;
86
87 fn set_threshold(&mut self, cpu_id: CpuId, threshold: Priority) -> InterruptResult<()>;
89
90 fn get_threshold(&self, cpu_id: CpuId) -> InterruptResult<Priority>;
92
93 fn claim_interrupt(&mut self, cpu_id: CpuId) -> InterruptResult<Option<InterruptId>>;
95
96 fn complete_interrupt(
98 &mut self,
99 cpu_id: CpuId,
100 interrupt_id: InterruptId,
101 ) -> InterruptResult<()>;
102
103 fn is_pending(&self, interrupt_id: InterruptId) -> bool;
105
106 fn max_interrupts(&self) -> InterruptId;
108
109 fn max_cpus(&self) -> CpuId;
111}
112
113#[derive(Debug, Clone, Copy, PartialEq, Eq)]
115pub enum LocalInterruptType {
116 Timer,
118 Software,
120 External,
122}
123
124pub 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>, }
134
135unsafe impl Send for InterruptControllers {}
136unsafe impl Sync for InterruptControllers {}
137
138impl InterruptControllers {
139 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 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 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 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 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 pub fn register_external_controller(
190 &mut self,
191 controller: Box<dyn ExternalInterruptController>,
192 ) {
193 self.external_controller = Some(controller);
194 }
195
196 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 pub fn local_controller(&self, index: usize) -> Option<&Box<dyn LocalInterruptController>> {
207 self.local_controllers.get(index)
208 }
209
210 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 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 pub fn external_controller_mut(&mut self) -> Option<&mut Box<dyn ExternalInterruptController>> {
229 self.external_controller.as_mut()
230 }
231
232 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 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 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 pub fn has_local_controller(&self) -> bool {
270 !self.local_controllers.is_empty()
271 }
272
273 pub fn has_external_controller(&self) -> bool {
275 self.external_controller.is_some()
276 }
277
278 pub fn local_controller_count(&self) -> usize {
280 self.local_controllers.len()
281 }
282
283 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}