ARMv8 GICv3 学习笔记(一)

GIC 介绍

众所周知,要想获取一个功能的执行状态,我们可以采用两种方式:

  1. 定时查询: 查询功能是否完成;
  2. 产生中断: 告诉CPU某个功能已经完成。

为了尽可能提高 CPU 处理数据的性能,提高获取功能完成状态的实时性,中断是一个很好的选择, 为什么还要一个中断控制器呢?直接将外设的中断引到 CPU 上不更简单吗?

  • 如果每个外设的中断都直接给到 CPU,外设数量众多导致连接 CPU 引脚数量增加 CPU 的体积增加
  • 如果同多个中断发生,CPU 需要自己维护中断,维护队列和判定优先级都会占用 CPU 的时间,降低 CPU 的性能

因此中断控制器就应运而生了,它是为了减少CPU的负载,让CPU更专注于计算。 中断控制器相当于一个代理,外设产生的中断会先发给中断控制器,中断控制器管理、控制可屏蔽中断,并且对中断的优先级进行判断,再将高优先级中断转交给CPU,CPU 既能专注计算又能及时响应到中断事件,并执行相应的中断服务程序。

image.png

当前主流芯片架构通常采用不同的中断控制器:

image.png

我们重点关注一下 ARM 使用的 GIC(Generic Interrupt Controller,通用中断控制器)中断控制器,它是ARM公司给 Cortex-A/R 内核提供的一个中断控制器,目前 GIC 有 4 个版本 GICv1~GICv4,V1是比较旧的版本当前已经被废弃了,下表总结了 GIC 的主要版本及应用的典型处理器:

image.png

GIC-v3 架构

GICv3 中断控制器的寄存器接口可分为三模块:

  • Distributor interface
  • Redistributor interface
  • CPU interface

通常,Distributor 和 Redistributor 用于配置中断,而 CPU 接口用于处理中断。

image.png

GIC 使用组优先级字段来确定待处理中断是否具有足够的优先级来抢占PE上的执行,具体规则如下:

  1. 中断的优先级值必须低于其优先级掩码的值
  2. 中断的组优先级字段的值必须低于 PE 上运行优先级的值

GICv3 为CPU处理所有连接到其上的中断,包括管理所有的中断源、中断行为、中断分组以及中断路由方式等,同时还提供相应的寄存器接口用于软件对这些行为的控制。设或软件触发中断后,GICv3根据中断配置信息,将其路由到特定 CPU 的 IRQ 或 FIQ 中断线上。CPU 接收到中断后执行必要的上下文保存后,跳转到中断异常入口,并执行相应的中断处理流程。

为了实现中断的配置、接收、仲裁和路由功能,GICv3 设计了不同组件如下:

PE (Process Element):处理器单元,中断的最终接收者和处理者。

Distributor: SPI 中断的管理,将中断发送给 Redistributor, 外设经特定硬件中断线连接到 Distributor, 判断 SPI 中断的优先级,决定优先处理哪个中断,同时维护中断的 active/pending/acknowledged 状态等,Distributor 提供了以下控制功能的接口:

  • 配置 SPIs 的中断优先级
  • 使能或者除能 SPIs
  • 生成基于消息信号的 SPIs
  • 控制 SPIs 的状态机
  • 每个 SPI 的路由信息
  • 设置 SPI 的触发模式,边沿触发或者电平触发

Redistributor: SGI PPI LPI 中断的管理,将中断发送给 CPU interface。每个PE对应了一个 Redistributor,它是 PPI/SGI/LPI 中断的管理者,决定它们的优先级,触发方式,控制它们的状态,以及 enable/disable 特定中断。Redistributor 提供了以下控制功能的接口:

  • 使能或除能 SGI 和 PPI
  • 配置 SGI 和 PPI 的优先级
  • 配置 PPI 的触发模式,边沿触发或者电平触发
  • 对每个 SGI 和 PPI 进行中断分组
  • 控制 SPI 和 PPI 的状态机
  • 控制 LPI 中断所需的配置信息表和 pending 状态表的内存基地址
  • 提供对所连接 PE 的电源管理

