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}, 14ce5850adSLoGin libs::{rwlock::RwLock, spinlock::SpinLock}, 15ce5850adSLoGin }; 16ce5850adSLoGin 17ce5850adSLoGin use super::{ 18*338f6903SLoGin dummychip::no_irq_chip, 19*338f6903SLoGin irqchip::{IrqChip, IrqChipData, IrqChipGeneric, IrqGcFlags}, 20*338f6903SLoGin irqdata::{IrqData, IrqHandlerData}, 21*338f6903SLoGin irqdesc::IrqFlowHandler, 22ce5850adSLoGin HardwareIrqNumber, IrqNumber, 23ce5850adSLoGin }; 24ce5850adSLoGin 25e2841179SLoGin static mut IRQ_DOMAIN_MANAGER: Option<Arc<IrqDomainManager>> = None; 26e2841179SLoGin 27e2841179SLoGin /// 获取中断域管理器的引用 28e2841179SLoGin #[inline(always)] 29e2841179SLoGin pub fn irq_domain_manager() -> &'static Arc<IrqDomainManager> { 30e2841179SLoGin unsafe { IRQ_DOMAIN_MANAGER.as_ref().unwrap() } 31e2841179SLoGin } 32e2841179SLoGin 33e2841179SLoGin pub(super) fn irq_domain_manager_init() { 34e2841179SLoGin unsafe { 35e2841179SLoGin IRQ_DOMAIN_MANAGER = Some(Arc::new(IrqDomainManager::new())); 36e2841179SLoGin } 37e2841179SLoGin } 38e2841179SLoGin /// 中断域管理器 39e2841179SLoGin pub struct IrqDomainManager { 40e2841179SLoGin domains: SpinLock<Vec<Arc<IrqDomain>>>, 41e2841179SLoGin inner: RwLock<InnerIrqDomainManager>, 42e2841179SLoGin } 43e2841179SLoGin 44e2841179SLoGin impl IrqDomainManager { 45e2841179SLoGin pub fn new() -> IrqDomainManager { 46e2841179SLoGin IrqDomainManager { 47e2841179SLoGin domains: SpinLock::new(Vec::new()), 48e2841179SLoGin inner: RwLock::new(InnerIrqDomainManager { 49e2841179SLoGin default_domain: None, 50e2841179SLoGin }), 51e2841179SLoGin } 52e2841179SLoGin } 53e2841179SLoGin 54*338f6903SLoGin /// 创建一个新的线性映射的irqdomain, 并将其添加到irqdomain管理器中 55*338f6903SLoGin /// 56*338f6903SLoGin /// 创建的irqdomain,中断号是线性的,即从0开始,依次递增 57*338f6903SLoGin /// 58*338f6903SLoGin /// ## 参数 59*338f6903SLoGin /// 60*338f6903SLoGin /// - `name` - 中断域的名字 61*338f6903SLoGin /// - `ops` - 中断域的操作 62*338f6903SLoGin /// - `irq_size` - 中断号的数量 63*338f6903SLoGin #[allow(dead_code)] 64*338f6903SLoGin pub fn create_and_add_linear( 65*338f6903SLoGin &self, 66*338f6903SLoGin name: String, 67*338f6903SLoGin ops: &'static dyn IrqDomainOps, 68*338f6903SLoGin irq_size: u32, 69*338f6903SLoGin ) -> Option<Arc<IrqDomain>> { 70*338f6903SLoGin self.create_and_add( 71*338f6903SLoGin name, 72*338f6903SLoGin ops, 73*338f6903SLoGin IrqNumber::new(0), 74*338f6903SLoGin HardwareIrqNumber::new(0), 75*338f6903SLoGin irq_size, 76*338f6903SLoGin ) 77*338f6903SLoGin } 78*338f6903SLoGin 79e2841179SLoGin /// 创建一个新的irqdomain, 并将其添加到irqdomain管理器中 80e2841179SLoGin /// 81e2841179SLoGin /// ## 参数 82e2841179SLoGin /// 83e2841179SLoGin /// - `name` - 中断域的名字 84e2841179SLoGin /// - `ops` - 中断域的操作 85e2841179SLoGin /// - `first_irq` - 起始软件中断号 86e2841179SLoGin /// - `first_hwirq` - 起始硬件中断号 87e2841179SLoGin /// - `irq_size` - 中断号的数量 88e2841179SLoGin /// 89e2841179SLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdomain.c?fi=__irq_domain_add#139 90e2841179SLoGin pub fn create_and_add( 91e2841179SLoGin &self, 92e2841179SLoGin name: String, 93e2841179SLoGin ops: &'static dyn IrqDomainOps, 94e2841179SLoGin first_irq: IrqNumber, 95e2841179SLoGin first_hwirq: HardwareIrqNumber, 96e2841179SLoGin irq_size: u32, 97e2841179SLoGin ) -> Option<Arc<IrqDomain>> { 98e2841179SLoGin let domain = IrqDomain::new( 99e2841179SLoGin None, 100e2841179SLoGin Some(name), 101e2841179SLoGin ops, 102e2841179SLoGin IrqDomainFlags::NAME_ALLOCATED, 103e2841179SLoGin IrqDomainBusToken::Any, 104e2841179SLoGin first_irq + irq_size, 105e2841179SLoGin first_hwirq + irq_size, 106e2841179SLoGin )?; 107e2841179SLoGin 108e2841179SLoGin self.add_domain(domain.clone()); 109e2841179SLoGin 110e2841179SLoGin self.domain_associate_many(&domain, first_irq, first_hwirq, irq_size); 111e2841179SLoGin 112e2841179SLoGin return Some(domain); 113e2841179SLoGin } 114e2841179SLoGin 115e2841179SLoGin fn add_domain(&self, domain: Arc<IrqDomain>) { 116e2841179SLoGin self.domains.lock_irqsave().push(domain); 117e2841179SLoGin } 118e2841179SLoGin 119e2841179SLoGin #[allow(dead_code)] 120e2841179SLoGin pub fn remove_domain(&self, domain: &Arc<IrqDomain>) { 121e2841179SLoGin let mut domains = self.domains.lock_irqsave(); 122e2841179SLoGin let index = domains 123e2841179SLoGin .iter() 124e2841179SLoGin .position(|x| Arc::ptr_eq(x, domain)) 125e2841179SLoGin .expect("domain not found"); 126e2841179SLoGin domains.remove(index); 127e2841179SLoGin } 128e2841179SLoGin 129e2841179SLoGin /// 获取默认的中断域 130e2841179SLoGin #[allow(dead_code)] 131e2841179SLoGin pub fn default_domain(&self) -> Option<Arc<IrqDomain>> { 132e2841179SLoGin self.inner.read().default_domain.clone() 133e2841179SLoGin } 134e2841179SLoGin 135e2841179SLoGin /// 设置默认的中断域 136e2841179SLoGin /// 137e2841179SLoGin /// 在创建IRQ映射的时候,如果没有指定中断域,就会使用默认的中断域 138e2841179SLoGin pub fn set_default_domain(&self, domain: Arc<IrqDomain>) { 139e2841179SLoGin self.inner.write_irqsave().default_domain = Some(domain); 140e2841179SLoGin } 141e2841179SLoGin 142e2841179SLoGin /// 将指定范围的硬件中断号与软件中断号一一对应的关联起来 143e2841179SLoGin /// 144e2841179SLoGin /// ## 参数 145e2841179SLoGin /// 146e2841179SLoGin /// - `domain` - 中断域 147e2841179SLoGin /// - `first_irq` - 起始软件中断号 148e2841179SLoGin /// - `first_hwirq` - 起始硬件中断号 149e2841179SLoGin /// - `count` - 数量 150e2841179SLoGin pub fn domain_associate_many( 151e2841179SLoGin &self, 152e2841179SLoGin domain: &Arc<IrqDomain>, 153e2841179SLoGin first_irq: IrqNumber, 154e2841179SLoGin first_hwirq: HardwareIrqNumber, 155e2841179SLoGin count: u32, 156e2841179SLoGin ) { 157e2841179SLoGin for i in 0..count { 158e2841179SLoGin if let Err(e) = self.domain_associate(domain, first_irq + i, first_hwirq + i) { 159e2841179SLoGin kwarn!("domain associate failed: {:?}, domain '{:?}' didn't like hwirq {} to virq {} mapping.", e, domain.name(), (first_hwirq + i).data(), (first_irq + i).data()); 160e2841179SLoGin } 161e2841179SLoGin } 162e2841179SLoGin } 163e2841179SLoGin 164e2841179SLoGin /// 将一个硬件中断号与一个软件中断号关联起来 165e2841179SLoGin /// 166e2841179SLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdomain.c#562 167e2841179SLoGin pub fn domain_associate( 168e2841179SLoGin &self, 169e2841179SLoGin domain: &Arc<IrqDomain>, 170e2841179SLoGin irq: IrqNumber, 171e2841179SLoGin hwirq: HardwareIrqNumber, 172e2841179SLoGin ) -> Result<(), SystemError> { 173e2841179SLoGin if hwirq >= domain.revmap.read_irqsave().hwirq_max { 174e2841179SLoGin kwarn!( 175e2841179SLoGin "hwirq {} is out of range for domain {:?}", 176e2841179SLoGin hwirq.data(), 177e2841179SLoGin domain.name() 178e2841179SLoGin ); 179e2841179SLoGin return Err(SystemError::EINVAL); 180e2841179SLoGin } 181e2841179SLoGin let irq_data = irq_desc_manager() 182e2841179SLoGin .lookup(irq) 183e2841179SLoGin .ok_or_else(|| { 184e2841179SLoGin kwarn!("irq_desc not found for irq {}", irq.data()); 185e2841179SLoGin SystemError::EINVAL 186e2841179SLoGin })? 187e2841179SLoGin .irq_data(); 188e2841179SLoGin if irq_data.domain().is_some() { 189e2841179SLoGin kwarn!( 190e2841179SLoGin "irq {} is already associated with domain {:?}", 191e2841179SLoGin irq.data(), 192e2841179SLoGin irq_data.domain().unwrap().name() 193e2841179SLoGin ); 194e2841179SLoGin return Err(SystemError::EINVAL); 195e2841179SLoGin } 196e2841179SLoGin 197e2841179SLoGin let mut irq_data_guard = irq_data.inner(); 198e2841179SLoGin irq_data_guard.set_hwirq(hwirq); 199e2841179SLoGin irq_data_guard.set_domain(Some(domain.clone())); 200e2841179SLoGin drop(irq_data_guard); 201e2841179SLoGin let r = domain.ops.map(&domain, hwirq, irq); 202e2841179SLoGin if let Err(e) = r { 203e2841179SLoGin if e != SystemError::ENOSYS { 204e2841179SLoGin if e != SystemError::EPERM { 205e2841179SLoGin kinfo!("domain associate failed: {:?}, domain '{:?}' didn't like hwirq {} to virq {} mapping.", e, domain.name(), hwirq.data(), irq.data()); 206e2841179SLoGin } 207e2841179SLoGin let mut irq_data_guard = irq_data.inner(); 208e2841179SLoGin irq_data_guard.set_domain(None); 209e2841179SLoGin irq_data_guard.set_hwirq(HardwareIrqNumber::new(0)); 210e2841179SLoGin return Err(e); 211e2841179SLoGin } 212e2841179SLoGin } 213e2841179SLoGin 214e2841179SLoGin if domain.name().is_none() { 215e2841179SLoGin let chip = irq_data.chip_info_read_irqsave().chip(); 216e2841179SLoGin domain.set_name(chip.name().to_string()); 217e2841179SLoGin } 218e2841179SLoGin 219e2841179SLoGin self.irq_domain_set_mapping(&domain, hwirq, irq_data); 220e2841179SLoGin 221e2841179SLoGin irq_manager().irq_clear_status_flags(irq, IrqLineStatus::IRQ_NOREQUEST)?; 222e2841179SLoGin 223e2841179SLoGin return Ok(()); 224e2841179SLoGin } 225e2841179SLoGin 226e2841179SLoGin fn irq_domain_set_mapping( 227e2841179SLoGin &self, 228e2841179SLoGin domain: &Arc<IrqDomain>, 229e2841179SLoGin hwirq: HardwareIrqNumber, 230e2841179SLoGin irq_data: Arc<IrqData>, 231e2841179SLoGin ) { 232e2841179SLoGin if domain.no_map() { 233e2841179SLoGin return; 234e2841179SLoGin } 235e2841179SLoGin 236e2841179SLoGin domain.revmap.write_irqsave().insert(hwirq, irq_data); 237e2841179SLoGin } 238e2841179SLoGin /// 递归调用 domain_ops->activate 以激活中断 239e2841179SLoGin /// 240e2841179SLoGin /// ## 参数 241e2841179SLoGin /// 242e2841179SLoGin /// - irq_data: 与中断关联的最外层 irq_data 243e2841179SLoGin /// - reserve: 如果为true,则仅预留一个中断向量,而不是分配一个 244e2841179SLoGin /// 245e2841179SLoGin /// 这是调用 domain_ops->activate 以编程中断控制器的第二步,以便中断实际上可以被传递。 246e2841179SLoGin pub fn activate_irq(&self, irq_data: &Arc<IrqData>, reserve: bool) -> Result<(), SystemError> { 247e2841179SLoGin let mut r = Ok(()); 248e2841179SLoGin if !irq_data.common_data().status().is_activated() { 249e2841179SLoGin r = self.do_activate_irq(Some(irq_data.clone()), reserve); 250e2841179SLoGin } 251e2841179SLoGin 252e2841179SLoGin if !r.is_ok() { 253e2841179SLoGin irq_data.common_data().status().set_activated(); 254e2841179SLoGin } 255e2841179SLoGin 256e2841179SLoGin return r; 257e2841179SLoGin } 258e2841179SLoGin 259e2841179SLoGin #[inline(never)] 260e2841179SLoGin fn do_activate_irq( 261e2841179SLoGin &self, 262e2841179SLoGin irq_data: Option<Arc<IrqData>>, 263e2841179SLoGin reserve: bool, 264e2841179SLoGin ) -> Result<(), SystemError> { 265e2841179SLoGin let mut r = Ok(()); 266e2841179SLoGin 267e2841179SLoGin if irq_data.is_some() && irq_data.as_ref().unwrap().domain().is_some() { 268e2841179SLoGin let domain = irq_data.as_ref().unwrap().domain().unwrap(); 269e2841179SLoGin 270e2841179SLoGin let irq_data = irq_data.unwrap(); 271e2841179SLoGin 272e2841179SLoGin let parent_data = irq_data.parent_data().map(|x| x.upgrade()).flatten(); 273e2841179SLoGin if let Some(parent_data) = parent_data.clone() { 274e2841179SLoGin r = self.do_activate_irq(Some(parent_data), reserve); 275e2841179SLoGin } 276e2841179SLoGin 277e2841179SLoGin if r.is_err() { 278e2841179SLoGin let tmpr = domain.ops.activate(&domain, &irq_data, reserve); 279e2841179SLoGin if let Err(e) = tmpr { 280e2841179SLoGin if e != SystemError::ENOSYS && parent_data.is_some() { 281e2841179SLoGin self.do_deactivate_irq(parent_data); 282e2841179SLoGin } 283e2841179SLoGin } 284e2841179SLoGin } 285e2841179SLoGin } 286e2841179SLoGin 287e2841179SLoGin return r; 288e2841179SLoGin } 289e2841179SLoGin 290e2841179SLoGin fn do_deactivate_irq(&self, irq_data: Option<Arc<IrqData>>) { 291e2841179SLoGin if let Some(irq_data) = irq_data { 292e2841179SLoGin if let Some(domain) = irq_data.domain() { 293e2841179SLoGin domain.ops.deactivate(&domain, &irq_data); 294e2841179SLoGin let pp = irq_data.parent_data().map(|x| x.upgrade()).flatten(); 295e2841179SLoGin 296e2841179SLoGin if pp.is_some() { 297e2841179SLoGin self.do_deactivate_irq(pp); 298e2841179SLoGin } 299e2841179SLoGin } 300e2841179SLoGin } 301e2841179SLoGin } 302*338f6903SLoGin 303*338f6903SLoGin /// `irq_domain_set_info` - 在 @domain 中为 @virq 设置完整的数据 304*338f6903SLoGin /// 305*338f6903SLoGin /// ## 参数 306*338f6903SLoGin /// 307*338f6903SLoGin /// - `domain`: 要匹配的中断域 308*338f6903SLoGin /// - `virq`: IRQ号 309*338f6903SLoGin /// - `hwirq`: 硬件中断号 310*338f6903SLoGin /// - `chip`: 相关的中断芯片 311*338f6903SLoGin /// - `chip_data`: 相关的中断芯片数据 312*338f6903SLoGin /// - `handler`: 中断流处理器 313*338f6903SLoGin /// - `handler_data`: 中断流处理程序数据 314*338f6903SLoGin /// - `handler_name`: 中断处理程序名称 315*338f6903SLoGin pub fn domain_set_info( 316*338f6903SLoGin &self, 317*338f6903SLoGin domain: &Arc<IrqDomain>, 318*338f6903SLoGin virq: IrqNumber, 319*338f6903SLoGin hwirq: HardwareIrqNumber, 320*338f6903SLoGin chip: Arc<dyn IrqChip>, 321*338f6903SLoGin chip_data: Option<Arc<dyn IrqChipData>>, 322*338f6903SLoGin flow_handler: &'static dyn IrqFlowHandler, 323*338f6903SLoGin handler_data: Option<Arc<dyn IrqHandlerData>>, 324*338f6903SLoGin handler_name: Option<String>, 325*338f6903SLoGin ) { 326*338f6903SLoGin let r = self.domain_set_hwirq_and_chip(domain, virq, hwirq, Some(chip), chip_data); 327*338f6903SLoGin if r.is_err() { 328*338f6903SLoGin return; 329*338f6903SLoGin } 330*338f6903SLoGin irq_manager().__irq_set_handler(virq, flow_handler, false, handler_name); 331*338f6903SLoGin irq_manager().irq_set_handler_data(virq, handler_data).ok(); 332*338f6903SLoGin } 333*338f6903SLoGin 334*338f6903SLoGin /// `domain_set_hwirq_and_chip` - 在 @domain 中为 @virq 设置 hwirq 和 irqchip 335*338f6903SLoGin /// 336*338f6903SLoGin /// ## 参数 337*338f6903SLoGin /// 338*338f6903SLoGin /// - `domain`: 要匹配的中断域 339*338f6903SLoGin /// - `virq`: IRQ号 340*338f6903SLoGin /// - `hwirq`: hwirq号 341*338f6903SLoGin /// - `chip`: 相关的中断芯片 342*338f6903SLoGin /// - `chip_data`: 相关的芯片数据 343*338f6903SLoGin pub fn domain_set_hwirq_and_chip( 344*338f6903SLoGin &self, 345*338f6903SLoGin domain: &Arc<IrqDomain>, 346*338f6903SLoGin virq: IrqNumber, 347*338f6903SLoGin hwirq: HardwareIrqNumber, 348*338f6903SLoGin chip: Option<Arc<dyn IrqChip>>, 349*338f6903SLoGin chip_data: Option<Arc<dyn IrqChipData>>, 350*338f6903SLoGin ) -> Result<(), SystemError> { 351*338f6903SLoGin let irq_data: Arc<IrqData> = self 352*338f6903SLoGin .domain_get_irq_data(domain, virq) 353*338f6903SLoGin .ok_or(SystemError::ENOENT)?; 354*338f6903SLoGin let mut inner = irq_data.inner(); 355*338f6903SLoGin let mut chip_info = irq_data.chip_info_write_irqsave(); 356*338f6903SLoGin 357*338f6903SLoGin inner.set_hwirq(hwirq); 358*338f6903SLoGin if let Some(chip) = chip { 359*338f6903SLoGin chip_info.set_chip(Some(chip)); 360*338f6903SLoGin } else { 361*338f6903SLoGin chip_info.set_chip(Some(no_irq_chip())); 362*338f6903SLoGin }; 363*338f6903SLoGin 364*338f6903SLoGin chip_info.set_chip_data(chip_data); 365*338f6903SLoGin 366*338f6903SLoGin return Ok(()); 367*338f6903SLoGin } 368*338f6903SLoGin 369*338f6903SLoGin /// `irq_domain_get_irq_data` - 获取与 @virq 和 @domain 关联的 irq_data 370*338f6903SLoGin /// 371*338f6903SLoGin /// ## 参数 372*338f6903SLoGin /// 373*338f6903SLoGin /// - `domain`: 要匹配的域 374*338f6903SLoGin /// - `virq`: 要获取 irq_data 的IRQ号 375*338f6903SLoGin pub fn domain_get_irq_data( 376*338f6903SLoGin &self, 377*338f6903SLoGin domain: &Arc<IrqDomain>, 378*338f6903SLoGin virq: IrqNumber, 379*338f6903SLoGin ) -> Option<Arc<IrqData>> { 380*338f6903SLoGin let desc = irq_desc_manager().lookup(virq)?; 381*338f6903SLoGin let mut irq_data = Some(desc.irq_data()); 382*338f6903SLoGin 383*338f6903SLoGin while irq_data.is_some() { 384*338f6903SLoGin let dt = irq_data.unwrap(); 385*338f6903SLoGin if dt.domain().is_some() && Arc::ptr_eq(dt.domain().as_ref().unwrap(), domain) { 386*338f6903SLoGin return Some(dt); 387*338f6903SLoGin } 388*338f6903SLoGin irq_data = dt.parent_data().map(|x| x.upgrade()).flatten(); 389*338f6903SLoGin } 390*338f6903SLoGin 391*338f6903SLoGin return None; 392*338f6903SLoGin } 393e2841179SLoGin } 394e2841179SLoGin 395e2841179SLoGin struct InnerIrqDomainManager { 396e2841179SLoGin default_domain: Option<Arc<IrqDomain>>, 397e2841179SLoGin } 398e2841179SLoGin 399ce5850adSLoGin /// 中断域 400ce5850adSLoGin /// 401ce5850adSLoGin /// 用于把硬件中断号翻译为软件中断号的映射的对象 402ce5850adSLoGin /// 403ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#164 404ce5850adSLoGin #[allow(dead_code)] 405ce5850adSLoGin #[derive(Debug)] 406ce5850adSLoGin pub struct IrqDomain { 407ce5850adSLoGin /// 中断域的名字 (二选一) 408ce5850adSLoGin name: Option<&'static str>, 409e2841179SLoGin allocated_name: SpinLock<Option<String>>, 410ce5850adSLoGin /// 中断域的操作 411ce5850adSLoGin ops: &'static dyn IrqDomainOps, 412ce5850adSLoGin inner: SpinLock<InnerIrqDomain>, 413ce5850adSLoGin /// 中断号反向映射 414ce5850adSLoGin revmap: RwLock<IrqDomainRevMap>, 415ce5850adSLoGin } 416ce5850adSLoGin 417ce5850adSLoGin #[allow(dead_code)] 418ce5850adSLoGin #[derive(Debug)] 419ce5850adSLoGin struct InnerIrqDomain { 420*338f6903SLoGin /// this field not touched by the core code 421*338f6903SLoGin host_data: Option<Arc<dyn IrqChipData>>, 422ce5850adSLoGin /// host per irq_domain flags 423ce5850adSLoGin flags: IrqDomainFlags, 424ce5850adSLoGin /// The number of mapped interrupts 425ce5850adSLoGin mapcount: u32, 426ce5850adSLoGin bus_token: IrqDomainBusToken, 427ce5850adSLoGin /// 指向 generic chip 列表的指针。 428ce5850adSLoGin /// 有一个辅助函数用于为中断控制器驱动程序设置一个或 429ce5850adSLoGin /// 多个 generic chip,该函数使用此指针并依赖于 generic chip 库。 430ce5850adSLoGin generic_chip: Option<Arc<IrqDomainChipGeneric>>, 431ce5850adSLoGin /// Pointer to a device that the domain represent, and that will be 432ce5850adSLoGin /// used for power management purposes. 433ce5850adSLoGin device: Option<Arc<dyn Device>>, 434ce5850adSLoGin /// Pointer to parent irq_domain to support hierarchy irq_domains 435ce5850adSLoGin parent: Option<Weak<IrqDomain>>, 436ce5850adSLoGin } 437ce5850adSLoGin 438ce5850adSLoGin impl IrqDomain { 439ce5850adSLoGin #[allow(dead_code)] 440ce5850adSLoGin pub fn new( 441ce5850adSLoGin name: Option<&'static str>, 442ce5850adSLoGin allocated_name: Option<String>, 443ce5850adSLoGin ops: &'static dyn IrqDomainOps, 444ce5850adSLoGin flags: IrqDomainFlags, 445ce5850adSLoGin bus_token: IrqDomainBusToken, 446e2841179SLoGin irq_max: IrqNumber, 447e2841179SLoGin hwirq_max: HardwareIrqNumber, 448ce5850adSLoGin ) -> Option<Arc<Self>> { 449ce5850adSLoGin if name.is_none() && allocated_name.is_none() { 450ce5850adSLoGin return None; 451ce5850adSLoGin } 452ce5850adSLoGin 453ce5850adSLoGin let x = IrqDomain { 454ce5850adSLoGin name, 455e2841179SLoGin allocated_name: SpinLock::new(allocated_name), 456ce5850adSLoGin ops, 457ce5850adSLoGin inner: SpinLock::new(InnerIrqDomain { 458*338f6903SLoGin host_data: None, 459ce5850adSLoGin flags, 460ce5850adSLoGin mapcount: 0, 461ce5850adSLoGin bus_token, 462ce5850adSLoGin generic_chip: None, 463ce5850adSLoGin device: None, 464ce5850adSLoGin parent: None, 465ce5850adSLoGin }), 466ce5850adSLoGin revmap: RwLock::new(IrqDomainRevMap { 467ce5850adSLoGin map: HashMap::new(), 468e2841179SLoGin hwirq_max, 469e2841179SLoGin irq_max, 470ce5850adSLoGin }), 471ce5850adSLoGin }; 472ce5850adSLoGin 473ce5850adSLoGin return Some(Arc::new(x)); 474ce5850adSLoGin } 475e2841179SLoGin 476e2841179SLoGin /// 中断域是否不对中断号进行转换 477e2841179SLoGin pub fn no_map(&self) -> bool { 478e2841179SLoGin self.inner 479e2841179SLoGin .lock_irqsave() 480e2841179SLoGin .flags 481e2841179SLoGin .contains(IrqDomainFlags::NO_MAP) 482e2841179SLoGin } 483e2841179SLoGin 484e2841179SLoGin #[allow(dead_code)] 485e2841179SLoGin fn set_hwirq_max(&self, hwirq_max: HardwareIrqNumber) { 486e2841179SLoGin self.revmap.write_irqsave().hwirq_max = hwirq_max; 487e2841179SLoGin } 488e2841179SLoGin 489e2841179SLoGin pub fn name(&self) -> Option<String> { 490e2841179SLoGin if let Some(name) = self.name { 491e2841179SLoGin return Some(name.to_string()); 492e2841179SLoGin } 493e2841179SLoGin return self.allocated_name.lock_irqsave().clone(); 494e2841179SLoGin } 495e2841179SLoGin 496e2841179SLoGin pub fn set_name(&self, name: String) { 497e2841179SLoGin *self.allocated_name.lock_irqsave() = Some(name); 498e2841179SLoGin } 499e2841179SLoGin 500e2841179SLoGin /// The number of mapped interrupts 501e2841179SLoGin pub fn map_count(&self) -> u32 { 502e2841179SLoGin self.revmap.read().map.len() as u32 503e2841179SLoGin } 504*338f6903SLoGin 505*338f6903SLoGin pub fn host_data(&self) -> Option<Arc<dyn IrqChipData>> { 506*338f6903SLoGin self.inner.lock_irqsave().host_data.clone() 507*338f6903SLoGin } 508*338f6903SLoGin 509*338f6903SLoGin pub fn set_host_data(&self, host_data: Option<Arc<dyn IrqChipData>>) { 510*338f6903SLoGin self.inner.lock_irqsave().host_data = host_data; 511*338f6903SLoGin } 512ce5850adSLoGin } 513ce5850adSLoGin 514ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#190 515ce5850adSLoGin #[allow(dead_code)] 516ce5850adSLoGin #[derive(Debug)] 517ce5850adSLoGin struct IrqDomainRevMap { 518e2841179SLoGin map: HashMap<HardwareIrqNumber, Arc<IrqData>>, 519ce5850adSLoGin hwirq_max: HardwareIrqNumber, 520e2841179SLoGin irq_max: IrqNumber, 521e2841179SLoGin } 522e2841179SLoGin 523e2841179SLoGin impl IrqDomainRevMap { 524e2841179SLoGin fn insert(&mut self, hwirq: HardwareIrqNumber, irq_data: Arc<IrqData>) { 525e2841179SLoGin self.map.insert(hwirq, irq_data); 526e2841179SLoGin } 527e2841179SLoGin 528e2841179SLoGin #[allow(dead_code)] 529e2841179SLoGin fn remove(&mut self, hwirq: HardwareIrqNumber) { 530e2841179SLoGin self.map.remove(&hwirq); 531e2841179SLoGin } 532e2841179SLoGin 533e2841179SLoGin #[allow(dead_code)] 534e2841179SLoGin fn lookup(&self, hwirq: HardwareIrqNumber) -> Option<Arc<IrqData>> { 535e2841179SLoGin self.map.get(&hwirq).cloned() 536e2841179SLoGin } 537ce5850adSLoGin } 538ce5850adSLoGin 539ce5850adSLoGin bitflags! { 540ce5850adSLoGin pub struct IrqDomainFlags: u32 { 541ce5850adSLoGin /// Irq domain is hierarchical 542ce5850adSLoGin const HIERARCHY = (1 << 0); 543ce5850adSLoGin /// Irq domain name was allocated dynamically 544ce5850adSLoGin const NAME_ALLOCATED = (1 << 1); 545ce5850adSLoGin /// Irq domain is an IPI domain with virq per cpu 546ce5850adSLoGin const IPI_PER_CPU = (1 << 2); 547ce5850adSLoGin /// Irq domain is an IPI domain with single virq 548ce5850adSLoGin const IPI_SINGLE = (1 << 3); 549ce5850adSLoGin /// Irq domain implements MSIs 550ce5850adSLoGin const MSI = (1 << 4); 551ce5850adSLoGin /// Irq domain implements MSI remapping 552ce5850adSLoGin const MSI_REMAP = (1 << 5); 553ce5850adSLoGin /// Quirk to handle MSI implementations which do not provide masking 554ce5850adSLoGin const MSI_NOMASK_QUIRK = (1 << 6); 555ce5850adSLoGin /// Irq domain doesn't translate anything 556ce5850adSLoGin const NO_MAP = (1 << 7); 557ce5850adSLoGin /// Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved 558ce5850adSLoGin /// for implementation specific purposes and ignored by the core code 559ce5850adSLoGin const NONCORE = (1 << 16); 560ce5850adSLoGin } 561ce5850adSLoGin } 562ce5850adSLoGin 563ce5850adSLoGin /// 如果多个域有相同的设备节点,但服务于不同的目的(例如,一个域用于PCI/MSI,另一个用于有线IRQs), 564ce5850adSLoGin /// 它们可以使用特定于总线的token进行区分。预计大多数域只会携带`DomainBusAny`。 565ce5850adSLoGin /// 566ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#78 567ce5850adSLoGin #[allow(dead_code)] 568ce5850adSLoGin #[derive(Debug, Clone, Copy, PartialEq, Eq)] 569ce5850adSLoGin pub enum IrqDomainBusToken { 570ce5850adSLoGin Any = 0, 571ce5850adSLoGin Wired, 572ce5850adSLoGin GenericMsi, 573ce5850adSLoGin PciMsi, 574ce5850adSLoGin PlatformMsi, 575ce5850adSLoGin Nexus, 576ce5850adSLoGin Ipi, 577ce5850adSLoGin FslMcMsi, 578ce5850adSLoGin TiSciIntaMsi, 579ce5850adSLoGin Wakeup, 580ce5850adSLoGin VmdMsi, 581ce5850adSLoGin } 582ce5850adSLoGin 583ce5850adSLoGin /// IrqDomain的操作方法 584ce5850adSLoGin /// 585ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#107 5863bc96fa4SLoGin pub trait IrqDomainOps: Debug + Send + Sync { 587ce5850adSLoGin /// 匹配一个中断控制器设备节点到一个主机。 588ce5850adSLoGin fn match_node( 589ce5850adSLoGin &self, 590*338f6903SLoGin _irq_domain: &Arc<IrqDomain>, 591*338f6903SLoGin _device_node: &Arc<DeviceNode>, 592*338f6903SLoGin _bus_token: IrqDomainBusToken, 593*338f6903SLoGin ) -> bool { 594*338f6903SLoGin false 595*338f6903SLoGin } 596ce5850adSLoGin 597ce5850adSLoGin /// 创建或更新一个虚拟中断号与一个硬件中断号之间的映射。 598ce5850adSLoGin /// 对于给定的映射,这只会被调用一次。 599e2841179SLoGin /// 600e2841179SLoGin /// 如果没有实现这个方法,那么就会返回`ENOSYS` 601ce5850adSLoGin fn map( 602ce5850adSLoGin &self, 603e2841179SLoGin _irq_domain: &Arc<IrqDomain>, 604e2841179SLoGin _hwirq: HardwareIrqNumber, 605e2841179SLoGin _virq: IrqNumber, 606e2841179SLoGin ) -> Result<(), SystemError> { 607e2841179SLoGin Err(SystemError::ENOSYS) 608e2841179SLoGin } 609ce5850adSLoGin 610ce5850adSLoGin /// 删除一个虚拟中断号与一个硬件中断号之间的映射。 611ce5850adSLoGin fn unmap(&self, irq_domain: &Arc<IrqDomain>, virq: IrqNumber); 612e2841179SLoGin 613e2841179SLoGin fn activate( 614e2841179SLoGin &self, 615e2841179SLoGin _domain: &Arc<IrqDomain>, 616e2841179SLoGin _irq_data: &Arc<IrqData>, 617e2841179SLoGin _reserve: bool, 618e2841179SLoGin ) -> Result<(), SystemError> { 619e2841179SLoGin Err(SystemError::ENOSYS) 620e2841179SLoGin } 621e2841179SLoGin 622e2841179SLoGin fn deactivate(&self, _domain: &Arc<IrqDomain>, _irq_data: &Arc<IrqData>) {} 623ce5850adSLoGin } 624ce5850adSLoGin 625ce5850adSLoGin #[allow(dead_code)] 626ce5850adSLoGin #[derive(Debug)] 627ce5850adSLoGin pub struct IrqDomainChipGeneric { 628ce5850adSLoGin inner: SpinLock<InnerIrqDomainChipGeneric>, 629ce5850adSLoGin } 630ce5850adSLoGin 631ce5850adSLoGin #[allow(dead_code)] 632ce5850adSLoGin #[derive(Debug)] 633ce5850adSLoGin struct InnerIrqDomainChipGeneric { 634ce5850adSLoGin irqs_per_chip: u32, 635ce5850adSLoGin flags_to_clear: IrqGcFlags, 636ce5850adSLoGin flags_to_set: IrqGcFlags, 637ce5850adSLoGin gc_flags: IrqGcFlags, 638ce5850adSLoGin gc: Vec<Arc<IrqChipGeneric>>, 639ce5850adSLoGin } 640