我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Linux中断子系统domain的示例分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Linux中断子系统domain的示例分析

这篇文章主要介绍Linux中断子系统domain的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

随着现代CPU的复杂度加大,外设中断数量增加,实际上系统可能同时需要多个中断控制器进行级联,面对这样的趋势,Linux引入了irq domain这个概念。

对于Linux系统中所有的interrupt controller都会形成树状结构,对于每个interrupt controller都可以连接若干个外设的中断请求,interrupt controller会对连接其上的interrupt source进行编号(也就是HW interrupt ID,后面我们叫hirq),但这个编号仅仅限制在本interrupt controller范围内。既然存在hirq,那么在系统软件中, 就存在一个全局统管的编号,这个编号可以定位控制器和控制器中的中断号,我们把这个编号叫做virq(我们在Linux系统中调用API request_irq中需要的irq号 实际上是virq号)。对于中断级联,我们以TI的TiTDA系列为例,如下图:

Linux中断子系统domain的示例分析
Linux中断子系统domain详解Linux中断子系统domain详解

如上图,该CPU是直接连接在中断控制器GICv3上面的,但是GIC不是直接和设备相连,而是与INTR控制器连接,而INTR控制器又与INTA控制器连接,最后INTA控制器才直接和设备相连。在这里其实就简单的形成了一个简单的树形结构。

domain里面的hirq排列可以是树形的也可以是线性的,本文主要说树形的

咋们先看看domain的结构(一个中断控制器就可以看成是一个domain):

