ARM中断来瞅瞅

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: ARM中断来瞅瞅

最近看到了一个前辈的公众号,讲关于中断的。

篇一:中断及ARM体系中对中断的处理

今天来看一下中断及ARM体系中对中断的处理,直接进入正题。

中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。

中断的几个主要目的。

  • 第一,通过中断可以提高CPU效率。假设一种场景,CPU通知其它设备完成某项工作,当设备完成任务后,CPU如何知道呢?一种方式是设备标记状态寄存器,等待CPU来查询,这种做法弊端是程序员在编写程序时不能确切知道设备完成任务所需的时间,也就是说需要定时去查询设备的状态。我们知道,现代CPU一般频率很高,如果去频繁查询外部设备,尤其是低速设备,必将浪费很多的CPU资源;如果查询的时间间隔长,那么外设的利用率就不高。有一种解决办法,那就是外设处理完任务,主动告诉CPU,从而省去了CPU的查询开销。
  • 中断的第二个用途是,可以维护系统正常运行。现代的操作系统都是多任务系统,表面看起来多个程序在并行,实际上真正的CPU是分时复用的(假设最简单的单核单线程),并不是真的并行。如果这时有一个恶意程序,一直霸占CPU资源不释放,是不是整个系统就会挂死呢?答案是并不会,因为CPU的分配是由操作系统负责完成的,原理就是通过中断把控制权从程序手中交还给操作系统。另外,CPU访问内存或其它设备时,也可能发生一些错误。对于不同错误有不同的处理方式,也可以通过中断来完成。

对于一些特定的应用场景,设备系统需要满足实时性。所谓实时性,就是要求系统在规定的或者可预期的时间内作出反应。此类需求也可以通过中断来满足。

还记得前面讲ARM异常时的概念吗?中断算一种异步异常,《ARM系列 – 异常和特权》。A系列处理器提供四个管脚来实现中断,分别是:

  • nIRQ:物理普通中断
  • nFIQ:物理快速中断
  • nVIRQ:虚拟普通中断
  • nVFIQ:虚拟快速中断
    如下图所示:

其中虚拟中断是为了实现虚拟化而准备的,这部分留待以后讲虚拟化时再说。我们只看物理中断。

在开始介绍中断概念时,我们说中断可能会有很多种,每个设备都可能要发中断,而ARM处理器只有两个管脚,那怎么办?这时,就需要有一个模块来收集所有的中断,然后转发给处理器在ARM的体系中,这个模块就是通用中断处理器(generic interrupt controller,以下简称GIC)。

类似ARM的处理器,GIC有架构和实现之分。GIC的架构经历了GICv1,GICv2,GICv3和GICv4。每个架构下有有对应的设计实现,** **

在介绍GIC-600之前,有必要先讲一下中断的一些基本概念。

  • 首先,中断是分优先级的。很多个设备同时发送中断,处理器必须遵守一定的规则来给所有中断排序,从而决定先响应哪个。这个规则就是中断优先级,操作系统需要维护中断处理器中的优先级寄存器。
  • 既然有了优先级,就有了中断嵌套。当处理器处理某个低优先级的中断时,来了一个高优先级的中断,CPU可以保留低优先级的中断处理现场,转而处理高优先级中断,待高优先级处理完再继续处理低优先级中断。如果CPU在某段时间内,选择不响应某设备,其中断也可以被屏蔽。

在ARM体系中,对于每个中断,有四个状态:

  • inactive:中断处于无效状态
  • pending:中断处于有效状态,但是CPU没有响应该中断
  • active:中断处于有效状态,CPU在响应该中断
  • active and pending:CPU在响应该中断,但是该中断源又发送中断过来

在ARM体系中,中断分为以下几个类型(不讨论虚拟中断):

  • PPI:(Private Peripheral Interrupt,私有外设中断),该中断来源于core,但是该中断只对指定的core有效,所谓的私有即指对core私有;
  • SPI:(Shared Peripheral Interrupt,共享外设中断),该中断来源于外部设备,该中断可以对所有的core有效;
  • SGI:(Software Generated Interrupt,软件中断),用于给其它的core发送中断信号;
  • LPI:(Locality-specific Peripheral Interrupt,特定局部外设中断),是一种基于消息的边沿中断。

