arm64架构的linux中断分析(一)

文章目录

    • 1. 中断的概念和作用
    • 2. Linux中断处理机制
      • 2.1 中断请求
      • 2.2 中断处理
      • 2.3 中断完成
      • 2.4.中断触发和处理步骤详解
        • 2.4.1 异常向量表的解读
      • 2.5 硬件中断号和软件中断号

1. 中断的概念和作用

当计算机的CPU需要在执行任务的同时响应外部事件时,中断是一种重要的机制。中断是异步事件的一种形式,这是指发起事件与处理事件之间的时间间隔没有固定的模式,而是在不同的时间点发生的。

在计算机系统中,中断可分为软件中断和硬件中断两类。在软件中断中,中断是由CPU执行的一条特殊指令造成的,它用于暂停CPU的正常执行流程,然后转而执行一个内部事件或处理程序。硬件中断则是由硬件设备发出的,它与处理器无关,并向CPU发出中断请求信号。

中断的作用主要有以下几个方面:

  1. 响应外部事件:当外部事件发生时,中断能够及时响应并引导CPU执行事件处理程序,保证事件能够得到及时处理。

  2. 提高系统效率:CPU无需主动地去轮询外部设备是否有数据需要处理,中断机制可以使CPU在处理器时间的同时响应必要的事件处理。

  3. 处理复杂任务:某些外部事件处理需要一段复杂的代码,中断处理程序可以协助CPU快速完成这些复杂任务。

  4. 进行设备驱动:硬件设备的驱动需要中断的支持,来达到与CPU通讯和协调工作的目的。

2. Linux中断处理机制

Linux操作系统具有广泛的应用,它的中断处理机制是实时、高效和可扩展的。Linux中断处理机制采用了事件驱动模型,对中断按照优先级进行排队,以确保最优先处理高优先级事件,同时保证低优先级事件不会被阻塞。下面从中断请求、中断处理和中断完成三个方面介绍Linux中断处理机制。

2.1 中断请求

在Linux中,中断被认为是分离的、独立的事件,因此中断的处理必须是实时的,使用优先级表进行调度和排序。Linux内核实现了基于可插拔中断体系结构的抽象机制,从而可以在处理器和设备机制之间提供更好的耦合性和深入性。这种体系结构允许中断请求线共享,提高了系统的可扩展性和可靠性,提升了系统的响应速度和性能表现。
当一个硬件设备需要处理器的处理时,它将通过硬件 Intline 请求一个中断。中断请求将被系统中断控制器传递,并被处理器接收。 Linux 支持多个中断请求,通常使用 PCI 设备接口来实现。当控制器接收到中断请求后,它会将请求传递给 Linux 中的 IRQ 子系统,于是就有了一个中断。

2.2 中断处理

中断处理是指系统响应中断事件的过程,它通常包含以下几个步骤:

  • 中断调度:中断请求被发送到CPU中心处理器上的中断控制器后,由硬件中断控制器将中断信号传递到内核。Linux内核根据中断向量号找到对应的中断处理程序。
  • 应答中断:内核通过设置正确的输入 / 输出引脚响应中断,这样中断控制器就可以发送指令将中断信息传递给 CPU。
  • 中断上下文的保存:当内核处理中断时,必须保存当前进程运行的上下文,为后续恢复工作做好准备。
  • 中断处理程序运行:中断程序处理中断,执行需要的中断服务程序,并最终返回到主线程。
  • 中断恢复工作:恢复中断执行前的上下文,这包括无序通知的应用程序。

2.3 中断完成

当中断处理完成后,处理器会向中断控制器发送完成中断的信号。中断控制器将中断信号发送回硬件设备。在中断完成的过程中,主要包含以下几个步骤:

  1. 中断状态恢复:在中断处理过程中,处理器会保存中断处理程序执行前的所有中断状态,包括进程的上下文、寄存器和状态字等。因此,在中断处理程序执行结束后,处理器需要通过对这些状态进行恢复,来重新运行之前被中断的进程。

  2. 设备控制器响应:当设备控制器接收到中断完成信号后,将在下一个可用的时钟周期中恢复设备操作,以继续处理新的输入或输出请求。此时,处理器将会准备新的请求或服务,以响应下一次中断请求。

中断完成是中断处理机制的最后一个阶段,通过该阶段可以使得设备控制器继续其后续的工作,同时为下一次中断请求做好准备。

2.4.中断触发和处理步骤详解

我们以gpio中断位例子讲解一下arm64中断的完整流程,先看看cpu到gpio的硬件上是怎么样的一个关系:
在这里插入图片描述
看到上面这个图片我们可以看到中断触发的流程:外部设备(比如按键)→GPIO控制器→GIC→CPU。
当触发流程走到cpu后,cpu会跳转到中断异常向量表,执行后面的操作:读取GIC信息,了解到是GPIO触发的中断,再读取GPIO控制器的信息,了解到是某一个GPIO的外设导致的,执行这个外设的中断处理函数。
看到上面这个简单的过程,感觉还是很不清晰。

arm64中断初始化,cpu接受到中断后为什么会自动跳转到异常向量表呢?
这是因为linux初始化的时候,会把异常向量表vectors的地址写入到vbar_el1寄存器中,我们linux内核触发了中断,则会自动跳转到vbar_el1这个这个地址上运行。具体初始化可以查看linux内核启动分析(一)。

我们再看看异常向量表是怎么样的,linux的异常向量表代码在arm64\kernel\entry.S:

SYM_CODE_START(vectors)
	kernel_ventry	1, sync_invalid			// Synchronous EL1t
	kernel_ventry	1, irq_invalid			// IRQ EL1t
	kernel_ventry	1, fiq_invalid			// FIQ EL1t
	kernel_ventry	1, error_invalid		// Error EL1t

	kernel_ventry	1, sync				// Synchronous EL1h
	kernel_ventry	1, irq				// IRQ EL1h
	kernel_ventry	1, fiq_invalid			// FIQ EL1h
	kernel_ventry	1, error			// Error EL1h

	kernel_ventry	0, sync				// Synchronous 64-bit EL0
	kernel_ventry	0, irq				// IRQ 64-bit EL0
	kernel_ventry	0, fiq_invalid			// FIQ 64-bit EL0
	kernel_ventry	0, error			// Error 64-bit EL0

#ifdef CONFIG_COMPAT
	kernel_ventry	0, sync_compat, 32		// Synchronous 32-bit EL0
	kernel_ventry	0, irq_compat, 32		// IRQ 32-bit EL0
	kernel_ventry	0, fiq_invalid_compat, 32	// FIQ 32-bit EL0
	kernel_ventry	0, error_compat, 32		// Error 32-bit EL0
#else
	kernel_ventry	0, sync_invalid, 32		// Synchronous 32-bit EL0
	kernel_ventry	0, irq_invalid, 32		// IRQ 32-bit EL0
	kernel_ventry	0, fiq_invalid, 32		// FIQ 32-bit EL0
	kernel_ventry	0, error_invalid, 32		// Error 32-bit EL0
#endif
SYM_CODE_END(vectors)

2.4.1 异常向量表的解读

其实,在 ARM64 体系结构中,异常分为同步异常和异步异常。
同步异常是试图执行指令时生成的异常,或是作为指令的执行结果生成的异常。同步异常包括如下。

  1. 系统调用。异常级别 0 使用 svc指令陷入异常级别 1,异常级别1 使用hv指令陷入异常级别2,异常级别 2 使用 smc指令陷入异常级别 3。
  2. 数据中止,即访问数据时的页错误异常,虚拟地址没有映射到物理地址,或者没有写权限。
  3. 指令中止,即取指令时的页错误异常,虚拟地址没有映射到物理地址,或者没有执行权限。
  4. 栈指针或指令地址没有对齐。
  5. 没有定义的指令。
  6. 调试异常。

