Arm Generic Interrupt Controller v3 and v4

What is a Generic Interrupt Controller?

通用中断控制器(GIC)从外围设备接收中断,对其进行优先级排序,并将其传送到适当的处理器核心。下图显示了一个GIC从n个不同的外围设备接收中断,并将它们分配给两个不同的处理器。
在这里插入图片描述
GIC是Arm Cortex-A和Arm Cortex-R配置文件处理器的标准中断控制器。GIC提供了一种灵活且可扩展的中断管理方法,支持从单核到数百核的大型多芯片设计的系统。
A brief history of the Arm CoreLink GIC
与Arm体系结构一样,GIC体系结构也随着时间的推移而演变。下表总结了GIC规范的主要版本及其通常使用的处理器。
在这里插入图片描述
在这里插入图片描述
本指南涵盖Arm CoreLink GICv3和GICv4,它们被大多数Armv9-A、Armv8-A和Armv8-R设计所使用。
自发布以来,GICv3和GICv4也收到了一些小更新:
GICv3.1增加了对额外有线中断、安全虚拟化和内存系统资源分区与监控(MPAM)的支持
GICv3.2 added support for Armv8-R AArch64.
GICv3.2增加了对Armv8-R AArch64的支持。
GICv3.3增加了对不可屏蔽中断(non-maskable interrupts)的支持。
GICv4.1扩展了虚拟化支持,涵盖了虚拟软件生成中断(SGI)的直接注入(direct-injection of virtual Software Generated Interrupts (SGIs))。
GICv4.2增加了对直接注入不可屏蔽虚拟中断(directly-injecting non-maskable virtual interrupts)的支持。

Arm GIC fundamentals

在本节中,我们将了解Arm GICv3和v4中断控制器的基本操作。
Interrupt types
GIC可以处理四种不同类型的中断源:

  • Shared Peripheral Interrupt(SPI):可以传送到任何连接的core的外围中断。
  • Private Peripheral Interrupt (PPI):一个核心专用的外围中断。PPI的一个例子通用定时器的中断。
  • Software Generated Interrupt (SGI):SGI通常用于处理器间通信,并通过写入GIC中的SGI寄存器来生成。
  • Locality-specific Peripheral Interrupt (LPI):LPI最早是在GICv3中引入的,与其他三种类型的中断具有非常不同的编程模型。Arm CoreLink Generic Interrupt Controller v3 and v4:Locality specific Peripheral Interrupts guide中介绍了LPI的配置。

每个中断源由一个ID号标识,该ID号被称为INTID。前面列表中引入的中断类型是根据INTID的范围定义的:
在这里插入图片描述
How interrupts are signaled to the interrupt controller
传统上,使用专用硬件信号从外围设备向中断控制器发送中断信号,如下图所示:
在这里插入图片描述
Arm CoreLink GICv3支持这种模型,但也提供了一种额外的信令机制:消息信号中断(MSI)。MSIs是通过写入中断控制器中的寄存器来传输的,如您所见:
在这里插入图片描述
使用消息将中断从外围设备转发到中断控制器消除了对每个中断源的专用信号的要求。这对大型系统的设计者来说可能是一个优势,在大型系统中,可能有数百甚至数千个信号在SoC上路由,并汇聚在中断控制器上。

中断是作为消息发送还是使用专用信号发送,对中断处理代码处理中断的方式几乎没有影响。可能需要对外围设备进行一些配置。例如,可能需要指定中断控制器的地址。

在Arm CoreLink GICv3中,SPI可以是消息信号中断。LPI始终是消息信号中断。不同的寄存器用于不同的中断类型,如下表所示:
在这里插入图片描述
Interrupt state machine
中断控制器为每个SPI、PPI和SGI中断源维护一个状态机。此状态机由四个状态组成:

  • Inactive:当前未断言中断源。
  • Pending:中断源已被断言,但PE尚未确认中断
  • Active:中断源已被断言,并且中断已被PE确认。
  • Active and Pending:中断的一个实例已被确认(acknowledged),另一个实例正在pending。