ARM又为每种中断分配了中断号,用以区分,其中1020-1023是特殊的中断号。

图1 GICv3中断号分配

对于每个中断,从产生到处理再到结束,是有一个完整的生命周期的。

图2 物理中断生命周期

  • generate:外设或软件发起一个中断
  • distribute:中断经过分组,优先级仲裁等,发送给对应的CPU interface
  • deliver:CPU interface将中断发送给core
  • activate:当CPU core开始响应中断,GIC将最高激活优先级的中断设置为激活
  • priority drop: core发信号给GIC,通知最高优先级中断,GIC可以重置优先级
  • deactivation:清除中断

这里要解释一下CPU interface。前面也提到了,core提供给中断的物理管脚只有两个,中断会有成百上千个,GIC怎么把这些中断发送给core是一个问题。这时就需要CPU interface了。CPU interface将GIC发送的中断信息,通过IRQ,FIQ管脚,发送给连接到core。CPU interface提供了以下的功能:

  • 将中断请求发送给core
  • 中断进行认可
  • 中断完成识别
  • 设置中断优先级屏蔽
  • 定义中断抢占策略
  • 决定当前处于pending状态最高优先级中断

在GICv3架构中,CPU interface被抽离出来,实现在core内部的。也就是说,在GIC-600中,是不包含CPU interface的。这样做的好处是,可以减少中断响应的时间,并且减少系统总线的占用。对于众核SoC设计来说,其物理设计非常大,CPU interface实现在core内部,也就意味着某些中断寄存器可以放在其内部,这样core就可以很快的访问到这些寄存器了。对于那些常用的寄存器**,core不用跋山涉水的通过系统总线或片上网络去频繁访问GIC了。CPU interface与GIC之间,是通过专用的AXI-stream总线来传输信息的。**

今天就到这里吧,下面就开始详细GIC-600的内部结构。

篇二:GIC-600的内部结构

闲话少说,今天开始扒GIC-600。

为了适应大规模的SoC设计,GIC-600被设计成分布式IP。

所谓分布式,GIC-600由几种组件构成,每个组件可以跟其它相关模块在物理设计上摆放在一起,并与其拥有共同的电源域;组件之间通过片上网络(network on chip,简称NoC)通信,从而达到更好的时序。

GIC-600的重要组件包括以下几种:

  • Distributor:GIC-600的核心部件,负责与其它组件通信,主要处理SPI和LPI
  • Redistributor:与cluster或core交互,主要处理PPI和SGI
  • ITS(Interrupt Translation Service):处理基于消息的中断,用于解析LPI
  • SPI collator:顾名思义,收集整理SPI
  • Wake request:产生wake_request给core

在具体介绍每个组件之前,我们有必要先来研究一下这些组件之间是如何连接的。主要有两种方式,

如何连接

第一种是利用片上网络,比如CMN-600这样的IP

图1 利用NoC连接GIC-600的组件

第一种方法,适合大规模的物理设计,尤其是全局时钟方案复杂的SoC。比如有很多的cluster,一般而言,一个redistributor对应一个cluster,这样redistributor可以和cluster一起做布局布线,redistributor和cluster之间的通信可以保持在一个比较高的频率,且timing容易实现。同样,对于有很多PCIe控制器的设计,ITS可以和PCIe控制器放在一起,实现LPI。对于SPI来说,一般多是给低速的外设准备的,所以SPI collator可以和distributor放在一起。

Wake request组件的主要作用就是可以产生唤醒信号给core,如果SoC设计中没有做关于core功耗方面的设计,这个组件可以不需要;如果有功耗控制的需求,这些唤醒信号要给SCP(system control processor)或者相关的模块,再做进一步的设计,具体取决于设计需要了。

第二种是私有的桥接。

图2 利用私有桥接连接GIC-600的组件

第二种方法,适合规模较小的,全局时钟方案简单的SoC,GIC-600的组件不依赖于片上网络(因为没有可用接口,比如NIC等)。这种方法的弊端是,组件之间的走线可能会非常长,并且可能需要在别的IP中穿行。好处是,不占用任何NoC的带宽。

单个组件

