linux内核驱动:GIC中断总结

目录

    • 前言
    • 一、整体介绍
    • 二、GIC的模块功能说明
    • 三、函数接口、数据结构和驱动文件
      • 驱动文件
      • 数据结构
    • 四、中断使用流程
    • 五、中断的扩展

前言

本文基于linux5.10.xxx总结gic使用,gic版本为gicv3,包括gic结构、驱动代码、使用等,等,处理器架构为基于armv8指令集的cortex-A72内核的SOC,参考gicv3&v3技术规范手册和cortex-a72架构手册;

一、整体介绍

GICv3架构旨在与Armv8-A和Armv8-R兼容的处理元件PE一起运行。
通用中断控制器(GIC)架构定义了:
•处理连接到GIC的任何PE的所有中断源的架构要求。
•适用于单处理器或多处理器系统的通用中断控制器编程接口。
GIC是一种支持和控制中断的架构资源。它提供:
•用于管理中断源、中断行为以及将中断路由到一个或多个PE的寄存器。
•支持:
–Armv8架构。
–特定于本地的外围中断(LPI)。
–专用外围中断(PPI)。
–软件生成的中断(SGI)。
–共享外围中断(SPI)。
–中断屏蔽和优先级排序。
–单处理器和多处理器系统。
–电源管理环境中的唤醒事件。
对于每个PE,GIC架构描述了如何从不同类型的PE生成IRQ和FIQ中断系统内的中断。Armv8-A异常模型描述了PE如何处理这些IRQ和FIQ中断

中断处理还取决于Armv8架构的其他方面,例如安全状态和支持用于虚拟化。Arm架构提供两种安全状态,每种状态都有一个相关的物理内存地址空间:
•安全状态。
•不安全状态。
GIC架构支持路由和处理与两种安全状态相关的中断。
GIC架构支持Armv8模型,用于处理与虚拟中断相关的虚拟中断机器、VM。虚拟化系统具有:
•管理程序必须包括一个在EL2上执行的组件,负责在EL2和EL2之间进行切换VM。
•几个虚拟机在EL1上执行。
•在VM上以EL0执行的应用程序。

–以上来自《Arm® Generic Interrupt Controller
Architecture Specification
GIC architecture version 3 and version 4》

二、GIC的模块功能说明

逻辑框图
在这里插入图片描述
GICv3架构由一组逻辑组件组成:
•中断分配器
•中断再分配器,每个CPU核对应一个
•GIC接口控制器,每个CPU核对应一个
•中断务组件(ITS),支持可选的传输事件给LPI(局部外设中断)

GIC和具体处理器的关系可以参考下图:
在这里插入图片描述
GIC的CPU接口部分可以理解成在处理器内部,通过总线如AXI和GIC其它部分通信,实际操作中会通过系统寄存器中一些寄存器去控制GIC的CPU INTERFACE部分 ;

中断类型
GICv3支持Locality-specific Peripheral Interrupt (LPI)本地特定外设中断、Software Generated Interrupt (SGI)软件触发中断、Private Peripheral Interrupt (PPI)私有外设中断、Shared Peripheral Interrupt (SPI)共享外设中断;
中断号范围一般SGI为0~15,PPI为16 ~31,SPI为32 ~某个数值具体支持数量看SOC设计的需求;
在linux系统下设备树下会配置中断号为irq和gic支持的中断号hwirq之间会有转换函数,gic处理是基于硬中断号处理的;

中断状态
中断的生命周期包括Inactive、pending、active、active and pending状态,处理状态机如下,
在这里插入图片描述
中断寄存器
GIC的几个部件由相应的寄存器来进行控制,通过寄存器去对中断进行使能、失能、优先级配置、优先级分组等的处理
寄存器命名规则
所有GIC寄存器的名称都为寄存器的功能提供了一个简短的助记符(前缀):
•内存映射寄存器前缀为以下之一:
–GICC,表示CPU接口寄存器。
–GICD,表示分配器寄存器。
–GICH,表示虚拟接口控制寄存器,通常由管理程序访问。
–GICR,表示再分发器寄存器。
–GICV,表示虚拟CPU接口寄存器。
–GITS,表示ITS寄存器。
•系统寄存器前缀为:
–ICC表示物理GIC CPU接口系统寄存器。
–ICV用于指示虚拟GIC CPU接口系统寄存器。
–ICH表示虚拟接口控制系统寄存器。

GIC分配器寄存器
在这里插入图片描述
在这里插入图片描述
GIC再分配器寄存器

在这里插入图片描述
GIC的CPU interface寄存器
在这里插入图片描述

系统寄存器
在这里插入图片描述
在这里插入图片描述

