1ce5850adSLoGin use core::fmt::Debug; 2ce5850adSLoGin 3ce5850adSLoGin use alloc::{ 4e2841179SLoGin string::{String, ToString}, 5ce5850adSLoGin sync::{Arc, Weak}, 6ce5850adSLoGin vec::Vec, 7ce5850adSLoGin }; 8ce5850adSLoGin use hashbrown::HashMap; 9ce5850adSLoGin use system_error::SystemError; 10ce5850adSLoGin 11ce5850adSLoGin use crate::{ 12ce5850adSLoGin driver::{base::device::Device, open_firmware::device_node::DeviceNode}, 13e2841179SLoGin exception::{irqdata::IrqLineStatus, irqdesc::irq_desc_manager, manage::irq_manager}, 14f049d1afSLoGin libs::{ 15f049d1afSLoGin rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, 16f049d1afSLoGin spinlock::SpinLock, 17f049d1afSLoGin }, 18ce5850adSLoGin }; 19ce5850adSLoGin 20ce5850adSLoGin use super::{ 21338f6903SLoGin dummychip::no_irq_chip, 22338f6903SLoGin irqchip::{IrqChip, IrqChipData, IrqChipGeneric, IrqGcFlags}, 23338f6903SLoGin irqdata::{IrqData, IrqHandlerData}, 24f049d1afSLoGin irqdesc::{IrqDesc, IrqFlowHandler}, 25ce5850adSLoGin HardwareIrqNumber, IrqNumber, 26ce5850adSLoGin }; 27ce5850adSLoGin 28e2841179SLoGin static mut IRQ_DOMAIN_MANAGER: Option<Arc<IrqDomainManager>> = None; 29e2841179SLoGin 30e2841179SLoGin /// 获取中断域管理器的引用 31e2841179SLoGin #[inline(always)] 32e2841179SLoGin pub fn irq_domain_manager() -> &'static Arc<IrqDomainManager> { 33e2841179SLoGin unsafe { IRQ_DOMAIN_MANAGER.as_ref().unwrap() } 34e2841179SLoGin } 35e2841179SLoGin 36e2841179SLoGin pub(super) fn irq_domain_manager_init() { 37e2841179SLoGin unsafe { 38e2841179SLoGin IRQ_DOMAIN_MANAGER = Some(Arc::new(IrqDomainManager::new())); 39e2841179SLoGin } 40e2841179SLoGin } 41e2841179SLoGin /// 中断域管理器 42e2841179SLoGin pub struct IrqDomainManager { 43e2841179SLoGin domains: SpinLock<Vec<Arc<IrqDomain>>>, 44e2841179SLoGin inner: RwLock<InnerIrqDomainManager>, 45e2841179SLoGin } 46e2841179SLoGin 47e2841179SLoGin impl IrqDomainManager { 48e2841179SLoGin pub fn new() -> IrqDomainManager { 49e2841179SLoGin IrqDomainManager { 50e2841179SLoGin domains: SpinLock::new(Vec::new()), 51e2841179SLoGin inner: RwLock::new(InnerIrqDomainManager { 52e2841179SLoGin default_domain: None, 53e2841179SLoGin }), 54e2841179SLoGin } 55e2841179SLoGin } 56e2841179SLoGin 57338f6903SLoGin /// 创建一个新的线性映射的irqdomain, 并将其添加到irqdomain管理器中 58338f6903SLoGin /// 59338f6903SLoGin /// 创建的irqdomain,中断号是线性的,即从0开始,依次递增 60338f6903SLoGin /// 61338f6903SLoGin /// ## 参数 62338f6903SLoGin /// 63338f6903SLoGin /// - `name` - 中断域的名字 64338f6903SLoGin /// - `ops` - 中断域的操作 65338f6903SLoGin /// - `irq_size` - 中断号的数量 66338f6903SLoGin #[allow(dead_code)] 67338f6903SLoGin pub fn create_and_add_linear( 68338f6903SLoGin &self, 69338f6903SLoGin name: String, 70338f6903SLoGin ops: &'static dyn IrqDomainOps, 71338f6903SLoGin irq_size: u32, 72338f6903SLoGin ) -> Option<Arc<IrqDomain>> { 73338f6903SLoGin self.create_and_add( 74338f6903SLoGin name, 75338f6903SLoGin ops, 76338f6903SLoGin IrqNumber::new(0), 77338f6903SLoGin HardwareIrqNumber::new(0), 78338f6903SLoGin irq_size, 79338f6903SLoGin ) 80338f6903SLoGin } 81338f6903SLoGin 82e2841179SLoGin /// 创建一个新的irqdomain, 并将其添加到irqdomain管理器中 83e2841179SLoGin /// 84e2841179SLoGin /// ## 参数 85e2841179SLoGin /// 86e2841179SLoGin /// - `name` - 中断域的名字 87e2841179SLoGin /// - `ops` - 中断域的操作 88e2841179SLoGin /// - `first_irq` - 起始软件中断号 89e2841179SLoGin /// - `first_hwirq` - 起始硬件中断号 90e2841179SLoGin /// - `irq_size` - 中断号的数量 91e2841179SLoGin /// 92e2841179SLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdomain.c?fi=__irq_domain_add#139 93e2841179SLoGin pub fn create_and_add( 94e2841179SLoGin &self, 95e2841179SLoGin name: String, 96e2841179SLoGin ops: &'static dyn IrqDomainOps, 97e2841179SLoGin first_irq: IrqNumber, 98e2841179SLoGin first_hwirq: HardwareIrqNumber, 99e2841179SLoGin irq_size: u32, 100e2841179SLoGin ) -> Option<Arc<IrqDomain>> { 101e2841179SLoGin let domain = IrqDomain::new( 102e2841179SLoGin None, 103e2841179SLoGin Some(name), 104e2841179SLoGin ops, 105e2841179SLoGin IrqDomainFlags::NAME_ALLOCATED, 106e2841179SLoGin IrqDomainBusToken::Any, 107e2841179SLoGin first_irq + irq_size, 108e2841179SLoGin first_hwirq + irq_size, 109e2841179SLoGin )?; 110e2841179SLoGin 111e2841179SLoGin self.add_domain(domain.clone()); 112e2841179SLoGin 113e2841179SLoGin return Some(domain); 114e2841179SLoGin } 115e2841179SLoGin 116e2841179SLoGin fn add_domain(&self, domain: Arc<IrqDomain>) { 117e2841179SLoGin self.domains.lock_irqsave().push(domain); 118e2841179SLoGin } 119e2841179SLoGin 120e2841179SLoGin #[allow(dead_code)] 121e2841179SLoGin pub fn remove_domain(&self, domain: &Arc<IrqDomain>) { 122e2841179SLoGin let mut domains = self.domains.lock_irqsave(); 123e2841179SLoGin let index = domains 124e2841179SLoGin .iter() 125e2841179SLoGin .position(|x| Arc::ptr_eq(x, domain)) 126e2841179SLoGin .expect("domain not found"); 127e2841179SLoGin domains.remove(index); 128e2841179SLoGin } 129e2841179SLoGin 130e2841179SLoGin /// 获取默认的中断域 131e2841179SLoGin #[allow(dead_code)] 132e2841179SLoGin pub fn default_domain(&self) -> Option<Arc<IrqDomain>> { 133e2841179SLoGin self.inner.read().default_domain.clone() 134e2841179SLoGin } 135e2841179SLoGin 136e2841179SLoGin /// 设置默认的中断域 137e2841179SLoGin /// 138e2841179SLoGin /// 在创建IRQ映射的时候,如果没有指定中断域,就会使用默认的中断域 139e2841179SLoGin pub fn set_default_domain(&self, domain: Arc<IrqDomain>) { 140e2841179SLoGin self.inner.write_irqsave().default_domain = Some(domain); 141e2841179SLoGin } 142e2841179SLoGin 143e2841179SLoGin /// 将指定范围的硬件中断号与软件中断号一一对应的关联起来 144e2841179SLoGin /// 145e2841179SLoGin /// ## 参数 146e2841179SLoGin /// 147e2841179SLoGin /// - `domain` - 中断域 148e2841179SLoGin /// - `first_irq` - 起始软件中断号 149e2841179SLoGin /// - `first_hwirq` - 起始硬件中断号 150e2841179SLoGin /// - `count` - 数量 151e2841179SLoGin pub fn domain_associate_many( 152e2841179SLoGin &self, 153e2841179SLoGin domain: &Arc<IrqDomain>, 154e2841179SLoGin first_irq: IrqNumber, 155e2841179SLoGin first_hwirq: HardwareIrqNumber, 156e2841179SLoGin count: u32, 157e2841179SLoGin ) { 158e2841179SLoGin for i in 0..count { 159e2841179SLoGin if let Err(e) = self.domain_associate(domain, first_irq + i, first_hwirq + i) { 160e2841179SLoGin kwarn!("domain associate failed: {:?}, domain '{:?}' didn't like hwirq {} to virq {} mapping.", e, domain.name(), (first_hwirq + i).data(), (first_irq + i).data()); 161e2841179SLoGin } 162e2841179SLoGin } 163e2841179SLoGin } 164e2841179SLoGin 165e2841179SLoGin /// 将一个硬件中断号与一个软件中断号关联起来 166e2841179SLoGin /// 167e2841179SLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdomain.c#562 168e2841179SLoGin pub fn domain_associate( 169e2841179SLoGin &self, 170e2841179SLoGin domain: &Arc<IrqDomain>, 171e2841179SLoGin irq: IrqNumber, 172e2841179SLoGin hwirq: HardwareIrqNumber, 173e2841179SLoGin ) -> Result<(), SystemError> { 174e2841179SLoGin if hwirq >= domain.revmap.read_irqsave().hwirq_max { 175e2841179SLoGin kwarn!( 176e2841179SLoGin "hwirq {} is out of range for domain {:?}", 177e2841179SLoGin hwirq.data(), 178e2841179SLoGin domain.name() 179e2841179SLoGin ); 180e2841179SLoGin return Err(SystemError::EINVAL); 181e2841179SLoGin } 182e2841179SLoGin let irq_data = irq_desc_manager() 183e2841179SLoGin .lookup(irq) 184e2841179SLoGin .ok_or_else(|| { 185e2841179SLoGin kwarn!("irq_desc not found for irq {}", irq.data()); 186e2841179SLoGin SystemError::EINVAL 187e2841179SLoGin })? 188e2841179SLoGin .irq_data(); 189e2841179SLoGin if irq_data.domain().is_some() { 190e2841179SLoGin kwarn!( 191e2841179SLoGin "irq {} is already associated with domain {:?}", 192e2841179SLoGin irq.data(), 193e2841179SLoGin irq_data.domain().unwrap().name() 194e2841179SLoGin ); 195e2841179SLoGin return Err(SystemError::EINVAL); 196e2841179SLoGin } 197e2841179SLoGin 198e2841179SLoGin let mut irq_data_guard = irq_data.inner(); 199e2841179SLoGin irq_data_guard.set_hwirq(hwirq); 200e2841179SLoGin irq_data_guard.set_domain(Some(domain.clone())); 201e2841179SLoGin drop(irq_data_guard); 202b5b571e0SLoGin let r = domain.ops.map(domain, hwirq, irq); 203e2841179SLoGin if let Err(e) = r { 204e2841179SLoGin if e != SystemError::ENOSYS { 205e2841179SLoGin if e != SystemError::EPERM { 206e2841179SLoGin kinfo!("domain associate failed: {:?}, domain '{:?}' didn't like hwirq {} to virq {} mapping.", e, domain.name(), hwirq.data(), irq.data()); 207e2841179SLoGin } 208e2841179SLoGin let mut irq_data_guard = irq_data.inner(); 209e2841179SLoGin irq_data_guard.set_domain(None); 210e2841179SLoGin irq_data_guard.set_hwirq(HardwareIrqNumber::new(0)); 211e2841179SLoGin return Err(e); 212e2841179SLoGin } 213e2841179SLoGin } 214e2841179SLoGin 215e2841179SLoGin if domain.name().is_none() { 216e2841179SLoGin let chip = irq_data.chip_info_read_irqsave().chip(); 217e2841179SLoGin domain.set_name(chip.name().to_string()); 218e2841179SLoGin } 219e2841179SLoGin 220b5b571e0SLoGin self.irq_domain_set_mapping(domain, hwirq, irq_data); 221e2841179SLoGin 222e2841179SLoGin irq_manager().irq_clear_status_flags(irq, IrqLineStatus::IRQ_NOREQUEST)?; 223e2841179SLoGin 224e2841179SLoGin return Ok(()); 225e2841179SLoGin } 226e2841179SLoGin 227e2841179SLoGin fn irq_domain_set_mapping( 228e2841179SLoGin &self, 229e2841179SLoGin domain: &Arc<IrqDomain>, 230e2841179SLoGin hwirq: HardwareIrqNumber, 231e2841179SLoGin irq_data: Arc<IrqData>, 232e2841179SLoGin ) { 233e2841179SLoGin if domain.no_map() { 234e2841179SLoGin return; 235e2841179SLoGin } 236e2841179SLoGin 237e2841179SLoGin domain.revmap.write_irqsave().insert(hwirq, irq_data); 238e2841179SLoGin } 239e2841179SLoGin /// 递归调用 domain_ops->activate 以激活中断 240e2841179SLoGin /// 241e2841179SLoGin /// ## 参数 242e2841179SLoGin /// 243e2841179SLoGin /// - irq_data: 与中断关联的最外层 irq_data 244e2841179SLoGin /// - reserve: 如果为true,则仅预留一个中断向量,而不是分配一个 245e2841179SLoGin /// 246e2841179SLoGin /// 这是调用 domain_ops->activate 以编程中断控制器的第二步,以便中断实际上可以被传递。 247e2841179SLoGin pub fn activate_irq(&self, irq_data: &Arc<IrqData>, reserve: bool) -> Result<(), SystemError> { 248e2841179SLoGin let mut r = Ok(()); 249*0102d69fSLoGin // kdebug!( 250*0102d69fSLoGin // "activate_irq: irq_data.common_data().status().is_activated()={}", 251*0102d69fSLoGin // irq_data.common_data().status().is_activated() 252*0102d69fSLoGin // ); 253e2841179SLoGin if !irq_data.common_data().status().is_activated() { 254e2841179SLoGin r = self.do_activate_irq(Some(irq_data.clone()), reserve); 255e2841179SLoGin } 256e2841179SLoGin 257b5b571e0SLoGin if r.is_err() { 258e2841179SLoGin irq_data.common_data().status().set_activated(); 259e2841179SLoGin } 260e2841179SLoGin 261e2841179SLoGin return r; 262e2841179SLoGin } 263e2841179SLoGin 264e2841179SLoGin #[inline(never)] 265e2841179SLoGin fn do_activate_irq( 266e2841179SLoGin &self, 267e2841179SLoGin irq_data: Option<Arc<IrqData>>, 268e2841179SLoGin reserve: bool, 269e2841179SLoGin ) -> Result<(), SystemError> { 270e2841179SLoGin let mut r = Ok(()); 271e2841179SLoGin 272b5b571e0SLoGin if let Some(irq_data) = irq_data { 273*0102d69fSLoGin // kdebug!("do_activate_irq: irq_data={:?}", irq_data); 274b5b571e0SLoGin if let Some(domain) = irq_data.domain() { 275*0102d69fSLoGin // kdebug!("do_activate_irq: domain={:?}", domain.name()); 276b5b571e0SLoGin let parent_data = irq_data.parent_data().and_then(|x| x.upgrade()); 277e2841179SLoGin if let Some(parent_data) = parent_data.clone() { 278e2841179SLoGin r = self.do_activate_irq(Some(parent_data), reserve); 279e2841179SLoGin } 280e2841179SLoGin 281e2841179SLoGin if r.is_err() { 282e2841179SLoGin let tmpr = domain.ops.activate(&domain, &irq_data, reserve); 283e2841179SLoGin if let Err(e) = tmpr { 284e2841179SLoGin if e != SystemError::ENOSYS && parent_data.is_some() { 285e2841179SLoGin self.do_deactivate_irq(parent_data); 286e2841179SLoGin } 287e2841179SLoGin } 288e2841179SLoGin } 289e2841179SLoGin } 290b5b571e0SLoGin } 291e2841179SLoGin 292e2841179SLoGin return r; 293e2841179SLoGin } 294b5b571e0SLoGin #[allow(clippy::only_used_in_recursion)] 295e2841179SLoGin fn do_deactivate_irq(&self, irq_data: Option<Arc<IrqData>>) { 296e2841179SLoGin if let Some(irq_data) = irq_data { 297e2841179SLoGin if let Some(domain) = irq_data.domain() { 298e2841179SLoGin domain.ops.deactivate(&domain, &irq_data); 299b5b571e0SLoGin let pp = irq_data.parent_data().and_then(|x| x.upgrade()); 300e2841179SLoGin 301e2841179SLoGin if pp.is_some() { 302e2841179SLoGin self.do_deactivate_irq(pp); 303e2841179SLoGin } 304e2841179SLoGin } 305e2841179SLoGin } 306e2841179SLoGin } 307338f6903SLoGin 308338f6903SLoGin /// `irq_domain_set_info` - 在 @domain 中为 @virq 设置完整的数据 309338f6903SLoGin /// 310338f6903SLoGin /// ## 参数 311338f6903SLoGin /// 312338f6903SLoGin /// - `domain`: 要匹配的中断域 313338f6903SLoGin /// - `virq`: IRQ号 314338f6903SLoGin /// - `hwirq`: 硬件中断号 315338f6903SLoGin /// - `chip`: 相关的中断芯片 316338f6903SLoGin /// - `chip_data`: 相关的中断芯片数据 317338f6903SLoGin /// - `handler`: 中断流处理器 318338f6903SLoGin /// - `handler_data`: 中断流处理程序数据 319338f6903SLoGin /// - `handler_name`: 中断处理程序名称 320b5b571e0SLoGin #[allow(clippy::too_many_arguments)] 321338f6903SLoGin pub fn domain_set_info( 322338f6903SLoGin &self, 323338f6903SLoGin domain: &Arc<IrqDomain>, 324338f6903SLoGin virq: IrqNumber, 325338f6903SLoGin hwirq: HardwareIrqNumber, 326338f6903SLoGin chip: Arc<dyn IrqChip>, 327338f6903SLoGin chip_data: Option<Arc<dyn IrqChipData>>, 328338f6903SLoGin flow_handler: &'static dyn IrqFlowHandler, 329338f6903SLoGin handler_data: Option<Arc<dyn IrqHandlerData>>, 330338f6903SLoGin handler_name: Option<String>, 331338f6903SLoGin ) { 332338f6903SLoGin let r = self.domain_set_hwirq_and_chip(domain, virq, hwirq, Some(chip), chip_data); 333338f6903SLoGin if r.is_err() { 334338f6903SLoGin return; 335338f6903SLoGin } 336338f6903SLoGin irq_manager().__irq_set_handler(virq, flow_handler, false, handler_name); 337338f6903SLoGin irq_manager().irq_set_handler_data(virq, handler_data).ok(); 338338f6903SLoGin } 339338f6903SLoGin 340338f6903SLoGin /// `domain_set_hwirq_and_chip` - 在 @domain 中为 @virq 设置 hwirq 和 irqchip 341338f6903SLoGin /// 342338f6903SLoGin /// ## 参数 343338f6903SLoGin /// 344338f6903SLoGin /// - `domain`: 要匹配的中断域 345338f6903SLoGin /// - `virq`: IRQ号 346338f6903SLoGin /// - `hwirq`: hwirq号 347338f6903SLoGin /// - `chip`: 相关的中断芯片 348338f6903SLoGin /// - `chip_data`: 相关的芯片数据 349338f6903SLoGin pub fn domain_set_hwirq_and_chip( 350338f6903SLoGin &self, 351338f6903SLoGin domain: &Arc<IrqDomain>, 352338f6903SLoGin virq: IrqNumber, 353338f6903SLoGin hwirq: HardwareIrqNumber, 354338f6903SLoGin chip: Option<Arc<dyn IrqChip>>, 355338f6903SLoGin chip_data: Option<Arc<dyn IrqChipData>>, 356338f6903SLoGin ) -> Result<(), SystemError> { 357338f6903SLoGin let irq_data: Arc<IrqData> = self 358338f6903SLoGin .domain_get_irq_data(domain, virq) 359338f6903SLoGin .ok_or(SystemError::ENOENT)?; 360338f6903SLoGin let mut inner = irq_data.inner(); 361338f6903SLoGin let mut chip_info = irq_data.chip_info_write_irqsave(); 362338f6903SLoGin 363338f6903SLoGin inner.set_hwirq(hwirq); 364338f6903SLoGin if let Some(chip) = chip { 365338f6903SLoGin chip_info.set_chip(Some(chip)); 366338f6903SLoGin } else { 367338f6903SLoGin chip_info.set_chip(Some(no_irq_chip())); 368338f6903SLoGin }; 369338f6903SLoGin 370338f6903SLoGin chip_info.set_chip_data(chip_data); 371338f6903SLoGin 372338f6903SLoGin return Ok(()); 373338f6903SLoGin } 374338f6903SLoGin 375338f6903SLoGin /// `irq_domain_get_irq_data` - 获取与 @virq 和 @domain 关联的 irq_data 376338f6903SLoGin /// 377338f6903SLoGin /// ## 参数 378338f6903SLoGin /// 379338f6903SLoGin /// - `domain`: 要匹配的域 380338f6903SLoGin /// - `virq`: 要获取 irq_data 的IRQ号 381338f6903SLoGin pub fn domain_get_irq_data( 382338f6903SLoGin &self, 383338f6903SLoGin domain: &Arc<IrqDomain>, 384338f6903SLoGin virq: IrqNumber, 385338f6903SLoGin ) -> Option<Arc<IrqData>> { 386338f6903SLoGin let desc = irq_desc_manager().lookup(virq)?; 387338f6903SLoGin let mut irq_data = Some(desc.irq_data()); 388338f6903SLoGin 389338f6903SLoGin while irq_data.is_some() { 390338f6903SLoGin let dt = irq_data.unwrap(); 391338f6903SLoGin if dt.domain().is_some() && Arc::ptr_eq(dt.domain().as_ref().unwrap(), domain) { 392338f6903SLoGin return Some(dt); 393338f6903SLoGin } 394b5b571e0SLoGin irq_data = dt.parent_data().and_then(|x| x.upgrade()); 395338f6903SLoGin } 396338f6903SLoGin 397338f6903SLoGin return None; 398338f6903SLoGin } 399f049d1afSLoGin 400f049d1afSLoGin /// `resolve_irq_mapping` - 从硬件中断号找到中断号。 401f049d1afSLoGin /// 402f049d1afSLoGin /// ## 参数 403f049d1afSLoGin /// 404f049d1afSLoGin /// - `domain`: 拥有此硬件中断的域 405f049d1afSLoGin /// - `hwirq`: 该域空间中的硬件中断号 406f049d1afSLoGin /// - `irq`: 如果需要,可选的指针以返回Linux中断 407f049d1afSLoGin /// 408f049d1afSLoGin /// ## 返回 409f049d1afSLoGin /// 410f049d1afSLoGin /// 返回一个元组,包含中断描述符和中断号 411f049d1afSLoGin pub fn resolve_irq_mapping( 412f049d1afSLoGin &self, 413f049d1afSLoGin mut domain: Option<Arc<IrqDomain>>, 414f049d1afSLoGin hwirq: HardwareIrqNumber, 415f049d1afSLoGin ) -> Result<(Arc<IrqDesc>, IrqNumber), SystemError> { 416f049d1afSLoGin if domain.is_none() { 417f049d1afSLoGin domain = Some(self.default_domain().ok_or(SystemError::EINVAL)?); 418f049d1afSLoGin } 419f049d1afSLoGin 420f049d1afSLoGin let domain = domain.unwrap(); 421f049d1afSLoGin 422f049d1afSLoGin if domain.no_map() { 423f049d1afSLoGin if hwirq < domain.revmap_read_irqsave().hwirq_max { 424f049d1afSLoGin let irq_desc = irq_desc_manager() 425f049d1afSLoGin .lookup(IrqNumber::new(hwirq.data())) 426f049d1afSLoGin .ok_or(SystemError::EINVAL)?; 427f049d1afSLoGin if irq_desc.irq_data().hardware_irq() == hwirq { 428f049d1afSLoGin let irq = irq_desc.irq_data().irq(); 429f049d1afSLoGin return Ok((irq_desc, irq)); 430f049d1afSLoGin } 431f049d1afSLoGin } 432f049d1afSLoGin 433f049d1afSLoGin return Err(SystemError::EINVAL); 434f049d1afSLoGin } 435f049d1afSLoGin 436f049d1afSLoGin let revmap = domain.revmap_read_irqsave(); 437f049d1afSLoGin let irq_data = revmap.lookup(hwirq).ok_or(SystemError::EINVAL)?; 438f049d1afSLoGin let irq_desc = irq_data.irq_desc().unwrap(); 439f049d1afSLoGin return Ok((irq_desc, irq_data.irq())); 440f049d1afSLoGin } 441e2841179SLoGin } 442e2841179SLoGin 443e2841179SLoGin struct InnerIrqDomainManager { 444e2841179SLoGin default_domain: Option<Arc<IrqDomain>>, 445e2841179SLoGin } 446e2841179SLoGin 447ce5850adSLoGin /// 中断域 448ce5850adSLoGin /// 449ce5850adSLoGin /// 用于把硬件中断号翻译为软件中断号的映射的对象 450ce5850adSLoGin /// 451ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#164 452ce5850adSLoGin #[allow(dead_code)] 453ce5850adSLoGin #[derive(Debug)] 454ce5850adSLoGin pub struct IrqDomain { 455ce5850adSLoGin /// 中断域的名字 (二选一) 456ce5850adSLoGin name: Option<&'static str>, 457e2841179SLoGin allocated_name: SpinLock<Option<String>>, 458ce5850adSLoGin /// 中断域的操作 459ce5850adSLoGin ops: &'static dyn IrqDomainOps, 460ce5850adSLoGin inner: SpinLock<InnerIrqDomain>, 461ce5850adSLoGin /// 中断号反向映射 462ce5850adSLoGin revmap: RwLock<IrqDomainRevMap>, 463ce5850adSLoGin } 464ce5850adSLoGin 465ce5850adSLoGin #[allow(dead_code)] 466ce5850adSLoGin #[derive(Debug)] 467ce5850adSLoGin struct InnerIrqDomain { 468338f6903SLoGin /// this field not touched by the core code 469338f6903SLoGin host_data: Option<Arc<dyn IrqChipData>>, 470ce5850adSLoGin /// host per irq_domain flags 471ce5850adSLoGin flags: IrqDomainFlags, 472ce5850adSLoGin /// The number of mapped interrupts 473ce5850adSLoGin mapcount: u32, 474ce5850adSLoGin bus_token: IrqDomainBusToken, 475ce5850adSLoGin /// 指向 generic chip 列表的指针。 476ce5850adSLoGin /// 有一个辅助函数用于为中断控制器驱动程序设置一个或 477ce5850adSLoGin /// 多个 generic chip,该函数使用此指针并依赖于 generic chip 库。 478ce5850adSLoGin generic_chip: Option<Arc<IrqDomainChipGeneric>>, 479ce5850adSLoGin /// Pointer to a device that the domain represent, and that will be 480ce5850adSLoGin /// used for power management purposes. 481ce5850adSLoGin device: Option<Arc<dyn Device>>, 482ce5850adSLoGin /// Pointer to parent irq_domain to support hierarchy irq_domains 483ce5850adSLoGin parent: Option<Weak<IrqDomain>>, 484ce5850adSLoGin } 485ce5850adSLoGin 486ce5850adSLoGin impl IrqDomain { 487ce5850adSLoGin #[allow(dead_code)] 488ce5850adSLoGin pub fn new( 489ce5850adSLoGin name: Option<&'static str>, 490ce5850adSLoGin allocated_name: Option<String>, 491ce5850adSLoGin ops: &'static dyn IrqDomainOps, 492ce5850adSLoGin flags: IrqDomainFlags, 493ce5850adSLoGin bus_token: IrqDomainBusToken, 494e2841179SLoGin irq_max: IrqNumber, 495e2841179SLoGin hwirq_max: HardwareIrqNumber, 496ce5850adSLoGin ) -> Option<Arc<Self>> { 497ce5850adSLoGin if name.is_none() && allocated_name.is_none() { 498ce5850adSLoGin return None; 499ce5850adSLoGin } 500ce5850adSLoGin 501ce5850adSLoGin let x = IrqDomain { 502ce5850adSLoGin name, 503e2841179SLoGin allocated_name: SpinLock::new(allocated_name), 504ce5850adSLoGin ops, 505ce5850adSLoGin inner: SpinLock::new(InnerIrqDomain { 506338f6903SLoGin host_data: None, 507ce5850adSLoGin flags, 508ce5850adSLoGin mapcount: 0, 509ce5850adSLoGin bus_token, 510ce5850adSLoGin generic_chip: None, 511ce5850adSLoGin device: None, 512ce5850adSLoGin parent: None, 513ce5850adSLoGin }), 514ce5850adSLoGin revmap: RwLock::new(IrqDomainRevMap { 515ce5850adSLoGin map: HashMap::new(), 516e2841179SLoGin hwirq_max, 517e2841179SLoGin irq_max, 518ce5850adSLoGin }), 519ce5850adSLoGin }; 520ce5850adSLoGin 521ce5850adSLoGin return Some(Arc::new(x)); 522ce5850adSLoGin } 523e2841179SLoGin 524e2841179SLoGin /// 中断域是否不对中断号进行转换 525e2841179SLoGin pub fn no_map(&self) -> bool { 526e2841179SLoGin self.inner 527e2841179SLoGin .lock_irqsave() 528e2841179SLoGin .flags 529e2841179SLoGin .contains(IrqDomainFlags::NO_MAP) 530e2841179SLoGin } 531e2841179SLoGin 532e2841179SLoGin #[allow(dead_code)] 533f049d1afSLoGin fn revmap_read_irqsave(&self) -> RwLockReadGuard<IrqDomainRevMap> { 534f049d1afSLoGin self.revmap.read_irqsave() 535f049d1afSLoGin } 536f049d1afSLoGin 537f049d1afSLoGin #[allow(dead_code)] 538f049d1afSLoGin fn revmap_write_irqsave(&self) -> RwLockWriteGuard<IrqDomainRevMap> { 539f049d1afSLoGin self.revmap.write_irqsave() 540f049d1afSLoGin } 541f049d1afSLoGin 542f049d1afSLoGin #[allow(dead_code)] 543e2841179SLoGin fn set_hwirq_max(&self, hwirq_max: HardwareIrqNumber) { 544f049d1afSLoGin self.revmap_write_irqsave().hwirq_max = hwirq_max; 545e2841179SLoGin } 546e2841179SLoGin 547e2841179SLoGin pub fn name(&self) -> Option<String> { 548e2841179SLoGin if let Some(name) = self.name { 549e2841179SLoGin return Some(name.to_string()); 550e2841179SLoGin } 551e2841179SLoGin return self.allocated_name.lock_irqsave().clone(); 552e2841179SLoGin } 553e2841179SLoGin 554e2841179SLoGin pub fn set_name(&self, name: String) { 555e2841179SLoGin *self.allocated_name.lock_irqsave() = Some(name); 556e2841179SLoGin } 557e2841179SLoGin 558e2841179SLoGin /// The number of mapped interrupts 559e2841179SLoGin pub fn map_count(&self) -> u32 { 560f049d1afSLoGin self.revmap_read_irqsave().map.len() as u32 561e2841179SLoGin } 562338f6903SLoGin 563338f6903SLoGin pub fn host_data(&self) -> Option<Arc<dyn IrqChipData>> { 564338f6903SLoGin self.inner.lock_irqsave().host_data.clone() 565338f6903SLoGin } 566338f6903SLoGin 567338f6903SLoGin pub fn set_host_data(&self, host_data: Option<Arc<dyn IrqChipData>>) { 568338f6903SLoGin self.inner.lock_irqsave().host_data = host_data; 569338f6903SLoGin } 570ce5850adSLoGin } 571ce5850adSLoGin 572ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#190 573ce5850adSLoGin #[allow(dead_code)] 574ce5850adSLoGin #[derive(Debug)] 575ce5850adSLoGin struct IrqDomainRevMap { 576e2841179SLoGin map: HashMap<HardwareIrqNumber, Arc<IrqData>>, 577ce5850adSLoGin hwirq_max: HardwareIrqNumber, 578e2841179SLoGin irq_max: IrqNumber, 579e2841179SLoGin } 580e2841179SLoGin 581e2841179SLoGin impl IrqDomainRevMap { 582e2841179SLoGin fn insert(&mut self, hwirq: HardwareIrqNumber, irq_data: Arc<IrqData>) { 583e2841179SLoGin self.map.insert(hwirq, irq_data); 584e2841179SLoGin } 585e2841179SLoGin 586e2841179SLoGin #[allow(dead_code)] 587e2841179SLoGin fn remove(&mut self, hwirq: HardwareIrqNumber) { 588e2841179SLoGin self.map.remove(&hwirq); 589e2841179SLoGin } 590e2841179SLoGin 591e2841179SLoGin #[allow(dead_code)] 592e2841179SLoGin fn lookup(&self, hwirq: HardwareIrqNumber) -> Option<Arc<IrqData>> { 593e2841179SLoGin self.map.get(&hwirq).cloned() 594e2841179SLoGin } 595ce5850adSLoGin } 596ce5850adSLoGin 597ce5850adSLoGin bitflags! { 598ce5850adSLoGin pub struct IrqDomainFlags: u32 { 599ce5850adSLoGin /// Irq domain is hierarchical 600ce5850adSLoGin const HIERARCHY = (1 << 0); 601ce5850adSLoGin /// Irq domain name was allocated dynamically 602ce5850adSLoGin const NAME_ALLOCATED = (1 << 1); 603ce5850adSLoGin /// Irq domain is an IPI domain with virq per cpu 604ce5850adSLoGin const IPI_PER_CPU = (1 << 2); 605ce5850adSLoGin /// Irq domain is an IPI domain with single virq 606ce5850adSLoGin const IPI_SINGLE = (1 << 3); 607ce5850adSLoGin /// Irq domain implements MSIs 608ce5850adSLoGin const MSI = (1 << 4); 609ce5850adSLoGin /// Irq domain implements MSI remapping 610ce5850adSLoGin const MSI_REMAP = (1 << 5); 611ce5850adSLoGin /// Quirk to handle MSI implementations which do not provide masking 612ce5850adSLoGin const MSI_NOMASK_QUIRK = (1 << 6); 613ce5850adSLoGin /// Irq domain doesn't translate anything 614ce5850adSLoGin const NO_MAP = (1 << 7); 615ce5850adSLoGin /// Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved 616ce5850adSLoGin /// for implementation specific purposes and ignored by the core code 617ce5850adSLoGin const NONCORE = (1 << 16); 618ce5850adSLoGin } 619ce5850adSLoGin } 620ce5850adSLoGin 621ce5850adSLoGin /// 如果多个域有相同的设备节点,但服务于不同的目的(例如,一个域用于PCI/MSI,另一个用于有线IRQs), 622ce5850adSLoGin /// 它们可以使用特定于总线的token进行区分。预计大多数域只会携带`DomainBusAny`。 623ce5850adSLoGin /// 624ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#78 625ce5850adSLoGin #[allow(dead_code)] 626ce5850adSLoGin #[derive(Debug, Clone, Copy, PartialEq, Eq)] 627ce5850adSLoGin pub enum IrqDomainBusToken { 628ce5850adSLoGin Any = 0, 629ce5850adSLoGin Wired, 630ce5850adSLoGin GenericMsi, 631ce5850adSLoGin PciMsi, 632ce5850adSLoGin PlatformMsi, 633ce5850adSLoGin Nexus, 634ce5850adSLoGin Ipi, 635ce5850adSLoGin FslMcMsi, 636ce5850adSLoGin TiSciIntaMsi, 637ce5850adSLoGin Wakeup, 638ce5850adSLoGin VmdMsi, 639ce5850adSLoGin } 640ce5850adSLoGin 641ce5850adSLoGin /// IrqDomain的操作方法 642ce5850adSLoGin /// 643ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#107 6443bc96fa4SLoGin pub trait IrqDomainOps: Debug + Send + Sync { 645ce5850adSLoGin /// 匹配一个中断控制器设备节点到一个主机。 646ce5850adSLoGin fn match_node( 647ce5850adSLoGin &self, 648338f6903SLoGin _irq_domain: &Arc<IrqDomain>, 649338f6903SLoGin _device_node: &Arc<DeviceNode>, 650338f6903SLoGin _bus_token: IrqDomainBusToken, 651338f6903SLoGin ) -> bool { 652338f6903SLoGin false 653338f6903SLoGin } 654ce5850adSLoGin 655ce5850adSLoGin /// 创建或更新一个虚拟中断号与一个硬件中断号之间的映射。 656ce5850adSLoGin /// 对于给定的映射,这只会被调用一次。 657e2841179SLoGin /// 658e2841179SLoGin /// 如果没有实现这个方法,那么就会返回`ENOSYS` 659ce5850adSLoGin fn map( 660ce5850adSLoGin &self, 661e2841179SLoGin _irq_domain: &Arc<IrqDomain>, 662e2841179SLoGin _hwirq: HardwareIrqNumber, 663e2841179SLoGin _virq: IrqNumber, 664e2841179SLoGin ) -> Result<(), SystemError> { 665e2841179SLoGin Err(SystemError::ENOSYS) 666e2841179SLoGin } 667ce5850adSLoGin 668ce5850adSLoGin /// 删除一个虚拟中断号与一个硬件中断号之间的映射。 669ce5850adSLoGin fn unmap(&self, irq_domain: &Arc<IrqDomain>, virq: IrqNumber); 670e2841179SLoGin 671e2841179SLoGin fn activate( 672e2841179SLoGin &self, 673e2841179SLoGin _domain: &Arc<IrqDomain>, 674e2841179SLoGin _irq_data: &Arc<IrqData>, 675e2841179SLoGin _reserve: bool, 676e2841179SLoGin ) -> Result<(), SystemError> { 677e2841179SLoGin Err(SystemError::ENOSYS) 678e2841179SLoGin } 679e2841179SLoGin 680e2841179SLoGin fn deactivate(&self, _domain: &Arc<IrqDomain>, _irq_data: &Arc<IrqData>) {} 681ce5850adSLoGin } 682ce5850adSLoGin 683ce5850adSLoGin #[allow(dead_code)] 684ce5850adSLoGin #[derive(Debug)] 685ce5850adSLoGin pub struct IrqDomainChipGeneric { 686ce5850adSLoGin inner: SpinLock<InnerIrqDomainChipGeneric>, 687ce5850adSLoGin } 688ce5850adSLoGin 689ce5850adSLoGin #[allow(dead_code)] 690ce5850adSLoGin #[derive(Debug)] 691ce5850adSLoGin struct InnerIrqDomainChipGeneric { 692ce5850adSLoGin irqs_per_chip: u32, 693ce5850adSLoGin flags_to_clear: IrqGcFlags, 694ce5850adSLoGin flags_to_set: IrqGcFlags, 695ce5850adSLoGin gc_flags: IrqGcFlags, 696ce5850adSLoGin gc: Vec<Arc<IrqChipGeneric>>, 697ce5850adSLoGin } 698