异步异常不是由正在执行的指令生成的,和正在执行的指令没有关联。异步异常包括以下。

  1. 中断(normal priority interrupt,IRQ),即普通优先级的中断。
  2. 快速中断(fast interrupt,FIQ),即高优先级的中断。
  3. 系统错误(System Error,SError),是由硬件错误触发的异常,例如最常见的是把脏数据从缓存行写回内存时触发异步的数据中止异常。

当异常发生的时候,处理器需要执行异常的处理程序。存储异常处理程序的内存位置称为异常向量,通常把所有异常向量存放在一张表中,称为异常向量表。对于 ARM64 处理器的异常级别 1、2 和 3,每个异常级别都有自己的异常向量表,异常向量表的起始虚拟地址存放在寄存器 VBAR_ELn(向量基准地址寄存器,Vector Based Address Register)中。每个异常向量表有 16 项,分为 4 组,每组 4项,每项的长度是 128 字节(可以存放32 条指令)中。

我们看到有4组,每一组的4项都是分别表示发生了同步异常,irq,firq和系统错误。这4组的区别就是,第一组表示异常发生在EL0,处理异常的特权等级也是EL0。第二组表示异常发生在ELn(n可以为1,2,3),处理异常的特权等级也是ELn(n可以为1,2,3),但是这里是linux内核,所以我们的特权为EL1,我们可以理解为异常发生在EL1,处理异常的特权等级也是EL1。这两组的共同点是异常的发生和处理在同一个特权级别,不需要进行特区那级别的切换;而后面两组则是异常的发生和处理不在同一个特权级别,需要进行特区那级别的切换。在linux这里就是说,第三组和第四组表示异常发生在EL0,但是异常处理却在EL1,而他们的区别就是,第三组表示异常发生在64位环境下,第四组表示异常发生在32位环境下。
我们现在知道这4组,16项的含义了,我们看fiq都是invalid的,是因为linux不支持fiq,所以没有对fiq异常进行处理。我们也看到第一组都是invalid的,是因为EL0发生了异常,不会在EL0处理,会陷入EL1处理,所以第一组也不需要实现。
第二组第一项kernel_ventry 1, sync ,在这里就是b el1_sync ,也就是跳转到el1_sync函数了。到这里,我们把每一项支持的异常向量跳转函数写成表格就是:

异常向量跳转的函数
kernel_ventry 1, syncel1_sync
kernel_ventry 1, irqel1_irq
kernel_ventry 1, errorel1_error
kernel_ventry 0, syncel0_sync
kernel_ventry 0, irqel0_irq
kernel_ventry 0, errorel0_error
kernel_ventry 0, sync_compat, 32el0_sync_compat
kernel_ventry 0, irq_compat, 32el0_irq_compat
kernel_ventry 0, error_compat, 32el0_error_compat

也就是说linux在用户态触发中断会执行el0_irq,在内核态触发中断会执行el1_irq,这两个的代码看下面:

SYM_CODE_START_LOCAL_NOALIGN(el0_irq)
	kernel_entry 0
el0_irq_naked:
	el0_interrupt_handler handle_arch_irq
	b	ret_to_user
SYM_CODE_END(el0_irq)

SYM_CODE_START_LOCAL_NOALIGN(el1_irq)
	kernel_entry 1
	el1_interrupt_handler handle_arch_irq
	kernel_exit 1
SYM_CODE_END(el1_irq)

我么可以看到他们都是执行函数handle_arch_irq函数,最后返回各自的状态。handle_arch_irq在下面的gic控制器的初始化过程中会设置的。

2.5 硬件中断号和软件中断号

硬件中断号是中断控制器自己定义的中断号,每一个中断控制器都有0到n不同数量的中断号,用于识别连接到中断控制器的不同的硬件设备发生的中断事件。比如,GIC这个中断控制器,0-15是SGI中断,16-31是PPI中断,32-1023是SPI中断,我们的设备到是连接到SPI中断上的,甚至GPIO中断控制器也是连接到SPI上面的。GPIO中断控制器自己也有这0-n的中断。所以硬件中断号是某一个中断控制器上的硬件标识。