CPU interface: 传输中断给 PE, 每个 Redistributor 连接了一个CPU interface,它负责打开和关闭PE的中断处理能力,Acknowledge 中断,为PE维护一个中断优先级掩码(只响应更高优先级中断),定义中断抢占策略,执行中断降级等。CPU interface 提供了以下控制功能的接口:

  • 打开或关闭中断处理
  • 中断的应答
  • 中断处理完成,执行 priority drop and deactivation
  • 为 CPU 设置中断优先级掩码
  • 设置 CPU 的中断抢占(preemption)策略。
  • 在多个中断事件同时到来的时候,选择一个最高优先级的中断通知 CPU

ITS:ITS 接收消息信号,根据消息携带的 Event ID 和 Device ID,翻译得到物理中断号以及目标 PE 的编号或 目标 Redistributor 地址,ITS 与外设之间通过系统总线连接,外设采用写内存地址的形式发一个中断消息给 ITS。

中断的类型

GIC 通用中断控制器可以处理四种不同类型的中断源:

  1. 共享外设中断 Shared Peripheral Interrupt 简称 SPI,可以传递给任何连接的核心的外设中断。
  2. 私有外设中断 Private Peripheral Interrupt 简称 PPI,只传递给指定的一个核心的外设中断,例如来自通用定时器的中断就是 PPI 的一种。
  3. 软件生成中断 Shared Peripheral Interrupt 简称 SGI,通常用于处理器间通信,通过向 GIC 中的 SGI 寄存器写入来生成。
  4. 特定本地外设中断 Locality-specific Peripheral Interrupt 简称 LPI,首次在 GICv3 中引入,基于消息信号中断,具有与其他三种类型中断非常不同的编程模型。

每个中断源都由一个 ID 号标识,被称为 INTID,表中介绍的中断类型是根据中断的范围定义的:

image.png

中断信号传输

传统上,系统使用专用硬件连线,信号从外围设备到断控制器传递中断信号,如下图所示:

image.png

Arm CoreLink GICv3 支持这个模型,但也提供了一个额外的信令机制:消息信号中断 message-signaled interrupts 简称 MSI,MSI通过写入传输到中断控制器中的一个寄存器。如下图所示:

image.png

使用消息将中断从外围设备转发到中断控制器,消除了对每个中断源的专用信号线的要求,这对于大型系统的来说是一个优点,数百甚至数千个信号可能通过 SoC 路由并收敛到中断控制器上。在 Arm CoreLink GICv3 中,SPI 也可以支持通过消息信号发出,LPI则全部通过消息信号发出。他们可以通过不同的寄存器触发,如下:

image.png

中断状态机

中断控制器为每个 SPI、PPI 和 SGI 中断源维护一个状态机,此状态机由 4 种状态组成:

  1. 非活动状态 (Inactive) 当前并未 assert 该中断源
  2. 待定状态 (Pending) 中断源已被 assert ,但该中断尚未被 PE 应答 (ack)
  3. 活动状态 (Active) 该中断源已被 assert,并且该中断已被一个 PE 应答 (ack)
  4. 活动和待定状态 (Active and Pending) 该中断的一个实例已被应答 (ack),而另一个实例现在正在 pending

PS: 这里 Active and Pending 状态,我的理解是一个中断源可以产生多个中断或者叫中断实例 (instance),当中断源连续产生两个中断实例,前一个实例进入 active 状态,后一个实例进入 pending 状态,此时 Active and Pending 状态并不是描述这两个其中一个中断实例的状态,而是中断源的状态(这两个实例共享一个中断 ID 和 中断源),表示该中断源产生多了中断实例,一个正在被处理,剩下的正在等待。

image.png

上图中,中断选择哪种生命周期路径取决于它是被配置为电平触发模式还是边沿触发模式,二者主要区别在于:

  • 电平触发模式的中断,中断输入上的上升边缘导致中断进入 pending 状态,中断保持 asserted 直到外设 deassert 中断信号
  • 边沿触发模式的中断,中断输入上的上升边缘导致中断进入 pending 状态,但中断不会保持 asserted,也没有外设 deassert 掉。

例如下图的电平触发模式下中断的状态转换:

