ATF:givc3的中断处理流程

一、Bl31中断处理流程概述

中断处理需要软件和硬件配合完成,GICv3根据中断分组情况以及系统当前运行的异常等级确定中断是以IRQ还是FIQ触发。
  CPU通过设置SCR_EL3.IRQ和SCR_EL3.FIQ确定IRQ和FIQ中断分别是被路由到当前异常等级还是被路由到EL3
  若中断被路由到EL3,根据异常发生时系统所处的异常等级,使用的栈指针是SP_EL0还是SP_ELx(x> 0),以及使用的aarch32还是aarch64架构,在每个异常等级下都包含了四张异常等级表。以上具体的中断的路由规则可参考博文:【armv8中断路由机制】

bl31的异常向量表定义在runtime_exceptions.S中,其与下图的定义一致。

但在ATF中只实现了后面两种情形下的中断处理函数,即若当前系统运行在EL3下,则不允许异常发生。为简化讨论,我们只关注aarch64的情形,则实际上bl31只实现了下图中的第三种异常发生时中断的处理。

在这里插入图片描述

这是因为除了系统启动时以外,其它情况下系统运行在bl31则表示其本身是由低异常等级以smc指令进入的,此时系统本身就运行在异常上下文

而系统返回所需要的elr_el3和spsr_el3都被保存在了sp_el3栈中。在bl31中sp_el3只用于保存寄存器等系统状态信息,且所有的参数的存储位置都是预定义好的。此时,若发生了irq或fiq中断则中断处理函数也会将它的elr_el3和spsr_el3保存到sp_el3中,从而导致smc调用的返回信息被覆盖掉,从而使其无法返回。

因此bl31中的异常处理函数是非重入的,bl31运行时当前PE处于关中断状态当然,对于smp系统,由于每个PE的sp_el3是独立的,因此其它PE还是可以响应中断的。

当系统运行在低异常等级时产生group 0中断,则可以通过以上第三张异常向量表跳转到bl31的aarch64异常处理函数,下面以FIQ为例说明其中断处理流程。

二、FIQ为例说明其中断处理流程

1-保存环境

FIQ中断触发时,PE将异常发生时的PSTATE保存到SPSR_EL3将返回地址保存到ELR_EL3(以上是由硬件完成的),( pstate可能指CPU忙时的电源管理,也可能是其它的,但是肯定关于此时CPU状态的。)然后跳转到异常向量表入口处执行中断处理流程

2-执行中断处理流程

fiq_aarch64函数主要由handle_interrupt_exception宏实现,该宏的定义如下:

该函数主要实现了

  • 1、异常切换时的上下文保存
  • 2、运行时栈的切换
  • 3、中断处理函数查询
  • 4、参数设置和跳转功能。

其详细流程如下:

.macro	handle_interrupt_exception label
	bl	save_gp_pmcr_pauth_regs                                         (1)
(1)将通用寄存器(x0 – x29以及sp_el0),pmcr以及pauth寄存器保存到sp_el3指定的el3栈中

#if ENABLE_PAUTH
	/* Load and program APIAKey firmware key */
	bl	pauth_load_bl31_apiakey
#endif

	mrs	x0, spsr_el3
	mrs	x1, elr_el3
	stp	x0, x1, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]                (2)
	(2)将spsr_el3和elr_el3保存到sp_el3指定的el3栈中

	/* Switch to the runtime stack i.e. SP_EL0 */
	ldr	x2, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]             (3)
(3)从el3栈中读取sp_el0栈指针

	mov	x20, sp                                                       (4)
(4)将sp_el3栈指针暂存到x20寄存器中

	msr	spsel, #MODE_SP_EL0                                          (5)
(5)将当前的runtime栈切换为sp_el0

	mov	sp, x2                                                        (6)
(6)恢复sp_el0栈的值

	bl	plat_ic_get_pending_interrupt_type                              (7)
(7)读取当前中断的中断号,并根据中断号获取中断类型


	cmp	x0, #INTR_TYPE_INVAL
	b.eq	interrupt_exit_\label                                          (8)
(8)若中断类型为非法,则直接退出中断处理


	bl	get_interrupt_type_handler                                     (9)
(9)获取该中断类型对应的处理函数

	cbz	x0, interrupt_exit_\label                                       (10)
(10)若获取处理函数失败,则直接退出中断处理

	mov	x21, x0                                                      (11)
(11)将中断类型处理函数指针暂存到x21寄存器中


	mov	x0, #INTR_ID_UNAVAILABLE

	/* Set the current security state in the 'flags' parameter */
	mrs	x2, scr_el3
	ubfx	x1, x2, #0, #1                                                (12)
(12)设置中断处理函数的输入参数0和参数1


	/* Restore the reference to the 'handle' i.e. SP_EL3 */
	mov	x2, x20                                                      (13)
(13)将sp_el3指针设置中断处理函数的输入参数2


	/* x3 will point to a cookie (not used now) */
	mov	x3, xzr                                                     (14)
(14)设置中断处理函数的输入参数3,该参数始终当前为0


	/* Call the interrupt type handler */
	blr	x21                                                         (15)
(15)跳转到中断处理函数并执行实际的中断处理


interrupt_exit_\label:                                              
	/* Return from exception, possibly in a different security state */
	b	el3_exit

	.endm

(1)将通用寄存器(x0 – x29以及sp_el0),pmcr以及pauth寄存器保存到sp_el3指定的el3栈中

(2)将spsr_el3和elr_el3保存到sp_el3指定的el3栈中

(3)从el3栈中读取sp_el0栈指针

(4)将sp_el3栈指针暂存到x20寄存器中

(5)将当前的runtime栈切换为sp_el0

(6)恢复sp_el0栈的值

(7)读取当前中断的中断号,并根据中断号获取中断类型

(8)若中断类型为非法,则直接退出中断处理

(9)获取该中断类型对应的处理函数

(10)若获取处理函数失败,则直接退出中断处理

(11)将中断类型处理函数指针暂存到x21寄存器中

(12)设置中断处理函数的输入参数0和参数1

(13)将sp_el3指针设置中断处理函数的输入参数2

(14)设置中断处理函数的输入参数3,该参数始终当前为0

(15)跳转到中断处理函数并执行实际的中断处理

在bl31中实际的中断处理函数有两类,group 0中断和secure group 1中断。group 0中断由exception handler framework(ehf)管理,该框架实现了对bl31中group 0中断的注册和管理,当前sdei框架使用了这种中断类型。

而secure EL1中断一般是bl31为bl32接收并转发给bl32的,如optee在bl31中注册了一个secure el1中断处理函数opteed_sel1_interrupt_handler,该函数比较简单,只是执行了异常等级上下文切换,跳转到bl32的fiq异常处理入口,将中断处理转交给bl32。

3-ehf流程

ehf流程主要包括以下三部分:

  • (1)**向系统注册group 0中断处理函数,它是group 0中断处理的总入口函数。**当中断发生时,该中断处理函数会被上面的bl31异常入口函数查询并调用。(大多数使用的)

  • (2)向系统提供一个与不同优先级绑定的特定中断处理函数注册接口。不同的驱动可以把自己的中断处理函数注册到ehf框架中。

  • (3)ehf中断处理函数执行中断应答,以及查询并处理特定优先级中断处理函数功能。其基本处理流程如下图:

在这里插入图片描述

感动,这里竟然和我之前看的EHF框架联系起来了呜呜呜

https://zhuanlan.zhihu.com/p/520161285

猜你喜欢

转载自blog.csdn.net/weixin_45264425/article/details/129478452