1. 中断处理拆分的必要性
在NPU固件开发中,中断处理的设计直接影响系统性能和响应能力。NPU作为高吞吐量计算设备,其工作特性决定了传统的中断处理方式无法满足需求。
1.1 NPU的工作特点
典型的NPU工作场景:
- 单次推理任务涉及GB级数据搬运
- 需要执行数百万次矩阵运算
- 计算密集型操作占主导
- 多任务并发是常态
这种工作模式对中断处理提出了特殊要求。如果采用简单的轮询方式,CPU资源会被大量浪费在空转等待上。而如果使用同步阻塞等待中断,在多任务环境下会导致系统响应延迟显著增加。
1.2 中断上下文的限制
当CPU响应硬件中断时,会进入中断上下文,此时内核有以下严格限制:
- 禁止睡眠:不能调用任何可能导致调度的函数(如msleep、mutex_lock等)
- 执行时间受限:通常要求处理时间在微秒级别
- 内存分配受限:不能执行可能引起缺页异常的kmalloc操作
- 用户空间交互受限:不能执行copy_to_user等操作
这些限制使得在中断上下文中无法完成复杂的处理任务,特别是NPU这种需要处理大量数据的场景。
2. 顶半部/底半部设计原理
2.1 基本概念
Linux内核采用顶半部(Top Half)和底半部(Bottom Half)的中断处理模型来解决上述问题:
-
顶半部:
- 在中断上下文中执行
- 只做最必要的工作(如确认中断、清除中断标志)
- 必须快速完成(通常在微秒级)
-
底半部:
- 在进程上下文中执行
- 处理耗时的操作(如数据处理、状态更新)
- 可以睡眠、调度、执行复杂内存操作
2.2 NPU驱动中的典型划分
在NPU驱动中,典型的中断处理划分如下:
顶半部工作:
- 确认中断来源(哪个NPU核心触发)
- 读取中断状态寄存器
- 清除中断标志
- 调度底半部处理
底半部工作:
- 处理计算完成的任务结果
- 准备下一批计算数据
- 更新任务状态
- 通知用户空间
3. 底半部实现机制
Linux内核提供了多种底半部实现机制,适用于不同场景。
3.1 软中断(Softirq)
软中断是内核预定义的一种底半部机制,特点如下:
- 执行时机:在中断返回前或ksoftirqd内核线程中
- 执行上下文:仍然算是"软中断上下文",不能睡眠
- 延迟:非常低,通常在毫秒级内执行
- 适用场景:对延迟敏感但不复杂的操作
NPU驱动中可能使用软中断的场景:
- 简单的状态更新
- 快速的数据搬运确认
- 高优先级的中断后续处理
3.2 工作队列(Workqueue)
工作队列是更通用的底半部机制,特点如下:
- 执行时机:由内核工作线程异步执行
- 执行上下文:完全的进程上下文,可以睡眠
- 延迟:
