深入分析Linux中断子系统之通用框架处理

说明:

  1. Kernel版本:4.14
  2. ARM64处理器,Contex-A53,双核
  3. 使用工具:Source Insight 3.5, Visio

1. 概述

深入分析Linux中断子系统之中断控制器及驱动讲到了底层硬件GIC驱动,以及Arch-Specific的中断代码,本文将研究下通用的中断处理的过程,属于硬件无关层。当然,我还是建议你看一下上篇文章。

这篇文章会解答两个问题:

  1. 用户是怎么使用中断的(中断注册)?
  2. 外设触发中断信号时,最终是怎么调用到中断handler的(中断处理)?

2. 数据结构分析

先来看一下总的数据结构,核心是围绕着struct irq_desc来展开:


中断的处理主要有以下几个功能模块:

  1. 硬件中断号到Linux irq中断号的映射,并创建好irq_desc中断描述符;
  2. 中断注册时,先获取设备的中断号,根据中断号找到对应的irq_desc,并将设备的中断处理函数添加到irq_desc中;
  3. 设备触发中断信号时,根据硬件中断号得到Linux irq中断号,找到对应的irq_desc,最终调用到设备的中断处理函数;

上述的描述比较简单,更详细的过程,往下看吧。


更多linux内核视频教程文档资料免费领取后台私信【内核】自行获取.


3. 流程分析

3.1 中断注册

这一次,让我们以问题的方式来展开:先来让我们回答第一个问题:用户是怎么使用中断的?

  1. 熟悉设备驱动的同学应该都清楚,经常会在驱动程序中调用request_irq()接口或者request_threaded_irq()接口来注册设备的中断处理函数;
  2. request_irq()/request_threaded_irq接口中,都需要用到irq,也就是中断号,那么这个中断号是从哪里来的呢?它是Linux irq,它又是如何映射到具体的硬件设备的中断号的呢?

先来看第二个问题:设备硬件中断号到Linux irq中断号的映射


gic_irq_domain_alloc函数如下:


上述函数执行完成后,完成了两大工作:

  1. 硬件中断号与Linux中断号完成映射,并为Linux中断号创建了irq_desc中断描述符;
  2. 数据结构的绑定及初始化,关键的地方是设置了中断处理往上执行的入口;

再看第一个问题:中断是怎么来注册的?

设备驱动中,获取到了irq中断号后,通常就会采用request_irq/request_threaded_irq来注册中断,其中request_irq用于注册普通处理的中断,request_threaded_irq用于注册线程化处理的中断;

在讲具体的注册流程前,先看一下主要的中断标志位:

#define IRQF_SHARED		0x00000080              //多个设备共享一个中断号,需要外设硬件支持
#define IRQF_PROBE_SHARED	0x00000100              //中断处理程序允许sharing mismatch发生
#define __IRQF_TIMER		0x00000200               //时钟中断
#define IRQF_PERCPU		0x00000400               //属于特定CPU的中断
#define IRQF_NOBALANCING	0x00000800               //禁止在CPU之间进行中断均衡处理
#define IRQF_IRQPOLL		0x00001000              //中断被用作轮训
#define IRQF_ONESHOT		0x00002000              //一次性触发的中断,不能嵌套,1)在硬件中断处理完成后才能打开中断;2)在中断线程化中保持关闭状态,直到该中断源上的所有thread_fn函数都执行完
#define IRQF_NO_SUSPEND		0x00004000      //系统休眠唤醒操作中,不关闭该中断
#define IRQF_FORCE_RESUME	0x00008000              //系统唤醒过程中必须强制打开该中断
#define IRQF_NO_THREAD		0x00010000      //禁止中断线程化
#define IRQF_EARLY_RESUME	0x00020000      //系统唤醒过程中在syscore阶段resume,而不用等到设备resume阶段
#define IRQF_COND_SUSPEND	0x00040000      //与NO_SUSPEND的用户共享中断时,执行本设备的中断处理函数


3.2 中断处理

当完成中断的注册后,所有结构的组织关系都已经建立好,剩下的工作就是当信号来临时,进行中断的处理工作。

来回顾一下深入分析Linux中断子系统之中断控制器及驱动中的Arch-specific处理流程:


generic_handle_irq处理如下图:


来看看中断线程化处理后的唤醒流程吧__handle_irq_event_percpu->__irq_wake_thread


3.3 总结

中断的处理,总体来说可以分为两部分来看:

  1. 从上到下:围绕irq_desc中断描述符建立好连接关系,这个过程就包括:中断源信息的解析(设备树),硬件中断号到Linux中断号的映射关系、irq_desc结构的分配及初始化(内部各个结构的组织关系)、中断的注册(填充irq_desc结构,包括handler处理函数)等,总而言之,就是完成静态关系创建,为中断处理做好准备;
  2. 从下到上,当外设触发中断信号时,中断控制器接收到信号并发送到处理器,此时处理器进行异常模式切换,并逐步从处理器架构相关代码逐级回调。如果涉及到中断线程化,则还需要进行中断内核线程的唤醒操作,最终完成中断处理函数的执行。


首页 - 内核技术中文网 - 构建全国最权威的内核技术交流分享论坛

转载地址:深入分析Linux中断子系统之通用框架处理 - 圈点 - 内核技术中文网 - 构建全国最权威的内核技术交流分享论坛

展开阅读全文

页面更新:2024-04-14

标签:子系统   初始化   线程   指针   内核   控制器   函数   框架   接口   结构   硬件   设备

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top