软件中断号,有时候也叫虚拟中断号,是由内核定义的中断号,用于执行内核函数或服务。软件中断号是预定的,由系统中的中断控制器管理。硬件中断号的产生都会分配一个对应的软件中断号。所以软件中断号硬件无关,仅仅是被CPU用来标识一个外设中断,便于系统管理所有的中断。

这样,CPU和终中断控制器在标识中断上就有了一些不同的概念,但是,对于驱动工程师而言,我们和CPU视角是一样的,我们只希望得到一个软件中断号,而不关系具体是那个interrupt controller上的那个硬件中断号。这样一个好处是在中断相关的硬件发生变化的时候,驱动软件不需要修改。因此,linux内核中的中断子系统需要提供一个将硬件中断号映射到软件中断号上来的机制。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

6月份读书学习好文记录

看看CHATGPT在最近几个月的发展趋势 https://blog.csdn.net/csdnnews/article/details/130878125?spm1000.2115.3001.5927 这是属于 AI 开发者的好时代,有什么理由不多去做一些尝试呢。 北大教授陈钟谈 AI 未来:逼近 AGI、融进元宇宙,开源…

kafka消息队列的初步探索

消息队列的作用就是提高运行速度,防止线程堵塞。 kafka的作用 异步 通过在消息队列发送消息的方式,将对应的业务作为监听者,此时我们只需要考虑发送消息的时间即可,大大提高了运行的速度。 解耦 如果使用原来的直接调用对应业务的…

Spring高手之路6——Bean生命周期的扩展点:BeanPostProcessor

文章目录 1. 探索Spring的后置处理器(BeanPostProcessor)1.1 BeanPostProcessor的设计理念1.2 BeanPostProcessor的文档说明 2. BeanPostProcessor的使用2.1 BeanPostProcessor的基础使用示例2.2 利用BeanPostProcessor修改Bean的初始化结果的返回值2.3 …

Nacos配置中心交互模型是push还是pull?

对于Nacos大家应该都不太陌生,出身阿里名声在外,能做动态服务发现、配置管理,非常好用的一个工具。然而这样的技术用的人越多面试被问的概率也就越大,如果只停留在使用层面,那面试可能要吃大亏。 比如我们今天要讨论的…

leetcode216. 组合总和 III(回溯算法-java)

组合总和 III leetcode216. 组合总和 III题目描述解题思路代码演示 回溯算法专题 leetcode216. 组合总和 III 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/combination-sum-iii 题目描述 找出所有相加之和为 n 的 k 个…

ldsc python程序安装以及测试

教程参考: https://zhuanlan.zhihu.com/p/379628546https://github.com/bulik/ldsc 1. 软件安装 1.1 windows安装教程 首先配置: anaconda,为了需要conda环境git,为了下载github中的ldsc程序 打开windows电脑中的promote&am…

阿里云服务器价格如何?与其他云服务提供商的价格对比如何?