image.png

  1. Inactive to Pending, 当 assert 中断源时,中断将从 Inactive 状态转换为 Pending。此时如果中断被启用并且具有足够的优先级,那么 GIC 将向 PE assert 中断信号。
  2. Pending to Active & Pending, 当 PE 通过读取 CPU 接口中的一个中断确认寄存器(IAR)来 ACK 中断时,中断从 Pending 转换为 Active and Pending, 此时 GIC deassert 中断信号但外设还没有 deassert。
  3. Active & Pending to Active, 当外设 dessert 中断信号时,中断从 Active and Pending 转换为 Active。
  4. Active to Inactive, 当PE写入 CPU 接口中的中断结束寄存器(EOIR)时,中断从 Active 到 Inactive,这表明PE已经完成了对中断的处理。

总结下来有两个关键信息,当 GIC assert 外设中断时,此中断进去 Pending 状态进行等待,当 PE 应答 (ACK) 中断时,PE 立马处理该中断,但由于是电平触发模式,外设中断信号可能还处于 assert 状态,让中断进入一个中间过渡状态 Active & Pending,当外设 deassert 后才转为 Active,中断在 Active & Pending 时 PE 已经开始处理了。

例如下图的边沿触发模式下中断的状态转换:

image.png

  1. Inactive to Pending, 当 assert 中断源时,中断将从 Inactive 状态转换为 Pending。此时如果中断被启用并且具有足够的优先级,那么 GIC 将向 PE assert 中断信号。
  2. Pending to Active, 当 PE 通过读取 CPU 接口中的一个 IARs 寄存器来确认(ACK)中断时,中断将从 Pending 转换为Active。
  3. Active & Pending to Active, 如果外设 re-assert 信号,则中断将从 Active 转到 Pending to Active。
  4. Active & Pending to Pending, 当 PE 写入 CPU 接口中的一个 EOIR 寄存器时,中断从 Active & Pending 转 Pending。这表明 PE 已经完成了处理中断的第一个实例。此时,GIC 将向 PE 重新 assert 中断信号。

同样总结下来,中断状态机不是针对每个中断,而是针对每个中断源,边沿触发模式下的中断真正进入执行状态只需要 PE ACK 中断即可,不需要像电平触发模式还需要等待外设的 de-assert 信号,正常模式下只发出一个中断实例时的中断源状态只经历 Inactive -> Pening -> Active -> Inactive 转换,但在上图场景中,前一个中断实例正在被处理时,中断源状态机为 Active,同一个中断源又 assert 了一个中断实例,需要等待上一个中断实例完成(写 EOIR),才能让下一个中断实例进入,此时中断源状态为 Active & Pending 表示前一个中断实例的处理还未完成,后一个中断实例需要等待。

image.png

  • A1, A2. add pending state: 要么是外围设备产生中断的结果,要么是软件产生中断的结果。
  • B1, B2. remove pending state。
  • C. pending to active: PE 确认了对边缘触发的中断时, 当软件从 CPU 接口中读取一个 INTID 值时,就会发生这种转换
  • D. pending to active & pending: 这种转换发生在 PE 确认了电平触发模式的中断时
  • E1, E2. remove active state: 结束当前的中断实例时,后面没中断进入 Inactive,后面还有中断进入 Pending。

总结:当 PE ack 了中断,中断源进入 active 状态,当外设 assert 了中断,中断源进入 pending 状态,如果 ack 和 assert 同时发生,中断源就会进去 active & pending 状态。

中断的生命周期

了解了中断状态机,中断生命周期就好理解了:

image.png

  1. Generate:可以是外设也可以是软件
  2. Distribute:组件实现中断的分组,划分优先级并发送给 CPU 接口
  3. Deliver:CPU 接口将中断传输给对应的 PE
  4. Activate:当 PE ACK 中断后,将中断状态设置为 Active
  5. Priority drop:将当前中断的最高优先级进行重置,以便能够响应低优先级中断
  6. Deactuvation:将中断的状态,设置为 Inactive 状态

Priority drop 将在中断优先级章节详细介绍。

中断优先级

软件通过给每个中断源分配一个优先级值来配置 GIC 中的中断优先级。优先级值是一个 8 位的无符号二进制数。支持两个安全状态的 GIC 实现必须实现最少 32 个和最多 256 个物理优先级级别。只支持单个安全状态的 GIC 实现必须实现最少 16 个和最多 256 个物理优先级级别。如果 GIC 实现的优先级级别少于 256 个,则优先级字段的低位将被设置为 RAZ/WI(保留为零/写入忽略)。这意味着实现的优先级字段位数由实现定义:

