1 use core::{any::Any, fmt::Debug}; 2 3 use alloc::sync::{Arc, Weak}; 4 5 use crate::libs::spinlock::SpinLock; 6 7 use super::{ 8 irqchip::{IrqChip, IrqChipData}, 9 irqdomain::IrqDomain, 10 msi::MsiDesc, 11 HardwareIrqNumber, IrqNumber, 12 }; 13 14 /// per irq chip data passed down to chip functions 15 /// 16 /// 该结构体用于表示每个Irq的私有数据,且与具体的中断芯片绑定 17 /// 18 /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#179 19 #[allow(dead_code)] 20 #[derive(Debug)] 21 pub struct IrqData { 22 /// 中断号, 用于表示软件逻辑视角的中断号,全局唯一 23 irq: IrqNumber, 24 inner: SpinLock<InnerIrqData>, 25 } 26 27 impl IrqData { 28 pub fn new( 29 irq: IrqNumber, 30 hwirq: HardwareIrqNumber, 31 common_data: Arc<IrqCommonData>, 32 chip: Arc<dyn IrqChip>, 33 ) -> Self { 34 return IrqData { 35 irq, 36 inner: SpinLock::new(InnerIrqData { 37 hwirq, 38 common_data, 39 chip, 40 chip_data: None, 41 domain: None, 42 parent_data: None, 43 }), 44 }; 45 } 46 47 pub fn irqd_set(&self, status: IrqStatus) { 48 // clone是为了释放inner锁 49 let common_data = self.inner.lock().common_data.clone(); 50 common_data.irqd_set(status); 51 } 52 53 #[allow(dead_code)] 54 pub fn irqd_clear(&self, status: IrqStatus) { 55 // clone是为了释放inner锁 56 let common_data = self.inner.lock().common_data.clone(); 57 common_data.irqd_clear(status); 58 } 59 60 pub fn irq(&self) -> IrqNumber { 61 self.irq 62 } 63 64 pub fn hardware_irq(&self) -> HardwareIrqNumber { 65 self.inner.lock_irqsave().hwirq 66 } 67 68 pub fn chip(&self) -> Arc<dyn IrqChip> { 69 self.inner.lock_irqsave().chip.clone() 70 } 71 72 /// 是否为电平触发 73 pub fn is_level_type(&self) -> bool { 74 self.inner 75 .lock_irqsave() 76 .common_data 77 .inner 78 .lock() 79 .state 80 .is_level_type() 81 } 82 83 pub fn is_wakeup_set(&self) -> bool { 84 self.inner 85 .lock_irqsave() 86 .common_data 87 .inner 88 .lock() 89 .state 90 .is_wakeup_set() 91 } 92 } 93 94 #[allow(dead_code)] 95 #[derive(Debug)] 96 struct InnerIrqData { 97 /// 硬件中断号, 用于表示在某个IrqDomain中的中断号 98 hwirq: HardwareIrqNumber, 99 /// 涉及的所有irqchip之间共享的数据 100 common_data: Arc<IrqCommonData>, 101 /// 绑定到的中断芯片 102 chip: Arc<dyn IrqChip>, 103 /// 中断芯片的私有数据(与当前irq相关) 104 chip_data: Option<Arc<dyn IrqChipData>>, 105 /// 中断域 106 domain: Option<Arc<IrqDomain>>, 107 /// 中断的父中断(如果具有中断域继承的话) 108 parent_data: Option<Weak<IrqData>>, 109 } 110 111 /// per irq data shared by all irqchips 112 /// 113 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#147 114 #[derive(Debug)] 115 pub struct IrqCommonData { 116 inner: SpinLock<InnerIrqCommonData>, 117 } 118 119 impl IrqCommonData { 120 pub fn new() -> Self { 121 let inner = InnerIrqCommonData { 122 state: IrqStatus::empty(), 123 handler_data: None, 124 msi_desc: None, 125 }; 126 return IrqCommonData { 127 inner: SpinLock::new(inner), 128 }; 129 } 130 131 pub fn irqd_set(&self, status: IrqStatus) { 132 self.inner.lock_irqsave().irqd_set(status); 133 } 134 135 pub fn irqd_clear(&self, status: IrqStatus) { 136 self.inner.lock_irqsave().irqd_clear(status); 137 } 138 } 139 140 #[allow(dead_code)] 141 #[derive(Debug)] 142 struct InnerIrqCommonData { 143 /// status information for irq chip functions. 144 state: IrqStatus, 145 /// per-IRQ data for the irq_chip methods 146 handler_data: Option<Arc<dyn IrqHandlerData>>, 147 msi_desc: Option<Arc<MsiDesc>>, 148 // todo: affinity 149 } 150 151 impl InnerIrqCommonData { 152 pub fn irqd_set(&mut self, status: IrqStatus) { 153 self.state.insert(status); 154 } 155 156 pub fn irqd_clear(&mut self, status: IrqStatus) { 157 self.state.remove(status); 158 } 159 } 160 161 pub trait IrqHandlerData: Send + Sync + Any + Debug {} 162 163 bitflags! { 164 /// 中断线状态 165 /// https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h?fi=IRQ_TYPE_PROBE#77 166 pub struct IrqLineStatus: u32 { 167 /// 默认,未指明类型 168 const IRQ_TYPE_NONE = 0x00000000; 169 /// 上升沿触发 170 const IRQ_TYPE_EDGE_RISING = 0x00000001; 171 /// 下降沿触发 172 const IRQ_TYPE_EDGE_FALLING = 0x00000002; 173 /// 上升沿和下降沿触发 174 const IRQ_TYPE_EDGE_BOTH = Self::IRQ_TYPE_EDGE_RISING.bits | Self::IRQ_TYPE_EDGE_FALLING.bits; 175 /// 高电平触发 176 const IRQ_TYPE_LEVEL_HIGH = 0x00000004; 177 /// 低电平触发 178 const IRQ_TYPE_LEVEL_LOW = 0x00000008; 179 /// 过滤掉电平位的掩码 180 const IRQ_TYPE_LEVEL_MASK = Self::IRQ_TYPE_LEVEL_LOW.bits | Self::IRQ_TYPE_LEVEL_HIGH.bits; 181 /// 上述位掩码的掩码 182 const IRQ_TYPE_SENSE_MASK = 0x0000000f; 183 /// 某些PICs使用此类型要求 `IrqChip::irq_set_type()` 设置硬件到一个合理的默认值 184 /// (由irqdomain的map()回调使用,以便为新分配的描述符同步硬件状态和软件标志位)。 185 const IRQ_TYPE_DEFAULT = Self::IRQ_TYPE_SENSE_MASK.bits; 186 187 /// 特定于探测的过程中的特殊标志 188 const IRQ_TYPE_PROBE = 0x00000010; 189 190 /// 中断是电平类型。当上述触发位通过`IrqChip::irq_set_type()` 修改时,也会在代码中更新 191 const IRQ_LEVEL = 1 << 8; 192 /// 标记一个PER_CPU的中断。将保护其免受亲和性设置的影响 193 const IRQ_PER_CPU = 1 << 9; 194 /// 中断不能被自动探测 195 const IRQ_NOPROBE = 1 << 10; 196 /// 中断不能通过request_irq()请求 197 const IRQ_NOREQUEST = 1 << 11; 198 /// 中断在request/setup_irq()中不会自动启用 199 const IRQ_NOAUTOEN = 1 << 12; 200 /// 中断不能被平衡(亲和性设置) 201 const IRQ_NO_BALANCING = 1 << 13; 202 /// 中断可以从进程上下文中迁移 203 const IRQ_MOVE_PCNTXT = 1 << 14; 204 /// 中断嵌套在另一个线程中 205 const IRQ_NESTED_THREAD = 1 << 15; 206 /// 中断不能被线程化 207 const IRQ_NOTHREAD = 1 << 16; 208 /// Dev_id是一个per-CPU变量 209 const IRQ_PER_CPU_DEVID = 1 << 17; 210 /// 总是由另一个中断轮询。将其从错误的中断检测机制和核心侧轮询中排除 211 const IRQ_IS_POLLED = 1 << 18; 212 /// 禁用延迟的中断禁用 (Disable lazy irq disable) 213 const IRQ_DISABLE_UNLAZY = 1 << 19; 214 /// 在/proc/interrupts中不显示 215 const IRQ_HIDDEN = 1 << 20; 216 /// 从note_interrupt()调试中排除 217 const IRQ_NO_DEBUG = 1 << 21; 218 } 219 220 221 222 } 223 bitflags! { 224 /// 中断状态(存储在IrqCommonData) 225 /// 226 /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#227 227 pub struct IrqStatus: u32 { 228 /// 触发类型位的掩码 229 const IRQD_TRIGGER_MASK = 0xf; 230 /// 亲和性设置待处理 231 const IRQD_SETAFFINITY_PENDING = 1 << 8; 232 /// 中断已激活 233 const IRQD_ACTIVATED = 1 << 9; 234 /// 对此IRQ禁用平衡 235 const IRQD_NO_BALANCING = 1 << 10; 236 /// 中断是每个CPU特定的 237 const IRQD_PER_CPU = 1 << 11; 238 /// 中断亲和性已设置 239 const IRQD_AFFINITY_SET = 1 << 12; 240 /// 中断是电平触发 241 const IRQD_LEVEL = 1 << 13; 242 /// 中断配置为从挂起状态唤醒 243 const IRQD_WAKEUP_STATE = 1 << 14; 244 /// 中断可以在进程上下文中移动 245 const IRQD_MOVE_PCNTXT = 1 << 15; 246 /// 中断被禁用 247 const IRQD_IRQ_DISABLED = 1 << 16; 248 /// 中断被屏蔽 249 const IRQD_IRQ_MASKED = 1 << 17; 250 /// 中断正在处理中 251 const IRQD_IRQ_INPROGRESS = 1 << 18; 252 /// 唤醒模式已准备就绪 253 const IRQD_WAKEUP_ARMED = 1 << 19; 254 /// 中断被转发到一个虚拟CPU 255 const IRQD_FORWARDED_TO_VCPU = 1 << 20; 256 /// 亲和性由内核自动管理 257 const IRQD_AFFINITY_MANAGED = 1 << 21; 258 /// 中断已启动 259 const IRQD_IRQ_STARTED = 1 << 22; 260 /// 由于空亲和性掩码而关闭的中断。仅适用于亲和性管理的中断。 261 const IRQD_MANAGED_SHUTDOWN = 1 << 23; 262 /// IRQ只允许单个亲和性目标 263 const IRQD_SINGLE_TARGET = 1 << 24; 264 /// 预期的触发器已设置 265 const IRQD_DEFAULT_TRIGGER_SET = 1 << 25; 266 /// 可以使用保留模式 267 const IRQD_CAN_RESERVE = 1 << 26; 268 /// Non-maskable MSI quirk for affinity change required 269 const IRQD_MSI_NOMASK_QUIRK = 1 << 27; 270 /// 强制要求`handle_irq_()`只能在真实的中断上下文中调用 271 const IRQD_HANDLE_ENFORCE_IRQCTX = 1 << 28; 272 /// 激活时设置亲和性。在禁用时不要调用irq_chip::irq_set_affinity()。 273 const IRQD_AFFINITY_ON_ACTIVATE = 1 << 29; 274 /// 如果irqpm具有标志 IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND,则在挂起时中断被启用。 275 const IRQD_IRQ_ENABLED_ON_SUSPEND = 1 << 30; 276 } 277 } 278 279 #[allow(dead_code)] 280 impl IrqStatus { 281 pub const fn is_set_affinity_pending(&self) -> bool { 282 self.contains(Self::IRQD_SETAFFINITY_PENDING) 283 } 284 285 pub const fn is_per_cpu(&self) -> bool { 286 self.contains(Self::IRQD_PER_CPU) 287 } 288 289 pub const fn can_balance(&self) -> bool { 290 !((self.bits & (Self::IRQD_PER_CPU.bits | Self::IRQD_NO_BALANCING.bits)) != 0) 291 } 292 293 pub const fn affinity_was_set(&self) -> bool { 294 self.contains(Self::IRQD_AFFINITY_SET) 295 } 296 297 pub fn mark_affinity_set(&mut self) { 298 self.insert(Self::IRQD_AFFINITY_SET); 299 } 300 301 pub const fn trigger_type_was_set(&self) -> bool { 302 self.contains(Self::IRQD_DEFAULT_TRIGGER_SET) 303 } 304 305 pub fn mark_trigger_type_set(&mut self) { 306 self.insert(Self::IRQD_DEFAULT_TRIGGER_SET); 307 } 308 309 pub const fn trigger_type(&self) -> IrqLineStatus { 310 IrqLineStatus::from_bits_truncate(self.bits & Self::IRQD_TRIGGER_MASK.bits) 311 } 312 313 /// Must only be called inside irq_chip.irq_set_type() functions or 314 /// from the DT/ACPI setup code. 315 pub const fn set_trigger_type(&mut self, trigger: IrqLineStatus) { 316 self.bits &= !Self::IRQD_TRIGGER_MASK.bits; 317 self.bits |= trigger.bits & Self::IRQD_TRIGGER_MASK.bits; 318 319 self.bits |= Self::IRQD_DEFAULT_TRIGGER_SET.bits; 320 } 321 322 pub const fn is_level_type(&self) -> bool { 323 self.contains(Self::IRQD_LEVEL) 324 } 325 326 /// Must only be called of irqchip.irq_set_affinity() or low level 327 /// hierarchy domain allocation functions. 328 pub fn set_single_target(&mut self) { 329 self.insert(Self::IRQD_SINGLE_TARGET); 330 } 331 332 pub const fn is_single_target(&self) -> bool { 333 self.contains(Self::IRQD_SINGLE_TARGET) 334 } 335 336 pub fn set_handle_enforce_irqctx(&mut self) { 337 self.insert(Self::IRQD_HANDLE_ENFORCE_IRQCTX); 338 } 339 340 pub const fn is_handle_enforce_irqctx(&self) -> bool { 341 self.contains(Self::IRQD_HANDLE_ENFORCE_IRQCTX) 342 } 343 344 pub const fn is_enabled_on_suspend(&self) -> bool { 345 self.contains(Self::IRQD_IRQ_ENABLED_ON_SUSPEND) 346 } 347 348 pub const fn is_wakeup_set(&self) -> bool { 349 self.contains(Self::IRQD_WAKEUP_STATE) 350 } 351 352 pub const fn can_move_in_process_context(&self) -> bool { 353 self.contains(Self::IRQD_MOVE_PCNTXT) 354 } 355 356 pub const fn is_irq_disabled(&self) -> bool { 357 self.contains(Self::IRQD_IRQ_DISABLED) 358 } 359 360 pub const fn is_irq_masked(&self) -> bool { 361 self.contains(Self::IRQD_IRQ_MASKED) 362 } 363 364 pub const fn is_irq_in_progress(&self) -> bool { 365 self.contains(Self::IRQD_IRQ_INPROGRESS) 366 } 367 368 pub const fn is_wakeup_armed(&self) -> bool { 369 self.contains(Self::IRQD_WAKEUP_ARMED) 370 } 371 372 pub const fn is_forwarded_to_vcpu(&self) -> bool { 373 self.contains(Self::IRQD_FORWARDED_TO_VCPU) 374 } 375 376 pub fn set_forwarded_to_vcpu(&mut self) { 377 self.insert(Self::IRQD_FORWARDED_TO_VCPU); 378 } 379 380 pub const fn is_affinity_managed(&self) -> bool { 381 self.contains(Self::IRQD_AFFINITY_MANAGED) 382 } 383 384 pub const fn is_activated(&self) -> bool { 385 self.contains(Self::IRQD_ACTIVATED) 386 } 387 388 pub fn set_activated(&mut self) { 389 self.insert(Self::IRQD_ACTIVATED); 390 } 391 392 pub fn clear_activated(&mut self) { 393 self.remove(Self::IRQD_ACTIVATED); 394 } 395 396 pub const fn is_started(&self) -> bool { 397 self.contains(Self::IRQD_IRQ_STARTED) 398 } 399 400 pub const fn is_managed_and_shutdown(&self) -> bool { 401 self.contains(Self::IRQD_MANAGED_SHUTDOWN) 402 } 403 404 pub fn set_can_reserve(&mut self) { 405 self.insert(Self::IRQD_CAN_RESERVE); 406 } 407 408 pub const fn can_reserve(&self) -> bool { 409 self.contains(Self::IRQD_CAN_RESERVE) 410 } 411 412 pub fn clear_can_reserve(&mut self) { 413 self.remove(Self::IRQD_CAN_RESERVE); 414 } 415 416 pub fn set_msi_nomask_quirk(&mut self) { 417 self.insert(Self::IRQD_MSI_NOMASK_QUIRK); 418 } 419 420 pub fn clear_msi_nomask_quirk(&mut self) { 421 self.remove(Self::IRQD_MSI_NOMASK_QUIRK); 422 } 423 424 pub const fn is_msi_nomask_quirk(&self) -> bool { 425 self.contains(Self::IRQD_MSI_NOMASK_QUIRK) 426 } 427 428 pub fn set_affinity_on_activate(&mut self) { 429 self.insert(Self::IRQD_AFFINITY_ON_ACTIVATE); 430 } 431 432 pub const fn is_affinity_on_activate(&self) -> bool { 433 self.contains(Self::IRQD_AFFINITY_ON_ACTIVATE) 434 } 435 } 436