LPI有一个更简单的状态机。
状态机如下图所示:
在这里插入图片描述
中断的生命周期取决于它是配置为level-sensitive还是edge-triggered

  • level-sensitive中断:中断输入上的上升沿会导致中断pending,并且中断保持断言状态,直到外围设备取消断言中断信号。
  • edge-sensitive中断,中断输入的上升沿会导致中断变为pending,但中断未被保持断言。

Level sensitive interrupts
下图显示了中断状态转换如何与中断信号相对应:
在这里插入图片描述
依次考虑每个状态转换:
Inactive到pending。当中断源被断言时,中断从Inactive状态转换为

  • pending状态。此时,如果中断被启用并且具有足够的优先级,则GIC向PE断言中断信号。
  • pending到active and pending。当处理器元件(PE)通过读取CPU interface中的一个中断确认寄存器(IAR)来确认中断时,中断从pending转换为active and pending。这种读取通常是在发生中断异常后执行的中断处理例程的一部分。在这一点上,GIC取消对PE的中断信号的断言。
  • Active and pending到active。当外围设备解除对中断信号的断言时,中断从Active and pending转换为active。这通常发生在对外围设备中的状态寄存器进行响应软件写入时。
  • Active到inactive。当PE写入CPU interface中的一个中断结束寄存器(EOIR)时,中断从active变为inactive。这表示PE已经完成了对中断的处理。

Edge-triggered interrupts
下图显示了中断状态转换如何与中断信号相对应:
在这里插入图片描述
依次考虑每个状态转换:

  • Inactive到pending。当中断源被断言时,中断从Inactive状态转换为pending状态。此时,如果中断被启用并且具有足够的优先级,则GIC向PE断言中断信号。
  • pending到active。当PE通过读取CPU interface中的一个IAR来确认中断时,中断从pending转换为active。这种读取通常是在发生中断异常后执行的中断处理例程的一部分。然而,软件也可以轮询IAR。在这一点上,GIC取消对PE的中断信号的断言。
  • Active到active and pending。如果外围设备重新断言中断信号,则中断从Active变为active and pending。
  • Active and pending到pending。当PE写入CPU interface中的一个EOIR时,中断从Active and pending变为pending。这表明PE已经完成了对中断的第一个实例的处理。在这一点上,GIC向PE重新断言中断信号。

Target interrupts
Arm体系结构为每个PE分配一个称为亲和性的层次标识符。GIC使用亲和度值来针对特定核心的中断。
亲和度是一个32位的值,分为四个字段:
<affinity level 3>.<affinity level 2>.<affinity level 1>.<affinity level 0>
PE的亲和力在MPIDR_EL1寄存器。
不同亲和力水平的确切含义由特定处理器和SoC定义。例如,Arm Cortex-A53和Arm Cortex-A57处理器使用:
...
Arm Cortex-A55和Arm Cortex-A76处理器中使用的设计,使用:
...
所有可能的节点都存在于单个实现中是极不可能的。例如,用于移动设备的SoC可以具有如下布局:
0.0.0.[0:3] Cores 0 to 3 of a Cortex-A53 processor
0.0.1.[0:1] Cores 0 to 1 of a Cortex-A57 processor

AArch32状态和Armv7-A只能支持三个级别的亲和力。这意味着,使用AArch32状态的设计仅限于亲和力级别3(0.x.y.z)的单个节点。GICD_TYPER.A3V指示中断控制器是否可以支持多个级别3节点。

Security model
Arm GICv3体系结构支持Arm TrustZone技术。每个INTID必须通过软件分配一个组和安全设置。GICv3支持三种设置组合,如下表所示:
在这里插入图片描述
Group0 中断总是以FIQ的形式发出信号。根据PE的当前安全状态和异常级别,Group 1中断以IRQ或FIQ的形式发出信号,如下所示:
在这里插入图片描述
这些规则旨在补充AArch64安全状态和异常级别的路由控制。下图显示了一个简化的软件堆栈,以及在EL0下执行时发出不同类型的中断信号时会发生什么:
在这里插入图片描述
在这个例子中,IRQ被路由到EL1(SCR_EL3.IRQ==0),FIQ被路由至EL3(SCR_EL3。FIQ==1)。考虑到上述规则,当在EL1或EL0执行时,将当前安全状态Group 1中断作为IRQ

