添加irqdesc的抽象,并在系统初始化时创建irqdesc (#522)

* 添加irqdesc的抽象,并在系统初始化时创建irqdesc
This commit is contained in:
LoGin 2024-02-19 00:36:36 +08:00 committed by GitHub
parent ce5850adbf
commit 3bc96fa4a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 702 additions and 19 deletions

View File

@ -1,6 +1,6 @@
use system_error::SystemError;
use crate::exception::{InterruptArch, IrqFlags, IrqFlagsGuard};
use crate::exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber};
pub mod ipi;
@ -35,6 +35,15 @@ impl InterruptArch for RiscV64InterruptArch {
riscv::register::sstatus::clear_sie();
}
}
fn probe_total_irq_num() -> u32 {
// todo: 获取中断总数
256
}
fn ack_bad_irq(irq: IrqNumber) {
todo!("ack_bad_irq: {}", irq.data());
}
}
/// 中断栈帧结构体

View File

@ -12,7 +12,8 @@ use system_error::SystemError;
use crate::{
arch::CurrentIrqArch,
exception::{InterruptArch, IrqFlags, IrqFlagsGuard},
exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber},
kerror,
};
use self::entry::setup_interrupt_gate;
@ -78,6 +79,17 @@ impl InterruptArch for X86_64InterruptArch {
local_irq_restore(flags.flags());
compiler_fence(Ordering::SeqCst);
}
fn probe_total_irq_num() -> u32 {
// todo: 从APIC获取
// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/vector.c?r=&mo=19514&fi=704#704
256
}
fn ack_bad_irq(irq: IrqNumber) {
kerror!("Unexpected IRQ trap at vector {}", irq.data());
CurrentApic.send_eoi();
}
}
/// 中断栈帧结构体

View File

@ -873,3 +873,45 @@ impl DeviceMatcher<&str> for DeviceMatchName {
return device.name() == data;
}
}
/// Cookie to identify the device
#[derive(Debug, Clone)]
pub struct DeviceId {
data: Option<&'static str>,
allocated: Option<String>,
}
impl DeviceId {
#[allow(dead_code)]
pub fn new(data: Option<&'static str>, allocated: Option<String>) -> Option<Self> {
if data.is_none() && allocated.is_none() {
return None;
}
// 如果data和allocated都有值那么返回None
if data.is_some() && allocated.is_some() {
return None;
}
return Some(Self { data, allocated });
}
pub fn id(&self) -> Option<&str> {
if self.data.is_some() {
return Some(self.data.unwrap());
} else {
return self.allocated.as_deref();
}
}
pub fn set_allocated(&mut self, allocated: String) {
self.allocated = Some(allocated);
self.data = None;
}
}
impl PartialEq for DeviceId {
fn eq(&self, other: &Self) -> bool {
return self.id() == other.id();
}
}

View File

