ARM GIC(三) GIC V3 Handling Interrupts学习笔记。

Handling Interrupts

5.1 What happens when an interrupt becomes pending(中断什么时候变成挂起状态)

当中断被挂起时,中断控制器决定是否发送中断连接到其中一个已连接的PE。中断控制器选择的PE(如果有)取决于以下设置:
在这里插入图片描述

5.2 Interrupt acknowledge(中断响应)

CPU接口有两个IAR。读取IAR返回INTID在典型的中断处理程序中,处理中断的第一步是获取IAR。
在这里插入图片描述

5.3 Spurious interrupts(伪中断)

1020到1023是为特殊目的保留的。这些INTID可以通过读取IAR返回,并指示异常处理中的特殊情况。
在这里插入图片描述

在下面的例子中,一个移动系统有一个调制解调器中断,它向来电发出信号。此中断将由REE业务操作系统在非安全状态下处理。
在这里插入图片描述
1、当PE在安全EL1上 TEE 安全操作系统工作时,此时中断变为挂起。中断被配置为非安全组non-secure Group1时,它将作为FIQ发出信号。此时EL3 SCR_EL3.FIQ==1,IRQ == 0。

2、在EL3执行的安全监控软件读取IAR,IAR返回1021。1021指示中断预计将在非安全状态下处理,那么EL3需要执行必要的上下文切换操作。

3、现在PE处于非安全状态,中断被作为IRQ发出信号,并被带到非安全状态EL1将由REE操作系统异常向量表中处理。

上图中示例中,非安全组1中断将会导致CPU立即退出安全操作系统。这可能并不总是需要或想要的。图11显示了一个替代模型,其中中断最初用于保护EL1,也是目前TF-A主流推荐配置。

Figure 11 Alternative routing model

1、当PE在安全EL1上执行受信任的操作系统时,调制解调器中断变为挂起。当调制解调器中断被配置为非安全组1时,它将作为FIQ发出信号。但是此时SCR_EL3.FIQ==0,采取异常以保护EL1。
2、受信任的操作系统执行完其内部所有操作之后。当它准备好时,TEE-OS系统将使用SMC指令,切回非安全状态,此时CPU回到REE系统中
3、SMC例外情况适用于EL3。在EL3执行的安全监视器软件执行以下操作:必要的上下文切换操作。
4、现在PE处于非安全状态,中断被作为IRQ发出信号,并被路由到当前层级异常向量表中处理。

5.4 Running priority & preemption(优先级和抢占)

PMR设置中断必须转发到特定PE的最小优先级。这个GICv3体系结构具有运行优先级的概念。当PE确认一个中断时,它的运行优先级变成了中断的优先级。当PE写入时,运行优先级返回到它以前的值其中一个EOI寄存器。当前运行优先级报告在CPU接口的运行优先级寄存器中(ICC_RPR_EL1)。在考虑抢占时,运行优先级的概念很重要。抢占发生在优先级中断被发信号给已经在处理低优先级中断的PE。先发制人为软件带来了一些额外的复杂性,但它可以防止低优先级中断阻塞处理更高优先级的中断。

在 distributor 和 CPU interface 中都存在中断优先级的概念,高优先级的中断信号自然是优先处理,优先处理分为两种概念,一种是抢占优先,高优先级的中断可以直接抢占低优先级中断执行,另一种是并发的优先级,也就是当两个中断同时触发时,才会使用根据优先级来判断谁先执行,而如果低优先级中断正在处理,也只能等着。

在 gic 中,优先级由 8 位表示,总共 256 个等级,具体的实现可以不使用这么多,最少可以使用 4 bits 来表示,即 16 个优先级,优先级值的 value 越低,对应的执行优先级越高,因此,优先级为 0 总是表示最高优先级的中断,而最低优先级对应的 value,根据使用的优先级 bits 而定。

在 gic 中,存在两种类型的优先级,一种就是上面说的每个中断源都可配置为一个静态的中断优先级(由 distributor 管理),这个优先级可通过软件动态地修改,另一种是 CPU interface 的 runtime 优先级,即当前正在处理的优先级,当前中断的优先级高于正在处理的优先级时,中断才会将当前中断发送到 CPU 核,不同优先级的中断之间可以配置抢占,也就是在 CPU 正在处理低优先级中断时,再次发送一个高优先级中断,不过发送归发送,具体的实现中 CPU 是不是会受理该新的中断,根据实现而定,比如 linux 中,即使配置 gic 支持抢占,也会因为 linux 处理中断时会关闭中断而禁止中断的抢占。