另一个安全状态的中断触发FIQ并且异常被带到EL3。这允许在EL3执行的软件执行必要的上下文切换。

Impact on software
当实现Armv9-A领域管理扩展时,GIC将领域状态视为非安全状态的扩展。
当配置中断控制器时,软件控制INTID到中断组的分配。只有在安全状态下执行的软件才能将INTID分配给中断组。
通常,只有在安全状态下执行的软件才能访问安全中断的设置和状态:Group 0和安Secure Group 1。
可以启用从非安全状态到安全中断设置和状态的访问。这是使用GICD_NSACRn和GICR_NSACR寄存器为每个INTID单独控制的。

LPI始终被视为Non-secure Group 1 中断。

Support for single Security state
GICv3支持Arm TrustZone技术,但使用TrustZone是可选的。这意味着您可以将实现配置为具有单个安全状态或两个安全状态:

  • GICD_CTLR.DS==0支持安全和非安全两种安全状态。
  • GICD_CTLR.DS==1仅支持单个安全状态。

将GIC配置为使用与所连接PE相同数量的安全状态。通常,这意味着GIC在连接到Arm Cortex-A配置文件处理器时将支持两种安全状态,在连接到Arm Cortex-R配置文件处理器后将支持一种安全状态。

Programmer’s model
GICv3中断控制器的寄存器接口分为三组:

  • Distributor interface
  • Redistributor interface
  • CPU interface
    这些接口如下图所示:
    在这里插入图片描述
    通常,Distributor和Redistributors用于配置中断,CPU interface用于处理中断。
    Distributor
    Distributor寄存器是内存映射的,用于配置SPI。Distributor为以下各项提供编程接口:
  • Interrupt prioritization and distribution of SPIs
  • Enable and disable SPIs
  • Set the priority level of each SPI
  • Route information for each SPI
  • Set each SPI to be level-sensitive or edge-triggered
  • Generate message-signaled SPIs ?
  • Control the active and pending state of SPIs
  • Determine the programmer’s model that is used in each Security state: affinity routing or legacy.

Redistributors
每个连接的core有一个Redistributor。Redistributors提供了一个编程接口,用于:

  • Enable and disable SGIs and PPIs.
  • Set the priority level of SGIs and PPIs
  • Set each PPI to be level-sensitive or edge-triggered
  • Assign each SGI and PPI to an interrupt group
  • Control the state of SGIs and PPIs
  • Control the base address for the data structures in memory that support the associated interrupt properties and pending state for LPIs?
  • Provide power management support for the connected PE

CPU interfaces
每个core都包含一个CPU interface,这些接口是在中断处理过程中使用的系统寄存器。CPU interface提供编程接口,用于:

  • Provide general control and configuration to enable interrupt handling.
  • Acknowledge an interrupt
  • Perform a priority drop and deactivation of interrupts
  • Set an interrupt priority mask for the PE
  • Define the preemption policy for the PE
  • Determine the highest priority pending interrupt for the PE

在Arm CoreLink GICv3中,CPU interface寄存器作为系统寄存器进行访问:ICC_*_ELn

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

Configuring the Arm GIC

本节介绍了如何在裸机(bare metal)环境中启用和配置符合GICv3的中断控制器。有关寄存器的详细说明,请参阅Arm Generic Interrupt Controller Architecture Specification GIC architecture version 3.0 and 4.

特定于本地的外围中断(LPI)的配置与共享外围中断(SPI)、专用外围中断(PPI)和软件生成中断(SGI)的设置有很大不同,超出了本指南的范围。要了解更多信息,请参阅我们的指南Arm CoreLink Generic Interrupt Controller v3和v4:Locality specific Peripheral Interrupts。

大多数使用GICv3中断控制器的系统都是多核系统,也可能是多处理器系统。有些设置是全局设置,这意味着会影响所有连接的PE。其他设置是单个PE特有的。