@ -0,0 +1,111 @@
use alloc::sync::Arc;
use system_error::SystemError;
use crate::arch::CurrentIrqArch;
use super::{
irqchip::{IrqChip, IrqChipFlags},
irqdata::IrqData,
InterruptArch,
};
static mut NO_IRQ_CHIP: Option<Arc<NoIrqChip>> = None;
static mut DUMMY_IRQ_CHIP: Option<Arc<DummyIrqChip>> = None;
#[inline(never)]
pub fn no_irq_chip() -> Arc<dyn IrqChip> {
unsafe { NO_IRQ_CHIP.as_ref().unwrap().clone() }
}
#[allow(dead_code)]
#[inline(never)]
pub fn dummy_irq_chip() -> Arc<dyn IrqChip> {
unsafe { DUMMY_IRQ_CHIP.as_ref().unwrap().clone() }
}
fn ack_bad(irq_data: &Arc<IrqData>) {
// todo: print_irq_desc
CurrentIrqArch::ack_bad_irq(irq_data.irq());
}
#[derive(Debug)]
struct NoIrqChip;
impl NoIrqChip {
pub const fn new() -> Self {
NoIrqChip
}
}
impl IrqChip for NoIrqChip {
fn name(&self) -> &'static str {
"none"
}
fn irq_enable(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
Ok(())
}
fn irq_disable(&self, _irq: &Arc<IrqData>) {}
fn irq_ack(&self, irq: &Arc<IrqData>) {
ack_bad(irq);
}
fn irq_startup(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
Ok(())
}
fn irq_shutdown(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
Ok(())
}
fn flags(&self) -> IrqChipFlags {
IrqChipFlags::IRQCHIP_SKIP_SET_WAKE
}
}
#[derive(Debug)]
struct DummyIrqChip;
impl DummyIrqChip {
pub const fn new() -> Self {
DummyIrqChip
}
}
impl IrqChip for DummyIrqChip {
fn name(&self) -> &'static str {
"dummy"
}
fn irq_enable(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
Ok(())
}
fn irq_disable(&self, _irq: &Arc<IrqData>) {}
fn irq_ack(&self, _irq: &Arc<IrqData>) {}
fn irq_mask(&self, _irq: &Arc<IrqData>) {}
fn irq_unmask(&self, _irq: &Arc<IrqData>) {}
fn irq_startup(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
Ok(())
}
fn irq_shutdown(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
Ok(())
}
fn flags(&self) -> IrqChipFlags {
IrqChipFlags::IRQCHIP_SKIP_SET_WAKE
}
}
#[inline(never)]
pub fn dummy_chip_init() {
unsafe {
NO_IRQ_CHIP = Some(Arc::new(NoIrqChip::new()));
DUMMY_IRQ_CHIP = Some(Arc::new(DummyIrqChip::new()));
}
}

View File

@ -0,0 +1,27 @@
use alloc::sync::Arc;
use crate::arch::CurrentIrqArch;
use super::{
irqdesc::{IrqDesc, IrqFlowHandler},
InterruptArch,
};
/// 获取用于处理错误的中断的处理程序
#[inline(always)]
pub fn bad_irq_handler() -> &'static dyn IrqFlowHandler {
&HandleBadIrq
}
/// handle spurious and unhandled irqs
#[derive(Debug)]
struct HandleBadIrq;
impl IrqFlowHandler for HandleBadIrq {
/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/handle.c?fi=handle_bad_irq#33
fn handle(&self, irq_desc: &Arc<IrqDesc>) {
// todo: print_irq_desc
// todo: 增加kstat计数
CurrentIrqArch::ack_bad_irq(irq_desc.irq());
}
}

View File