系统寄存器和gic内存映射寄存器中GIC cpu interface寄存器的关系
在这里插入图片描述
规范手册中有句描述如下:
在这里插入图片描述
意思为同时访问以上表格中对应的内存映射映射部分的寄存器和系统寄存器可能导致状态不一致现象,arm推荐通过设置后,访问系统寄存器来代替表格中内存映射的寄存器(备注 内存映射的寄存器可以理解成被SOC实现为外设的一部分可以看到寄存器对应的外设地址,而系统寄存器只能看到名字),代码中使用如下宏访问系统寄存器

//in file arch_gicv3.h
#define read_gicreg(r)			read_sysreg_s(SYS_ ## r)
#define write_gicreg(v, r)		write_sysreg_s(v, SYS_ ## r)//in file  sysreg.h
#define read_sysreg_s(r) ({						\u64 __val;							\asm volatile(__mrs_s("%0", r) : "=r" (__val));			\__val;								\
})
#define write_sysreg_s(v, r) do {					\u64 __val = (u64)(v);						\asm volatile(__msr_s(r, "%x0") : : "rZ" (__val));		\
} while (0)

三、函数接口、数据结构和驱动文件

驱动文件

头文件
include/linux/interrupt.h:
devm_request_irq函数等位于此文件

include/linux/irqdesc.h:
include/linux/irq.h:
include/linux/irqdomain.h

kernel/irq/目录下
kernel/irq/affinity.c
kernel/irq/devres.c
kernel/irq/irqdesc.c:irqdesc结构处理
kernel/irq/pm.c
kernel/irq/autoprobe.c
kernel/irq/dummychip.c
kernel/irq/irqdomain.c
kernel/irq/proc.c
kernel/irq/chip.c
kernel/irq/handle.c :
kernel/irq/manage.c
kernel/irq/resend.c
kernel/irq/cpuhotplug.c
kernel/irq/ipi.c
kernel/irq/msi.c
kernel/irq/spurious.c

drivers/irqchip/目录下
drivers/irqchip/irqchip.c: gic节点的platform_driver的注册
drivers/irqchip/irq-gic-common.c
drivers/irqchip/irq-gic-v3.c:解析设备树后使用gic的寄存器等信息进行gic的初始化

数据结构

struct irqaction
中断动作描述符,表示一个动作或者处理过程,作为struct irq_desc结构的一个指针成员,定义于include/linux/interrupt.h

struct irqaction {irq_handler_t		handler; //中断服务函数void			*dev_id; //当对同一个中断号进行中断请求,中断标识为shared时这个字段需要明确定义void __percpu		*percpu_dev_id;struct irqaction	*next; //当同一个中断号被申请多次中断时,中断服务会次形成链表irq_handler_t		thread_fn; //为线程化的中断服务函数,struct task_struct	*thread;struct irqaction	*secondary;unsigned int		irq; //中断号unsigned int		flags;unsigned long		thread_flags;unsigned long		thread_mask;const char		*name;struct proc_dir_entry	*dir;
} ____cacheline_internodealigned_in_smp;

struct irq_desc
一个中断号会对应一个这个结构,实际上有个irq_desc irq_desc[]的数组,数组的下标索引为中断号,定义于include/linux/irqdesc.h

struct irq_desc {struct irq_common_data	irq_common_data;struct irq_data		irq_data;  //具体中断的数据,如irq  hwirq  irqchip等unsigned int __percpu	*kstat_irqs;irq_flow_handler_t	handle_irq;struct irqaction	*action;	/* IRQ action list */unsigned int		status_use_accessors;unsigned int		core_internal_state__do_not_mess_with_it;unsigned int		depth;		/* nested irq disables */unsigned int		wake_depth;	/* nested wake enables */unsigned int		tot_count;unsigned int		irq_count;	/* For detecting broken IRQs */unsigned long		last_unhandled;	/* Aging timer for unhandled count */unsigned int		irqs_unhandled;atomic_t		threads_handled;int			threads_handled_last;raw_spinlock_t		lock;struct cpumask		*percpu_enabled;const struct cpumask	*percpu_affinity;//。。。。。。。。省略。。。。。。。//。。。。。。。。省略。。。。。。。const char		*name;
} ____cacheline_internodealigned_in_smp;

struct irq_data
对应一个中断号的数据描述,定义于include/linux/irq.h,是irq_desc 的一个数据成员

struct irq_data {u32			mask;unsigned int		irq; //中断号unsigned long		hwirq;  //硬件中断号struct irq_common_data	*common;struct irq_chip		*chip; //底层硬件表示,表示一个中断控制器struct irq_domain	*domain;
#ifdef	CONFIG_IRQ_DOMAIN_HIERARCHYstruct irq_data		*parent_data;
#endifvoid			*chip_data;
};

struct irq_chip
表示一个中断控制器,内部包括具体中断控制器需要实现的函数,定义于include/linux/irq.h ,是irq_data的一个指针成员