让我们看看全局设置,然后看看每个PE的设置。

Global settings
Distributor寄存器(GICD_CTLR)必须配置为启用中断组并设置路由模式,如下所示:
Enable Affinity routing (ARE bits): GICD_CTLR中的ARE位控制GIC是在GICv3模式下操作还是在传统模式下操作。传统模式提供了与GICv2的向后兼容性。本指南假设ARE位设置为1,因此使用GICv3模式。
启用: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不支持传统操作,并且ARE位永久设置为1。

Settings for each PE
本节介绍特定于单芯或PE的设置。

Redistributor configuration
每个核心都有自己的Redistributor,如下所示:
在这里插入图片描述
Redistributor包含一个名为GICR_WAKER的寄存器,用于记录连接的PE是联机还是脱机。中断仅转发给GIC认为在线的PE。重置时,所有PE都被视为处于脱机状态。

要将连接的PE标记为联机,软件必须:

  • 清除GICR_WAKER.Processor睡眠至0。
  • 轮询GICR_WAKER.ChildrenAsleep,直到其读数为0。

重要的是,软件在配置CPU interface之前执行这些步骤,否则行为可能是不可预测的。

当PE离线时(GICR_WAKER.ProcessorSleep==1),针对PE的中断将导致唤醒请求信号被断言。通常,该信号将进入系统的功率控制器。然后,电源控制器打开PE。在唤醒时,该PE上的软件将清除ProcessorSleep位,从而允许转发唤醒PE的中断。

CPU interface configuration
CPU interface负责将中断异常传递到与其连接的PE。要启用CPU interface,软件必须配置以下内容:
1.Enable System register access
CPU interfaces(ICC_*_ELn)部分描述了CPU interfaces寄存器,以及如何在GICv3中将它们作为系统寄存器进行访问。软件必须通过设置ICC_SRE_ELn寄存器中的SRE位来启用对CPU interfaces寄存器的访问。

2.Set Priority Mask and Binary Point registers
CPU interface包含Priority Mask 寄存器(ICC_PMR_EL1)和Binary Point寄存器(ICC_BPRn_EL1)。优先级掩码设置中断必须具有的最低优先级,以便转发到PE。Binary Point寄存器用于优先级分组和抢占。两个寄存器的使用在处理中断中有更详细的描述。

3.Set EOI mode
CPU interface中的ICC_CTLR_EL1和ICC_CTLR_EL3中的EOI模式位控制如何处理中断的完成。这在中断结束中有更详细的描述。

4.Enable signaling of each interrupt group
在CPU interface将每个中断组的中断转发到PE之前,必须启用该中断组的信令。要启用信令,软件必须为Group 1中断写入ICC_IGRPEN1_EL1寄存器,为Group 0中断写入ICC _IGRPEN0_EL1寄存器。ICC_IGRPEN1_EL1由安全状态存入。这意味着ICC_GRPEN1_EL1控制当前安全状态Group 1。在EL3,软件可以使用ICC_IGRPEN1_EL3访问两个Group 1启用。

PE configuration
还需要对PE进行一些配置,以允许其接收和处理中断。对此的详细描述超出了本指南的范围。在本指南中,我们将描述在AArch64状态下执行Armv8-A兼容PE所需的基本步骤。

Routing controls
中断的路由控制在PE的SCR_EL3和HCR_EL2中。路由控制位决定中断的异常级别。这些寄存器中的路由位在复位时具有未知值,因此必须由软件进行初始化。
Interrupt masks
PE在PSTATE中也有异常掩码位。当这些位被设置时,中断被屏蔽。这些位是在复位时设置的。
Vector table
PE的矢量表的位置由VBAR_ELn寄存器设置。与SCR_EL3和HCR_EL2一样,VBAR_ELn寄存器在复位时具有UNKNOWN值。软件必须将VBAR_ELn寄存器设置为指向内存中适当的矢量表。
SPI, PPI, and SGI configuration
到目前为止,我们已经研究了配置中断控制器本身。现在我们将讨论各个中断源的配置。

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

  • SPI通过Distributor,配置,使用GICD_*寄存器。
  • PPI和SGI通过单独的Redistributor进行配置,使用GICR_*寄存器。
    这些不同的配置机制如下图所示:
    在这里插入图片描述
    对于每个INTID,软件必须配置以下内容:
    Priority: GICD_IPRIORITYn , GICR_IPRIORITYn
    每个INTID都有一个相关的优先级,表示为一个8位无符号值。0x00是可能的最高优先级,0xFF是可能的最低优先级。运行优先级(Running priority)和抢占描述了GICD_IPRIORITYn和GICR_IPRIORITYn中的优先级值如何屏蔽低优先级中断,以及它如何控制抢占。不需要中断控制器来实现所有8个优先级位。如果GIC支持两种安全状态,则必须实现至少5位。如果GIC仅支持单个安全状态,则必须实现至少4位