image.png

在 GIC 的优先级化方案中,较低的数值具有较高的优先级。优先级字段值 0 始终表示最高可能的中断优先级,而最低优先级值取决于实现的优先级级别数量。

GICD_IPRIORITYR 寄存器保存每个支持的 SPI 的优先级值,该寄存器的个数为 255 个,因为实现可以为特定目的保留一个 SPI,并分配一个固定的优先级给该中断,该中断的优先级值是只读的,对于其他SPI,软件可以写入 GICD_IPRIORITYR 寄存器来设置中断优先级。

image.png

在多处理器实现中,GICR_IPRIORITYR 和 GICR_IPRIORITYRE 寄存器为每个目标 PE 独立定义了每个 SGI 和 PPI INTID 的中断优先级,针对 LPI 类型的中断,主要通过在内存中的 LPI 配置表存储关于 LPI 的优先级信息,而不是寄存器。

image.png

优先级重置

关于 Priority drop,需要先了解 Running priority and preemption (抢占)。

在 CPU 接口中,需要设置优先级掩码寄存器,来指定中断必须转发到 PE 的最小优先级。GICv3 体系结构也具有运行优先级的概念。当 PE 确认一个中断时,中断的优先级就会赋给运行优先级。当 PE 写入中断结束(EOI)寄存器时,运行的优先级会返回到以前的值。下图显示了PE随时间的运行优先级的示例:

image.png

在使用中断抢占策略时,运行优先级的概念就很重要了。当高优先级中断发送到已经在处理低优先级中断的 PE 时,就会发生抢占。抢占为软件带来了一些额外的复杂性,但它可以防止低优先级中断阻止对高优先级中断的处理。

image.png

如上图,不启用抢占功能时,高优先级中断会被阻止,直到低优先级中断完成后进行 Priority drop 优先级重置回复到之前的运行时优先级才能处理后面的高优先级。

image.png

开启抢占功能时,当高优先级中断变为 Pending ,它优先于先前发出信号的低优先级中断。上图显示了一个级别的抢占。然而,也有可能有多个层次的 抢占。Arm CoreLink GICv3 架构允许软件通过指定抢占发生所需的优先级规则来控制抢占。这是通过二进制点寄存器来控制的: ICC_BPRn_EL1。

组优先级和子优先级

二进制点寄存器将优先级值分成两个字段:组优先级和子优先级。在确定抢占时,具有相同组优先级的所有中断被认为具有相同的优先级,而不考虑子优先级。

image.png

对于抢占只考虑组优先级位忽略子优先级位,二进制点寄存器只影响抢占策略

例如,考虑以下三个中断:INTID A 的优先级为0x10,INTID B 的优先级为0x20, INTID C 的优先级为0x21。在这个例子中,我们需要的抢占策略为:A 可以抢占 B 或 C,但 B 不能抢占 C, B 和 C 有相似的优先级。为了实现这一点,可以将组和子优先级之间的划分设置为 N=4,有了这种分裂,B 和 C 有相同优先权,然而 A 仍然有更高的优先级,如下图:

image.png

GIC 使用组优先级字段来确定待处理中断是否具有足够的优先级来抢占PE上的执行,具体规则如下:

  1. 中断的优先级值必须低于其优先级掩码的值
  2. 中断的组优先级字段的值必须低于 PE 上运行优先级的值

