【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

1.概述

本文介绍:

  1. GICv3中断控制器的相关操作
  2. 如何在裸机环境下配置GICv3中断控制器

本文是_Arm CoreSight Generic Interrupt Controllers_相关指南的三部曲其一:

  • Arm CoreLink Generic Interrupt Controller v3 and v4: Overview (this guide)
  • Arm CoreLink Generic Interrupt Controller v3 and v4: Locality-specific Peripheral Interrupts
  • Arm CoreLink Generic Interrupt Controller v3 and v4: Virtualization

1.1 背景

GIC两个至关重要的作用:优先级排序和路由。

GIC可以提高处理器效率以及使能中断虚拟化。

GICs的实现基于Arm GIC架构。这个架构由GICv1发展到最新的 GICv3 和 GICv4 版本。Arm设计了若干通用中断控制器,向Arm Cortex多处理器系统提供一系列的中断管理方案。这些控制器的范围从用于CPU核数较少的系统的最简单的GIC-400到用于高性能和多芯片系统的GIC-600。GIC-600AE为高性能ASIL B系统增加了额外的安全功能。

看完本文,你将学会:

  • 不同类型的中断
  • 能够编写代码,使能FIC以及配置不同的中断类型

2.开始之前

本指南涵盖了GICv3和v4的基本操作,以及共享外围中断(spi)、私有外围中断(PPIs)和软件生成中断(SGIs)的使用。本文是对Arm Generic Interrupt Controller Architecture Specification GIC architecture version 3.0 and 4.0的补充。

GICv3和GICv4允许不同的配置和用例。为了简单起见,本指南集中于这些配置和用例的子集,其中:

  • 存在两种安全状态
  • 每一种安全状态的Affinity路由使能
  • 所有异常等级的系统寄存器访问使能
  • 处理器兼容Armv8-A,所有异常等级都实现且每种异常等级都使用AArch64

本文不包括:

  • Legacy operation
  • 使用AArch32

前置知识:异常模型

3.什么是通用中断控制器(Generic Interrupt Controller)

GIC处理来自外设的中断,根据优先级排序,将中断分发到合适的处理器核。下图显示了一个GIC接收来自n个不同外设的中断,并将它们分配给两个不同的处理器。

【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

GIC是Arm Cortex-A和Arm Cortex-R处理器的标准中断控制器。

3.1 Arm CoreLink GIC简史

主要特征
GICv1 支持8个处理单元
支持1020个中断号
支持两种安全状态
GICv2 所有GICv1的主要特征
支持虚拟化
GICv3 所有GICv2的主要特征
支持超过8个处理单元
支持消息信号中断
系统寄存器访问CPU接口寄存器
安全模型增强:分离了安全和非安全的Group 1中断
GICv4 所有GICv3的主要特征
直接注入虚拟中断

本文涵盖了Arm CoreLink GICv3和GICv4,它们被大多数Armv8-A和Armv8-R设计所使用。

版本小更新:

  • GICv3.1:
    • 增加了支持额外的有线中断,安全虚拟化和内存系统资源
    • 分区和监视(MPAM)
  • GICv4.1:
    • 扩展的虚拟化支持,包括直接注入虚拟软件生成的中断(SGIs)

4.Arm CoreLink GIC基本原理

在本节中,我们将看看Arm CoreLink GICv3和v4中断控制器的基本操作。

4.1 中断类型

GIC可以处理四种不同类型的中断源:

  • SPI:可以转发给任意相关的核
  • PPI:属于某个核私有。例如通用计时器
  • SGI(Software Generated Interrupt):典型用于处理器间通信。向GIC中的SGI寄存器写值将生成SGI。
  • LPI(Locality-specific Peripheral Interrupt)(不太懂):Arm CoreLink Generic Interrupt Controller v3 and v4: Locality-specific Peripheral Interrupts一文中介绍了LPI的配置

每个中断源都由一个ID号标识,这个ID号被称为INTID。上述列表中引入的中断类型是根据intid范围定义的:

INTID 中断类型 注释
0 - 15 SGIs Banked per PE
16 – 31
1056 – 1119 (GICv3.1)
PPIs Banked per PE
32 – 1019
4096 – 5119 (GICv3.1)
SPIs
1020 - 1023 特殊的中断号 详情见5.2
1024 - 8191 Reserved
8192~ LPIs 上线由具体厂家定义

