范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

深入分析Linux中断子系统之中断控制器及驱动

  说明:Kernel版本:4.14  ARM64处理器,Contex-A53,双核  使用工具:Source Insight 3.5, Visio  1. 概述
  从这篇文章开始,来聊一聊中断子系统。中断是处理器用于异步处理外围设备请求的一种机制,可以说中断处理是操作系统管理外围设备的基石,此外系统调度、核间交互等都离不开中断,它的重要性不言而喻。
  来一张概要的分层图:
  硬件层:最下层为硬件连接层,对应的是具体的外设与SoC的物理连接,中断信号是从外设到中断控制器,由中断控制器统一管理,再路由到处理器上;  硬件相关层:这个层包括两部分代码,一部分是架构相关的,比如ARM64处理器处理中断相关,另一部分是中断控制器的驱动代码;  通用层:这部分也可以认为是框架层,是硬件无关层,这部分代码在所有硬件平台上是通用的;  用户层:这部分也就是中断的使用者了,主要是各类设备驱动,通过中断相关接口来进行申请和注册,最终在外设触发中断时,进行相应的回调处理;
  中断子系统系列文章,会包括硬件相关、中断框架层、上半部与下半部、Softirq、Workqueue等机制的介绍,本文会先介绍硬件相关的原理及驱动,前戏结束,直奔主题。 2. GIC硬件原理ARM公司提供了一个通用的中断控制器 GIC(Generic Interrupt Controller) ,GIC 的版本包括V1 ~ V4 ,由于本人使用的SoC中的中断控制器是V2 版本,本文将围绕GIC-V2 来展开介绍;
  来一张功能版的框图:
  GIC-V2 从功能上说,除了常用的中断使能、中断屏蔽、优先级管理等功能外,还支持安全扩展、虚拟化等; GIC-V2 从组成上说,主要分为Distributor 和CPU Interface 两个模块,Distributor 主要负责中断源的管理,包括优先级的处理,屏蔽、抢占等,并将最高优先级的中断分发给CPU Interface ,CPU Interface 主要用于连接处理器,与处理器进行交互; Virtual Distributor 和Virtual CPU Interface 都与虚拟化相关,本文不深入分析;
  再来一张细节图看看Distributor 和CPU Interface 的功能:
  GIC-V2 支持三种类型的中断: SGI(software-generated interrupts) :软件产生的中断,主要用于核间交互,内核中的IPI:inter-processor interrupts 就是基于SGI ,中断号ID0 - ID15 用于SGI ; PPI(Private Peripheral Interrupt) :私有外设中断,每个CPU都有自己的私有中断,典型的应用有local timer ,中断号ID16 - ID31 用于PPI ; SPI(Shared Peripheral Interrupt) :共享外设中断,中断产生后,可以分发到某一个CPU上,中断号ID32 - ID1019 用于SPI ,ID1020 - ID1023 保留用于特殊用途; Distributor 功能: 全局开关控制 Distributor 分发到CPU Interface ; 打开或关闭每个中断;  设置每个中断的优先级;  设置每个中断将路由的CPU列表;  设置每个外设中断的触发方式:电平触发、边缘触发;  设置每个中断的Group:Group0或Group1,其中Group0用于安全中断,支持FIQ和IRQ,Group1用于非安全中断,只支持IRQ;  将 SGI 中断分发到目标CPU上; 每个中断的状态可见;  提供软件机制来设置和清除外设中断的pending状态;  CPU Interface 功能: 使能中断请求信号到CPU上;  中断的确认;  标识中断处理的完成;  为处理器设置中断优先级掩码;  设置处理器的中断抢占策略;  确定处理器的最高优先级pending中断;
  中断处理的状态机如下图:
  Inactive :无中断状态; Pending :硬件或软件触发了中断,但尚未传递到目标CPU,在电平触发模式下,产生中断的同时保持pending 状态; Active :发生了中断并将其传递给目标CPU,并且目标CPU可以处理该中断; Active and pending :发生了中断并将其传递给目标CPU,同时发生了相同的中断并且该中断正在等待处理;
  GIC检测中断流程如下: GIC捕获中断信号,中断信号assert,标记为pending状态;  Distributor 确定好目标CPU后,将中断信号发送到目标CPU上,同时,对于每个CPU,Distributor 会从pending信号中选择最高优先级中断发送至CPU Interface ; CPU Interface 来决定是否将中断信号发送至目标CPU; CPU完成中断处理后,发送一个完成信号 EOI(End of Interrupt) 给GIC;
  更多linux内核视频教程文档资料免费领取后台私信【内核】自行获取.
  3. GIC驱动分析3.1 设备信息添加
  ARM平台的设备信息,都是通过Device Tree 设备树来添加,设备树信息放置在arch/arm64/boot/dts/ 下
  下图就是一个中断控制器的设备树信息:
  compatible 字段:用于与具体的驱动来进行匹配,比如图片中arm, gic-400 ,可以根据这个名字去匹配对应的驱动程序; interrupt-cells 字段:用于指定编码一个中断源所需要的单元个数,这个值为3。比如在外设在设备树中添加中断信号时,通常能看到类似interrupts = ; 的信息,第一个单元0,表示的是中断类型(1:PPI,0:SPI ),第二个单元23表示的是中断号,第三个单元4表示的是中断触发的类型; reg 字段:描述中断控制器的地址信息以及地址范围,比如图片中分别制定了GIC Distributor(GICD) 和GIC CPU Interface(GICC) 的地址信息; interrupt-controller 字段:表示该设备是一个中断控制器,外设可以连接在该中断控制器上; 关于设备数的各个字段含义,详细可以参考 Documentation/devicetree/bindings 下的对应信息;
  设备树的信息,是怎么添加到系统中的呢?Device Tree 最终会编译成dtb 文件,并通过Uboot传递给内核,在内核启动后会将dtb 文件解析成device_node 结构。关于设备树的相关知识,本文先不展开,后续再找机会补充。来一张图,先简要介绍下关键路径:
  设备树的节点信息,最终会变成 device_node 结构,在内存中维持一个树状结构; 设备与驱动,会根据 compatible 字段进行匹配; 3.2 驱动流程分析
  GIC驱动的执行流程如下图所示:
  首先需要了解一下链接脚本 vmlinux.lds ,脚本中定义了一个__irqchip_of_table 段,该段用于存放中断控制器信息,用于最终来匹配设备; 在GIC驱动程序中,使用 IRQCHIP_DECLARE 宏来声明结构信息,包括compatible 字段和回调函数,该宏会将这个结构放置到__irqchip_of_table 字段中; 在内核启动初始化中断的函数中, of_irq_init 函数会去查找设备节点信息,该函数的传入参数就是__irqchip_of_table 段,由于IRQCHIP_DECLARE 已经将信息填充好了,of_irq_init 函数会根据arm,gic-400 去查找对应的设备节点,并获取设备的信息。中断控制器也存在级联的情况,of_irq_init 函数中也处理了这种情况; or_irq_init 函数中,最终会回调IRQCHIP_DECLARE 声明的回调函数,也就是gic_of_init ,而这个函数就是GIC驱动的初始化入口函数了; GIC的工作,本质上是由中断信号来驱动,因此驱动本身的工作就是完成各类信息的初始化,注册好相应的回调函数,以便能在信号到来之时去执行;  set_smp_process_call 设置__smp_cross_call 函数指向gic_raise_softirq ,本质上就是通过软件来触发GIC的SGI中断 ,用于核间交互; cpuhp_setup_state_nocalls 函数,设置好CPU进行热插拔时GIC的回调函数,以便在CPU热插拔时做相应处理; set_handle_irq 函数的设置很关键,它将全局函数指针handle_arch_irq 指向了gic_handle_irq ,而处理器在进入中断异常时,会跳转到handle_arch_irq 执行,所以,可以认为它就是中断处理的入口函数了; 驱动中完成了各类函数的注册,此外还完成了 irq_chip , irq_domain 等结构体的初始化,这些结构在下文会进一步分析; 最后,完成GIC硬件模块的初始化设置,以及电源管理相关的注册等工作;  3.3 数据结构分析
  先来张图:
  GIC驱动中,使用 struct gic_chip_data 结构体来描述GIC控制器的信息,整个驱动都是围绕着该结构体的初始化,驱动中将函数指针都初始化好,实际的工作是由中断信号触发,也就是在中断来临的时候去进行回调; struct irq_chip 结构,描述的是中断控制器的底层操作函数集,这些函数集最终完成对控制器硬件的操作; struct irq_domain 结构,用于硬件中断号和Linux IRQ中断号(virq,虚拟中断号)之间的映射;
  还是上一下具体的数据结构代码吧,关键注释如下: struct irq_chip { 	struct device	*parent_device;     //指向父设备 	const char	*name;      //  /proc/interrupts中显示的名字 	unsigned int	(*irq_startup)(struct irq_data *data);  //启动中断,如果设置成NULL,则默认为enable 	void		(*irq_shutdown)(struct irq_data *data);     //关闭中断,如果设置成NULL,则默认为disable 	void		(*irq_enable)(struct irq_data *data);   //中断使能,如果设置成NULL,则默认为chip->unmask 	void		(*irq_disable)(struct irq_data *data);  //中断禁止   	void		(*irq_ack)(struct irq_data *data);  //开始新的中断 	void		(*irq_mask)(struct irq_data *data); //中断源屏蔽 	void		(*irq_mask_ack)(struct irq_data *data); //应答并屏蔽中断 	void		(*irq_unmask)(struct irq_data *data);   //解除中断屏蔽 	void		(*irq_eoi)(struct irq_data *data);  //中断处理结束后调用   	int		(*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest, bool force); //在SMP中设置CPU亲和力 	int		(*irq_retrigger)(struct irq_data *data);    //重新发送中断到CPU 	int		(*irq_set_type)(struct irq_data *data, unsigned int flow_type); //设置中断触发类型 	int		(*irq_set_wake)(struct irq_data *data, unsigned int on);    //使能/禁止电源管理中的唤醒功能   	void		(*irq_bus_lock)(struct irq_data *data); //慢速芯片总线上的锁 	void		(*irq_bus_sync_unlock)(struct irq_data *data);  //同步释放慢速总线芯片的锁   	void		(*irq_cpu_online)(struct irq_data *data); 	void		(*irq_cpu_offline)(struct irq_data *data);   	void		(*irq_suspend)(struct irq_data *data); 	void		(*irq_resume)(struct irq_data *data); 	void		(*irq_pm_shutdown)(struct irq_data *data);   	void		(*irq_calc_mask)(struct irq_data *data);   	void		(*irq_print_chip)(struct irq_data *data, struct seq_file *p); 	int		(*irq_request_resources)(struct irq_data *data); 	void		(*irq_release_resources)(struct irq_data *data);   	void		(*irq_compose_msi_msg)(struct irq_data *data, struct msi_msg *msg); 	void		(*irq_write_msi_msg)(struct irq_data *data, struct msi_msg *msg);   	int		(*irq_get_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool *state); 	int		(*irq_set_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool state);   	int		(*irq_set_vcpu_affinity)(struct irq_data *data, void *vcpu_info);   	void		(*ipi_send_single)(struct irq_data *data, unsigned int cpu); 	void		(*ipi_send_mask)(struct irq_data *data, const struct cpumask *dest);   	unsigned long	flags; };   struct irq_domain { 	struct list_head link;  //用于添加到全局链表irq_domain_list中 	const char *name;   //IRQ domain的名字 	const struct irq_domain_ops *ops;   //IRQ domain映射操作函数集 	void *host_data;    //在GIC驱动中,指向了irq_gic_data 	unsigned int flags;  	unsigned int mapcount;  //映射中断的个数   	/* Optional data */ 	struct fwnode_handle *fwnode; 	enum irq_domain_bus_token bus_token; 	struct irq_domain_chip_generic *gc; #ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY 	struct irq_domain *parent;  //支持级联的话,指向父设备 #endif #ifdef CONFIG_GENERIC_IRQ_DEBUGFS 	struct dentry		*debugfs_file; #endif   	/* reverse map data. The linear map gets appended to the irq_domain */ 	irq_hw_number_t hwirq_max;  //IRQ domain支持中断数量的最大值 	unsigned int revmap_direct_max_irq; 	unsigned int revmap_size;   //线性映射的大小 	struct radix_tree_root revmap_tree; //Radix Tree映射的根节点 	unsigned int linear_revmap[];   //线性映射用到的查找表 };   struct irq_domain_ops { 	int (*match)(struct irq_domain *d, struct device_node *node, 		     enum irq_domain_bus_token bus_token);      // 用于中断控制器设备与IRQ domain的匹配 	int (*select)(struct irq_domain *d, struct irq_fwspec *fwspec, 		      enum irq_domain_bus_token bus_token); 	int (*map)(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw);    //用于硬件中断号与Linux中断号的映射 	void (*unmap)(struct irq_domain *d, unsigned int virq); 	int (*xlate)(struct irq_domain *d, struct device_node *node, 		     const u32 *intspec, unsigned int intsize, 		     unsigned long *out_hwirq, unsigned int *out_type);     //通过device_node,解析硬件中断号和触发方式   #ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY 	/* extended V2 interfaces to support hierarchy irq_domains */ 	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); 	void (*activate)(struct irq_domain *d, struct irq_data *irq_data); 	void (*deactivate)(struct irq_domain *d, struct irq_data *irq_data); 	int (*translate)(struct irq_domain *d, struct irq_fwspec *fwspec, 			 unsigned long *out_hwirq, unsigned int *out_type); #endif };3.3.1 IRQ domain
  IRQ domain用于将硬件的中断号,转换成Linux系统中的中断号(virtual irq, virq ),来张图:
  每个中断控制器都对应一个IRQ Domain;  中断控制器驱动通过 irq_domain_add_*() 接口来创建IRQ Domain; IRQ Domain支持三种映射方式:linear map(线性映射),tree map(树映射),no map(不映射);  linear map:维护固定大小的表,索引是硬件中断号,如果硬件中断最大数量固定,并且数值不大,可以选择线性映射;  tree map:硬件中断号可能很大,可以选择树映射;  no map:硬件中断号直接就是Linux的中断号;
  三种映射的方式如下图:
  图中描述了三个中断控制器,对应到三种不同的映射方式;  各个控制器的硬件中断号可以一样,最终在Linux内核中映射的中断号是唯一的;  4. Arch-speicific代码分析中断也是异常模式的一种,当外设触发中断时,处理器会切换到特定的异常模式进行处理,而这部分代码都是架构相关的;ARM64的代码位于 arch/arm64/kernel/entry.S 。 ARM64处理器有四个异常级别Exception Level:0~3,EL0级对应用户态程序,EL1级对应操作系统内核态,EL2级对应Hypervisor,EL3级对应Secure Monitor;  异常触发时,处理器进行切换,并且跳转到异常向量表开始执行,针对中断异常,最终会跳转到 irq_handler 中;
  代码比较简单,如下: /*  * Interrupt handling.  */ 	.macro	irq_handler 	ldr_l	x1, handle_arch_irq 	mov	x0, sp 	irq_stack_entry 	blr	x1 	irq_stack_exit 	.endm
  来张图:
  中断触发,处理器去异常向量表找到对应的入口,比如EL0的中断跳转到 el0_irq 处,EL1则跳转到el1_irq 处; 在GIC驱动中,会调用 set_handle_irq 接口来设置handle_arch_irq 的函数指针,让它指向gic_handle_irq ,因此中断触发的时候会跳转到gic_handle_irq 处执行; gic_handle_irq 函数处理时,分为两种情况,一种是外设触发的中断,硬件中断号在16 ~ 1020 之间,一种是软件触发的中断,用于处理器之间的交互,硬件中断号在16以内; 外设触发中断后,根据 irq domain 去查找对应的Linux IRQ中断号,进而得到中断描述符irq_desc ,最终也就能调用到外设的中断处理函数了;
  首页 - 内核技术中文网 - 构建全国最权威的内核技术交流分享论坛
  转载地址:深入分析Linux中断子系统之中断控制器及驱动 - 圈点 - 内核技术中文网 - 构建全国最权威的内核技术交流分享论坛

网友建议调整黄山市域铁路布局官方回应大皖新闻讯近日,有网友在人民网留言,称根据当前黄山市发展现状,建议修改市域旅游铁路布局,将黄山火车站进行改造,将货运功能迁移至现在的金村火车站,并将其改造为黄山南站。而现有的黄山火在零点钟声响起时看到家人,远在海外的他们很感动惊喜张雨晴插图唐建平那年8月末,距离赴马里执行维和任务的日子越来越近了,特战小队队长殷培馨的手机上终于收到了最后一份视频。对方解释说,家里老人不会用手机,他又在外地工作,抽空回家才俄乌冲突升级,德国导弹进入战备状态,普京对美欧发出最后通牒不知不觉,俄乌冲突已经从2022年2月份持续到了2023年2月份,就目前看,这场持续了快一年的战争,丝毫没有要画上句号的迹象。关键时刻,普京忍无可忍了。2月2日,普京在发表全国讲话西藏冒险王王相军为冒险和家人失联9年,29岁掉入冰河身亡2020年12月20日,西藏冒险王王相军在西藏探险依噶冰川时,意外失足坠落河中,不幸身亡,享年29岁。从2012年开始,他已经爬上了中国西部70多条冰川,拍摄了300余条冰川视频,曼联再赢球挺进联赛杯决赛,状态火热的背后是什么近期曼联状态可谓十分火热,在联赛杯总比分50拿下诺丁汉森林后成功晋级联赛杯决赛,这也是曼联在世界杯后12场比赛中的第10场胜利,稳定的成绩令人忘记球队前2个赛季还是英超著名神经刀。杭州建德草莓有多热?90后博士村干部当起农场主眼下正是草莓季,春节返乡的你,有没有去家附近的草莓大棚,体验一次采摘游?杭州建德被誉为中国草莓之乡,这里的草莓全产业链产值超45亿元,产值规模浙江省第一全国第三。当地种植有包括建德天水清水县新春草莓红游客采摘乐2月1日,在天水清水县红堡镇安坪村的温室大棚草莓园里,一簇簇翠绿的植株间,一个个红似小灯笼的草莓缀满枝头,果香四溢,吸引了不少游客前来采摘品尝。从去年12月开始,这里的草莓便陆续成正月十五元宵节,这道吉祥又如意的菜肴,好吃易做,下酒下饭超棒天南地北大拜年正月十五元宵节,一道吉祥又如意的菜肴送给您,好吃易做不复杂,下酒下饭超棒!今年的2月5号是元宵节,也是年后迎来的第一个大节日,虽然大多数人早已开启了工作模式,但我们的菠菜配什么最好吃?分享4种不同做法,鲜甜不涩口,顿顿吃光盘虽然衰老不可避免,但抗衰老非常必要!这种物质对于上了年纪的中老年人就是不老元素叶酸!叶酸不光能促进新生儿生长发育,同样是缓解中老年人大脑老化预防痴呆健忘降低心血管疾病的一剂良药。菠巨下饭!这食材太家常,做出来比肉都好吃来源昆明日报掌上春城原料茄子2根豆腐半块肉末150克黄豆酱1大勺蒜蓉酱半勺蒜末适量生抽2勺蚝油1勺盐少许糖少许。做法步骤1。豆腐控干水分,切片,沾淀粉。2。平底锅加油烧热,放入豆腐猕猴桃虽好吃,其实这4类人不宜多吃,要多注意了营养专家说每天可以吃三种以上水果,可以满足身体对多种营养物质需求,特别是纤维素维生素矿物质微量元素,这些营养提供对免疫能力增强有帮助。而水果种类非常多,常见的有香蕉苹果樱桃柠檬猕猴
盈利艰难亟待上市补血优必选新增港股上市整体协调人经济观察网记者李华清2月13日,港交所官网披露,深圳市优必选科技股份有限公司(以下简称优必选)修订上市整体协调人,由原来委托国泰君安证券作为整体协调人调整为新增中信里昂证券中信建投金羊网评真抓实干,汇聚起高质量发展强大合力春潮澎湃,激荡万千气象。又是一年春耕时,阡陌田畴间,机声隆隆,人影绰绰,奏响人勤春来早,田间耕作忙的春耕曲新春伊始拼经济,街头商圈人流如织,车站地铁熙熙攘攘,人头涌动中蕴藏着被重新慕容看世界6千英法联军攻陷北京,曾国藩12万大军为何见死不救?清朝末期的历史是最让人们铭记的,因为他们的腐败无能,清朝沦为半封建半殖民的处境,也导致清朝时期的百姓一直生活在水深火热当中。曾经因为惹怒西方国家,导致六千名英法联军集体进攻北京,皇永州经开区举行第四十八次政企交流主题日活动红网时刻新闻2月15日讯(通讯员卿超平刘佳宾)近日,永州经开区第四十八次政企交流主题日活动举行,市委常委副市长永州经开区党委第一书记何恩广出席并讲话。区党委副书记管委会主任周润润,1953年,九岁男孩独闯北京,自称是毛主席的外孙,结果怎么样了?我叫宋阳正,我要找我外公1953年8月20日,毛主席的秘书田家英正在家中小憩,突然,客厅传来一阵急促的铃声,电话那头的人是中南海的警卫员,说有个声称是毛主席亲信的人指名要找他,结束从拼多多到TEMU,在如此内卷的电商时代,TEMU能再创辉煌吗?拼多多旗下TEMU在美国超级杯广告主打像个亿万富翁般购物前天是美国的超级杯(SuperBowl)星期天(一般来说在一月底最后一个星期天或是二月第一个星期天举行),这时段也是各大品牌AI学习者王慧文太忙了现在。2月13日上午11时许,当21世纪经济报道记者拨通王慧文的电话时,这位近日持续搅动AI圈的前美团点评联合创始人,在电波那头直言道。两个小时前,王慧文在社交平台上披露了自机械师F117X未来战舰III代评测13代酷睿联袂RTX显卡,强芯战未来!今年,在13代酷睿处理器的助力之下,机械师F117X未来战舰III代这款人气游戏主机再攀性能新高。强芯战未来!它的性能到底如何,此次评测便为大家一探究竟。机械师F117X未来战舰I物价低幸福感高的天使之城,被唐人街探案一再带火出圈头条创作挑战赛今天想带大家去一座我个人很喜欢的泰国城市曼谷看一看。它离国内超近,上海直飞4个小时就到了,拿上护照说走就能走。性价比还很高(不如跟我们的路线走高),人均100不到就能绝对冷门又美到窒息的自驾线,一次打卡滇川藏三大绝美省份!绝对冷门又美到窒息的泸亚线,一次就能打卡滇川藏三大绝美省份!这是一条连接泸沽湖稻城亚丁的天堂之路,在这里,美是真的,整条路线串联起大香格里拉的核心区域香格里拉泸沽湖木里稻城亚丁几乎亲家母,饭好了吗大爷去儿子家做客,两周后,一家四口变一口导语人到晚年,孤独寂寞,倘若遇上老伴去世,独居在家,那种孤独更是难以形容。因此有很多老人,趁着自己身体还能动,平时又有大把的时间,没事就去亲戚朋友家转转,当然最常去的,还是子女家里