前言
ARMV8的异常向量表较ARMV7的异常向量表有了很大的变动,但是实际上换汤不换药,做事情的方式变了,但是做的事情还是一样的。本文会详细介绍一下ARMV8的异常向量表。
异常routing
下面是异常发生时,exception level切换表:
我们举两个例子来说明下:
第一个红色框的内容表示:在此种配置下,EL0和EL1状态下产生的异步异常,会导致CPU进入EL1。
第一个红色框的内容表示:在此种配置下,EL0和EL1状态下产生的异步异常,会导致CPU进入EL1,而EL2状态下产生的异常,不会导致exception level切换。
Linux内核只支持EL0和EL1,EL0对应用户态,EL1对应内核态,当CPU运行在用户态时,产生的异步异常会导致CPU切换到EL1,当CPU运行在内核态时,产生的异步异常不会导致exception level的切换。
中断向量表
闲话不多说,我们先来看一下ARMV8异常向量表的定义:
这张表告诉我们以下几点事实:
- 实际上有四张表,每张表有四个异常入口,分别对应同步异常,IRQ,FIQ和出错异常。
- 如果发生异常并不会导致exception level切换,并且使用的栈指针是SP_EL0,那么使用第一张异常向量表。
- 如果发生异常并不会导致exception level切换,并且使用的栈指针是SP_EL1/2/3,那么使用第二张异常向量表。
- 如果发生异常会导致exception level切换,并且比目的exception level低一级的exception level运行在AARCH64模式,那么使用第三张异常向量表。
- 如果发生异常会导致exception level切换,并且比目的exception level低一级的exception level运行在AARCH32模式,那么使用第四张异常向量表。
- 另外我们还可以看到的一点是,每一个异常入口不再仅仅占用4bytes的空间,而是占用0x80 bytes空间,也就是说,每一个异常入口可以放置多条指令,而不仅仅是一条跳转指令。
Linux内核异常向量表
ENTRY(vectors)
kernel_ventry el1_sync_invalid // Synchronous EL1t
kernel_ventry el1_irq_invalid // IRQ EL1t
kernel_ventry el1_fiq_invalid // FIQ EL1t
kernel_ventry el1_error_invalid // Error EL1t
kernel_ventry el1_sync // Synchronous EL1h
kernel_ventry el1_irq // IRQ EL1h
kernel_ventry el1_fiq_invalid // FIQ EL1h
kernel_ventry el1_error // Error EL1h
kernel_ventry el0_sync // Synchronous 64-bit EL0
kernel_ventry el0_irq // IRQ 64-bit EL0
kernel_ventry el0_fiq_invalid // FIQ 64-bit EL0
kernel_ventry el0_error // Error 64-bit EL0
#ifdef CONFIG_COMPAT
kernel_ventry el0_sync_compat // Synchronous 32-bit EL0
kernel_ventry el0_irq_compat // IRQ 32-bit EL0
kernel_ventry el0_fiq_invalid_compat // FIQ 32-bit EL0
kernel_ventry el0_error_compat // Error 32-bit EL0
#else
kernel_ventry el0_sync_invalid // Synchronous 32-bit EL0
kernel_ventry el0_irq_invalid // IRQ 32-bit EL0
kernel_ventry el0_fiq_invalid // FIQ 32-bit EL0
kernel_ventry el0_error_invalid // Error 32-bit EL0
#endif
END(vectors)
首先我们要知道,用户态即EL0使用SP_EL0,内核态即EL1使用SP_EL1,再结合前两节的内容,我们可以得出如下结论:
- 第一张异常向量表是用不到的,因为EL0使用SP_EL0,但是EL0发生异常会routing到EL1。
- 第二章异常向量表用于CPU运行在EL1即内核态时,发生异常,因为EL1使用SP_EL1,并且exception level不会发生切换。
- 第三张向量表用于CPU运行在EL0即用户态AARCH32时,发生异常。
- 第四张向量表用于CPU运行在EL0即用户态AARCH64时,发生异常。
我们下一篇文章会继续分析异常处理逻辑。
参考文档:
DDI0487C_a_armv8_arm.pdf