4.1.1 中断如何通知中断控制器

传统上,中断使用专用硬件信号从外设发送到中断控制器,如下图所示:

【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

Arm CoreLink GICv3增加了一种信号机制:message-signaled interrupts (MSI)。MSI通过向中断控制器的寄存器写值发送。如下:

【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

通过消息发送中断,中断源无需专门的信号。

这两种发送中断的方式对于中断如何处理几乎没有影响。可能需要一些对外设的配置。例如,可能需要指定中断控制器的地址。外设的配置不在本文范畴之内。

Arm CoreLink GICv3中,SPI可以是message-signaled中断。LPI总是message-signaled中断。不同的寄存器用于不同的中断类型,如下所示:

中断类型 寄存器
SPI GICD_SETSPI_NSR 断言中断
GICD_CLRSPI_NSR解除中断
LPI GITS_TRANSLATER

4.2 中断状态机

中断控制器为每个SPI、PPI和SGI中断源维护一个状态机。这个状态机包含四个状态:

  • Inactive:中断源当前没有断言
  • Pending:中断源已经断言,但是没有PE接收。
  • Active:中断源已经断言,且已被PE接收
  • Active and Pending:一个中断已被接收,另一个中断在排队。

注意:LPIs有着类似的状态机。详情请查看6.2节。