阿里云服务器价格如何?与其他云服务提供商的价格对比如何?   阿里云服务器价格概述   作为全球领先的云计算服务提供商,阿里云在确保服务器性能和安全性的同时,也非常注重产品的价格竞争力。阿里云服务器(ECS&…

基于STM32 ARM+FPGA的电能质量分析仪方案(一)硬件设计

本章主要给出了本系统的设计目标和硬件设计方案,后面详细介绍了硬件电路的设计 过程,包括数据采集板、 FPGAARM 控制板。 3.1系统设计目标 本系统的主要目的是实现电能质量指标的高精度测量和数据分析,其具体技术指标如 下所示&#xff1…

微服务中常见问题

Spring Cloud 组件 Spring Cloud五大组件有哪些? Eureka:注册中心 Ribbon:负载均衡 Feign:远程调用 Hystrix:服务熔断 Zuul/Gateway:服务网关 随着SpringCloud Alibaba在国内兴起,我们项目中…

C语言/C++ 之 打飞机游戏

【项目简介】 1、设计思想:本项目主要是为了实现打飞机游戏,主要包括5个函数模块,和1个主函数框架。分别是chu_shi_hua();、you_cao_zuo;、wu_cao_zuo();、show();、main();等。项目完成过程中主要运用了C/C中的输入输…

网络爬虫是什么

网络爬虫又称网络蜘蛛、网络机器人,它是一种按照一定的规则自动浏览、检索网页信息的程序或者脚本。网络爬虫能够自动请求网页,并将所需要的数据抓取下来。通过对抓取的数据进行处理,从而提取出有价值的信息。 认识爬虫 我们所熟悉的一系列…

3 python进阶篇

文章目录 面向对象类属性和类方法类属性类方法静态方法 单例模式__new__ 方法类实现单例模式 异常 、模块和包异常自定义异常 模块和包模块的搜索顺序包的init文件发布模块(了解) 文件seek文件/目录的常用管理操作eval函数 补充性知识位运算小技巧 参考我…

Python入门教程:掌握for循环、while循环、字符串操作、文件读写与异常处理等基础知识

文章目录 for循环while循环字符串操作访问字符串中的字符切片总结字符串拼接 文件读写try...except 异常处理函数模块和包类和面向对象编程完结 for循环 在 Python 中,for 循环用于遍历序列(list、tuple、range 对象等)或其他可迭代对象。for…

Java中反射机制,枚举,Lambda的使用

目录 一、反射机制 1、含义 2、作用 3、※反射相关的几个类 3.1、Class类(Class对象是反射的基石) 3.2、Class类中相关的方法 3.2.1 (※重要)常用获得类相关的方法 3.2.2 (※重要)常用获得类中属性、变量Field相关的方法 3.2.3 获得类中注解相…

N-Gram语言模型工具kenlm的详细安装教程

【本配置过程基于Linux系统】 下载源代码: wget -O - https://kheafield.com/code/kenlm.tar.gz |tar xz 编译: makdir kenlm/build cd kenlm/build cmake .. && make -j4 发现报错: 系统中没有cmake,按照错误提示&am…

ChatGPT 指南:角色扮演让回答问题更专业

让 ChatGPT 进行角色扮演 Act as ...,比如,律师、内科医生、心理医生、运动教练、哲学家、翻译、平面设计师、IT 工程师等等,从而才能让 ChatGPT 从这个角色角度来分析我们的问题,不然,它的回答可能会过于广泛。 下面以…

实在智能RPA亮相2023全球人工智能技术博览会,“能对话的数字员工”引领智能自动化新篇章

随着ChatGPT火爆全网,人工智能再次成为学术界和科技领域“新宠”,一场“智能革命”的序幕悄然掀开。 6月13日,“智能驱动 砥砺前行”为主题的2023全球人工智能技术博览会在杭州未来科技城学术交流中心圆满落下帷幕。此次博览会以展示智能科技…

51单片机 - 期末复习重要图

AT89S51片内硬件结构 1.内部硬件结构图 2.内部部件简单介绍 3. 26个特殊功能寄存器分类 按照定时器、串口、通用I/O口和CPU 中断相关寄存器:3IE - 中断使能寄存器IP - 中断优先级寄存器 定时器相关寄存器6TCON - 定时器/计数器控制寄存器TMOD - 定时器/计数器模…

【Leetcode60天带刷】day07哈希表——454.四数相加II , 383. 赎金信 ,15. 三数之和 , 18. 四数之和

题目&#xff1a;454.四数相加II 454. 四数相加 II 给你四个整数数组 nums1、nums2、nums3 和 nums4 &#xff0c;数组长度都是 n &#xff0c;请你计算有多少个元组 (i, j, k, l) 能满足&#xff1a; 0 < i, j, k, l < nnums1[i] nums2[j] nums3[k] nums4[l] 0 …

神经网络:参数更新

在计算机视觉中&#xff0c;参数更新是指通过使用梯度信息来调整神经网络模型中的参数&#xff0c;从而逐步优化模型的性能。参数更新的作用、原理和意义如下&#xff1a; 1. 作用&#xff1a; 改进模型性能&#xff1a;参数更新可以使模型更好地适应训练数据&#xff0c;提高…
最新文章