热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【笔记】ArmCoreLinkGenericInterruptControllerv3andv4Overview

1.概述本文介绍:GICv3中断控制器的相关操作如何在裸机环境下配置GICv3中断控制器本文是_ArmCoreSightGenericInterruptControllers_相关




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个不同外设的中断,并将它们分配给两个不同的处理器。

image-20210107203034828

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 - 15SGIsBanked per PE
16 – 31
1056 – 1119 (GICv3.1)
PPIsBanked per PE
32 – 1019
4096 – 5119 (GICv3.1)
SPIs
1020 - 1023特殊的中断号详情见5.2
1024 - 8191Reserved
8192~LPIs上线由具体厂家定义

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

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

image-20210107205949338

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

image-20210107210116115

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

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

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


中断类型寄存器
SPIGICD_SETSPI_NSR 断言中断
GICD_CLRSPI_NSR解除中断
LPIGITS_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 边沿触发中断

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

image-20210107214353752

依次考虑每个状态转换:


  • 从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位,被分为四个区域:

​ ...

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

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

. .

.

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

.

..

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


4.4 安全模型

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


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

Group 0的中断总是FIQ。

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


EL和安全状态Group 0Secure Group 1Non-secure Group 1
Secure EL0/1FIQIRQFIQ
Non-secure EL0/1/2FIQFIQIRQ
EL3FIQFIQFIQ

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

image-20210108132237252

在这个例子中,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

这些接口如下图所示:

image-20210108134300678

通常,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配置

image-20210108145307721

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进行配置

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

image-20210108193042129

对于每个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:

image-20210108203110644

处理中断的步骤如下:


  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的运行优先级随时间变化的示例:

image-20210108203929728

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

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

image-20210108204233142

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

image-20210108204337296

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

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

image-20210108204634047

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

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


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

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


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

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

image-20210108204944398

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寄存器的基本格式:

image-20210108211830776


7.1.1 控制SGI ID

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


7.1.2 控制目标

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


  • IRM = 0

    中断被发向:...,其中每个下的affinity 0节点在被编码为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/EL1ICC_SGI0R_EL1Secure Group 0
Secure Group 1
Non-secure Group 1


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

ICC_ASGI1R_EL1Secure Group 0
Secure Group 0
Non-Secure Group 1


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

ICC_SGI1R_EL1Secure Group 0
Secure Group 0
Non-Secure Group 1
由GICR_NSACR配置 (*)
由GICR_NSACR配置
ICC_ASGI1R_EL1Secure 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,如下:

image-20210108214403652

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



推荐阅读
  • 本文详细介绍了Java代码分层的基本概念和常见分层模式,特别是MVC模式。同时探讨了不同项目需求下的分层策略,帮助读者更好地理解和应用Java分层思想。 ... [详细]
  • 深入解析 Lifecycle 的实现原理
    本文将详细介绍 Android Jetpack 中 Lifecycle 组件的实现原理,帮助开发者更好地理解和使用 Lifecycle,避免常见的内存泄漏问题。 ... [详细]
  • 兆芯X86 CPU架构的演进与现状(国产CPU系列)
    本文详细介绍了兆芯X86 CPU架构的发展历程,从公司成立背景到关键技术授权,再到具体芯片架构的演进,全面解析了兆芯在国产CPU领域的贡献与挑战。 ... [详细]
  • 如果应用程序经常播放密集、急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了。因为MediaPlayer存在如下缺点:1)延时时间较长,且资源占用率高 ... [详细]
  • 本文将带你快速了解 SpringMVC 框架的基本使用方法,通过实现一个简单的 Controller 并在浏览器中访问,展示 SpringMVC 的强大与简便。 ... [详细]
  • IOS Run loop详解
    为什么80%的码农都做不了架构师?转自http:blog.csdn.netztp800201articledetails9240913感谢作者分享Objecti ... [详细]
  • 本文介绍了在 Java 编程中遇到的一个常见错误:对象无法转换为 long 类型,并提供了详细的解决方案。 ... [详细]
  • 解决Only fullscreen opaque activities can request orientation错误的方法
    本文介绍了在使用PictureSelectorLight第三方框架时遇到的Only fullscreen opaque activities can request orientation错误,并提供了一种有效的解决方案。 ... [详细]
  • 多线程基础概览
    本文探讨了多线程的起源及其在现代编程中的重要性。线程的引入是为了增强进程的稳定性,确保一个进程的崩溃不会影响其他进程。而进程的存在则是为了保障操作系统的稳定运行,防止单一应用程序的错误导致整个系统的崩溃。线程作为进程的逻辑单元,多个线程共享同一CPU,需要合理调度以避免资源竞争。 ... [详细]
  • 本文对比了杜甫《喜晴》的两种英文翻译版本:a. Pleased with Sunny Weather 和 b. Rejoicing in Clearing Weather。a 版由 alexcwlin 翻译并经 Adam Lam 编辑,b 版则由哈佛大学的宇文所安教授 (Prof. Stephen Owen) 翻译。 ... [详细]
  • 本文详细介绍了如何在Unity中实现一个简单的广告牌着色器,帮助开发者更好地理解和应用这一技术。 ... [详细]
  • Java高并发与多线程(二):线程的实现方式详解
    本文将深入探讨Java中线程的三种主要实现方式,包括继承Thread类、实现Runnable接口和实现Callable接口,并分析它们之间的异同及其应用场景。 ... [详细]
  • 本文介绍了如何使用 Node.js 和 Express(4.x 及以上版本)构建高效的文件上传功能。通过引入 `multer` 中间件,可以轻松实现文件上传。首先,需要通过 `npm install multer` 安装该中间件。接着,在 Express 应用中配置 `multer`,以处理多部分表单数据。本文详细讲解了 `multer` 的基本用法和高级配置,帮助开发者快速搭建稳定可靠的文件上传服务。 ... [详细]
  • 为了在Hadoop 2.7.2中实现对Snappy压缩和解压功能的原生支持,本文详细介绍了如何重新编译Hadoop源代码,并优化其Native编译过程。通过这一优化,可以显著提升数据处理的效率和性能。此外,还探讨了编译过程中可能遇到的问题及其解决方案,为用户提供了一套完整的操作指南。 ... [详细]
  • ### 优化后的摘要本学习指南旨在帮助读者全面掌握 Bootstrap 前端框架的核心知识点与实战技巧。内容涵盖基础入门、核心功能和高级应用。第一章通过一个简单的“Hello World”示例,介绍 Bootstrap 的基本用法和快速上手方法。第二章深入探讨 Bootstrap 与 JSP 集成的细节,揭示两者结合的优势和应用场景。第三章则进一步讲解 Bootstrap 的高级特性,如响应式设计和组件定制,为开发者提供全方位的技术支持。 ... [详细]
author-avatar
小布丁她Daddy
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有