本文目录
4.配置GIC
本章介绍如何在bare metal环境中启用和配置GICv3中断控制器,有关寄存器的详细说明,请参考文档 ARM® Generic Interrupt Controller Architecture Specification GIC architecture version 3.0 and 4。大多数使用GICv3中断控制器的系统都是多核系统或多处理器系统。有些配置属于全局性的,会影响所有PE,有些配置需要单独配置每个PE。
4.1 全局配置
主要配置的为GICD_CTLR寄存器,需要使能中断分组,设置路由模式。
- Enable Affinity routing (ARE bits)
GICD_CTLR的ARE域段,用于控制是否使能亲和性路由。如果不使能的话,GICv3使用Legacy operation。在亲和性路由使能的情况下,安全和非安全状态下是分开控制的。 - Enables
Group 0, Secure Group 1 and Non-secure Group 1的中断是独立使能的,只能使能对应的bit对应分组的中断才能由GIC发送给PE。
4.2 每个PE的配置
4.2.1 Redistributor的配置
复位时,Redistributor认为连接的PE处于睡眠状态,需要通过配置GICR_WAKER寄存器去唤醒对应的PE。软件应该按照如下流程进行操作:
- 清除 GICR_WAKER .ProcessorSleep ==0
- 轮询 GICR_WAKER .ChildrenAsleep,直到读出为0
使能和配置LPI中断在配置LPI章节单独描述。
当GICR_WAKER .ProcessorSleep=1或GICR_WAKER .ChildrenAsleep=1时,对系统寄存器操作会导致不可预测的行为(除了操作 ICC_SRE_ELn)
4.2.2 cpu interface的配置
CPU interface负责将中断传递到与其连接的PE。要启用CPU interface,软件必须配置以下内容:
- 使能系统寄存器访问
GICv3架构中,软件通过系统寄存器的方式对cpu interface寄存器进行访问,需要配置ICC_SRE_ELn.SRE将系统寄存器访问使能 - 设置优先级门限和 binary point寄存器
Priority Mask register(ICC_PMR_EL1)用于设置可以发送给PE的中断的最低优先级。和Binary Point registers(ICC_BPRn_EL1)用于中断分组和中断抢占 - 设置EOI模式
ICC_CTLR_EL1和 ICC_CTLR_EL3中的EOImode 用于控制如何处理中断的完成 - 使能中断分组
在CPU interface将每个中断分组的中断转发到PE之前,必须使能该中断分组。通过ICC_IGRPEN1_EL1设置Group 1中断,通过ICC_IGRPEN0_EL1设置Group 0中断。在EL3,软件可以通过ICC_IGRPEN1_EL3,访问安全Group 1中断和非安全Group 1中断的使能。
4.2.3 PE的配置
需要对PE进行部分配置,以便PE可以接收并处理中断。这里只介绍ARMv8-A在AArch64状态下执行的PE所需的基本步骤。
- 路由控制
路由控制位决定中断被送到哪个异常等级处理,可以通过配置 SCR_EL3 和 HCR_EL2 实现。 - 中断屏蔽
PE的PSTATE中存在异常屏蔽位,当对应bit被置位,此类中断会被屏蔽。 - Vector table
VBAR_ELn存放vector table的地址,复位时,该寄存器的值是未知的,因此必须使用软件将VBAR_ELn寄存器设置为指向Vector table
4.3 SPI/PPI/SGI的配置
通过配置Distributor的GICD_寄存器产生SPI中断,配置Redistributors的GICR_ 寄存器产生PPI和SGI中断。对于每个INTID都需要配置如下几项:
-
中断优先级 (GICD_IPRIORITYn 或 GICR_IPRIORITYn)
每个INTID都有对应的优先级,使用8位无符号数表示,其中0x00是最高优先级,oxFF为最低优先级。第5章描述了GICD_IPRIORITYn和GICR_IPRIORITYn中的优先级值是如何屏蔽低优先级中断,以及如何控制抢占的。 -
中断分组(GICD_IGROUPn, GICD_IGRPMODn, GICR_IGROUP0, GICR_IGRPMOD0)
每个INTID都可以配置成 Group 0, Secure Group 1 或 Non-secure Group 1中的一种。
-
中断触发方式(GICD_ICFGRn, GICR_ICFGRn)
如果中断是通过物理信号的形式发送的,那么需要将其触发方式配置成边沿触发或电平敏感型。SGI中断一直是边沿触发的,因此GICR_ICFGR0寄存器是RAO/WI的。 -
中断使能(GICD_ISENABLERn, GICD_ICENABLER, GICR_ISENABLER0, GICR_ICENABLER0)
每个INIID都有一个使能位。设置启用寄存器和清除启用寄存器消除了“读取-修改-写入”例程的要求。
对于bare metal环境,在初始化完成后,通常不需要再进行改配。但是,如果必须重新配置中断,例如更改中断分组,建议首先禁用该特定INTID。大多数配置寄存器的复位值都是“执行定义”的,这意味着中断控制器的设计者决定值是什么,并且值可能在不同系统之间变化。
4.3.1 设置SPI中断的路由目标
对于SPI中断,中断的路由目标必须单独进行配置,具体是通过配置GICD_IROUTERn实现的。每一个SPI都对应一个GICD_IROUTERn,同时Interrupt_Routing_Mode(IRM)位控制采用哪种路由策略。
-
IRM == 0
SPI中断会路由到a.b.c.d指定的PE,在该路由中,a、b、c和d分别是字段Aff3、Aff2、Aff1和Aff0的值 -
IRM == 1
SPI可以被传递到参与中断组的分发的任何连接的PE。Distributor(而不是软件)选择目标PE,并且这可以在每次发出中断信号时发生变化。这种类型的路由被称为1-of-N
PE可以选择不接收1-of-N中断。这由GICR_CTLR中的DPG1S、DPG1NS和DPG0位控制
5.处理中断
5.1 当中断挂起时会发生什么
在GICv3/v4-软件概述(一)第3.2节中,描述了当中断源被断言时,中断状态会从Inactive -> pending。这通常是由于外设assert专用中断信号。
当中断变为Pending时,中断控制器决定是否将中断发送到PE。中断控制器选择的PE(如果有)取决于以下设置:
- Group Enable
在GICv3/v4-软件概述(一)第3.4节中,我们知道每一个INITID都要分配到一个Group(Group 0, Secure Group 1 或 Non-secure Group 1),同时每一个Group在 Distributor和CPU interface中都对应一个Enable位,只有该使能位开启,中断才能发送给PE。 - Interrupt enables
如果对应的中断屏蔽位没有使能,中断仍然可以变为Pending状态,但是不会传递给PE - Routing controls
根据中断的类型,中断控制器必须决定哪些PE可以接收中断。对于SPI,这由GICD_IROUTERn控制,SPI可以路由至特定的PE或者任何一个相连的PE。PPI只能路由到某个指定的PE且只能由该PE处理。对于SGI,在配置产生SGI中断的时候指定路由的目标。对于LPI,如果实现了ITS,则路由信息来自ITS - Interrupt priority & priority mask
每个PE在其cpu interface中都有一个优先级掩码寄存器(ICC_PMR_EL1),此寄存器设置了将中断转发到该PE所需的最低优先级,只有优先级高于寄存器中值的中断才会用信号发送到PE - Running priority
下文第5.4节描述了运行优先级的概念以及对中断抢占的影响。如果PE尚未处理中断,则运行优先级为空闲优先级(0xFF),只有优先级高于运行优先级的中断才能抢占当前中断。
5.2中断应答
cpu interface有两个IAR寄存器,读取IAR返回INTID,并推进中断状态机状态跳转。在典型的中断处理程序中,处理中断的第一步是读取其中一个IAR。
5.3 伪中断
在GICv3/v4-软件概述(一)第3.1.2节描述了INTID范围1020到1023是为特殊目而保留的。这些INTID可以通过读取IAR返回,并指示异常处理中的特殊场景
举例一:INITID 1021
在一个手机系统中有一个modem中断,该中断在即将来临电话时会被触发。该中断打算在Non-secure态的Rich OS进行处理。
1.当PE在Secure EL1执行Trusted OS时,modem中断变为挂起状态(即此时有电话进来)。由于modem中断被配置为 Non-secure Group 1,它将被作为FIQ发送中断;又因为SCR_EL3.FIQ=1,该中断会taken to EL3。
2.运行在EL3的Secure Monitor读取IAR寄存器,返回INITID为1021,表明该中断期望在Non-secure态进行处理。Secure Monitor会执行必要的切换上下文操作。
3.此时PE处于Non-secure态,它将被作为IRQ发送中断,又因为SCR_EL3.IRQ=0,该中断在Rich OS taken to Non-secure EL1处理
在上图所示的示例中,Non-secure Group 1的中断导致立即从Secure OS退出。这可能并不总是想要的。下图显示了一个替代模型,其中中断最初taken to Secure EL1
1.当PE在Secure EL1执行Trusted OS时,modem中断变为挂起状态(即此时有电话进来)。由于modem中断被配置为 Non-secure Group 1,它将被作为FIQ发送中断;又因为SCR_EL3.FIQ=0,该中断会taken to Secure EL1
2.Trusted OS保存好内部状态后,使用SMC指令准备陷入 Non-secure 态
3.SMC异常taken to EL3,运行在EL3的Secure Monitor软件会执行必要的切换上下文操作
4.此时PE处于Non-secure态,它将被作为IRQ发送中断,又因为SCR_EL3.IRQ=0,该中断在Rich OS taken to Non-secure EL1处理。
5.4 运行优先级和抢占
PMR设置中断转发到特定PE的最低优先级。GICv3体系结构具有运行优先级的概念,当PE应答中断时,其运行优先级变为中断的优先级,当PE写入其中一个EOI寄存器时,运行优先级返回到以前的值。
Running Priority register(ICC_PRP_EL1)记录了当前运行优先级的值。
运行优先级的概念在讨论中断抢占时比较重要。当PE正在处理低优先级中断时,此时接收到一个高优先级中断,会发生中断抢占。
当向已经在处理低优先级中断的PE发送高优先级中断信号时,就会发生抢占。抢占为软件引入了额外的复杂性,但它可以防止低优先级中断阻塞对高优先级中断的处理。
如下图不支持中断抢占,低优先级的中断会阻塞高优先级中断的处理,只有低优先级的中断处理完成后,才会执行后续的高优先级中断。
如下图支持中断抢占,低优先级的中断在执行过程中,当接收到高优先级中断时,会优先执行高优先级中断,高优先级中断处理完成后,会继续执行低优先级中断。
上图显示的为一层中断抢占的例子,实际情况可能有多层中断抢占,当然在某些情形,可能不需要支持中断抢占。 GICv3体系结构允许通过Binary Point registers(ICC_BPRn_EL1)控制抢占所需的优先级。
Binary Point registers将中断优先级拆分为两部分: group priority 和 subpriority
在考虑中断抢占时,只要关注Group priority。举例说明:
假设配置ICC_BPRn_EL1将优先级拆分成如下两部分,此时A可以抢占B和C,但是B不能抢占C,因为B和C有相同的Group Priority。
Note:中断抢占要求中断处理程序必须支持嵌套。详细内容不在此讨论,请查阅其他资料
5.5中断结束
当中断完成处理后,软件必须通知中断控制器已经完成中断处理,以便状态机可以转换到下一个状态。GICv3体系结构分两步执行:
-
Priority drop
将运行优先级降回处理中断之前的值。 -
Deactivation
更新当前被处理中断的状态机。通常此时会由 Active -> Inactive。
在GICv3架构中, Priority drop 和 Deactivation可以独立进行或合并在一起执行,可以通过控制 ICC_CTLR_ELn.EOImode实现。
-
EOImode = 0
ICC_EOIR0_EL1(Group 0)和ICC_EOIR1_EL1(Group 1),此时Priority drop 和 Deactivation会一起执行。这种配置通常适用于bare metal环境。 -
EOImode = 1
ICC_EOIR0_EL1(Group 0)和ICC_EOIR1_EL1(Group 1)会单独执行Priority drop;再次配置ICC_DIR_EL1会完成Deactivation。这种配置经常用于虚拟化
5.6检查系统当前状态
5.6.1 最高优先级的Pending中断和运行优先级
正如名称所表示的,Highest Priority Pending Interrupt registers(ICC_HPPIR0_EL1 & ICC_HPPIR1_EL1)记录了该PE上挂起的最高优先级中断的中断号(INTID)。
运行优先级记录在ICC_RPR_EL1寄存器中。
5.6.2 单个中断的状态
SPI中断的状态记录在GICD_*中,PPI和SGI中断的状态记录在GICR_*中。通过这些寄存器还可以将中断直接转换到某种状态。在没有外设的情况下,通过这些寄存器可以很方便的测试配置的正确性。下表为active状态寄存器的描述,pending寄存器与此类似。
7.发送和接收SGI
通过配置cpu interface的系统寄存器产生SGI中断。
7.1中断的产生
寄存器的格式:
SGI ID:表示软中断号,范围0-15
IRM:SGI的路由方式(Interrupt Routing Mode)
···0x0:该中断支持路由给{Aff3,Aff2,Aff1,Target list},target List表示每个aff0上的节点。这意味着,该中断最多可以发送给16个PE
···0x1:该中断可以路由给除本身之外,所有连接着的PE
ICC_SGI0R_EL1, ICC_SGI1R_EL1, or ICC_ASGIR_EL1用于控制安全状态,该寄存器由发起中断的PE进行配置,ICC_SGI0R_EL1用于产生Group 0中断,ICC_SGI1R_EL1用于产生安全Group 1中断,ICC_ASGIR_EL1用于产生非安全Group 1中断。
GICR_IGROUPR0 和 GICR_IGRPMODR0 用于控制中断目标PE的中断分组
7.2 中断的安全和分组
在Secure下执行的软件可以发送Secure / Non-Secure SGI。
在Non-Secure下执行的软件是否能够生成Secure SGI 受GICR_NSACR控制。只有在安全状态下执行的软件才能访问此寄存器。
下表显示了发出中断的PE的Secure状态、SGI寄存器和中断目标PE的配置的多种组合,以及该是否可以转发