linux中断调用流程(arm)

文章目录

      • [ARM架构下Linux中断处理全流程解析:从硬件触发到驱动调用 ⚡](#ARM架构下Linux中断处理全流程解析:从硬件触发到驱动调用 ⚡)
        • [**一、中断触发与硬件层响应** 🔌](#一、中断触发与硬件层响应 🔌)
          • [**1. 设备触发中断** 📡](#1. 设备触发中断 📡)
        • [**二、CPU阶段:异常入口与上下文处理** 🖥️](#二、CPU阶段:异常入口与上下文处理 🖥️)
          • [**1. 异常模式切换** 🔄](#1. 异常模式切换 🔄)
          • [**2. 跳转至中断向量表** 🗺️](#2. 跳转至中断向量表 🗺️)
        • [**三、内核中断处理框架** ⚙️](#三、内核中断处理框架 ⚙️)
          • [**1. 中断向量表初始化** 📜](#1. 中断向量表初始化 📜)
          • [**2. 中断控制器驱动注册** 🔧](#2. 中断控制器驱动注册 🔧)
          • [**3. 中断分发与设备处理** 🔀](#3. 中断分发与设备处理 🔀)
        • [**四、设备驱动中的中断处理流程** 🛠️](#四、设备驱动中的中断处理流程 🛠️)
          • [**1. 驱动注册中断处理函数** 📝](#1. 驱动注册中断处理函数 📝)
          • [**2. 实现中断处理函数** 🛠️](#2. 实现中断处理函数 🛠️)
          • [**3. 释放中断资源** 🗑️](#3. 释放中断资源 🗑️)
        • [**五、示例:网卡中断处理全流程** 🌐](#五、示例:网卡中断处理全流程 🌐)
        • [**六、关键数据结构与机制** 📊](#六、关键数据结构与机制 📊)

ARM架构下Linux中断处理全流程解析:从硬件触发到驱动调用 ⚡


一、中断触发与硬件层响应 🔌
1. 设备触发中断 📡

当外设(如网卡、键盘)需要CPU处理时,其硬件控制器会通过物理中断线(IRQ)向中断控制器发送信号。以ARM的通用中断控制器(GICv3)为例:

  • 中断接收 :GIC Distributor模块接收中断请求,并根据中断类型(SPI/PPI/SGI)分类。
    🛠️ 关键点:SPI用于共享外设中断,PPI为CPU私有中断。
  • 优先级仲裁 :Distributor根据中断优先级(配置于寄存器GICD_IPRIORITYRn)和屏蔽状态,选择最高优先级中断。
    ⚖️ 优先级规则:数值越小优先级越高,0为最高。
  • 路由到目标CPU :通过Redistributor模块将中断传递给目标CPU核心(支持多核负载均衡)。
    🌐 多核优化:避免单核过载,提升系统吞吐量。
  • 物理信号触发 :GIC通过CPU的IRQ引脚触发异常模式切换。
    信号传递:硬件自动完成,无需软件干预。

二、CPU阶段:异常入口与上下文处理 🖥️
1. 异常模式切换 🔄

CPU收到中断信号后,硬件自动完成以下操作:

  • 保存上下文 :将当前程序状态(PSTATEPCSP等)压入内核栈。
    📦 关键寄存器:包括通用寄存器、程序计数器、栈指针。
  • 切换异常级别
    • 用户态(EL0)→ 内核态(EL1) :触发完整的上下文切换。
      🔒 安全隔离:防止用户程序直接访问内核资源。
    • 内核态(EL1)→ EL1 :仅保存关键寄存器,复用当前内核栈。
      快速路径:减少模式切换开销。
2. 跳转至中断向量表 🗺️
  • 向量表基址 :由寄存器VBAR_EL1指定,指向内核预定义的向量表(arch/arm64/kernel/entry.S)。
    🏷️ 配置时机 :内核启动时通过set_vbar()初始化。
  • 入口偏移计算
    • IRQ入口VBAR_EL1 + 0x280(EL1h模式)。
      🔍 偏移规则:每种异常类型有固定偏移量。
    • 同步异常入口VBAR_EL1 + 0x400(用于系统调用)。
      📌 示例 :系统调用通过svc指令触发同步异常。
assembly 复制代码
// arch/arm64/kernel/entry.S
kernel_ventry 1, irq       // EL1h模式IRQ入口

三、内核中断处理框架 ⚙️
1. 中断向量表初始化 📜

ARM64的中断向量表通过汇编宏kernel_ventry定义,每个条目对应一种异常类型:

  • IRQ处理入口 :最终调用handle_arch_irq(全局函数指针)。
    🔗 跳转逻辑:从汇编跳转到C语言函数。

  • 关键汇编跳转

    assembly 复制代码
    irq_handler:
        bl    handle_arch_irq   // 跳转到C语言处理函数
2. 中断控制器驱动注册 🔧

以GIC驱动为例,初始化时完成中断处理函数的绑定:

c 复制代码
// drivers/irqchip/irq-gic.c
void __init gic_init(...) {
    gic_dist_init(gic);       // 初始化Distributor
    gic_cpu_init(gic);        // 初始化CPU Interface
    set_handle_irq(gic_handle_irq);  // 注册全局处理函数
}
  • set_handle_irq :将gic_handle_irq赋值给handle_arch_irq,建立汇编到C的桥梁。
    🌉 桥梁作用:屏蔽硬件差异,统一中断入口。
3. 中断分发与设备处理 🔀

GIC驱动通过gic_handle_irq读取中断号并分发给设备驱动:

c 复制代码
static void __exception_irq_entry gic_handle_irq(...) {
    u32 irqnr = gic_read_iar();      // 读取GIC中断应答寄存器
    handle_domain_irq(gic_data.domain, irqnr, regs);  // 映射并处理
}

c 复制代码
// kernel/irq/irqdesc.c
int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq,
                        bool lookup, struct pt_regs *regs) {
    ...
    irq_enter();  // 进入中断上下文
    irq = irq_find_mapping(domain, hwirq);  // 硬件中断号映射为虚拟中断号
    if (irq合法) {
        generic_handle_irq(irq);  // 调用中断处理链
    } else {
        ack_bad_irq(irq);        // 错误处理
    }
    irq_exit();  // 退出中断上下文
    ...
}
  • handle_domain_irq的核心作用
    1. 中断上下文标记irq_enter()进入原子上下文,禁用调度。
      🚫 禁止行为:禁止睡眠、内存分配等非原子操作。
    2. 硬件中断号映射 :通过irq_domain将硬件IRQ转换为Linux虚拟IRQ。
      🗂️ 映射策略:支持线性映射、树映射等多种方式。
    3. 调用设备ISR :从irq_desc[].action链表中执行驱动注册的中断处理函数。
      快速响应:上半部处理时间通常小于1ms。

四、设备驱动中的中断处理流程 🛠️
1. 驱动注册中断处理函数 📝

设备驱动通过request_irq注册中断服务例程(ISR):

c 复制代码
int request_irq(unsigned int irq, irq_handler_t handler, 
               unsigned long flags, const char *name, void *dev);
  • 参数说明
    • irq:虚拟中断号(由irq_of_parse_and_map解析设备树获得)。
      🌳 设备树示例

      dts 复制代码
      interrupts = <0 168 IRQ_TYPE_EDGE_RISING>;  // SPI 168,上升沿触发
    • flags:标志位(如IRQF_SHARED表示共享中断)。
      ⚠️ 共享中断 :需唯一dev_id标识不同设备。

    • dev:设备标识符(共享中断时用于区分设备)。
      📌 示例 :PCI设备使用pci_dev指针作为标识。

2. 实现中断处理函数 🛠️
  • 上半部(Top Half):快速响应硬件,禁止阻塞或睡眠。

    c 复制代码
    static irqreturn_t my_irq_handler(int irq, void *dev_id) {
        struct net_device *dev = dev_id;
        // 1. 读取硬件状态(如网卡DMA缓冲区)
        u32 status = readl(dev->reg_base + STATUS_REG);
        // 2. 清除中断标志
        writel(STATUS_CLEAR, dev->reg_base + STATUS_REG);
        // 3. 触发下半部(如tasklet)
        tasklet_schedule(&dev->tasklet);
        return IRQ_HANDLED;
    }

    🚨 注意事项 :避免在中断上下文中调用kmalloc()mutex_lock()

  • 下半部(Bottom Half):处理耗时任务,支持多种机制:

    • SoftIRQ :内核预定义的高优先级任务(如网络收包)。
      🌟 优势:支持多CPU并行处理。
    • Tasklet :基于SoftIRQ,单CPU串行执行。
      适用场景:GPIO按键去抖动处理。
    • Workqueue :运行于进程上下文,允许休眠。
      🛌 示例:文件I/O或网络协议栈处理。
3. 释放中断资源 🗑️

驱动卸载时需调用free_irq释放中断号:

c 复制代码
void free_irq(unsigned int irq, void *dev_id);

⚠️ 内存安全:必须在驱动卸载路径中调用,防止资源泄漏。


五、示例:网卡中断处理全流程 🌐
  1. 硬件触发 :网卡接收数据包,向GIC发送IRQ信号。
    📡 触发时机:DMA传输完成或FIFO缓冲区非空。
  2. GIC路由 :Distributor将中断路由至CPU0,分配硬件中断号168。
    🔄 负载均衡:GICv3支持动态调整目标CPU。
  3. CPU跳转 :CPU0执行向量表VBAR_EL1 + 0x280处的irq入口。
    ⏱️ 低延迟:硬件自动跳转,无需软件轮询。
  4. GIC处理gic_handle_irq读取中断号168,调用handle_domain_irq
    🔍 中断号解析 :通过GICC_IAR寄存器获取。
  5. 中断映射 :通过irq_domain将168映射为Linux虚拟IRQ 200。
    🌉 映射关系 :存储在irq_desc[200].irq_data.hwirq
  6. 驱动处理 :执行irq_desc[200].action中的网卡ISR(如NAPI收包)。
    🚀 性能优化:NAPI在收包时切换为轮询模式,减少中断风暴。
  7. 中断返回 :恢复上下文,触发软中断(如NET_RX_SOFTIRQ)处理数据。
    📦 数据传递sk_buff从内核空间传递到用户空间。

六、关键数据结构与机制 📊
组件/机制 功能说明 示例/API
GIC Distributor 接收外设中断,优先级仲裁,路由到目标CPU核心。 gic_dist_init()
VBAR_EL1 存储中断向量表基址,决定异常入口跳转位置。 set_vbar()
irq_domain 管理硬件中断号(HW IRQ)到Linux虚拟中断号(VIRQ)的映射。 irq_domain_add_linear()
irq_desc[] 全局中断描述符数组,存储中断处理函数链(action链表)。 struct irq_desc
request_irq() 驱动注册中断处理函数,关联到irq_desc[VIRQ].action链表。 request_irq()

相关推荐
这货不是陈进坚1 分钟前
vmware虚拟机与宿主机共享文件夹
linux·运维·服务器
来杯@Java4 分钟前
计算机毕设JAVA——某高校宿舍管理系统(基于SpringBoot+Vue前后端分离的项目)
java·spring boot·vue·课程设计
wuqingshun3141598 分钟前
蓝桥杯 团建
c语言·数据结构·c++·算法·蓝桥杯·深度优先
m0_7482405410 分钟前
常见的 Spring 项目目录结构
java·后端·spring
这辈子_安静的努力着14 分钟前
Idea编译项目很久之后,提示 Error:java:OutOfMemoryError:insufficient memory
java·ide
C_V_Better22 分钟前
Spring Security 如何防止 CSRF 攻击?
java·开发语言·数据结构·后端·算法·spring·csrf
推敲模拟44 分钟前
Chapter 4 Noise performance of elementary transistor stages
单片机
levitgu1 小时前
西电应用密码学与网络安全实验通关指南
c++·经验分享·安全·ai·密码学·rsa·实验
tkokof11 小时前
崩溃(Crash)简记
数据结构·c++·ue5·ue4·crash
程序员架构笔记1 小时前
15. C++多线程编程-网络编程-GUI编程(如Qt)学习建议
c++