optee3.14中的异常向量表、VBAR_EL1、中断实现的介绍

★★★ 个人博客导读首页—点击此处 ★★★
.
说明:
在默认情况下,本文讲述的都是ARMV8-aarch64架构,optee3.14版本, 未开启FF-A

文章目录

  • 1、armv8-aarch64的异常向量表介绍
  • 2、armv8的VBAR_ELx寄存器
  • 3、optee异常向量表的实现
  • 4、optee异常向量表基地址的定义
  • 5、elx_irq和elx_fiq

1、armv8-aarch64的异常向量表介绍


我们可以看出,实际上有四组表,每组表有四个异常入口,分别对应同步异常,IRQ,FIQ和serror。

  • 如果发生异常后并没有exception level切换,并且发生异常之前使用的栈指针是SP_EL0,那么使用第一组异常向量表。
  • 如果发生异常后并没有exception level切换,并且发生异常之前使用的栈指针是SP_EL1/2/3,那么使用第二组异常向量表。
  • 如果发生异常导致了exception level切换,并且发生异常之前的exception
    level运行在AARCH64模式,那么使用第三组异常向量表。
  • 如果发生异常导致了exception level切换,并且发生异常之前的exception
    level运行在AARCH32模式,那么使用第四组异常向量表。

另外我们还可以看到的一点是,每一个异常入口不再仅仅占用4bytes的空间,而是占用0x80 bytes空间,也就是说,每一个异常入口可以放置多条指令,而不仅仅是一条跳转指令

2、armv8的VBAR_ELx寄存器

armv8定义了VBAR_EL1、VBAR_EL2、VBAR_EL3三个基地址寄存器

3、optee异常向量表的实现

(optee_os/core/arch/arm/kernel/thread_a64.S)#define INV_INSN 0
FUNC thread_excp_vect , : align=2048/* -----------------------------------------------------* EL1 with SP0 : 0x0 - 0x180* -----------------------------------------------------*/.balign   128, INV_INSN
el1_sync_sp0:store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3b    el1_sync_abortcheck_vector_size el1_sync_sp0.balign 128, INV_INSN
el1_irq_sp0:store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3b elx_irqcheck_vector_size el1_irq_sp0.balign 128, INV_INSN
el1_fiq_sp0:store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3b elx_fiqcheck_vector_size el1_fiq_sp0.balign 128, INV_INSN
el1_serror_sp0:b    el1_serror_sp0check_vector_size el1_serror_sp0/* -----------------------------------------------------* Current EL with SP1: 0x200 - 0x380* -----------------------------------------------------*/.balign  128, INV_INSN
el1_sync_sp1:b  el1_sync_sp1check_vector_size el1_sync_sp1.balign   128, INV_INSN
el1_irq_sp1:b   el1_irq_sp1check_vector_size el1_irq_sp1.balign 128, INV_INSN
el1_fiq_sp1:b   el1_fiq_sp1check_vector_size el1_fiq_sp1.balign 128, INV_INSN
el1_serror_sp1:b    el1_serror_sp1check_vector_size el1_serror_sp1/* -----------------------------------------------------* Lower EL using AArch64 : 0x400 - 0x580* -----------------------------------------------------*/.balign  128, INV_INSN
el0_sync_a64:restore_mappingmrs x2, esr_el1mrs  x3, sp_el0lsr   x2, x2, #ESR_EC_SHIFTcmp    x2, #ESR_EC_AARCH64_SVCb.eq el0_svcb    el0_sync_abortcheck_vector_size el0_sync_a64.balign 128, INV_INSN
el0_irq_a64:restore_mappingb    elx_irqcheck_vector_size el0_irq_a64.balign 128, INV_INSN
el0_fiq_a64:restore_mappingb    elx_fiqcheck_vector_size el0_fiq_a64.balign 128, INV_INSN
el0_serror_a64:b    el0_serror_a64check_vector_size el0_serror_a64/* -----------------------------------------------------* Lower EL using AArch32 : 0x0 - 0x180* -----------------------------------------------------*/.balign    128, INV_INSN
el0_sync_a32:restore_mappingmrs x2, esr_el1mrs  x3, sp_el0lsr   x2, x2, #ESR_EC_SHIFTcmp    x2, #ESR_EC_AARCH32_SVCb.eq el0_svcb    el0_sync_abortcheck_vector_size el0_sync_a32.balign 128, INV_INSN
el0_irq_a32:restore_mappingb    elx_irqcheck_vector_size el0_irq_a32.balign 128, INV_INSN
el0_fiq_a32:restore_mappingb    elx_fiqcheck_vector_size el0_fiq_a32.balign 128, INV_INSN
el0_serror_a32:b    el0_serror_a32check_vector_size el0_serror_a32