struct irq_domain {   struct list_head link;   const char *name;    // domain的名字   const struct irq_domain_ops *ops; // 当前domain的处理函数   void *host_data;   // 存放私有数据   unsigned int flags;   unsigned int mapcount;      struct fwnode_handle *fwnode;  // 和设备树有关系   enum irq_domain_bus_token bus_token;  // bus标记,用于匹配domain   struct irq_domain_chip_generic *gc;#ifdef    CONFIG_IRQ_DOMAIN_HIERARCHY   struct irq_domain *parent;          // 树形结构的父节点domain#endif   irq_hw_number_t hwirq_max;    // hwirq树形(radix tree)支持的最大节点数量   unsigned int revmap_direct_max_irq; // hwirq和virq 1:1映射支持的最大数量   unsigned int revmap_size;     // 线性映射支持的最大数量   struct radix_tree_root revmap_tree;  // radix tree的树根   struct mutex revmap_tree_mutex;   unsigned int linear_revmap[];       // 线性映射的数组}

如上图可知,domain的结构里面基本都是关于hirq相关信息的,因此,我们可以推断domain就是用于管理hirq的(每个domain都有自己的一套hirq),而domain中的ops字段就是用于操作这些hirq的, 下面是domain的操作函数ops的结构:

struct irq_domain_ops {   int (*match)(struct irq_domain *d, struct device_node *node,        enum irq_domain_bus_token bus_token); // 用于匹配domain,优先级低于selec   int (*select)(struct irq_domain *d, struct irq_fwspec *fwspec,        enum irq_domain_bus_token bus_token); // 用于匹配domain,优先级高于match   int (*map)(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw); // 线性映射   void (*unmap)(struct irq_domain *d, unsigned int virq);   int (*xlate)(struct irq_domain *d, struct device_node *node, // 通过参数,线性hirq获取        const u32 *intspec, unsigned int intsize,        unsigned long *out_hwirq, unsigned int *out_type);#ifdef    CONFIG_IRQ_DOMAIN_HIERARCHY      int (*alloc)(struct irq_domain *d, unsigned int virq,//树形节点申请,映射(只有树形才有这个)        unsigned int nr_irqs, void *arg);   void (*free)(struct irq_domain *d, unsigned int virq,        unsigned int nr_irqs);   int (*activate)(struct irq_domain *d, struct irq_data *irqd, bool reserve); // 中断激活   void (*deactivate)(struct irq_domain *d, struct irq_data *irq_data);   int (*translate)(struct irq_domain *d, struct irq_fwspec *fwspec, //通过参数对树形hirq获取            unsigned long *out_hwirq, unsigned int *out_type);#endif}

如上图,对于domain的hirq,我们可以看到结构里面有查询分配hirq,以及hirq与virq的映射的函数。现在,我们已经了解了domain的数据结构,下面是一个中断控制器注册一个domain的流程:

irq_domain_add_hierarchy       irq_domain_create_tree            __irq_domain_add                 list_add(&domain->link, &irq_domain_list)

可见最终所有的domain都添加到irq_domain_list链表当中的。但是我们知道,我们调用request_irq用的是virq号,而并不是hirq,因为hirq号不是唯一的,每个domain都可能会存在一个相同的hirq,因此Linux才增加的virq编号,这个编号是独立的且唯一。现在domain已经注册好了,但是hirq和virq直接的关系还没有建立起来,因此我们还不能用virq来注册中断,如下是把hirq和virq做一个映射函数调用:

irq_create_fwspec_mapping(传入domain和参数)   irq_find_matching_fwspec       domain->ops->match // 查看当前domain和参数指定的domain是否匹配   irq_domain_translate       domain->ops->translate // 通过参数申请一个hirq号   irq_find_mapping // 通过hirq去查询,这个hirq是否已经映射,如果已经映射,就返回virq   irq_domain_alloc_irqs // hirq没有映射,通过该函数去申请一个virq并映射       __irq_domain_alloc_irqs           irq_domain_alloc_descs // 申请一个irq_desc描述           irq_domain_alloc_irq_data // 为virq设置irq_data树,该virq会为它所在的domain的父domain,一直到root domain添加irq_data           irq_domain_alloc_irqs_hierarchy // 向domain申请hirq,并和virq做映射               domain->ops->alloc                   irq_domain_set_hwirq_and_chip // 将hirq与virq的irq_data关联           irq_domain_insert_irq//将virq信息插入到每一级irq_data里面(一个domain对应一个irq_data)

如上图,当驱动调用irq_create_fwspec_mapping函数的时候,该函数会通过参数在指定的domain里面的申请hirq,然后申请一个virq,并将virq和hirq关联起来。下图是,irq_data的结构图: Linux中断子系统domain的示例分析

如上图所示,在domain里面利用linear_revmap(线性)或者revmap_tree(radix tree)来保存irq_data结构,在接收到中断的时候,我们只知道hirq号和对应的domain,因此可以以hirq为key值从revmap_tree或者linear_revmap当中获取到irq_data数据结构;当我们调用request_irq的时候,只填入了virq,因此也可以通过virq做为key在irq_desc_tree或者irq_desc[]数组中获取到irq_desc描述,从而获取到这个描述的irq_data。irq_data包含irq_chip(中断控制屏蔽掩码,设置触发方式等函数)、virq(这个值和该irq_data的父节点parent_data(irq_data)的virq的值相同),hwirq(每个irq_data的hwirq是不同的,对应不同的domain内部编号)、domain(指向当前irq_data所在的domain)、chip_data(指向当前irq_data所在domain的私有数据)、parent_data(指向irq_data的父节点,这个父节点存放父domain相关信息)。

linear_revmap和revmap_tree是domain结构里面的变量,每个domain都有,用于保存hirq与irq_data的对应关系;irq_desc_tree和irq_desc[]是全局变量,用于保存irq_desc结构的链表或者树。

通常在ARMv8体系结构中,中断处理的流程,如下图:

Linux中断子系统domain的示例分析

如上图,我们这个处理流程是el1模式的,在el1模式的时候,汇编级别的共用中断函数为el1_irq。图中我们可以看见几个箭头指示的点,1、handle_arch_irq;2、desc->handle_irq;3、irqaction->handler。我们知道,通常ARM体系结构的CPU都和GIC中断控制器相连,详细《ARM中断控制器-GICv2》,因此,handle_arch_irq这个全局函数指针,是有通用的中断控制器GIC驱动设置的(GIC驱动调用set_handle_irq函数设置),这样CPU上的所有异常中断都经过GIC的回调函数处理。GIC的这个回调函数gic_handle_irq(就是handle_arch_irq),负责mask中断和eoi中断(eoi就是ack控制器)。在这个回调函数里面,我们可以通过寄存器值获取到当前控制的那个中断号(该domain的hirq)触发了中断,然后通过hirq可以获取到对应的virq,从而获取到irq_desc描述,最后调用irq_desc描述的handle_irq来处理该中断。由图中,我们还看到handle_irq这个函数其实也是注册的,但是为了方便统一,这个回调通常都是gic驱动为每个中断注册一个统一的回调函数(handle_fasteoi_irq);handle_fasteoi_irq这个函数支持中断共享,然后依次调用挂在irq_desc下面的irqaction结构中的handle函数(玩家每调用依次request_irq就会在对应的virq上增加一个irqaction)。

irq_desc是一个virq对应的描述结构体,每个virq对应一个该结构。在irq_desc结构体里面有irq_data和irqaction变量,一个用于存放与当前virq映射的hirq信息,另一个用于存放该virq的中断回调处理函数。nr_irqs全局变量保存当前支持最大的中断数(可以通过irq_expand_nr_irqs函数扩展)

以上是“Linux中断子系统domain的示例分析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网行业资讯频道!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Linux中断子系统domain的示例分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Linux中断子系统domain的示例分析

这篇文章主要介绍Linux中断子系统domain的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!随着现代CPU的复杂度加大,外设中断数量增加,实际上系统可能同时需要多个中断控制器进行级联,面对这样的趋势,Li
2023-06-27

Linux设备模型之input子系统的示例分析

这篇文章主要介绍Linux设备模型之input子系统的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!本节重点: 输入子系统的框架结构 各层对应内核中的文件位置
2023-06-13

Linux中网络系统的示例分析

这篇文章主要介绍了Linux中网络系统的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。网络信息修改主机名# hostname node01 //本次登录修改# h
2023-06-22

Linux内核中断的示例分析

这篇文章主要介绍了Linux内核中断的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。中断是指在CPU正常运行期间,由于内外部事件或由程序预先安排的事件引起的CPU暂时
2023-06-27

Linux系统中Shell编程的示例分析

这篇文章主要介绍Linux系统中Shell编程的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一. 什么是Shell 1. 在学习Shell编程之前,我们应该要先知道什么是Shell用户、She
2023-06-26

Linux操作系统的示例分析

这篇文章给大家分享的是有关Linux操作系统的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、Linux简介Linux可以有狭义和广义两种定义。狭义来说,Linux实际上指Linux kernel (内
2023-06-13

Linux系统结构的示例分析

这篇文章主要介绍Linux系统结构的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Linux系统一般有4个主要部分:内核、shell、文件系统和应用程序。内核、shell和文件系统一起形成了基本的操作系统结构
2023-06-15

Linux系统进程的示例分析

这篇文章主要为大家展示了“Linux系统进程的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Linux系统进程的示例分析”这篇文章吧。1. 什么是进程进程是处于执行期的程序以及它所包含的
2023-06-13

Linux系统配置的示例分析

这篇文章主要为大家展示了“Linux系统配置的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Linux系统配置的示例分析”这篇文章吧。前言 Linux操作系统中包含了大量的服务程
2023-06-22

linux系统管理mail电子邮件日志的示例分析

这篇文章主要为大家展示了“linux系统管理mail电子邮件日志的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“linux系统管理mail电子邮件日志的示例分析”这篇文章吧。我们都知道很
2023-06-13

linux系统中文件I/O的示例分析

小编给大家分享一下linux系统中文件I/O的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!linux 文件I/O一,文件描述符对内核而言,所以打开的文件
2023-06-13

LINUX系统中硬链接数的示例分析

这篇文章主要介绍了LINUX系统中硬链接数的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1、打开LINUX操作系统,可以使用UBUNTU。2、找到左边任务栏的终端窗
2023-06-28

Linux系统中内核调试的示例分析

这篇文章主要介绍了Linux系统中内核调试的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。调试是软件开发过程中一个必不可少的环节,在 Linux 内核开发的过程中也不
2023-06-12

Linux系统netcat命令的示例分析

这篇文章的内容主要围绕Linux系统netcat命令的示例分析进行讲述,文章内容清晰易懂,条理清晰,非常适合新手学习,值得大家去阅读。感兴趣的朋友可以跟随小编一起阅读吧。希望大家通过这篇文章有所收获!netcat是网络工具中的瑞士军刀,它能
2023-06-28

Linux系统DNS文件的示例分析

这篇文章将为大家详细讲解有关Linux系统DNS文件的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。DNS一般指域名系统。DNS是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库
2023-06-28

Linux系统线程池的示例分析

Linux系统线程池的示例分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。实现原理程序启动之前,创建一定数量的线程,放入空闲的队列中,初始化线程池。这些线程均处于阻塞状态
2023-06-28

linux系统下Centos中vim配置的示例分析

这篇文章将为大家详细讲解有关linux系统下Centos中vim配置的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1.简单的页面设置(附有效果图)首先,使用cd /etc命令进入etc的目录下,
2023-06-10

linux中根文件系统挂载的示例分析

这篇文章主要介绍linux中根文件系统挂载的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!st1\:*{behavior:url(#ieooui) }一:前言前段时间在编译kernel的时候发现rootfs挂
2023-06-12

linux系统安装字体的示例分析

小编给大家分享一下linux系统安装字体的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!linux系统安装字体详细介绍前言:使用linux做桌面系统有很多
2023-06-09

Linux系统安全配置的示例分析

这篇文章主要介绍Linux系统安全配置的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1.为LILO增加开机口令  在/etc/lilo.conf文件中增加选项,从而使LILO启动时要求输入口令,以加强系统的
2023-06-13

编程热搜

目录