接下来看看每个组件。

  • 首先是distributor,一个SoC只有一个。其
  • 它的组件只能与distributor通信。所以,可以看出,distributor是GIC-600中的核心,其作用是收集所有的中断,并转发给相应的目标core。

    图3 GIC-600 distributor和SPI collator

对于core来说,可以通过上图中的ACE-Lite slave接口访问GIC-600中除去GITS_TRANSLATER的所有寄存器。由于为了实现LPI,GIC-600的distributor要维护几张表,且这些表格保存在内存中,所以需要一个master接口去访存。在上图中,对应的是ACE-Lite master总线接口。Distributor还包含三组AXI4-Stream接口,分别用于redistributor,ITS和其它distributor(比如多路服务器)的通信。至于Q-channel,不知道大家还记得多少,《SoC设计之功耗 – Q channel》,在这里主要是为了做时钟管理。

SPI collator对外的接口比较简单,输入SPIs,是来自外设的中断线。在GIC-600中,SPI数目是32的整数倍,目前最多支持960。输出SPI_r,是经过时钟同步的SPI信号,如果需要,可以送给发出SPI的外设。

Wake request模块是配合SoC功耗管理用的,如果需要实现core的idle状态管理,或者powergating,在distributor把中断发给目标core之前必须唤醒该core。所以唤醒信号是每个core一个。功耗管理取决于具体的设计,可以参考前面的文章,《ARM系列 – PCSA(二)》。

简单介绍完distributor,需要再讲讲AXI4-Stream总线。

图4 AMBA演进

在AXI4-Stream中,去掉了地址项,允许无限制的数据突发传输规模。正如spec中所说,这个总线是用于master和slave之间交换数据用的。接口信号比较简单,如下图:

图5 AXI4-Stream接口信号列表

大部分信号和AXI类似,ACLK和ARESETn信号,不必多说。TREADY和TVALID是mater和salve的握手信号,slave可以通过TREADY反压master的数据传送。需要注意的是TDEST和TID,TDEST提供数据流的路由信息,也就是说一个master可以接几个slave设备。TID提供数据流的标识,意味着master可以给slave交叉发送不同数据流。

如果两个设备要实现双向传输,就需要互为master和slave。拿GIC-600来说,一个SoC中只有一个distributor,同时可以有若干redistributor,但是redistributor只与distributor通信,且需要双向传输。也就是说distributor能看到多个redistributor,而一个redistributor只能看到distributor。Distributor可以通过TDEST把数据路由给相对应的redistributor,并且通过redistributor发过来的TID以区分不同的redistributor。

TDATA数据流包含三种类型:data、position、null。data是数据;position作为占位符使用,可以用来表征data的相对位置,null不包含任何有用的信息。数据流的结构可以有很多种,比如可以只传数据;也可以将数据和null或position混合传输。

图6 连续且对齐的数据流

图7 连续不对齐的数据流

图8 byte数据流

ACE-Lite总线就复杂多了,不是一两篇短文能说清楚的,留在以后吧。

篇三:redistributor

跟distributor连接的部分就不说了。Cpu_active是指示cluster或core的状态,可以用于idle管理。ppi_id用于多核设计时,区分每个redistributor。PPIs就是PPI中断线,在GIC-600是这么描述PPI的:

图2 PPI描述

从上面可以看出来,所谓的“私有”是说这些中断信号是core专有的。对于PPI,ARMv8定义了三种规格,8,12和16。所以对于不同的core来说,可能PPI数量不一样。

上面是ARMv8-A的架构spec里,关于timer的图。我们可以看到,core的timer会发PPI,而中断控制器返回FIQ或者IRQ给core。细心的同学可能会问了,在redistributor上面没有FIQ和IRQ的信号啊?其实在第一篇文章里就说了,在现有的GICv3架构下,关于中断FIQ和IRQ,以及系统寄存器等放在了cluster/core端,对外留出了一组接口,叫cpu interface(在GICv2中实现在中断控制器这一侧),也就是图1中最下面的接口。其实这是一组简化的AXI4-Stream。

图4 GIC stream协议接口

由于是双向,所以是两组信号

图5 redistributor到CPU的信号

图6 CPU到redistributor的信号