(1)、check_vector_size
check_vector_size其实就是检查异常向量中的指令size,不能草果32*4=128字节,因为armv8-arch64定义的异常向量每一个offset中的地址范围是128字节

 .macro check_vector_size since.if (. - \since) > (32 * 4).error "Vector exceeds 32 instructions".endif.endm

(2)、128字节对其的异常向量
balign 128就是告诉汇编代码,接下来的函数定义是128字节对其的。这也和armv8-arch64定义的异常向量的地址范围一致

.balign  128, INV_INSN

(3)、异常向量实现的总结

异常向量 处理的函数 判定是否实现
第一组 el1_sync_sp0 b el1_sync_abort Y
第一组 el1_irq_sp0 b elx_irq Y
第一组 el1_fiq_sp0 b elx_fiq Y
第一组 el1_serror_sp0 b el1_serror_sp0
自己跳转到自己,相当于死循环
N
第二组 el1_sync_sp1 b el1_sync_sp1
自己跳转到自己,相当于死循环
N
第二组 el1_irq_sp1 b el1_irq_sp1
自己跳转到自己,相当于死循环
N
第二组 el1_fiq_sp1 b el1_fiq_sp1
自己跳转到自己,相当于死循环
N
第二组 el1_serror_sp1 b el1_serror_sp1
自己跳转到自己,相当于死循环
N
第三组 el0_sync_a64 b el0_sync_abort Y
第三组 el0_irq_a64 b elx_irq Y
第三组 el0_fiq_a64 b elx_fiq Y
第三组 el0_serror_a64 b el0_serror_a64
自己跳转到自己,相当于死循环
N
第四组 el0_sync_a32 b el0_svc Y
第四组 el0_irq_a32 b elx_irq Y
第四组 el0_fiq_a32 b elx_fiq Y
第四组 el0_serror_a32 b el0_serror_a32
自己跳转到自己,相当于死循环
N

总结一下也是很好理解:

  • 在optee os中,使用的sp_el0栈,同时支持aarch32、aarch64的user程序,所以实现了第一、三、四组异常向量,另外optee不处理serror异常,所以serror也不实现。
  • 在Linux kernel中,使用sp_el1栈,同时支持aarch32、aarch64的user程序,所以实现了第二、三、四组异常向量.
    (注:虽然Linux Kernel实现了FIQ向量,但该向量下的逻辑最终跳转到panic()函数,也就是如果触发了target到Linux Kernel的FIQ,将发生panic.)

(4)、elx_irq和elx_fiq
以irq/fiq为例,我们还可以发现,无论是哪种分组异常,最终跳转的都是同一类函数:elx_irq和elx_fiq,即无论是下面哪种情况,跳转的都是elx_irq和elx_fiq函数。

  • PE在optee os特权级(S-EL1)执行时,来了一个irq/fiq中断
  • PE在userspace非特权级(S-EL0)执行aarch64时,来了一个irq/fiq中断
  • PE在userspace非特权级(S-user mode)执行aarch32时,来了一个irq/fiq中断

4、optee异常向量表基地址的定义

从上文的异常向量表的实现中可以发现,异常向量定义在了thread_excp_vect函数中, 那么该函数(异常向量)是如何布局到内存的? 该函数的基地址又是如何写入到VBAR_EL1的?

FUNC thread_excp_vect , : align=2048


thread_init_vbar(vaddr_t addr)将addr写入到vbar_el1

(optee_os/core/arch/arm/kernel/thread_a64.S)FUNC thread_init_vbar , :msr vbar_el1, x0ret
END_FUNC thread_init_vbar