状态机如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-syx4n2lg-1610113945096)(https://image-1304693124.cos.ap-shanghai.myqcloud.com/img/image-20210107213122412.png)]

中断的生命周期取决于它是被配置为电平触发还是边沿触发:

  • 对于电平敏感的中断,在中断输入上的上升边缘会导致中断成为挂起,并且中断被保持,直到外围设备解除中断信号。
  • 对于边缘敏感中断,在中断输入上的上升边缘会导致中断成为挂起,但是中断不会被保持。

4.2.2 边沿触发中断

下图显示了中断状态转换与中断信号的对应关系:

【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

依次考虑每个状态转换:

  • 从Inactive到pending:发生在中断源被断言的时候。如果中断使能且优先级适当,那么GIC就向PE断言了中断信号

  • 从Pending到active:发生在PE通过读取CPU接口中的IAR寄存器接收中断的时候。这个读取通常发生在中断异常发生之后,属于中断处理过程的一部分。但是,软件也可以轮询IAR。这种时候GIC将解封(de-asserts)中断信号。

  • 从Active到active and pending:发生在外设重新断言中断信号的时候。

  • 从Active and pending到pending:发生在PE写某一个CPU接口中的EOIR寄存器的时候。此时PE已经处理完了第一个中断。此时GIC重新断言了一个中断信号。

4.3 Target interrupts

Arm架构中每个PE被分配了一个层级标识符,称作affinity。GIC通过affinity的值来确定中断将转发给哪一个特定的核。

affinity共32位,被分为四个区域:

​ <affinity level 3>.<affinity level 2>.<affinity level 1>.<affinity level 0>

每一个PE的affinity记录在MPIDR_EL1中。

affinity不同的层级的确切含义由特定处理器和SoC规定。举个例子,Arm Cortex-A53和Arm Cortex-A57处理器使用:

​ <group of groups>. <group of processors>.<processor>.<core>

Arm Cortex-A55和Arm Cortex-A76处理器中使用的设计,则使用:

​ <group of processors>.<processor>.<core>.<thread>

注意,AArch32状态,和Armv7-A智能支持三层affinity。GICD_TYPER.A3V指示断控制器是否支持多个level 3节点。

4.4 安全模型

Arm CoreLink GICv3架构支持Arm TrustZone技术。每一个INTID都要被软件指定一个组和安全度。GICv3支持三种设置的组合,如下所示。

中断类型 示例
Secure Group 0 EL3的中断(安全固件)
Secure Group 1 安全EL1的中断(可信操作系统)
Non-secure Group 1 Non-secure状态的中断(OS或Hypervisor)

Group 0的中断总是FIQ。

Group 1的中断可以是IRQ也可以是FIQ,取决于目前的安全状态和异常等级。如下所示:

EL和安全状态 Group 0 Secure Group 1 Non-secure Group 1
Secure EL0/1 FIQ IRQ FIQ
Non-secure EL0/1/2 FIQ FIQ IRQ
EL3 FIQ FIQ FIQ

这些规则是为了补充AArch64安全状态和异常级别路由控制而设计的。下图展示了一个简单的软件栈,以及当在EL0执行时,不同类型的中断被触发 会发生什么

【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

在这个例子中,IRQ被路由到EL1(SCR_EL3.IRQ==0),FIQ被路由到EL3(SCR_EL3.FIQ==1)。考虑到上面描述的规则,当执行EL1或EL0时,当前安全状态的Group 1中断被视为IRQ。

用于其他安全状态的中断会触发FIQ,并将异常传递给EL3。这允许在EL3执行的软件执行必要的上下文切换。

4.4.1 对于软件的影响

在配置中断控制器时,软件控制给中断组分配INTID。只有在安全状态下执行的软件才能为中断组分配INTID。

通常,只有在安全状态下执行的软件才能访问安全中断的设置和状态:Group 0和Secure Group 1。

从非安全状态访问安全中断设置和状态能够被使能。使用GICD_NSACRn和GICR_NSACR寄存器分别为每个INTID控制。

注意:LPI总是被视为Non-secure Group 1中断。

4.4.2 支持单一安全状态

GICv3支持Arm TrustZone技术,但是TrustZone的使用是可选的。你可以选择配置以决定是使用单独的安全状态还是两个安全状态:

  • GICD_CTLR.DS == 0

    两个安全状态

  • GICD_CTLR.DS == 1

    只有一个安全状态

将GIC配置成与PE使用相同数目的安全状态。

4.5 编程模型

GICv3中断控制器的寄存器接口被分成三组:

  • Distributor interface
  • Redistributor interface
  • CPU interface

这些接口如下图所示:

【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

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

4.5.1 Distributor(GICD_*)

Distributor寄存器是内存映射的,用于配置SPI。Distributor提供编程接口用于:

  • 中断优先级排序、分发SPI
  • 使能或禁止SPI
  • 对每一个SPI设置优先级
  • 为每个SPI路由
  • 设置每一个SPI是电平触发还是边沿触发
  • 生成message-signaled SPIs
  • 控制SPI的活动和挂起状态
  • 确定每一个安全状态下的编程模型:affinity routing或legacy

4.5.2 Redistributors (GICR_*)

每个相接的核都有一个Redistributor。Redistributor提供编程接口实现以下功能:

  • 使能和关闭SGI和PPI
  • 设置SGIs和PPIs的优先级
  • 设置每个PPI为电平触发或边缘触发
  • 将每个SGI和PPI分组
  • 控制SGI和PPI的状态
  • 控制内存中支持LPI的相关中断属性和挂起状态的数据结构的基址
  • 为所连接的PE提供电源管理支持

4.5.3 CPU interfaces (ICC_*_ELn)

每个内核包含一个CPU接口,它是在中断处理期间使用的系统寄存器。CPU接口提供了一个编程接口实现以下功能:

  • 提供通用控制和配置来启用中断处理
  • 接收中断
  • 实现中断的优先级删除和停用
  • 为PE设置中断优先级mask
  • 定义PE的抢占策略
  • 为PE确定最高优先级的pending中断

在Arm CoreLink GICv3中,CPU接口寄存器作为系统寄存器来访问:ICC_*_ELn。

在使用这些寄存器之前,软件必须启用系统寄存器接口。这是由ICC_SRE_ELn寄存器中的SRE位控制的,其中“n”指定了异常级别:EL1-EL3。

5.配置Arm CoreLink GIC

本章讲述怎么在裸机环境下使能和配置GICv3中断控制器。

配置LPI与SPI、PPI和SGI有很大的不同。本文不会描述,可以参考Arm CoreLink Generic Interrupt Controller v3 and v4: Locality-specific Peripheral Interrupts一文。

使用GICv3控制器的大多为多核甚至多处理器系统。有些设置是全局的,有一些是针对于单个PE。

5.1 全局设置

分配器控制寄存器Distributor control register (GICD_CTLR)必须按照下面的原则启用中断组以及设置路由模式:

  • Enable Affinity routing (ARE bits):GICD_CTLR中的ARE位控制GIC是在GICv3模式还是legacy模式下运行。legacy向后兼容GICv2。本文默认ARE位为1,即使用GICv3模式
  • Enables:GICD_CTLR对于Group 0, Secure Group 1和Non-secure Group 1有各自的使能位。
    • EnableGrp1S位使能Secure Group 1中断分发
    • EnableGrp1NS位使能Non-secure Group 1中断分发
    • EnableGrp0使能Group 0中断分发功能

注意:Arm CoreLink GIC-600不支持legacy操作,故ARE位始终为1。

5.2 单个PE设置

5.2.1 Redistributor配置

【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

Redistributor包括一个寄存器GICR_WAKER,用于记录相应的PE是在线还是脱机。中断只转发给GIC认为在线的PE。复位的情况下,所有的PE视为脱机。

要将相应的PE标记为在线,软件必须:

  • 将GICR_WAKER.ProcessorSleep位清零
  • 轮询GICR_WAKER.ChildrenAsleep直到读到0。

重要:软件必须在配置CPU接口之前实现上述两步。否则行为将不可预测。

当PE脱机的时候(GICR_WAKER.ProcessorSleep==1),一个发往PE的中断将导致一个唤醒请求信号被断言。

通常,这个信号会到达系统的电源控制器。电源控制器将打开PE。在唤醒时,PE上的软件将清除ProcessorSleep位,允许唤醒PE的中断被转发。

5.2.2 CPU接口配置

CPU接口负责向它所连接的PE发送中断异常。为了使能CPU接口,软件必须进行如下配置:

  • 使能系统寄存器访问

    4.5.3节描述了CPU接口寄存器,以及它们如何作为GICv3中的系统寄存器访问。软件必须使能访问CPU接口寄存器,通过设置ICC_SRE_ELn寄存器的SRE位。

注意:很多近期的Arm Cortex不支持legacy操作,所以SRE位固定为被设置。在这些处理器上这一步可以跳过。

  • 设置优先级Mask和Binary Point寄存器

    CPU接口包括Priority Mask寄存器(ICC_PMR_EL1)和Binary Point寄存器(ICC_BPRn_EL1)。

    优先级掩码 设置 为了转发到PE中断必须具有的 最小优先级。

    二进制点寄存器用于优先级分组和抢占。

    第六章进一步讲述了两个寄存器的用法。

  • 设置EOI模式

    CPU接口中的ICC_CTLR_EL1ICC_CTLR_EL3中的EOImode位控制了一个中断的完成是怎么处理的。

    6.4节有进一步的描述

  • 使能每个中断组的信号

    每个中断组的信号必须开启后,该中断组的中断才会通过CPU接口转发到PE。

    为了使能信号,软件必须写ICC_IGRPEN1_EL1寄存器以实现Group 1中断,写ICC_IGRPEN0_EL1寄存器以实现Group 0中断。

    ICC_IGRPEN1_EL1属于安全状态。

    在EL3,软件可以使用ICC_IGRPEN1_EL3访问Group 1。

5.2.3 PE配置

我们将描述在AArch64状态下执行Armv8-A兼容PE所需的基本步骤。

  • 路由控制

    中断路由控制信息在SCR_EL3和HCR_EL2中。路由控制位决定了中断将发往那个异常的等级。路由位在复位时值未知,所以需要被软件初始化。

  • 中断掩码

    PSTATE中有异常掩码位。当置位时,中断被屏蔽。复位时将置位。

  • 向量表

    由VBAR_ELn寄存器设置PE向量表所在位置。VBAR_ELn复位时的值不确定。软件必须将VBAR_ELn寄存器设置为指向内存中适当的向量表。

5.2.4 SPI, PPI和SGI的配置

我们将讨论各个中断源的配置。

哪些寄存器用于配置中断取决于中断的类型:

  • spi是通过Distributor配置的,使用GICD_*寄存器。
  • PPIs和SGIs使用GICR_*寄存器通过单独的Redistributors进行配置

这些不同的配置机制如下图所示:

【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

对于每个INTID,软件必须配置如下:

  • Priority: GICD_IPRIORITYn, GICR_IPRIORITYn

    每个INTID都有一个相关的优先级,用8位无符号值表示。0x00是可能的最高优先级,0xFF是可能的最低优先级。

    6.3节描述了ICD_IPRIORITYn和GICR_IPRIORITYn中的优先级值如何屏蔽低优先级中断,以及如何控制抢占。中断控制器不需要实现所有8个优先级位。如果GIC支持两种安全状态,则必须至少实现5位。如果GIC只支持单一的安全状态,则必须实现至少4位。

  • Group: GICD_IGROUPn, GICD_IGRPMODn, GICR_IGROUPn, GICR_IGRPMODn

    可以通过这些寄存器设为三种Group中的一个

  • Edge-triggered or level-sensitive: GICD_ICFGRn, GICR_ICFGRn

    对于PPIs和SPI,软件必须指定中断是边缘触发还是电平触发。SGIs总是被视为边沿触发的,因此对于这些中断,GICR_ICFGR0表现为Read-As-One, Writes Ignored (RAO/WI)。

  • Enable: GICD_ISENABLERn, GICD_ICENABLER, GICR_ISENABLERn, GICR_ICENABLERn

    每个INTID都有一个使能位。设置启用寄存器和清除启用寄存器消除了执行读-修改-写例程的要求。Arm建议在启用INTID之前配置本节中概述的设置。

对于裸机环境,通常在初始配置后不需要更改设置。但是,如果一个中断必须被重新配置,例如改变组设置,你应该在改变它的配置之前先禁用中断。

大多数配置寄存器的reset值是厂家定义的。这意味着中断控制器的设计者决定这些值是什么,这些值在不同的系统中可能会有所不同。

5.2.5 Arm CoreLink GICv3.1和扩展的INTID范围

Arm CoreLink GICv3.1增加了对其他SPI和PPI INTID的支持。配置这些中断的寄存器与原始中断范围相同,只是它们有一个E后缀。如:

GICR_ISENABLERn 原PPI的范围的使能位
GICR_ISENABLERnE 额外的PPI的使能位

5.2.6 设置SPI对应的PE

对于spi,必须配置中断的目标。由GICD_IROUTERn或GICv3.1扩展的GICD_IROUTERnE进行控制。每个SPI有一个GICD_IROUTERn寄存器,且Interrupt_Routing_Mode位控制着路由策略。如下:

  • GICD_IROUTERn.Interrupt_Routing_Mode == 0

    SPI被交付给PE A.B.C.D,这是在寄存器中指定的 affinity co-ordinates。

  • GICD_IROUTERn.Interrupt_Routing_Mode == 1

    SPI可以发送给任何相关的PE,这些PE参与了中断分组的分发。由Distributor而不是软件选择目标PE。因此,每次发出中断信号的时候,目标都可以改变,这种类型的路由称为1-of-N。

    PE可以选择不接收1-of-N中断。这是由GICR_CTLR中的DPG1S、DPG1NS和DPG0位控制的。

6.处理中断

本节描述中断发生时发生的事情:例如,中断如何路由到PE,中断如何对彼此进行优先排序,以及在中断结束时发生了什么。

6.1 路由一个挂起的中断到PE

4.2节描述了中断的源被断言时,中断是如何从inactive状态转换到pending状态的。当中断挂起的时候,中断控制器根据下面的测试情况决定是否将中断发送到相连的PE上。下面的测试决定将中断发给哪一个PE:

  • 检查与中断相关的组是否启用。

    4.4描述了每个INTID是怎么分配给Group中的。对于每个组,在Distributor和每个CPU接口中都有一个Group使能位。

    中断控制器检查是否为与该中断的INTID相关联的组设置了组使能位。

    如果所在的Group被禁用了,那么中断不能向PE发送信号。这些中断将被挂起知道相应的Group使能。

  • 检查中断是否启用。

    单独禁用的中断可能会挂起但是不会发往PE。

  • 检查路由控制以决定哪个PE可以接收中断。

    哪些PE能接收到中断取决于正在发送哪种类型的中断:

    • 对于SPI,路由由GICD_IROUTERn控制。一个SPI可以发往特定的PE,或者是相连的任何PE。
    • 对于LPI而言,路由信息来自ITS。
    • PPI只能发往一个PE且只能被该PE所处理。
    • 对于SGI,源PE决定可以发往的PE。在第7章将进一步描述。
  • 检查中断优先级和优先级掩码,以决定哪些PE适合处理中断

    每个PE在其CPU接口中都有一个优先级掩码寄存器ICC_PMR_EL1。这个寄存器设置中断被转发到那个PE所需要的最小优先级。只有优先级高于掩码的中断才会通知PE。

  • 检查运行优先级,以决定哪些PE可用来处理中断

    6.3节包括运行优先级,以及它如何影响抢占。如果PE还没有处理中断,运行优先级是空闲优先级:0xFF。只有优先级高于运行优先级的中断才能抢占当前中断。

如果中断通过了所有这些测试,它将作为IRQ或FIQ异常转发到适当的核。可以回顾下5.2.6节。

6.2 获取中断

当进入异常处理程序时,软件不知道它所接受的是哪个中断。处理程序必须读取一个Interrupt Acknowledge Registers(IARs)来获取中断的INTID。

有两个IAR:

寄存器 用途
ICC_IAR0_EL1 用于获取Group 0中断。通常在FIQ处理程序中读取。
ICC_IAR1_EL1 用于确认第一组中断。通常用于IRQ处理程序中。

读取IAR将返回已获取的中断的INTID,并推进中断的状态机。通常,IARs是在中断处理程序进入时读取的。然而,软件在任何时候都可以*读取寄存器。

有时,IAR不能返回一个有效的INTID。例如,读取ICC_IAR0_EL1,得知Group 0发生中断,但是挂起的中断属于Group 1。这种情况下,将读到一个保留的INTID,如下所示:

ID 意义 场景案例
1020 仅通过读取ICC_IAR0_EL1返回
最高挂起的中断是Secure Group 1。
只能被EL3查看。
当PE在非安全状态下执行时,一个受信任操作系统的中断被通知。这被当作到EL3的FIQ,这样安全监视器就可以上下文切换到受信任的操作系统。
1021 仅通过读取ICC_IAR0_EL1返回。
最高挂起的中断是Non-secure Group 1。
只能被EL3查看。
当PE在安全状态下执行时,一个属于rich OS的中断信号发生。这将被视为到EL3的FIQ,这样安全监视器就可以上下文切换到rich OS。
1022 仅用于legacy操作 遗留操作超出了本文的范围。
1023 虚假的中断。
没有所启用的INTID处于挂起状态,或者该挂起状态中的所有intid都没有足够的优先级需要获取。
当轮询IARs时,这个值表示没有中断可以确认。

读取IAR返回这些值的话,并不获取中断。

6.2.1 中断处理的例子

下图展示了一个手机系统。当有一个来电时,发生了一个中断。这个中断将由非安全状态下的Rich OS进行处理。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-id0dp2EX-1610113945109)(https://image-1304693124.cos.ap-shanghai.myqcloud.com/img/image-20210108202204721.png)]

处理中断的步骤如下:

  1. 当PE在Secure EL1执行Trusted OS时,中断被挂起。因为中断被配置为Non-secure Group 1,它将作为FIQ信号。因为SCR_EL3.FIQ==1,异常被发向EL3。
  2. EL3的安全监控软件读取IAR,返回值为1021。这个值表示中断希望在非安全状态下处理。安全监控软件切换上下文。
  3. PE现在是非安全状态,中断将被视作IRQ,并发向Non-secure EL1,被Rich OS处理。

在本例中,Non-secure Group 1中断导致立刻退出Secure OS。可能有些情况下我们不希望发生这种情况。下面是一个替代的模型案例,中断先被发向Secure EL1:

【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

处理中断的步骤如下:

  1. 当PE在Secure EL1上执行的时候,中断挂起。因为中断被配置为Non-secure Group 1,它将被视作FIQ信号。因为SCR_EL3.FIQ==0,异常将发往Secure EL1。
  2. Trusted OS执行清理其内部状态的操作。就绪后,Trusted OS使用SMC指令转向Non-secure状态。
  3. SMC异常被发往EL3,EL3的安全监控软件执行必要的上下文切换。
  4. 现在PE处于非安全状态,中断被作为IRQ发出的信号,被Rich OS处理

6.3 运行优先级和抢占

Priority Mask寄存器设置了中断要发往PE所需的最低优先级。GICv3架构具有运行优先级的概念。当PE获取中断,它的运行优先级将和这个中断的优先级一样高。当PE写一个EOI寄存器时,运行优先级返回到它之前的值。下图显示了一个PE的运行优先级随时间变化的示例:

【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

当前的运行优先级在CPU接口的Running Priority寄存器ICC_RPR_EL1中上显示。当一个高优先级中断被通知给已经在处理一个低优先级中断的PE时,抢占发生。抢占给软件带来了额外的复杂性,但是它可以防止低优先级中断阻塞处理高优先级中断。

下面的图表显示了如果不允许抢占会发生什么:

【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

高优先级中断被阻塞,直到先前发出信号的低优先级中断被占用。现在考虑相同的情况,但是启用了抢占:

【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

Arm CoreLink GICv3架构允许软件通过指定抢占发生所需的优先级差异来控制抢占。由Binary Point寄存器来控制: ICC_BPRn_EL1

Binary Point寄存器将优先级划分为两个区域,group priority 和 sub-priority:

【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

抢占时,只考虑组优先级位。次优先级位被忽略。

例如,考虑下面三种中断:

  • INTID A has priority 0x10.
  • INTID B has priority 0x20.
  • INTID C has priority 0x21.

在这个例子中,我们决定:

  • A能抢占B、C
  • B不能抢占C,B,C优先级相同

为了实现这一点,组和次优先级之间的划分可以设置为N=4,如下:

【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

Binary Point只影响抢占。即,在处理另一个中断的时候是否要发送当前中断的信号。Binary Point不用于在挂起的中断中进行选择。

注意:抢占机制要求中断处理支持嵌套。

6.4 中断结束

一旦中断被处理,软件必须通知中断控制器中断已经被处理,以便状态机可以转换到下一个状态。Arm CoreLink GICv3架构将此视为两个任务:

  • Priority drop

    这意味着将优先级调低至中断前的优先级

  • Deactivation

    这意味着更新当前正在处理的中断的状态机。通常将导致Active state到the Inactive state的状态切换。

GICv3架构中,priority drop和deactivation可一起发生或是单独发生,由ICC_CTLR_ELn.EOImode决定:

  • EOImode = 0

    写ICC_EOIR0_EL1和ICC_EOIR1_EL1都将一起执行priority drop和deactivation。这种模式通常在裸机环境执行。

  • EOImode = 1

    写ICC_EOIR0_EL1和ICC_EOIR1_EL1将导致优先级回落。Deactivation需要写ICC_DIR_EL1。虚拟化通常采用这种模式。

大多数软件将使用EOIMode==0。EOImode==1最常被hypervisor使用。

6.5 检查当前系统的状态

6.5.1 挂起中断的最高优先级和运行优先级

Highest Priority Pending Interrupt寄存器ICC_HPPIR0_EL1ICC_HPPIR1_EL1,传递优先级最高的挂起的中断的INTID。

ICC_RPR_EL1传递运行优先级。

6.5.2 个体INTID的状态

Distributor提供每个SPI的当前状态的寄存器。类似的,Redistributor指示相连的PPI和SGI的状态的寄存器。

这些寄存器能够将中断移动到特定的状态。例如,用于在没有外设断言中断的情况下,测试配置是否正确。

有单独的寄存器来报告活动状态和挂起状态。下表列出了活动状态寄存器。挂起状态寄存器有相同的格式:

寄存器 描述
GICD_ISACTIVERn 设置SPI的活动状态
每个INTID占用一个bit
返回值表示INTID状态:
1表示INTID active
0表示INTID非激活
写1表示激活相应的INTID
写0没有任何用处
GICR_ISACTIVERn 设置SGIs和PPI的激活状态
每个INTID占用一个bit
返回值表示INTID状态:
1表示INTID active
0表示INTID非激活
写1表示激活相应的INTID
写0没有任何用处
GICR_ICACTIVERn 清除SGIs和PPIs的激活状态
每个INTID占用一个bit
返回值表示INTID状态:
1表示INTID active
0表示INTID非激活
写1表示解激活
写0没有用处

注意:非安全状态下执行的软件不能看到Group 0和Secure Group 1的中断的状态,除非由GICD_NASCRn 或GICR_NASCRn允许。

7.发送和接收Software Generated Interrupts

软件生成中断(SGIs)是软件可以通过写入中断控制器中的寄存器来触发的中断。

7.1 生成SGI

一个SGI是通过在CPU接口中写入以下SGI寄存器来生成的:

系统寄存器接口 描述
ICC_SGI0R_EL1 生成Secure Group 0中断
ICC_SGI1R_EL1 在PE当前的安全状态下,生成Group 1中断
ICC_ASGI1R_EL1 在其他PE的安全状态下,生成Group 1中断

你可以在下图中看到SGI寄存器的基本格式:

【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

7.1.1 控制SGI ID

SGI ID字段控制生成哪一个INTID。参考4.1,SGI的INTID范围为0-15。

7.1.2 控制目标

IRM(中断路由模式)字段在SGI寄存器控制一个SGI被发送到哪些PE。有两种选择:

  • IRM = 0

    中断被发向:<aff3>.<aff2>.<aff1>.<Target List>,其中每个<aff1>下的affinity 0节点在<target list>被编码为1位。这意味着中断最多可发往16个PE。

  • IRM = 1

    中断被发往所有相连的PE,除了源PE。

7.1.3 控制安全状态和分组

SGI的安全状态和分组通过下面进行控制:

  • SGI寄存器:ICC_SGI0R_EL1, ICC_SGI1R_EL1, 或 ICC_ASGIR_EL1。由源PE上的软件进行写操作
  • 目标PE的GICR_IGROUPR0GICR_IGRPMODR0寄存器。

在安全状态下执行的软件可以发送安全的和不安全的SGI。在非安全状态下运行的软件是否能够生成安全的SGIs由GICR_NSACR控制。该寄存器只能被在安全状态下执行的软件访问。下表显示GIC通过以下检查来决定中断是否被转发:

  • 发起PE的安全状态
  • 中断所针对的PE的中断处理的配置
  • SGI寄存器
发送方PE的安全状态 写入的SGI寄存器 接收方PE的配置 发送?
Secure EL3/EL1 ICC_SGI0R_EL1 Secure Group 0
Secure Group 1
Non-secure Group 1


ICC_SGI1R_EL1 Secure Group 0
Secure Group 0
Non-Secure Group 1
否(*)

ICC_ASGI1R_EL1 Secure Group 0
Secure Group 0
Non-Secure Group 1


Non-secure EL2/EL1 ICC_SGI0R_EL1 Secure Group 0
Secure Group 0
Non-Secure Group 1
由GICR_NSACR配置 (*)

ICC_SGI1R_EL1 Secure Group 0
Secure Group 0
Non-Secure Group 1
由GICR_NSACR配置 (*)
由GICR_NSACR配置
ICC_ASGI1R_EL1 Secure Group 0
Secure Group 0
Non-Secure Group 1
由GICR_NSACR配置 (*)
由GICR_NSACR配置

这张表假设GICD_CTLR.DS==0。当GICD_CTLR.DS==1时,(*)标记的总是转发。

7.2 比较GICv3和GICv2

在Arm CoreLink GICv2中,SGI的INTID好归属于源PE和目的PE。这意味着一个给定的PE中,相同的SGI INTID可能同时存在,最多8个。

Arm CoreLink GICv3中,SGI只属于目的PE。

让我们用一个例子来说明这一区别。

PE A和B同时发送INTID为5的SGI给PE C,如下:

【笔记】Arm CoreLink Generic Interrupt Controller v3 and v4 Overview

C会收到多少中断?

  • GICv2:2个

    GIC将同时接收来自A和B的中断。两个中断的顺序取决于设计和到达的时间。可以通过以下方法区分这两个中断:GICC_IAR中返回的值中,PE的ID是INTID的前缀。

  • GICv3:1个。因为源PE不存储SGI,相同的中断不能挂起在两个PE上。因此,C只接收到一个ID为5的中断,没有前缀。

该示例假设两个中断是同时或几乎同时发送的。如果C能够在第二个SGI到达之前确认第一个SGI,那么C将在GICv3中看到两个中断。

注意:在legacy操作中,即当GICD_CTLR.ARE=0时,SGIs的行为与Arm CoreLink GICv2相同。

参考

https://developer.arm.com/architectures/learn-the-architecture/arm-corelink-generic-interrupt-controller-v3-and-v4-overview

上一篇:查询mongodb 结果后写入csv


下一篇:第17天 文件类型分析