Group: GICD_IGROUPn , GICD_IGRPMODn , GICR_IGROUPn , GICR_IGRPMODn
如安全模型中所述,可以将中断配置为属于三个中断组中的一个。这些中断组是Group 0、Secure Group 1和Non-secure Group 1。
Edge-triggered or level-sensitive: GICD_ICFGRn , GICR_ICFGRn
对于PPI和SPI,软件必须指定中断是edge-triggered的还是level-sensitive的。SGI始终被视为edge-triggered,因此对于这些中断,GICR_ICFGR0表现为“一体读取”、“忽略写入”(RAO/WI)。
Enable: GICD_ISENABLERn , GICD_ICENABLER , GICR_ISENABLERn , GICR_ICENABLERn
每个INTID都有一个使能位。Set-enable寄存器和Clear-enable寄存器消除了执行读取-修改-写入例程的要求。Arm建议在启用INTID之前配置本节中概述的设置。
Non-maskable: Interrupts configured as non-maskable are treated as higher priority than all other interrupts belonging to the same Group. That is, a non-maskable Non-secure Group 1 interrupt is treated as higher priority than all other Non-secure Group 1 interrupts.

  • non-maskable属性在GICv3.3中添加,并且需要PE中的匹配支持。
  • 只有Secure Group 1和Non-secure Group 1中断可以标记为non-maskable。
    对于裸机(bare metal)环境,通常不需要在初始配置后更改设置。但是,如果必须重新配置中断,例如要更改组设置,则应先禁用中断,然后再更改其配置。

Arm GICv3.1 and the extended INTID ranges
Arm GICv3.1增加了对额外SPI和PPI INTID的支持。配置这些中断的寄存器与原始中断范围相同,只是它们有一个E后缀。例如:
GICR_ISENABLERn:原始PPI范围的启用位
GICR_ISENABLERnE:为GICv3.1中引入的附加PPI启用位

Setting the target PE for SPIs
对于SPI,必须配置中断的目标。这由GICv3.1扩展SPI的GICD_IROUTERn或GICD_IROUTERnE控制。每个SPI都有一个GICD_IROUTERn寄存器,Interrupt_Routing_Mode位控制路由策略。选项包括:
GICD_IROUTERn.Interrupt_Routing_Mode == 0
SPI被传送到PE A.B.C.D,这是寄存器中指定的亲和坐标。

GICD_IROUTERn.Interrupt_Routing_Mode == 1
SPI可以被传递到参与中断组的分发的任何连接的PE。Distributor而不是软件来选择目标PE。因此,每次发出中断信号时,目标可能会发生变化。这种类型的路由被称为1-of-N。
PE可以选择不接收1-of-N的中断。这是由GICR_CTLR中的DPG1S、DPG1NS和DPG0位控制的。

Handling interrupts

本节描述了当中断发生时会发生什么:例如,如何将中断路由到PE,如何对中断进行优先级排序,以及在中断结束时会发生些什么。
Routing a pending interrupt to a PE
中断状态机部分描述了当中断源被断言时,中断如何从inactive状态转换到pending状态。当中断变为pending时,中断控制器根据以下检查决定是否将中断发送到连接的PE之一。这些检查确定将中断发送到哪个PE(如果有的话):
Check that the group associated with the interrupt is enabled.
安全模型部分描述了如何将每个INTID分配给一个组:Group 0,、Secure
Group 1或Non-secure Group 1。对于每个组,Distributor 和每个CPU Interface中都有一个组启用位。
中断控制器检查是否为与该中断的INTID相关联的组设置了组使能位。
作为禁用组成员的中断不能用信号通知PE。这些中断在组启用之前一直处于pending状态。

