ver0.1
前言
我们在观看很多的影视剧过程中,尤其是军旅体裁类型的布景中,经常会看见高级干部的办公桌上都会有几部电话机。这样的电话可不能小看,重要的事情尤其是突发和紧急的情况都要通过这几部电话第一时间通知给决策者。这几部电话,必须举报几个特点:及时性好、稳定性好、私密性好、传递的信息重要性高。
当然生活中的决策者一般都是重要组织的高级Leader,那些电话离我们普通人也很远。对于码农来说,计算机才是我们的世界。这个世界中也有一个地位无与伦比的决策者,SOC世界中的Leader,那就是CPU。那这个世界中的电话就是我们接下来要讨论的主题-GIC(通用中断控制器)。
研究GIC的目的还是为了研究虚拟化技术打下基础,中断的虚拟化也是虚拟化技术领域的重要基础之一,Hypervisor自己不想多干活就要好好的利用硬件提供的辅助能力。在ARM体系下,中断属于异常模型的范畴,所以大家在阅读本文之前,还是建议提前看看前序文章建立起对异常的基本感觉:
(1) [V-05] 虚拟化基础-异常模型(Exception)(AArch64)
正文
1.1 中断的背景
独木不成林,SOC的世界中不能只有CPU,还需要搭配各种各样的设备才能构成有价值的功能单元,必要的时候还需要通过接口扩展,链接进来更多的外部设备,如图1-1。
到这里,我们已经帮助CPU配置齐了一套设备,下一步就要考虑如何管理这些设备了。考虑下面一种场景,CPU分配了一块显存交给GPU去渲染,GPU接到指令后自然是不敢怠慢,加班加点的干活。当GPU完了CPU交办的渲染任务之后,自然是要向CPU复命的。那么问题来了,GPU要怎么通知CPU它已经干完活了呢?或者说,CPU要怎么知道GPU当前的渲染状态呢?你也许会说,CPU直接去问一下GPU不就行行了吗?事实上还真有这种方式,通过CPU主动查询的方式。GPU可以和CPU提前做好约定,例如在GPU的IO空间中分配一个寄存器,GPU可以在工作的过程中更新这个寄存器的状态,CPU可以在想要的时候不断的去读取GPU这个寄存器的状态。这样做法看似简单,实则一点也不难。只是这么个搞法会有一个效率的问题:
(1) CPU到底要啥时候去访问这个GPU的寄存器啊? 早了吧,GPU可能还没有干完活,CPU白跑一趟。晚了吧,GPU可能早就干完了,CPU白等了好长时间。
(2) 设个定时查询的机制,让CPU不断的轮询行不行呢?也不行的,因为同样会浪费很多CPU的时间片资源。就比如说,到底定时多长时间去轮询一次啊,这个值就不好确定。
似乎看上去CPU主动去查询的方式效率不高,处理不当会造成很大的CPU资源浪费。这个方向不行,就换一个方向考虑问题,让设备通知CPU就可以了。还是以GPU为例,CPU交办的任务是否完成了、完成的进度如何、实施的过程中是否有问题,只有GPU自己最了解情况,因此让GPU主动通知GPU是比较合理的处理方式了。这样CPU该干啥干啥,只是需要的时候由设备发起通知让CPU介入处理一下就可以了,双方都很满意。这种由设备主动发起通知CPU的行为就称为中断:中断是指计算机运⾏过程中,出现某些意外情况需主机⼲预时,机器能⾃动停⽌正在运⾏的程序并转⼊处理新情况的程序,处理完毕后⼜返回原被暂停的程序继续运⾏ 。
1.2 中断控制器(GIC)
1.2.1 GIC的基本概念
通过上一个小结的介绍,我们搞清楚了一个基本的事实,设备通过中断的方式可以实现和CPU的交流。那么是不是有了中断的机制后就可以万事大吉了,从此就可以CPU面南称孤,从此高枕无忧了。我们还是从图1-1就能看出,SOC有那么多的设备,大家都涉及到和CPU交流的问题。平时各个设备各忙各的,等到要和CPU交流的时候,都发中断,到底行不行? 我们来思考几个问题:
(1) 从硬件的角度,一个设备要和CPU交流中断信号,总得有一根线连接彼此吧。那么多的设备都要和CPU交流,是不是就需要很多根线啊,这对CPU宝贵的引脚资源可是一个严峻的考验。
(2) 两个设备如果同时发送中断信号给CPU,那么CPU总得一个一个处理的吧,总得有个优先级的概念吧,总不能一个设备发出了高温预警,一个设备只是例行请安,让火上房的事情先等等吧。
(3) 现在的CPU最大的特点那就是多核架构,多个PE-Core同时工作,那么中断信号来了应该如何处理,让哪个PE-Core去处理比较合理,是不是也得仔细掂量一下。
(4) 现代的PE-Core执行的状态其实越来越多的上下文其实是虚拟化的场景。这种场景下设备资源的虚拟化是绕不开的,甚至都不需要真实的设备存在,同样要模拟一个设备,既然是设备就涉及到和CPU或者vCPU通信的问题。
通过上面的分析,似乎中断这点事儿好像也不是那么简单的,的确如此。ARM体系下设计了一个专门的总线控制器来管理所有设备的中断,就是GIC(通用中断控制器),如图1-2所示。
看一下手册中对GIC的描述:
Small systems might have only a few interrupt sources and a single processor. However, larger systems might have many more potential interrupt sources and processors. The GIC performs the critical tasks of interrupt management, prioritization, and routing. The GIC marshals all interrupts from across the system, prioritizes them, and sends them to a core to be dealt with. GICs are primarily used to boost processor efficiency and to enable interrupt virtualization.
A Generic Interrupt Controller (GIC) takes interrupts from peripherals, prioritizes them, and delivers them to the appropriate processor core.
结合上图和手册的描述,我们来简单总结一下GIC:
(1) ARM体系下GIC作为独立的硬件模块存在连接了设备和处理器。
(2) GIC需要汇总设备的中断请求,并按照特定的规则进行分类、分级然后路由到相应的CPU上。
(3) GIC控制器支持虚拟化的工作场景。
1.2.2 GIC的总线架构
对GIC的基本概念有了初步的认知之后,我们换一个角度再来看一下GIC,如图1-3所示。
结合上图我们简单归纳一下:
(1) 从系统架构的角度看过去,GIC也是总线上的一个Master设备,当然也有属于自己的IO空间,供GPU进行访问。
(2) GIC和CPU是通过硬线链接,如果说MMU是CPU的带刀护卫,那么GIC就是CPU的忠诚信使。
(3) GIC和其他设备可以通过硬线、也可以通过一致性总线接口交换信息。
1.2.3 GIC的版本
GIC的架构也在不断的迭代升级中,目前经历了4个版本,GICv1、GICv2、GICv3、GICv4。GICv1已经比较久远了,比较新的这几代GIC架构支持的核心Feature,如图1-4所示。
我们接下来的文章主要会围绕GICv3和GICv4这两个版本展开。
1.3 GIC的系统架构
通过前面章节的讲解,我们已经搞清楚了,GIC的基本概念和其在总线架构下的位置。我们可以了解到GIC的硬件形态和CPU以及SOC的设计与实现是高度相关的,这里我们直接给出几个具象化(GIC-720AE)的设计实例供大家参考,如图1-5、图1-6、图1-7所示:
上面的两种实现方式,就比较适合集成大规模CPU的SOC设计,也就是一个物理硬件上有多个Cluster,因为GIC的各个组件可以实现总线层面的解耦,因为高度依赖一致性总线的能力,自身业务布线相对比较容易,也可以简单理解为去中心化比较容易。
上面这种实现方式就不太适合大规模物理模型的设计了,反而比较设规模相对较小,方案简单的SOC布局,虽然布线可能会较长,麻烦一些,但是会降低总线的设计难度,且不占用总线的带宽。
下面我们看一下手册中对GIC-720AE的具体介绍:
The GIC-720AE is a Functional Safety (FuSa) variant of the GIC‑700. The GIC-720AE is a Generic Interrupt Controller (GIC) that handles interrupts from peripherals to the cores and between cores. The GIC-720AE supports a distributed microarchitecture containing several individual blocks that are used to provide a flexible GIC implementation.
The GIC-720AE consists of the following blocks:
Distributor (GICD)
The Distributor is the hub of all the GIC communications and contains the functionality for all Shared Peripheral Interrupts (SPIs) and also Locality-specific Peripheral Interrupts (LPIs). It is responsible for the entire GIC programmers model, except for the GITS_TRANSLATER register, which is hosted in the Interrupt Translation Service (ITS) block.
In configurations that support GICv4.1, the Distributor also manages vSGIs and the management of vPEs.
The Distributor also maintains the coherency of the SPI register space in multichip configurations.
The LPI functionality for all cores on a chip is combined into a single cache in the Distributor.
GIC Cluster Interface (GCI)
The GCI maintains the Private Peripheral Interrupts (PPIs) and Software Generated Interrupts (SGIs) for a particular set of cores. A GCI can scale from 1-64 cores and is best placed next to the processors that it is servicing to reduce wiring to the cores.
A GCI is also referred to as a Redistributor.
Interrupt Translation Service (ITS)
The ITS translates message-based interrupts, Message-Signaled Interrupts (MSI/MSIx), from an external PCI Express (PCIe) Root Complex (RC), or other sources. The ITS also manages LPIs during core power management.
The GIC-720AE supports up to 32 ITS blocks for each chip.
MSI-64 Encapsulator
The MSI-64 Encapsulator is a small block that combines the DeviceID (DID), required by writes to the GITS_TRANSLATER register, into a single memory access.
SPI Collator
The GIC-720AE supports up to 1984 SPIs that are spread across the system. The SPI Collator enables SPIs to be converted into messages remotely from the Distributor.
Up to 32 SPI Collators can be supported in a single configuration. The 1984 SPIs can be spread across 32 SPI Collators, with a maximum of 1024 SPIs in one SPI Collator.
Wake Request
The Wake Request contains all the architecturally defined wake_request signals for each core on the chip. It is a separate block that can be positioned remotely from the Distributor, such as next to a system control processor.
GIC interconnect
The GIC interconnect is a set of components that can be used for routing the AXI5-Stream interfaces between the different blocks.
Top level
The top level has no specific interfaces but combines the interfaces of other blocks within the clock or power domain to reduce the number of domain bridges. The GIC-720AE build scripts enable you to build the GIC from either:
• A single combined block that uses a dedicated 16-bit AXI5-Stream interconnect.
• A set of individual blocks that interconnect using your own transport layer.
结合上图中实现实例以及手册中的描述简单归纳如下:
(1) GIC系统内部已经组件化,可以根据具体的应用场景进行差异化的设计,不管怎么设计,目的是不变的,就是为了实现系统中断信号到PE-Core的路由。
(2) GIC不仅支持外部设备的中断信号管理和转发,还支持PE-Core之间的中断信息传递。
(3) 中断信息的传递途径可以是硬中断信号的形式,还支持基于消息的形式传递,GIC内部提高专门的硬件模块来管理这些消息。
对GIC的系统架构,我们暂时就介绍到这里,后面的文章我们会围绕着这些核心组件,展开具体的介绍。以这些组件为线索,逐步展开GIC的工作原理。
结语
本文我们从中断这个概念诞生的背景开始逐步延展到基于ARM的中断控制器GIC的诞生,并且带着大家从总线的视角认识了GIC。希望通过本文大家能建立对GIC硬件总线层面的概念,为我们进一步的分解GIC打下基础。谢谢大家,请保持关注。
Reference
[00] <Armv8-A-virtualization.pdf>
[01] <DEN0024A_v8_architecture_PG.pdf>
[02] <learn_the_architecture_aarch64_exception_model.pdf>
[03] <corelink_gic_720ae_generic_interrupt_controller_trm.pdf>
[04] <arm_generic_interrupt_controller_v3_and_v4_virtualization_guide.pdf>
[05] <learn_the_architecture_generic_interrupt_controller_v3_and_v4_lpis.pdf>
[06] <80-ARM-GIC-wx0005_Arm-gicv3_v4学习这一篇就够了.pdf>
[07] <80-ARM-GIC-wx0003_ARM架构Generic-Interrupt-Controller-GIC之Distributor和CPU-interface.pdf>
[08] <80-ARM-GIC-HK0001-一文搞懂GICv3中断控制器的工作原理.pdf>
[09] <80-ARM-GIC-wx0001_ARM-gicv3_gicv4的总结-基础篇.pdf>
[10] <80-ARM-INT-yk0001_万字长文玩转中断:从硬件看中断之GIC.pdf>
Glossary
GIC - Generic Interrupt Controller
SCMI - System Control and Management Interface (SCMI)
ACPI - Advanced Configuration and Power Interface (ACPI)
PSCI - Power State Coordination Interface (PSCI)
UEFI - Unified Extensible Firmware Interface (UEFI)
UART - Universal Asynchronous Receiver/Transmitter
SPI - Shared Peripheral Interrupt
PPI - Private Peripheral Interrupt
SGI - Software Generated Interrupts
MPAM - Memory System Resource Partitioning and Monitoring
LPI - Locality-specific Peripheral Interrupt (LPI)
PE - Processing Element
MSI - message-signaled interrupts (MSI)
IAR - Interrupt Acknowledge Registers
EOIR - End of Interrupt Registers
IRM - Interrupt Routing Mode
ITS - Interrupt Translation Service
ITT - Interrupt Translation Tables