在 GIC 的初始化阶段就已经为每个外部中断初始化了优先级,在外部中断传递的过程中,优先级和抢占的功能体现在下面的情况中

  • distributor 总是会将最高优先级的外部中断传递给 CPU interface,而 CPU interface 会维护当前正在处理或者正在 assert CPU IRQ 线的中断优先级。

  • CPU interface assert CPU 的 IRQ 线,CPU 再通过寄存器的读操作获取外部中断 ID.但是,在 CPU 的 IRQ 线被 assert 到 CPU 读取寄存器的过程中,产生了更高优先级的中断,会发生什么? distributor 会将新发生的高优先级的中断传递给 CPU interface,因此执行到 CPU 读取中断 ID 寄存器时,读取的也就是新中断的 ID 号,这种情况下,实现了高优先级中断的优先处理,从 CPU interface 的角度来说,这算是中断抢占,因为旧的中断已经提交,而新的高优先级中断横插一脚,而对于 CPU 来说,这并不算中断抢占,毕竟 CPU 还没有真正开始执行旧的中断,算是合理的优先级排序,毕竟抢占的概念通常用在正在执行的对象上。

  • 当 CPU 读取中断 ID 寄存器时,同时意味着向 CPU interface ack 了该中断,并开始处理中断,如果这时候产生了更高优先级的中断,此时这个中断在满足以下条件的情况下就会抢占当前的中断。

  • GIC 配置中断可抢占,中断的优先级配置中可以对中断进行分组,目前支持两个组:grp0 和 grp1,grp0 通常是针对 secure 模式,grp0 的中断可以传递搭配 CPU 的 IRQ 和 FIQ 线,而 grp1 通常应用在 nonsecure 模式,GIC 在初始化的时候可以为每个中断进行分组. 产生中断抢占的条件之一就是新的 pending 中断优先级要比当前 active 中断的优先级高,也就是抢占其实是以组为单位的. 在 linux 默认的 GIC 驱动中,默认运行在 nonsecure 模式,而且不使用 FIQ 引脚,因此默认是不配置抢占功能的。

  • 硬件上的抢占是一回事,软件上是否响应又是另一回事,当 CPU ack 了一个外部中断时,这时候 CPU interface 会 deassert CPU IRQ 中断线,如果产生了中断抢占的条件 ,新的中断就会重新 assert CPU IRQ 线,对于 arm 来说,在中断处理的时候关闭了 CPU 的中断,即使 IRQ 被重新 assert 也不会理会,当然, linux 系统是完全开放的,如果你是一个有想法又技术不错的 hacker,完全可能通过自行配置在 linux 中支持中断抢占。

5.5 End of interrupt(中断处理)

当中断已被处理时,软件必须通知中断控制器中断已被处理已被处理,以便状态机可以转换到下一个状态。当 CPU 中断处理完之后,需要将中断处理完的消息通知 GIC,这个消息通知包含两个部分

  • 优先级下降 —— 降低 CPU interface 的上报优先级
    这意味着将运行优先级降低到中断之前的值。

  • 失活 —— deactivate 处理完的中断,切换中断的状态
    这意味着更新当前正在处理的中断的状态机。通常是这样将从活动状态转换为非活动状态。

在GICv3体系结构中,优先级下降和停用可以同时发生,也可以单独发生。这是由ICC的设置决定。ICC_CTLR_ELn.EOImode。
在这里插入图片描述
在具体的实现中,这两个过程可配置为统一操作和分开操作的模式,由寄存器 GICC_CTLR 的 EOI 配置位进行配置,在 GIC 中被称为 EOI(end of interrupt) mode,当 EOI mode 被使能时,写寄存器 GICC_EOIR 将会触发中断的 priority drop,而 deactivate 操作需要通过写 GICC_DIR 寄存器实现,当 EOI mode 被 disable (对应上图中EOImode = 0)时,直接写 GICC_EOIR 将会同时触发 priority drop 和中断的 deactivate。

中断如何上报呢?

前面几篇博文主要结合手册梳理了中断一些基础概念,以及中断路由,中断嵌套的概念。下面以一个常见的低电平触发的中断为例,下面是一个中断的完整上报流程

  • 外设产生中断,拉低连接到 gic 的中断线,gic 中对应中断线的 pending bit 被置位,表示中断产生,这是 gic 的硬件自动完成的。

  • 如果该中断和全局中断传递使能,distributor 根据该中断设置的 CPU mask 将中断传递到对应的单个或多个 CPU interface,一般来说,只会将中断传递给一个 CPU 处理,如果为一个中断设置多个 target CPU,中断源的触发会导致多个 CPU 的 IRQ 引脚被拉低从而进入中断模式,实际上又只会有一个 CPU 处理该中断。但是在 GIC 手册中,是支持这种做法的,也就是一个中断源配置多个 target CPU(1-N中断),第一个 CPU ack 了该中断之后,后续的 CPU 查询中断 ID 寄存器返回无效的中断号 1023,退出中断处理,尽管我暂时没见过哪些中断需要这么干,但这种做法确实是被允许的。 如果存在多个中断,distributor 会将最高优先级的中断发送给 CPU interface。

  • CPU interface 决定是否将中断发送给 CPU 核,也就是触发对应 CPU 的 irq 引脚,取决于中断传递是否使能以及中断是否有足够的优先级,如果 CPU 当前没有正在处理中断,自然是可以传递的,如果 CPU 正在处理中断,那就看新中断的优先级是否更高同时还取决于是否配置了中断的抢占

  • 在 arm linux 中,CPU interface 将中断信号传递给 CPU,实际上就是 assert CPU 的 IRQ 中断线,如果 CPU 没有屏蔽 irq 中断线,就会跳转到中断模式,处理中断,经过一系列的现场保存工作等准备工作之后,CPU 会读取 GICC_IAR 寄存器获取中断 ID,读这个寄存器也意味着 CPU ack 了该中断,该中断在 gic 中记录的状态切换为 active and pending,因为即使 CPU ack 了中断,当前中断线的电平并没有被拉高,还是处于触发状态。 如果是边沿触发的中断,在 CPU ack 了之后,就会切换为 active 状态

  • 系统的中断代码会调用到用户自定义的中断处理程序,在自定义处理程序中,用户需要将该外部中断 deassert,也就是将中断线重新置为高,该 gic 的状态也就从 active and peding 切换为 active,如果没有这一个步骤,中断会被反复触发。

  • 中断处理完之后就是收尾工作,在这阶段,CPU 需要告诉 GIC 当前中断的处理已经完成,把当前中断源状态设置为 inactive,同时将 CPU interface 的优先级降低,linux 内核中也会重新开启中断(操作 CPSR 的 i bit),gic 也就可以重新发送其它的 pending 中断到 CPU 上了。