Check that the interrupt is enabled.
单独禁用的中断可能会pending,但不会转发到PE。

Check the routing controls to decide which PEs can receive the interrupt.
哪些PE可以接收中断取决于发送的中断类型:

  • 对于共享外设中断(SPI),路由由GICD_IROUTERn控制。SPI可以针对一个特定的PE,或任何一个连接的PE.
  • 对于特定于地区的外围中断(LPI),路由信息来自ITS。
  • 专用外围设备中断(PPI)特定于一个PE,只能由该PE处理。
  • 对于软件生成中断(SGI),始发PE定义目标PE的列表。这将在发送和接收软件生成的中断中进一步描述。

Check the interrupt priority and priority mask to decide which PEs are suitable to handle the interrupt.
每个PE在其CPU interface中都有一个优先级掩码寄存器ICC_PMR_EL1。此寄存器设置将中断转发到该PE所需的最低优先级。只有优先级高于掩码的中断才会用信号发送到PE。

Check the running priority to decide which PEs are available to handle the interrupt.
Running priority and preemption covers章节包括running priority,以及这对抢占的影响。如果PE尚未处理中断,则running priority为idle priority:0xFF。只有优先级高于running priority的中断才能抢占当前中断。
如果中断通过了所有这些检查,它将作为IRQ或FIQ异常转发到适当的core。

Taking an interrupt
当进入异常处理程序时,软件不知道它接受了哪个中断。处理程序必须读取其中一个中断确认寄存器(IAR)才能获得中断的INTID。
有两个IAR:
在这里插入图片描述
读取IAR将返回所取中断的INTID,并使中断的状态机前进。通常,在进入中断处理程序时读取IAR。然而,软件可以在任何时候自由读取寄存器。

有时,IAR无法返回有效的INTID。例如,软件读取ICC_IAR0_EL1,确认Group 0中断,但挂起的中断属于Group 1。在这种情况下,读取返回一个保留的INTID,如下表所示:
在这里插入图片描述

1020

  • 仅通过读取ICC_IAR0_EL1返回
  • 最高pending中断为Secure Group 1。
  • 仅在EL3中可见。
    示例场景:
    PE在Non-secure状态下执行时,发出了Trusted OS的中断信号。这被视为EL3的FIQ,因此Secure Monitor可以上下文切换到Trusted OS。

1021

  • 仅通过读取ICC_IAR0_EL1返回。
  • 最高的pending中断是 Non-secure Group 1。
  • 仅在EL3中可见。
    示例场景:
    PE在Secure状态下执行时,发出了rich OS中断的信号。这将被视为EL3的FIQ,这样Secure Monitor就可以上下文切换到rich OS。

1022

  • 读取ICC_IAR1_EL1时返回。
  • 最高的挂起中断是Non-secure Group 1。non-maskable property。
    示例场景:
    使用不同的寄存器确认具有non-maskable property的中断。

1023

  • Spurious中断
  • 在pending状态下没有启用的INTID,或者该pending状态中的所有INTID的优先级都不足。
    示例场景:
    当轮询IAR时,该值表示没有可供确认的中断。

如果存在中断,则对返回这些保留值之一的IAR的读取不会确认中断。

Example of interrupt handling
下图显示了一个带有调制解调器中断的移动系统示例,该调制解调器中断会发出来电信号。此中断旨在由处于Non-secure状态的Rich OS处理。
在这里插入图片描述
处理中断所涉及的步骤如下:

  1. 当PE在Secure EL1执行Trusted OS时,调制解调器中断变为pending。由于调制解调器中断被配置为Non-secure Group 1,因此它将被作为FIQ发送信号。在SCR_EL3.FIQ==1的情况下,异常被带到EL3。
  2. 在EL3执行的Secure Monitor软件读取IAR,IAR返回1021。该值表示中断预计将在Non-secure状态下处理。然后,Secure Monitor执行必要的上下文切换操作。
  3. 现在PE处于Non-secure状态,中断被重新发送信号作为IRQ,并被带到Non-secure EL1由Rich OS处理。