get_excp_vect()返回异常向量表基地址(当然是虚拟地址)

(optee_os/core/arch/arm/kernel/thread.c)static vaddr_t get_excp_vect(void)
{#ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SECuint32_t midr = read_midr();if (get_midr_implementer(midr) != MIDR_IMPLEMENTER_ARM)return (vaddr_t)thread_excp_vect;switch (get_midr_primary_part(midr)) {#ifdef ARM32case CORTEX_A8_PART_NUM:case CORTEX_A9_PART_NUM:case CORTEX_A17_PART_NUM:
#endifcase CORTEX_A57_PART_NUM:case CORTEX_A72_PART_NUM:case CORTEX_A73_PART_NUM:case CORTEX_A75_PART_NUM:return select_vector((vaddr_t)thread_excp_vect_workaround);
#ifdef ARM32case CORTEX_A15_PART_NUM:return select_vector((vaddr_t)thread_excp_vect_workaround_a15);
#endifdefault:return (vaddr_t)thread_excp_vect;}
#endif /*CFG_CORE_WORKAROUND_SPECTRE_BP_SEC*/return (vaddr_t)thread_excp_vect;
}

关于从cpu的启动(从cpu启动时设置VBAR_EL1):

  • 如果在整个系统中有实现ATF,则CFG_WITH_ARM_TRUSTED_FW宏是打开的,那么从cpu是从boot_cpu_on_handler启动,也就是从ATF调来的。
  • 如果在整个系统中没有实现ATF,则CFG_WITH_ARM_TRUSTED_FW宏是关闭的,那么从cpu是从reset_secondary---->boot_init_secondary调用过来的
(optee_os/core/arch/arm/kernel/boot.c)#if defined(CFG_WITH_ARM_TRUSTED_FW)
unsigned long boot_cpu_on_handler(unsigned long a0 __maybe_unused,unsigned long a1 __unused)
{init_secondary_helper(PADDR_INVALID);return 0;
}
#else
void boot_init_secondary(unsigned long nsec_entry)
{init_secondary_helper(nsec_entry);
}
#endif

细心的同学看代码可以发现:

  • armv8-aarch64架构都是有实现ATF,一般情况下CFG_WITH_ARM_TRUSTED_FW宏也都是打开的
  • 在optee的aarch64体系中,是没有调用boot_init_secondary函数的,仅仅在optee_os/core/arch/arm/kernel/entry_a32.S中的reset_secondary中进行了调用boot_init_secondary()

5、elx_irq和elx_fiq

gicv3/gicv2有着不同的处理

  • 如果是gicv2,则会将irq视为外系统中断,fiq视为本系统中断;
  • 如果是gicv3,恰好相反,将fiq视为外系统中断,irq视为本系统中断.

(注从optee中断软件的视角来看,gic可以分为两类,gicv2、非gicv2, 这里说说的gicv3其实就是非gicv2,如果你使用的是gicv4,那么也会定义CFG_ARM_GICV3宏)

本系统中断和外部系统中断的处理:

  • 如果是本系统中断,则调用native_intr_handler
  • 如果是外部系统中断则调用foreign_intr_handler
(optee_os/core/arch/arm/kernel/thread_a64.S)LOCAL_FUNC elx_irq , :#if defined(CFG_ARM_GICV3)native_intr_handler  irq#elseforeign_intr_handler    irq#endifEND_FUNC elx_irqLOCAL_FUNC elx_fiq , :#if defined(CFG_ARM_GICV3)foreign_intr_handler   fiq#elsenative_intr_handler fiq#endifEND_FUNC elx_fiq