struct irq_chip {struct device	*parent_device;const char	*name;unsigned int	(*irq_startup)(struct irq_data *data);void		(*irq_shutdown)(struct irq_data *data);void		(*irq_enable)(struct irq_data *data);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);int		(*irq_retrigger)(struct irq_data *data);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);int		(*irq_nmi_setup)(struct irq_data *data);void		(*irq_nmi_teardown)(struct irq_data *data);unsigned long	flags;
};

struct irq_domain
对于中断控制器支持的所有中断进行管理,定义于include/linux/irqdomain.h

struct irq_domain {struct list_head link;const char *name;const struct irq_domain_ops *ops; //操作函数级void *host_data;unsigned int flags;unsigned int mapcount;/* Optional data */struct fwnode_handle *fwnode; //中断控制器的设备树节点dev_node 中的数组成员enum irq_domain_bus_token bus_token;struct irq_domain_chip_generic *gc;
#ifdef	CONFIG_IRQ_DOMAIN_HIERARCHYstruct irq_domain *parent;
#endif
#ifdef CONFIG_GENERIC_IRQ_DEBUGFSstruct dentry		*debugfs_file;
#endif/* reverse map data. The linear map gets appended to the irq_domain */irq_hw_number_t hwirq_max; //硬件中断号最大编号,从0开始unsigned int revmap_direct_max_irq;unsigned int revmap_size;struct radix_tree_root revmap_tree; //对所有中断进行管理,键值为硬件中断号 struct mutex revmap_tree_mutex;unsigned int linear_revmap[];
};

四、中断使用流程

初始化流程
gic初始化如下
在这里插入图片描述
应用请求irq初始化
在这里插入图片描述
中断处理流程
在这里插入图片描述
中断的调试方式
cat /proc/interupts 显示硬件中断号,在各个CPU核上发生的情况;
sys/kernel/irq/XX/hwirq,可以查看到硬件中断号,XX为本机所有中断从0开始的逻辑号;
/proc/irq/XX/一些信息,可以看到中断的信息,XX为本机所有中断从0开始的逻辑号;

五、中断的扩展

底半部机制
1、工作队列
2、tasklet
3、软中断

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/398070.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

入门学习使用overleaf和latex

文章目录 1.下载对应的latex论文模板2.overleaf平台的使用2.1overleaf平台的介绍2.2overleaf平台模板文件的上传2.3latex语法的学习2.3.2 分段(如下图显示)2.3.3 其他2.3.4简单latex实操2.3.5 换行符和换页符2.3.6左右居中对齐2.3.7 字体设置2.3.8插入固定位置图片2.3.9文字包围…

基于区块链的数字身份应用开发(上)

基于区块链的数字身份应用开发(上) 任务一:环境准备 (1)更新镜像源 apt update(2)安装openssl、jdk、git (3)配置JAVA_HOME环境变量 echo "export JAVA_HOME/usr/lib/jvm/j…

HarmonyOS.FA开发流程

开发环境配置 1、DevEco Studio的安装 2、DevEcoStudio模拟运行工程:运行Tools->Device Manager,使用已认证的HW开发者联盟帐号Login(在DP平台申请测试者权限),点击"允许"授权,选择一个设备运…

Windows10、ARM开发板、虚拟机Ubuntu可同时上网

一、Windows10端设置 1、打开网络配置 2、打开适配器 3、将window连接的wifi网卡设置为共享模式 4、查看本地连接的ip 到此,window10端设置完毕 二、设置虚拟机端(Ubuntu) 1、打开网络配置 2、打开适配器 3、查看本地连接的网卡名称 4、配置…

docker RUN覆盖容器主进程命令

docker容器启动失败正常都是由于启动主进程退出导致的,主进程启动命令往往都是由镜像Dockerfile文件最后的ENTRYPOINT或CMD定义的,此时可覆盖主进程启动命令,更换一个挂起的命令即可。我常用挂起命令:/bin/bash 1、检查容器启动主…

Maven的理解与应用

Maven使用 一、Maven的含义 Maven是一个构建项目的工具,也是一个管理项目的工具 二、Maven的应用 构建项目 管理依赖 做项目的热部署 基于项目做多模块(modle)的构建 三、Maven的安装 注意:maven本身不需要安装,下…

机器学习笔记:门控循环单元的建立

目录 介绍 结构 模型原理 重置门与更新门 候选隐状态 输出隐状态 模型实现 引入数据 初始化参数 定义模型 训练与预测 简洁实现GRU 思考 介绍 门控循环单元(Gated Recurrent Unit,简称GRU)是循环神经网络一种较为复杂的构成形式…

【网络编程】UDP通信基础模型实现

udpSer.c #include<myhead.h> #define SER_IP "192.168.119.143" #define SER_PORT 7777 int main(int argc, const char *argv[]) {//1.创建int sfd socket(AF_INET,SOCK_DGRAM,0);if(sfd -1){perror("socket error");return -1;}//2.连接struct…