在本例中,Non-secure Group 1中断导致Secure OS立即退出。这可能并不总是需要或想要的。下图显示了此示例的替代模型,其中中断最初被用于Secure EL1:
在这里插入图片描述
现在,处理中断所涉及的步骤如下:

  1. 当PE在Secure EL1执行Trusted OS时,调制解调器中断变为pending。因为调制解调器中断被配置为Non-secure Group 1,所以它将被作为FIQ发送信号。在SCR_EL3.FIQ==0的情况下,Secure EL1 执行异常。
  2. Trusted OS执行操作以整理其内部状态。当它准备就绪时,Trusted OS使用SMC指令进入Non-secure state。
  3. SMC例外情况被带到EL3。在EL3执行的Secure Monitor软件执行必要的上下文切换操作。
  4. 现在PE处于Non-secure状态,中断作为IRQ发出信号,并被带到Non-secure EL1,由Rich OS处理。

Running priority and preemption
Priority Mask寄存器设置中断转发到PE的最低优先级。GICv3体系结构也有running priority的概念。当PE确认中断时,其running priority与中断的优先级相同。当PE写入其中一个中断结束(EOI)寄存器时,运行优先级返回到其以前的值。下图显示了PE在一段时间内的running priority示例:
在这里插入图片描述
当前运行优先级报告在CPU interface的Running Priority寄存器中:ICC_RPR_EL1。
在考虑抢占时,Running Priority的概念很重要。当高优先级中断被信号发送给已经在处理低优先级中断的PE时,就会发生抢占。抢占会给软件带来一些额外的复杂性,但它可以防止低优先级中断阻止处理高优先级中断。
下图显示了如果不允许抢占会发生什么:
在这里插入图片描述
高优先级中断被阻止,直到先前用信号通知的低优先级中断被采用为止。现在考虑同样的情况,但启用了抢占:
在这里插入图片描述
当较高优先级的中断变为pending时,它会抢占先前发出信号的低优先级中断。上图显示了抢占的一个级别。然而,可以有多个级别的抢占。

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

Binary Point寄存器将优先级分为两个字段,组优先级子优先级,如您所见:
在这里插入图片描述
对于抢占,只考虑组优先级比特。子优先级位被忽略。
例如,考虑以下三个中断:

  • INTID A 优先级 0x10. INTID
  • B 优先级 0x20. INTID
  • C 优先级 0x21.
    在这个例子中,我们决定:
  • A可以抢占B或C。
  • B不能抢占C,因为B和C的优先级相似。

为了实现这一点,组和子优先级之间的划分可以设置为N=4,如您所见:
在这里插入图片描述
通过这种拆分,B和C现在具有相同的优先权以实现抢占。然而,A仍然具有更高的优先级,这意味着它可以抢占B或C。
Binary Point寄存器只影响抢占,也就是说,在处理不同的中断时,是否应该发出中断信号。在pending中断之间进行选择时,不使用Binary Point寄存器。
抢占要求编写一个或多个中断处理程序以支持嵌套。

End of interrupt
一旦中断被处理,软件必须通知中断控制器中断已经被处理,以便状态机可以转换到下一个状态。Arm CoreLink GICv3体系结构将此视为两项任务:
Priority drop:
这意味着将running priority降回中断之前的值。
Deactivation:
这意味着更新当前正在处理的中断的状态机。通常,这将是从Active状态到Inactive状态的转换。

