ARM GIC介绍

一、GIC介绍

GIC(Generic Interrupt Controller)ARM公司提供的一个通用的中断控制器,目前有4个版本GICv1 ~ GICv4GICv1已弃用;GICv2最多支持8个ARM CoreGICv3/GICv4支持更多的ARM Core)。

GIC的核心功能:对SOC中外设的中断源的管理,并提供给软件,配置以及控制这些中断源。当对应的中断源有效时,GIC根据中断源配置,决定是否将该中断信号发给CPU。如果有多个中断源有效,那么GIC还会进行仲裁,选择最高优先级中断,发送给CPU。当CPU接收到GIC发送的中断,通过读取GIC的寄存器,可以知道中断的来源,从而做对应的处理。当CPU处理完中断后,会配置GIC寄存器,表示该中断已处理完毕。GIC接收到信息后,就将该中断源取消,避免又重新发送该中断给CPU,以及允许中断抢占。

 

二、GIC IP

对于不同的GIC版本,ARM公司设计了对应的GIC IP

1)GIC-400:支持GICv2版本。

2)GIC-500:支持GICv3版本。

3)GIC-600:支持GICv3版本。

4)GIC-700:支持GICv3/GICv4.1版本。

CPUGIC之间兼容性见下图:

 

三、GIC框架

GICv3架构包括:

1、Distributor

DistributorSPI外设中断分发器,外设经特定硬件中断线连接到DistributorDistributor判断SPI中断的优先级,决定优先处理哪个中断,使用中断重映射表决定中断的目的PE,同时维护中断的active/pending/acknowledged状态。

2、Redistributor

Redistributor:管理SGI/PPI/LPI中断,决定他们的优先级,触发方式,控制他们的状态,以及enable/disable特定中断。

3、CPU interface

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

4、ITS

ITS(Interrupt Translation Service):接收LPI消息中断,根据消息携带的event iddevice id,翻译得到物理中断线以及目标PEITSdevice之间通过系统总线连接,device采用内存地址的形式发一个中断消息给ITS

5、 PE

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

GICv2GICv3少了RedistributorITS等功能。

GICv4GICv3的功能基本相同,增加了直接注入虚拟中断的能力。

 

四、GIC中断类型

GIC中断类型包括:

1、 SGI(Software Generated Interrupt)

软中断,主要用于核间通信,通过写SGI寄存器产生。

2、PPI(Private Peripheral Interrupt)

私有外设中断,为某个核的私有中断。例(arch/arm64/boot/dts/rockchip/rk3399.dtsi):

        # RK3399小核CortexA53 pmu PPI中断
        pmu_a53 {
                compatible = "arm,cortex-a53-pmu";
                interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_cluster0>;
        };

        # RK3399大核CortexA72 pmu PPI中断
        pmu_a72 {
                compatible = "arm,cortex-a72-pmu";
                interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_cluster1>;
        };
        ...
        # ARMV8 timer PPI中断
        timer {
                compatible = "arm,armv8-timer";
                interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW 0>,
                             <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW 0>,
                             <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW 0>,
                             <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW 0>;
                arm,no-tick-in-suspend;
        };

3、SPI(Shared Peripheral Interrupt)

共享外设中断,外设中断可以发送到任何一个连接的core。例(arch/arm64/boot/dts/rockchip/rk3399.dtsi):

        # RK3399 uart SPI中断
        uart0: serial@ff180000 {
                compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
                reg = <0x0 0xff180000 0x0 0x100>;
                clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
                clock-names = "baudclk", "apb_pclk";
                interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH 0>;
                reg-shift = <2>;
                reg-io-width = <4>;
                pinctrl-names = "default";
                pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
                status = "disabled";
        };

4、 LPI(Locality-specific Peripheral Interrupt)

特定区域外设中断。只在GICv3GICv4上支持。

不同中断类型的INITD范围如下:

注:目前Linux内核驱动中,使用的是IRQ中断,没有使用FIQ中断,同时禁止IRQ中断嵌套。

五、GIC中断触发方式

GIC中断触发方式包括:

1、edge-triggered interrupt

边沿触发中断。支持的中断类型有:SGI/PPI/SPI/LPI

2、 level-sensitive interrupt

电平触发中断。支持的中断类型有:PPI/SPI

 

注:GICv2/v3 SPI中断只支持上升沿或高电平触发。

代码如下:

drivers/irqchip/irq-gic-v3.c

static int gic_set_type(struct irq_data *d, unsigned int type)
{
        unsigned int irq = gic_irq(d);
        void (*rwp_wait)(void);
        void __iomem *base;

        /* Interrupt configuration for SGIs can't be changed */
        if (irq < 16)
                return -EINVAL;

        ## GICv3 SPI只支持高电平和上升沿触发中断
        /* SPIs have restrictions on the supported types */
        if (irq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
                         type != IRQ_TYPE_EDGE_RISING)
                return -EINVAL;
        ...
}

drivers/irqchip/irq-gic.c

static int gic_set_type(struct irq_data *d, unsigned int type)
{
        void __iomem *base = gic_dist_base(d);
        unsigned int gicirq = gic_irq(d);

        /* Interrupt configuration for SGIs can't be changed */
        if (gicirq < 16)
                return -EINVAL;

        ## GICv2 SPI只支持高电平和上升沿触发中断
        /* SPIs have restrictions on the supported types */
        if (gicirq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
                            type != IRQ_TYPE_EDGE_RISING)
                return -EINVAL;
        ...
}

 

六、GIC中断状态

GIC中断状态包括:

1、 Inactive

该中断源当前无效,未发生中断。

2、 Pending

已产生中断,未被PE响应。

3、 Active

该中断源已经发生并且已被PE响应。

4、 Active and pending

这个中断已被响应,再一次的中断正在被pending

GIC中断处理状态机如下:

 

七、GIC中断周期

GIC中断处理基于GIC中断生命周期,中断生命周期为描述中断处理过程,包括:

1、Generate interrupt

外设或软件产生一个中断。

2、Distribute

IRI(Interrupt Router Interface)实现中断分组、中断优先级控制、并控制中断转发到CPU接口。PPI/SGI是各个Core独有的中断,不参与目的Core仲裁。SPI是所有Core共享的,根据配置决定中断发往的Core。最后选择优先级最高的中断发给CPU interface。寄存器用GICD_做前缀。

3、Deliver

CPU接口将中断发给PE。将GICD发送的中断信息,通过IRQ、FIRQ引脚传输给Core。寄存器使用GICC_做前缀。

4、Activate

PE通过读取GICC_IAR寄存器识别中断,设置最高优先级的SGI/PPI/SPI中断为激活状态。

5、Priority drop

PE通过配置GICC_EOIR寄存器,实现优先级重置。

6、Deactivation

PE通过配置GICC_DIR寄存器,使该中断无效。

中断生命周期流程如下:

 

参考:

https://developer.arm.com/documentation/ka002107/1-0

IHI0048B_b_gic_architecture_specification.pdf

IHI0069H_gic_architecture_specification.pdf

{{o.name}}
{{m.name}}

猜你喜欢

转载自my.oschina.net/u/4702401/blog/8563064
GIC
今日推荐