image.png

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
# 学习对象在全民造车、造芯的大时代,在努力去解决卡脖子的时代,ASIC硬件、SOC底层软件、Linux Kernel等操作系统软件(内核/驱动)、软硬件方面的系统架构师等的岗位需求也越来越明显,社会一直都是非常缺人的,缺的是核心的那一小撮、领头的那一小撮,社会所缺的更是能够软硬件融合的那一小撮人……总之,要想在这个时代,站稳自己的脚跟,能够在大公司或行业上拥有一席之地,就必需深入学习底层技术原理,核心技术才是您的看家本领。本课程设计之初,主要针对SOC底层软件开发的者、系统开发者,或者励志成为这样的人。既适合资深/高级工程师来查缺补漏,又适合初级工程师入门。(理论上该课程和ASIC硬件电路设计无关,该课程偏软件,但事实购买该课程的做ASIC的同学已然超过了15%)适用人群1、芯片开发者(包括底层软件、或做ASIC硬件的)。不限行业,例如车、云、物联网、移动端等领域;2、汽车行业开发者(主机厂、tier1、SOC厂家、各级供应商);3、嵌入式开发者、kernel开发者、驱动、软件工程师;4、学生。既适合学生从入门到精通,也适合资深工程师查缺补漏;您的收益:1、全体系的掌握ARMv8/ARMv9的核心知识点(ARM基础、异常中断GIC、MMU/Cache、architecture...);2、掌握ARM架构、掌握SOC架构、掌握常规IP(gic、smmu、timer、AXI/ACE/CHI、TZC400...);3、快速熟悉常规系统软件(bootrom、spl、ATF、TEE、bootloader、kernel...), Secureboot安全启动...4、技术水平提升N个level, 掌握快速的学习方法;# 学习什么在ARM蓬勃发展的年代,不仅仅涉及到物联网IOT、移动领域(如手机)、汽车电子领域,现在还涉及到PC、服务器的,简直就是各行各业。ARMv8出来已经有10年了,ARMv9也2年时间了。在技术不断更新迭代的背景下,此时再去学习十五年前的ARMv7、二十年前的ARMv5/v6显然不是明智的选择。本课程主要基于当前最新的架构,ARMv8的aarch64和ARMv9,如涉及具体的ARM Core IP主要还是以最新的ARM Core IP为主,软件架构也是以当前最主流的/未来所趋势的架构来讲解。以下也给大家列举初了一个ARM产品的timeline的总结(在本课程中有着大量的这种总结),从这张图中,您是可以清晰的看到本课程拥有独具一格的风格、拥有全网最新(且唯一)的资料总结或学习路线。# 本课程大纲和规划(课程持续更新中,课程总量统计:2022/10/02  当前是 61节课, 22小时)第一章:主要是快速学习: ARM简介、指令集、寄存器总结等。第二章:本系列视频的一大亮点,系统全面地讲解了arm异常中断gic等相关的软硬件知识,本人一直在倡导“学arm安全其实就是学arm架构,学arm架构其实就是学习arm的异常和中断”,异常中断是领着你进入架构的入门,是让你变成系统软硬件架构师的必走之路。第三章:安全专题,这也是本视频最核心的东西。因为你无论买书还是看博客等,你都很难找到讲解安全的教程,这里就是有和无的区别。本人系统的整理的安全的知识,带领你快速入门。第四章:mmu专题,透过事务看本质的讲解,白话式的演讲。在所有模块中,mmu也算是相对较简单模块。相信人人听得懂,人人学得会。第五章:cache专题,一切追求实事求是,不人云亦云,一切知识点都有迹可循,推翻了网络的很多观念。在众多模块中,cache算是一个比较难的模块。了解了cache后,才能算真正了解系统的软硬件架构。第六章:虚拟化,本人不擅长,会啥就随便讲点啥。(以后学会了再来补)第七章:architecture,就是零散和零碎的系统架构知识,如exclusive、arch timer、reset、系统启动、SOC设计、AMBA/AXI/ACE、DSU、WFE/WFI这样的。第八章: 新增的ARMv9 CCA/RME安全架构专题第九章:主要放置一些直播课。# 课程收益1、知道我学习什么,我要怎么去学习,从此之后有了一个明确的学习路线。2、认识一些共同目标的人,相互讨论问题,共同进步。勤学、共学、助学。3、ARM不再神秘,SOC不在神秘,让您短期内就能cover住全局4、熟悉ARM Architecture架构知识5、熟悉SOC架构知识6、熟悉主流的系统软件框架7、熟悉各项硬件原理和机制,如异常中断、MMU、cache、TLB、VMSA、Trustzone6、深入了解当前的系统架构、软硬件架构,能够看懂这些大家,将来也能够自己设计。7、熟悉系统的启动流程、Secureboot等8、熟悉各类标准和规范9、能够进入芯片厂商干活、能够在非芯片产生成为技术担当。10、学习资料的获取方法,会看11500多页的ARM手册,会看数以百计的ARM各项参考手册。 本课程会持续更新。也希望通过本课程的学习,能够让大家的ARMv8/ARMv9开发技术能有质的飞越,能找到自己心仪的工作。在购买之前,也建议大家看一看第一章第一节的课程介绍。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值