optee3.14中的异常向量表解读--中断处理解读相关推荐

  1. Linux Kernel 5.14 arm64异常向量表解读-中断处理解读

    ★★★ 个人博客导读首页-点击此处 ★★★ . 说明: 在默认情况下,本文讲述的都是ARMV8-aarch64架构,linux kernel 5.14 文章目录 1.armv8-aarch64的异常向 ...

  2. [optee]-optee中的异常向量表的实现

    Optee异常向量表 ARMV8-aarch64 1.optee中定义的异常向量表 2.optee中设置向量表基地址VBAR_EL1 ARMV8-aarch32.ARMV7-aarch32 1.opt ...

  3. optee3.14中MMU页表查询的所需配置--深入解读

    从arm官方文档来看,物理地址的有效位支持32.36.40.42.44.48,最大为48,如果开启了ARMv8.2-LPA,则也支持52 而对应的虚拟地址的有效位,是没用规定的,但是有一条潜规则,虚拟 ...

  4. optee中关于异常向量表、中断等的深入思考

    快速链接: .

  5. 在linux、optee、ATF中的中断异常向量表

    目录 1.在linux中的异常向量表 (1).arm64的异常向量表-(irq,fiq,svc......) (2).arm32的异常向量表-(irq,fiq,swi......) 2.在optee中 ...

  6. optee的异常向量表-(irq,fiq,svc...)

    文章目录 1. optee中的异常向量表thread_excp_vect 1.1.异步异常elx_irq.elx_fiq中断的处理 1.2.同步异常el0_sync_a64.el0_sync_a32中 ...

  7. inside uboot (三) 异常向量表

    1. 异常向量表概述 从上面的地址映射来看,中断向量表的地址为0xD0037400,因此如果我们想在SRAM中,也就是BL1中处理异常的话, 就需要把我们的异常向量表拷贝到这个地址上.或者我们可以在链 ...

  8. [答疑]-ATF中异常向量表为何没有实现“Current Exception level with SP_ELx, x>0.“

    先看下ARM官方文档中所定义的向量表 第一行描述: 没有发生Exception切换,且SP使用的是SP_EL0 第二行描述: 没有发生Exception切换,且SP使用的是SP_ELx(x=1,2,3 ...

  9. [ARM异常]-linux中(aarch/aarch64)异常向量表介绍

    文章目录 1.ARM的异常向量表基地址寄存器--VBAR 1.1.armv8 : VBAR寄存器 1.2.armv7 : VBAR寄存器 2.ARM的异常向量表的定义 2.1 armv8 :异常向量表 ...

最新文章

  1. UC伯克利博士尤洋回国创业,曾破ImageNet纪录!已获超千万融资
  2. 项目分析(map复习)
  3. 分析脚本文件AndroidInitProcess分析心得(1)
  4. Taro+react开发(70):flex布局
  5. CSS中的box-sizing
  6. java字符串替换的问题
  7. 分蛋糕问题 —— 9 个烧饼分给 10 个人
  8. python模块之subprocess
  9. JDK-阻塞队列、非阻塞队列原理
  10. Webstorm中文乱码的问题
  11. python文件操作方法seek_Python文件操作及seek偏移详解
  12. WebView启动支付宝客户端支付失败的解决办法
  13. html基础、h5c3高级c3动画 、 JavaScript初高级、css预处理器和git 部分面试题
  14. 2022金九银十Android大厂面试题来袭,面试字节跳动被问Android屏幕适配方案
  15. 中国 SaaS 二十年的回顾
  16. [014量化交易] python 通过tushare 获取股票数据、名称、股票代码、指定股票名
  17. 分布式系统中CAP原理
  18. ZOJ 3084 SG函数
  19. 【记录】数据处理方法总结及实现
  20. 理性行为理论和计划行为理论

热门文章

  1. 数据中心的清洁与扫除
  2. bootstrap项目更改为vue_取代Jquery,用Vue 构建Bootstrap 4 应用
  3. js 获取屏幕高宽_JS获取屏幕的宽高。
  4. 数据传输完整性_生产系统数据完整性事件常见指标(下)
  5. java opengl_java基于OpenGL ES实现渲染实例
  6. Python之 sklearn:sklearn中的train_test_split函数的简介及使用方法之详细攻略
  7. 成功解决OpenCV Error: Assertion failed (ssize.width 0 ssize.height 0) in cv::resize, file C:\proj
  8. Dataset之MNIST:自定义函数mnist.load_mnist根据网址下载mnist数据集(四个ubyte.gz格式数据集文件)
  9. Py之PyTables:PyTables的简介、安装、使用方法详细攻略
  10. 使用ML.NET + Azure DevOps + Azure Container Instances打造机器学习生产化