@ -2,13 +2,16 @@ use system_error::SystemError;
use crate::arch::CurrentIrqArch;
use super::InterruptArch;
use super::{dummychip::dummy_chip_init, irqdesc::early_irq_init, InterruptArch};
/// 初始化中断
#[inline(never)]
pub fn irq_init() -> Result<(), SystemError> {
// todo: 通用初始化
dummy_chip_init();
early_irq_init().expect("early_irq_init failed");
// 初始化架构相关的中断
unsafe { CurrentIrqArch::arch_irq_init() }?;
return Ok(());

View File

@ -41,18 +41,18 @@ pub trait IrqChip: Sync + Send + Any + Debug {
fn irq_ack(&self, irq: &Arc<IrqData>);
/// mask an interrupt source
fn irq_mask(&self, irq: &Arc<IrqData>);
fn irq_mask(&self, _irq: &Arc<IrqData>) {}
/// ack and mask an interrupt source
fn irq_mask_ack(&self, irq: &Arc<IrqData>);
fn irq_mask_ack(&self, _irq: &Arc<IrqData>) {}
/// unmask an interrupt source
fn irq_unmask(&self, irq: &Arc<IrqData>);
fn irq_unmask(&self, _irq: &Arc<IrqData>) {}
/// end of interrupt
fn irq_eoi(&self, irq: &Arc<IrqData>);
fn irq_eoi(&self, _irq: &Arc<IrqData>) {}
// todo: set affinity
/// retrigger an IRQ to the CPU
fn retrigger(&self, irq: &Arc<IrqData>);
fn retrigger(&self, _irq: &Arc<IrqData>) {}
/// set the flow type of an interrupt
///
@ -83,14 +83,14 @@ pub trait IrqChip: Sync + Send + Any + Debug {
/// function called from core code on suspend once per
/// chip, when one or more interrupts are installed
fn irq_suspend(&self, irq: &Arc<IrqData>);
fn irq_suspend(&self, _irq: &Arc<IrqData>) {}
/// function called from core code on resume once per chip,
/// when one ore more interrupts are installed
fn irq_resume(&self, irq: &Arc<IrqData>);
fn irq_resume(&self, _irq: &Arc<IrqData>) {}
/// function called from core code on shutdown once per chip
fn irq_pm_shutdown(&self, irq: &Arc<IrqData>);
fn irq_pm_shutdown(&self, _irq: &Arc<IrqData>) {}
/// Optional function to set irq_data.mask for special cases
fn irq_calc_mask(&self, _irq: &Arc<IrqData>) {}
@ -135,7 +135,7 @@ pub trait IrqChip: Sync + Send + Any + Debug {
// todo: set vcpu affinity
/// send a single IPI to destination cpus
fn send_single_ipi(&self, irq: &Arc<IrqData>, cpu: u32);
fn send_single_ipi(&self, _irq: &Arc<IrqData>, _cpu: u32) {}
// todo: send ipi with cpu mask
@ -145,7 +145,9 @@ pub trait IrqChip: Sync + Send + Any + Debug {
}
/// function called from core code after disabling an NMI
fn irq_nmi_teardown(&self, irq: &Arc<IrqData>);
fn irq_nmi_teardown(&self, _irq: &Arc<IrqData>) {}
fn flags(&self) -> IrqChipFlags;
}
#[allow(dead_code)]
@ -214,7 +216,7 @@ struct InnerIrqChipGeneric {
chip_types: Vec<IrqChipType>,
}
pub trait IrqChipGenericOps: Debug {
pub trait IrqChipGenericOps: Debug + Send + Sync {
/// Alternate I/O accessor (defaults to readl if NULL)
unsafe fn reg_readl(&self, addr: VirtAddr) -> u32;
@ -237,3 +239,33 @@ pub trait IrqChipGenericPrivateData: Sync + Send + Any + Debug {}
pub struct IrqChipType {
// todo https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#1024
}
bitflags! {
/// IrqChip specific flags
pub struct IrqChipFlags: u32 {
/// 在调用chip.irq_set_type()之前屏蔽
const IRQCHIP_SET_TYPE_MASKED = 1 << 0;
/// 只有在irq被处理时才发出irq_eoi()
const IRQCHIP_EOI_IF_HANDLED = 1 << 1;
/// 在挂起路径中屏蔽非唤醒irq
const IRQCHIP_MASK_ON_SUSPEND = 1 << 2;
/// 只有在irq启用时才调用irq_on/off_line回调
const IRQCHIP_ONOFFLINE_ENABLED = 1 << 3;
/// 跳过chip.irq_set_wake()对于这个irq芯片
const IRQCHIP_SKIP_SET_WAKE = 1 << 4;
/// 单次触发不需要屏蔽/取消屏蔽
const IRQCHIP_ONESHOT_SAFE = 1 << 5;
/// 芯片在线程模式下需要在取消屏蔽时eoi()
const IRQCHIP_EOI_THREADED = 1 << 6;
/// 芯片可以为Level MSIs提供两个门铃
const IRQCHIP_SUPPORTS_LEVEL_MSI = 1 << 7;
/// 芯片可以传递NMIs仅适用于根irqchips
const IRQCHIP_SUPPORTS_NMI = 1 << 8;
/// 在挂起路径中如果它们处于禁用状态则调用__enable_irq()/__disable_irq()以唤醒irq
const IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND = 1 << 9;
/// 在启动前更新默认亲和性
const IRQCHIP_AFFINITY_PRE_STARTUP = 1 << 10;
/// 不要在这个芯片中改变任何东西
const IRQCHIP_IMMUTABLE = 1 << 11;
}
}

View File

@ -21,6 +21,50 @@ use super::{
pub struct IrqData {
/// 中断号, 用于表示软件逻辑视角的中断号,全局唯一
irq: IrqNumber,
inner: SpinLock<InnerIrqData>,
}
impl IrqData {
pub fn new(
irq: IrqNumber,
hwirq: HardwareIrqNumber,
common_data: Arc<IrqCommonData>,
chip: Arc<dyn IrqChip>,
) -> Self {
return IrqData {
irq,
inner: SpinLock::new(InnerIrqData {
hwirq,
common_data,
chip,
chip_data: None,
domain: None,
parent_data: None,
}),
};
}
pub fn irqd_set(&self, status: IrqStatus) {
// clone是为了释放inner锁
let common_data = self.inner.lock().common_data.clone();
common_data.irqd_set(status);
}
#[allow(dead_code)]
pub fn irqd_clear(&self, status: IrqStatus) {
// clone是为了释放inner锁
let common_data = self.inner.lock().common_data.clone();
common_data.irqd_clear(status);
}
pub fn irq(&self) -> IrqNumber {
self.irq
}
}
#[allow(dead_code)]
#[derive(Debug)]
struct InnerIrqData {
/// 硬件中断号, 用于表示在某个IrqDomain中的中断号
hwirq: HardwareIrqNumber,
/// 涉及的所有irqchip之间共享的数据
@ -28,9 +72,9 @@ pub struct IrqData {
/// 绑定到的中断芯片
chip: Arc<dyn IrqChip>,
/// 中断芯片的私有数据与当前irq相关
chip_data: Arc<dyn IrqChipData>,
chip_data: Option<Arc<dyn IrqChipData>>,
/// 中断域
domain: Arc<IrqDomain>,
domain: Option<Arc<IrqDomain>>,
/// 中断的父中断(如果具有中断域继承的话)
parent_data: Option<Weak<IrqData>>,
}
@ -38,12 +82,32 @@ pub struct IrqData {
/// per irq data shared by all irqchips
///
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#147
#[allow(dead_code)]
#[derive(Debug)]
pub struct IrqCommonData {
inner: SpinLock<InnerIrqCommonData>,
}
impl IrqCommonData {
pub fn new() -> Self {
let inner = InnerIrqCommonData {
state: IrqStatus::empty(),
handler_data: None,
msi_desc: None,
};
return IrqCommonData {
inner: SpinLock::new(inner),
};
}
pub fn irqd_set(&self, status: IrqStatus) {
self.inner.lock_irqsave().irqd_set(status);
}
pub fn irqd_clear(&self, status: IrqStatus) {
self.inner.lock_irqsave().irqd_clear(status);
}
}
#[allow(dead_code)]
#[derive(Debug)]
struct InnerIrqCommonData {
@ -55,6 +119,16 @@ struct InnerIrqCommonData {
// todo: affinity
}
impl InnerIrqCommonData {
pub fn irqd_set(&mut self, status: IrqStatus) {
self.state.insert(status);
}
pub fn irqd_clear(&mut self, status: IrqStatus) {
self.state.remove(status);
}
}
pub trait IrqHandlerData: Send + Sync + Any + Debug {}
bitflags! {

View File

@ -0,0 +1,294 @@
use core::{any::Any, fmt::Debug};
use alloc::{
collections::BTreeMap,
string::String,
sync::{Arc, Weak},
vec::Vec,
};
use system_error::SystemError;
use crate::{
arch::CurrentIrqArch,
driver::base::{
device::DeviceId,
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
kset::KSet,
},
filesystem::kernfs::KernFSInode,
libs::{
rwlock::{RwLockReadGuard, RwLockWriteGuard},
spinlock::{SpinLock, SpinLockGuard},
},
process::ProcessControlBlock,
};
use super::{
dummychip::no_irq_chip,
handle::bad_irq_handler,
irqdata::{IrqCommonData, IrqData, IrqStatus},
sysfs::IrqKObjType,
HardwareIrqNumber, InterruptArch, IrqNumber,
};
/// 中断流处理程序
pub trait IrqFlowHandler: Debug + Send + Sync {
fn handle(&self, irq_desc: &Arc<IrqDesc>);
}
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdesc.h#55
#[derive(Debug)]
pub struct IrqDesc {
inner: SpinLock<InnerIrqDesc>,
handler: SpinLock<Option<&'static dyn IrqFlowHandler>>,
kobj_state: LockedKObjectState,
}
impl IrqDesc {
#[inline(never)]
pub fn new(irq: IrqNumber, name: Option<String>, irqd_flags: IrqStatus) -> Arc<Self> {
// 初始化的过程参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#392
let common_data = Arc::new(IrqCommonData::new());
let irq_data = Arc::new(IrqData::new(
irq,
HardwareIrqNumber::new(irq.data()),
common_data.clone(),
no_irq_chip(),
));
irq_data.irqd_set(IrqStatus::IRQD_IRQ_DISABLED);
common_data.irqd_set(IrqStatus::IRQD_IRQ_MASKED);
let irq_desc = IrqDesc {
inner: SpinLock::new(InnerIrqDesc {
common_data,
irq_data,
actions: Vec::new(),
name,
parent_irq: None,
depth: 1,
wake_depth: 0,
kern_inode: None,
kset: None,
parent_kobj: None,
}),
handler: SpinLock::new(None),
kobj_state: LockedKObjectState::new(Some(KObjectState::INITIALIZED)),
};
irq_desc.set_handler(bad_irq_handler());
irq_desc.inner().irq_data.irqd_set(irqd_flags);
return Arc::new(irq_desc);
}
pub fn set_handler(&self, handler: &'static dyn IrqFlowHandler) {
let mut guard = self.handler.lock_irqsave();
*guard = Some(handler);
}
fn inner(&self) -> SpinLockGuard<InnerIrqDesc> {
self.inner.lock_irqsave()
}
pub fn irq(&self) -> IrqNumber {
self.inner().irq_data.irq()
}
}
#[allow(dead_code)]
#[derive(Debug)]
struct InnerIrqDesc {
/// per irq and chip data passed down to chip functions
common_data: Arc<IrqCommonData>,
irq_data: Arc<IrqData>,
actions: Vec<Arc<IrqAction>>,
name: Option<String>,
parent_irq: Option<IrqNumber>,
/// nested irq disables
depth: u32,
/// nested wake enables
wake_depth: u32,
kern_inode: Option<Arc<KernFSInode>>,
kset: Option<Arc<KSet>>,
parent_kobj: Option<Weak<dyn KObject>>,
}
impl KObject for IrqDesc {
fn as_any_ref(&self) -> &dyn Any {
self
}
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
self.inner().kern_inode = inode;
}
fn inode(&self) -> Option<Arc<KernFSInode>> {
self.inner().kern_inode.clone()
}
fn parent(&self) -> Option<Weak<dyn KObject>> {
self.inner().parent_kobj.clone()
}
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
self.inner().parent_kobj = parent;
}
fn kset(&self) -> Option<Arc<KSet>> {
self.inner().kset.clone()
}
fn set_kset(&self, kset: Option<Arc<KSet>>) {
self.inner().kset = kset;
}
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
Some(&IrqKObjType)
}
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {}
fn name(&self) -> String {
self.inner().name.clone().unwrap_or_else(|| format!(""))
}
fn set_name(&self, _name: String) {}
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
self.kobj_state.read()
}
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
self.kobj_state.write()
}
fn set_kobj_state(&self, state: KObjectState) {
*self.kobj_state_mut() = state;
}
}
/// 每个中断的响应动作的描述符
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/interrupt.h#118
#[allow(dead_code)]
#[derive(Debug)]
pub struct IrqAction {
inner: SpinLock<InnerIrqAction>,
}
impl IrqAction {
#[allow(dead_code)]
pub fn new(
irq: IrqNumber,
name: String,
handler: Option<&'static dyn IrqFlowHandler>,
) -> Arc<Self> {
let action = IrqAction {
inner: SpinLock::new(InnerIrqAction {
dev_id: None,
handler,
thread_fn: None,
thread: None,
secondary: None,
irq,
flags: IrqHandleFlags::empty(),
name,
}),
};
return Arc::new(action);
}
}
#[allow(dead_code)]
#[derive(Debug)]
struct InnerIrqAction {
/// cookie to identify the device
dev_id: Option<DeviceId>,
/// 中断处理程序
handler: Option<&'static dyn IrqFlowHandler>,
/// interrupt handler function for threaded interrupts
thread_fn: Option<&'static dyn IrqFlowHandler>,
/// thread pointer for threaded interrupts
thread: Option<Arc<ProcessControlBlock>>,
/// pointer to secondary irqaction (force threading)
secondary: Option<Arc<IrqAction>>,
/// 中断号
irq: IrqNumber,
flags: IrqHandleFlags,
/// name of the device
name: String,
}
// 定义IrqFlags位标志
bitflags! {
/// 这些标志仅由内核在中断处理例程中使用。
pub struct IrqHandleFlags: u32 {
/// IRQF_SHARED - 允许多个设备共享中断
const IRQF_SHARED = 0x00000080;
/// IRQF_PROBE_SHARED - 当预期出现共享不匹配时,由调用者设置
const IRQF_PROBE_SHARED = 0x00000100;
/// IRQF_TIMER - 标记此中断为定时器中断
const __IRQF_TIMER = 0x00000200;
/// IRQF_PERCPU - 中断是每个CPU的
const IRQF_PERCPU = 0x00000400;
/// IRQF_NOBALANCING - 将此中断从中断平衡中排除
const IRQF_NOBALANCING = 0x00000800;
/// IRQF_IRQPOLL - 中断用于轮询(出于性能原因,只有在共享中断中首次注册的中断会被考虑)
const IRQF_IRQPOLL = 0x00001000;
/// IRQF_ONESHOT - 在硬中断处理程序完成后,不会重新启用中断。由需要在运行线程处理程序之前保持中断线路禁用的线程中断使用。
const IRQF_ONESHOT = 0x00002000;
/// IRQF_NO_SUSPEND - 在挂起期间不禁用此IRQ。不能保证此中断会从挂起状态唤醒系统。
const IRQF_NO_SUSPEND = 0x00004000;
/// IRQF_FORCE_RESUME - 即使设置了IRQF_NO_SUSPEND也强制在恢复时启用它
const IRQF_FORCE_RESUME = 0x00008000;
/// IRQF_NO_THREAD - 中断不能被线程化
const IRQF_NO_THREAD = 0x00010000;
/// IRQF_EARLY_RESUME - 在syscore而不是在设备恢复时间早期恢复IRQ。
const IRQF_EARLY_RESUME = 0x00020000;
/// IRQF_COND_SUSPEND - 如果IRQ与NO_SUSPEND用户共享则在挂起中断后执行此中断处理程序。对于系统唤醒设备用户需要在他们的中断处理程序中实现唤醒检测。
const IRQF_COND_SUSPEND = 0x00040000;
/// IRQF_NO_AUTOEN - 当用户请求时不会自动启用IRQ或NMI。用户稍后会通过enable_irq()或enable_nmi()显式启用它。
const IRQF_NO_AUTOEN = 0x00080000;
/// IRQF_NO_DEBUG - 从IPI和类似处理程序的逃逸检测中排除取决于IRQF_PERCPU。
const IRQF_NO_DEBUG = 0x00100000;
const IRQF_TIMER = Self::__IRQF_TIMER.bits | Self::IRQF_NO_SUSPEND.bits | Self::IRQF_NO_THREAD.bits;
}
}
#[inline(never)]
pub(super) fn early_irq_init() -> Result<(), SystemError> {
let irqcnt = CurrentIrqArch::probe_total_irq_num();
let mut manager = IrqDescManager::new();
for i in 0..irqcnt {
let irq_desc = IrqDesc::new(IrqNumber::new(i), None, IrqStatus::empty());
manager.insert(IrqNumber::new(i), irq_desc);
}
return CurrentIrqArch::arch_early_irq_init();
}
pub(super) struct IrqDescManager {
irq_descs: BTreeMap<IrqNumber, Arc<IrqDesc>>,
}
impl IrqDescManager {
fn new() -> Self {
IrqDescManager {
irq_descs: BTreeMap::new(),
}
}
/// 查找中断描述符
#[allow(dead_code)]
pub fn lookup(&self, irq: IrqNumber) -> Option<Arc<IrqDesc>> {
self.irq_descs.get(&irq).map(|desc| desc.clone())
}
fn insert(&mut self, irq: IrqNumber, desc: Arc<IrqDesc>) {
self.irq_descs.insert(irq, desc);
}
}

View File

@ -145,7 +145,7 @@ pub enum IrqDomainBusToken {
/// IrqDomain的操作方法
///
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#107
pub trait IrqDomainOps: Debug {
pub trait IrqDomainOps: Debug + Send + Sync {
/// 匹配一个中断控制器设备节点到一个主机。
fn match_node(
&self,

View File

@ -2,13 +2,17 @@ use system_error::SystemError;
use crate::arch::CurrentIrqArch;
pub mod dummychip;
pub mod handle;
pub mod init;
pub mod ipi;
pub mod irqchip;
pub mod irqdata;
pub mod irqdesc;
pub mod irqdomain;
pub mod msi;
pub mod softirq;
pub mod sysfs;
/// 中断的架构相关的trait
pub trait InterruptArch: Send + Sync {
@ -24,6 +28,16 @@ pub trait InterruptArch: Send + Sync {
/// 保存当前中断状态,并且禁止中断
unsafe fn save_and_disable_irq() -> IrqFlagsGuard;
unsafe fn restore_irq(flags: IrqFlags);
/// 检测系统支持的中断总数
fn probe_total_irq_num() -> u32;
fn arch_early_irq_init() -> Result<(), SystemError> {
Ok(())
}
/// 响应未注册的中断
fn ack_bad_irq(irq: IrqNumber);
}
#[derive(Debug, Clone, Copy)]

View File

@ -116,7 +116,7 @@ impl MsiDesc {
}
}
pub trait MsiDescFunc: Debug {
pub trait MsiDescFunc: Debug + Send + Sync {
/// Callback that may be called when the MSI message
/// address or data changes.
fn write_msi_msg(&self, data: Arc<dyn MsiDescFuncData>);

View File

@ -0,0 +1,65 @@
use alloc::sync::Arc;
use system_error::SystemError;
use unified_init::macros::unified_init;
use crate::{
driver::base::kobject::{KObjType, KObject, KObjectSysFSOps},
filesystem::{
sysfs::{Attribute, AttributeGroup, SysFSOps},
vfs::syscall::ModeType,
},
init::initcall::INITCALL_POSTCORE,
};
/// 中断描述符的kobjtype
///
/// https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#280
#[derive(Debug)]
pub(super) struct IrqKObjType;
impl KObjType for IrqKObjType {
fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
Some(&KObjectSysFSOps)
}
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&IrqAttrGroup])
}
fn release(&self, _kobj: Arc<dyn KObject>) {
// https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#428
}
}
#[derive(Debug)]
struct IrqAttrGroup;
impl AttributeGroup for IrqAttrGroup {
fn name(&self) -> Option<&str> {
None
}
fn attrs(&self) -> &[&'static dyn Attribute] {
todo!("irq_attr_group.attrs")
// todo: https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#268
}
fn is_visible(
&self,
_kobj: Arc<dyn KObject>,
attr: &'static dyn Attribute,
) -> Option<ModeType> {
Some(attr.mode())
}
}
/// 初始化irq模块在sysfs中的目录
///
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#313
#[unified_init(INITCALL_POSTCORE)]
fn irq_sysfs_init() -> Result<(), SystemError> {
// todo!("irq_sysfs_init");
kwarn!("Unimplemented: irq_sysfs_init");
Ok(())
}