element-ui周选择器,如何获取年、周、起止日期?

说明 版本&#xff1a;vue2、element-ui2.15.14 element-ui的日期选择器可以设为周&#xff0c;即typeweek&#xff0c;官方示例如下&#xff1a; 如果你什么都不操作&#xff0c;那么获取的周的值为&#xff1a; value1: Tue Aug 06 2024 00:00:00 GMT0800 (中国标准时间)如…

asp.net医院权限管理系统

医院管理的设计与实现程序 医院管理系统asp.netsqlserver 医院权限管理系统sqlserver 挂号管理 挂号类型管理 挂号登记 挂号查询 药品管理 计量单位管理药 品分类管理 药品编辑 病人资料 病人资料录入 病人资料编辑 病人资料查询 住院管理 住院登记 住院查询办理出院 病例管理 …

鸿蒙HarmonyOS开发:如何灵活运用动画效果提升用户体验

文章目录 一、动画概述1、动画的目的 二、显式动画 (animateTo)1、接口2、参数3、AnimateParam对象说明4、示例5、效果 三、属性动画 (animation)1、接口2、参数3、AnimateParam对象说明4、系统可动画属性4、示例5、效果 一、动画概述 动画的原理是在一个时间段内&#xff0c;…

HAProxy原理及实例

目录 目录 haproxy简介 haproxy的基本信息 haproxy下载并查看版本 haproxy的基本配置信息 global配置 ​编辑多进程和多线程 启用多进程 启用多线程 haproxy开启多线程和多进程有什么用 proxies配置 defaults frontend backend listen socat工具 实例&#xff1a…

Particle Swarm Optimization粒子群算法

目录 1.粒子群算法入门 1.1 简单的优化问题 1.1.1 盲目搜索 1.1.2 粒子群算法流程图 1.1.3 粒子群算法的核心公式 1.1.4 预设参数 1.1.5 初始化粒子的位置和速度 1.1.6 计算适应度 1.1.7 循环体&#xff1a;更新粒子速度和位置 1.1.8 模型改进 2.深入研究粒子群算法 …

CLEFT 基于高效大语言模型和快速微调的语言-图像对比学习

CLEFT: Language-Image Contrastive Learning with Efficient Large Language Model and Prompt Fine-Tuning github.com paper CLEFT是一种新型的对比语言图像预训练框架&#xff0c;专为医学图像而设计。它融合了医学LLM的预训练、高效微调和提示上下文学习&#xff0c;展…

【Linux】线程同步与互斥

目录 线程相关问题 线程安全 常见的线程安全的情况 常见的线程不安全的情况 可重入函数与不可重入函数 常见不可重入的情况 常见可重入的情况 可重入与线程安全的关系 联系 区别 线程同步与互斥 互斥锁 使用 死锁 死锁的四个必要条件 如何避免死锁 条件变量 同…

Unity读取Android外部文件

最近近到个小需求,需要读Android件夹中的图片.在这里做一个记录. 首先读写部分,这里以图片为例子: 一读写部分 写入部分: 需要注意的是因为只有这个地址支持外部读写,所以这里用到的地址都以 :Application.persistentDataPath为地址起始. private Texture2D __CaptureCamera…

【JavaEE】初步认识多线程

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【Java】登神长阶 史诗般的Java成神之路 &#x1f3b7; 一.线程 1.概念 线程&#xff08;Thread&#xff09;是在计算机科学中&#xff0c;特别是操作系统领域里的一个关键概念。它是操作系统能够进行…

Android中的Binder

binder是Android平台的一种跨进程通信&#xff08;IPC&#xff09;机制&#xff0c;从应用层角度来说&#xff0c;binder是客户端和服务端进行通信的媒介。 ipc原理 ipc通信指的是两个进程之间交换数据&#xff0c;如图中的client进程和server进程。 Android为每个进程提供了…

【聚类算法】

聚类算法是一种无监督学习方法&#xff0c;用于将数据集中的数据点自动分组到不同的类别中&#xff0c;这些类别也称为“簇”或“群”。聚类的目标是让同一簇内的数据点尽可能相似&#xff0c;而不同簇之间的数据点尽可能不相似。聚类算法广泛应用于多种领域&#xff0c;如数据…

xtrabackup搭建MySQL 8.0 主从复制

xtrabackup搭建MySQL 8.0 主从复制 安装MySQL 8.0.37安装xtrabackupGTIDs初始化从库参考&#xff1a;GTID概述GTID相较与传统复制的优势GTID自身存在哪些限制GTID工作原理简单介绍如何开启GTID复制GTID与传统模式建立复制时候语句的不同点传统复制GTID复制 GTID同步状态简单解析…