在GICv3体系结构中,priority drop和deactivation可以同时发生,也可以单独发生。这是由ICC_CTLR_ELn.EOI模式的设置决定的:
EOImode = 0:
对Group 0中断的ICC_EOIR0_EL1或对Group 1中断的ICC _EOIR1_EL1的写入执行priority drop和deactivation。这种模式通常用于简单的裸机 (bare meta)环境。
EOImode = 1:
对Group 0中断的ICC_EOIR0_EL1或对Group 1中断的ICC _EOIR1_EL1的写入会导致priority drop。需要对ICC_DIR_EL1进行单独写入以进行停用。此模式通常用于虚拟化。
大多数软件将使用EOIMode0。EOImode1最常被hypervisors使用。

Checking the highest priority pending interrupt and running priority
正如其名称所示,Highest Priority Pending中断寄存器ICC_HPPIR0_EL1和ICC_HPPIR1_EL1报告PE的最高优先级挂断的INTID。
Running priority由Running priority寄存器(ICC_RPR_EL1)报告。

Checking the state of individual INTIDs
Distributor提供了指示每个SPI的当前状态的寄存器。类似地,Redistributors为其连接的PE提供指示PPI和SGI状态的寄存器。

这些寄存器还可以将中断移动到特定状态。例如,这对于在不需要外围设备断言中断的情况下测试配置是否正确是有用的。

有单独的寄存器来报告active状态和pending状态。下表列出了active状态寄存器。pending的状态寄存器具有相同的格式:
在这里插入图片描述
在Non-secure状态下执行的软件无法看到Group 0或Secure Group 1中断的状态,除非GICD_NAMESCRn或GICR_NAMESCRn允许访问。

Sending and receiving Software Generated Interrupts

软件生成的中断(SGI)是软件可以通过写入中断控制器中的寄存器来触发的中断。
通过写入CPU interface中的以下SGI寄存器之一生成SGI:
在这里插入图片描述
下图中看到SGI寄存器的基本格式:
在这里插入图片描述
Controlling the SGI ID
SGI ID字段控制生成哪个INTID。如中断类型中所述,INTID 0-15用于SGI。
Controlling the target
SGI寄存器中的IRM(中断路由模式)字段控制将SGI发送到哪个PE或哪些PE。有两个选项:
IRM = 0:
中断被发送到<aff3>,其中被编码为下每个affinity 0节点的1位。这意味着中断最多可以发送到16个PE,其中可能包括始发PE。
IRM = 1:
中断被发送到所有连接的PE,除了始发PE(自身)。

Controlling the Security state and grouping
SGI的安全状态和分组由以下各项控制:

  • SGI寄存器ICC_SGI0R_EL1、ICC_SGI1R_EL1或ICC_ASGIR_EL1,由始发PE上的软件编写。
  • 一个或多个目标PE的GICR_IGROUPR0和GICR_IGRPMODR0寄存器。

在安全状态下执行的软件可以发送安全和非安全的SGI。在非安全状态下执行的软件是否可以生成安全的SGI由GICR_NSACR控制。

只有在安全状态下执行的软件才能访问此寄存器。下表显示了GIC通过检查来确定是否转发中断:

  • 发起PE的安全状态。

  • 中断所针对的PE的中断处理配置。

  • SGI寄存器。
    在这里插入图片描述

  • 此表假设GICD_CTLR.DS0。当GICD_CTL R.DS1时,标记为(*)的SGI也会被转发。

Comparison of GICv3 and GICv2
在Arm GICv2中,SGI INTID由始发PE和目标PE存入banked。这意味着给定PE最多可以有八次相同的SGI INTID pending起,一次来自系统中的每个PE。

在Arm GICv3中,SGI仅由目标PE存入banked。这意味着给定的PE只能有一个SGI INTID实例pending。

让我们用一个例子来说明这种差异。PE A和B同时向PE C发送SGI INTID 5,如下所示:
在这里插入图片描述
C将接收多少次中断?
对于GICv2:两个中断
GIC将接收来自A和B的两个中断。两个中断的顺序取决于单独的设计和精确的时序。这两个中断可以通过以下事实来区分:以读取GICC_IAR返回的INTID为前缀的originating PE的ID。

对于GICv3:一次中断
因为originating PE不存储到SGI,所以同一中断不能在两个PE上挂起。因此,C只接收一个中断,ID为5,没有前缀。

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

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值