既然是简化的总线协议,为了更便于CPU和redistributor通信,ARM又规定了具体的数据包格式。下图是CPU端发出的命令格式,具体的解释请查阅GICv3的文档,此处就不过多的贴图了。

图7 CPU interface命令

至此,就剩下最复杂的ITS了,这一部分是为了实现基于消息的中断。前面介绍过,LPI是一种基于消息的中断。也就是中断信息不在通过中断线进行传递。ITS就是要将接收到的LPI中断进行解析。

图8 GIC-600的ITS组件

既然是信息中断,就一定要有区分这些中断的方法,这样才能找到合适的中断处理对策。所以这里有两个概念。

  • EventID,用来表示外设发送中断的事件类型
  • DeviceID,用来表示哪一个外设发起LPI

而ITS需要将外设发送的DeviceID,eventID,通过一系列查表,得到LPI的中断号,再使用LPI中断号查表得到该中断的目标CPU。为此,ITS需要维护几张表,分别是device table,interrupt translation tableh和collection。

当外设写GITS_TRANSLATER寄存器,产生了LPI。这时ITS首先要拿着DeviceID,从device table中选择索引为DeviceID的表项。从该表项中,得到interrupt translation table的位置;然后再根据EventID,从interrupt translation table中选择索引为EventID的表项。得到中断号,以及中断所属的collection号;最后,使用collection号,从collection table中,选择索引为collection号的表项。得到redistributor的映射信息,最后根据collection表项的映射信息,将中断信息路由发送给对应的redistributor。

最后,提一句,GICv3中开始支持亲和性路由(affinity routing)。请原谅我偷点懒,直接把文档中的部分贴出来:

里要解释一下什么是亲和性,我最初接触这个概念的时候简直是一头雾水,直到有一天看操作系统相关的书才明白是咋回事。CPU亲和性是一种调度属性(scheduler property),Linux调度器会根据affinity的设置让指定的进程运行在"绑定"的CPU上,而不会在别的CPU上运行。其中有一个好处是,可以提高cache的命中率。当一个进程在某个CPU上运行时,会在该CPU的缓存中维护许多状态。下次该进程在相同的CPU上运行时,由于缓存中的数据而执行的更快。因此,多处理器的调度器应该考虑这种亲和性,尽可能的进程保持在同一个CPU上。同理,对于并发程序也是有好处的。感慨一下,做CPU设计,到了最后肯定要与操作系统相爱相杀,哈哈哈~~~

本文内容来源链接:

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
存储 网络协议 Linux
基于ARM+Linux中断系统详细分析
基于ARM+Linux中断系统详细分析
基于ARM+Linux中断系统详细分析
|
Java
【嵌入式开发】ARM 关闭中断 ( CPRS 中断控制位 | 中断使能寄存器 | 中断屏蔽寄存器 | 关闭中断 | 汇编代码编写 )(二)
【嵌入式开发】ARM 关闭中断 ( CPRS 中断控制位 | 中断使能寄存器 | 中断屏蔽寄存器 | 关闭中断 | 汇编代码编写 )(二)
653 0
【嵌入式开发】ARM 关闭中断 ( CPRS 中断控制位 | 中断使能寄存器 | 中断屏蔽寄存器 | 关闭中断 | 汇编代码编写 )(二)
|
芯片
【嵌入式开发】ARM 关闭中断 ( CPRS 中断控制位 | 中断使能寄存器 | 中断屏蔽寄存器 | 关闭中断 | 汇编代码编写 )(一)
【嵌入式开发】ARM 关闭中断 ( CPRS 中断控制位 | 中断使能寄存器 | 中断屏蔽寄存器 | 关闭中断 | 汇编代码编写 )(一)
822 0
【嵌入式开发】ARM 关闭中断 ( CPRS 中断控制位 | 中断使能寄存器 | 中断屏蔽寄存器 | 关闭中断 | 汇编代码编写 )(一)
|
芯片
LINUX-内核-中断分析-中断向量表(3)-arm【转】
转自:http://blog.csdn.net/haolianglh/article/details/51986987 arm中断概念 在《ARM体系结构与编程》第9章中说到,ARM 中有个概念叫做“异常中断”,也就是包括外部中断在内的各种异常。
1756 0