这是一个 SPI 中断的处理流程,对于 SGI 来说,不同之处在于:

  • 中断是软件触发的,通过向对应的寄存器中写入需要触发的中断号(0-15)以及对应的 CPU ID。
    distributor 并不再需要通过读取 CPU mask 寄存器来决定该中断需要发送给哪个 CPU,SGI 的 target CPU 在触发中断时已经决定了。

  • SGI 中断可以发送给多个 CPU,而且经常作为 CPU 之间通信的方式,各个 CPU 之间处理 SGI 中断是独立的,比如对于 8 号 SGI 中断,每个 CPU 都可以独立处理,而且在处理的过程中,每个 CPU 对应该中断的中断状态也是独立的。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: "Linux ARM GIC 中断流程" 是指在 ARM 架构的 Linux 操作系统中,使用 Generic Interrupt Controller(GIC处理器来管理系统中各种中断的流程。它负责将来自不同设备和外部事件的中断请求,分派给适当的处理程序来处理,并确保系统按顺序执行这些处理程序。中断处理是系统中一个重要的组成部分,它允许设备和软件互相通信,并提高了系统的稳定性和可靠性。 ### 回答2: Linux是一个非常流行的开源操作系统,可以在不同架构的计算机上运行。ARM架构是一种广泛使用的嵌入式系统架构,因此,许多嵌入式设备都使用Linux作为其操作系统。在ARM架构上,通常会使用GIC(通用中断控制器)来管理中断,这个过程可以分为中断触发、CPU响应和中断处理个部分。 中断触发是指中断信号从设备到达GIC的过程。当一个设备需要发送一个中断时,它会向GIC发送一个中断请求信号,并指定中断号,这个中断号是唯一的,用于区分不同的中断GIC会根据中断号去查找到这个中断对应的中断控制器,进而把这个请求传递给指定的CPU。 CPU响应是指CPU接收到中断请求信号后的响应过程。当GIC中断请求传递给CPU时,CPU需要检查是否允许这个中断请求,也就是检查中断屏蔽寄存器(Interrupt Mask Register)。如果这个中断请求已被屏蔽,则CPU不会响应,否则,它会设置自己的中断挂起寄存器(Interrupt Pending Register),告诉GIC它已经准备好去处理这个中断中断处理是指CPU执行中断处理程序,处理具体的中断。当CPU设置了它的中断挂起寄存器后,GIC会向CPU发送一个中断信号。CPU会暂停当前的进程,并把当前的上下文信息(比如,寄存器)保存到内存中。之后,CPU会跳转到中断处理程序(Interrupt Service Routine),开始执行具体的中断处理代码。中断处理程序完成后,CPU会从内存中恢复之前保存的上下文信息,并恢复之前进程的执行。 总的来说,ARM架构上的Linux操作系统通常使用GIC来管理中断,其中包括中断触发、CPU响应和中断处理个方面。这个流程对于保证系统的稳定性和快速响应非常重要。 ### 回答3: 在ARM架构的Linux系统中,GIC(Generic Interrupt Controller)被用来管理中断。当发生中断时,GIC会将中断信号发送到CPU,然后CPU会停止当前的进程并处理中断GIC中断流程如下: 1. 报告中断:设备或其他外部事件引发中断信号,设备向GIC发送中断信号,GIC会产生一个中断源标识符,然后将其发给CPU。 2. 响应中断:CPU根据中断源标识符查询GIC,查看中断请求的优先级和处理器状态,如果中断请求的优先级高于当前中断处理器,那么CPU会中止当前进程,执行中断处理程序。 3. 中断处理中断处理程序会读取设备状态,进行相应的操作,处理完成后会发出一个中断信号,通知GIC中断已被处理。 4. 中断结束:GIC收到来自设备的中断完成信号后,将中断源标识符置为未激活状态。 在这个流程中,GIC起到了一种路由的作用,将中断信号从设备传输到CPU,同时根据中断请求的优先级来优先处理高优先级的中断。这样就可以保证系统的稳定性和可靠性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狂奔的乌龟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值