ARM深入理解-5.2-通往内核的大门(异常向量表_AArch64)

简介: ARM深入理解-5.2-通往内核的大门(异常向量表_AArch64)
  • 1 建立向量表
  • 2 建立向量表的示例
  • 3 使能中断


异常初始化的过程:

  1. 建立异常向量表
  2. 异常路由和屏蔽配置


1 建立向量表


AArch64中,reset不再是异常向量表的一部分,它有专用的配置输入管脚和寄存器。其余的异常存储在异常向量表中。


1.1 Reset向量


AArch64中,处理器的开始执行位置是跟处理器的实现有关的,由硬件输入管脚RVBARADDR控制,可以在RVBAR_EL3中读取该地址。启动(boot)代码应该放在该地址处。


1.2 向量表


每个异常级别都有专门的异常向量表,分别存储在下面的寄存器中:

  • VBAR_EL3
  • VBAR_EL2
  • VBAR_EL1

AArch64的向量表与AArch32的不同。每个向量占用128字节,最多包含32个指令。向量表按照2K大小对齐。初始化的时候,将向量表的基地址写入到VBAR_ELx寄存器中即可。

关于向量表更多的细节,可以参考ARM官方文档ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture规范中异常向量表部分。

下表展示了向量表的组成:

地址 异常类型 描述
VBAR_Eln+0x000 Synchronous 异常EL与异常前的EL相同,且使用SP_EL0
0x080 IRQ/vIRQ
0x100 FIQ/vFIQ
0x180 Serror/vSError
0x200 Synchronous 异常EL与异常前的EL相同, 且使用SP_ELx
0x280 IRQ/vIRQ
0x300 FIQ/vFIQ
0x380 Serror/vSError
0x400 Synchronous 异常前的EL比异常EL低,异常前系统模式为aarch64
0x480 IRQ/vIRQ
0x500 FIQ/vFIQ
0x580 Serror/vSError
0x600 Synchronous 异常前的EL比异常EL低,异常前系统模式为aarch32
0x680 IRQ/vIRQ
0x700 FIQ/vFIQ
0x780 Serror/vSError


2 建立向量表的示例


  • 示例1:展示了reset之后,如何初始化向量表基地址寄存器
LDR X1, = vector_table_el3
MSR VBAR_EL3, X1
LDR X1, = vector_table_el2
MSR VBAR_EL2, X1
LDR X1, = vector_table_el1
MSR VBAR_EL1, X1
  • 示例2:展示了AArch64状态下一个典型的异常向量表
.balign 0x800       // 向量表2k(2048字节)大小对齐
Vector_table_el3:
curr_el_sp0_sync:   // synchronous处理程序
                    // 来自当前EL的异常,使用SP0
.balign 0x80
curr_el_sp0_irq:    // IRQ中断处理程序
                    // 来自当前EL的异常,使用SP0
.balign 0x80
curr_el_sp0_fiq:    // FIQ快速中断处理程序
                    // 来自当前EL的异常,使用SP0
.balign 0x80
curr_el_sp0_serror: // Serror系统错误的处理程序
                    // 来自当前EL的异常,使用SP0
.balign 0x80
curr_el_spx_sync:   // synchronous处理程序
                    // 来自当前EL的异常,使用SPx
.balign 0x80
curr_el_spx_irq:    // IRQ中断处理程序
                    // 来自当前EL的异常,使用SPx
.balign 0x80
curr_el_spx_fiq:    // FIQ快速中断处理程序
                    // 来自当前EL的异常,使用SPx
.balign 0x80
curr_el_spx_serror: // Serror系统错误的处理程序
                    // 来自当前EL的异常,使用SPx
.balign 0x80
lower_el_aarch64_sync:  // synchronous处理程序
                        // 来自低EL且处于AArch64的异常
.balign 0x80
lower_el_aarch64_irq:   // IRQ中断处理程序
                        // 来自低EL且处于AArch64的异常
.balign 0x80
lower_el_aarch64_fiq:   // FIQ快速中断处理程序
                        // 来自低EL且处于AArch64的异常
.balign 0x80
lower_el_aarch64_serror:// Serror系统错误的处理程序
                        // 来自低EL且处于AArch64的异常
.balign 0x80
lower_el_aarch32_sync:  // synchronous处理程序
                        // 来自低EL且处于AArch32的异常
.balign 0x80
lower_el_aarch32_irq:   // IRQ中断处理程序
                        // 来自低EL且处于AArch32的异常
.balign 0x80
lower_el_aarch32_fiq:   // FIQ快速中断处理程序
                        // 来自低EL且处于AArch32的异常
.balign 0x80
lower_el_aarch32_serror:// Serror系统错误的处理程序
                        // 来自低EL且处于AArch32的异常


3 使能中断


异常分为异步和同步异常,异步异常通俗的讲就是我们常规意义上的中断,同步异常就是我们常规意义上的异常

中断包括SErrorIRQFIQ。这些中断在reset之后,默认是屏蔽掉的。因此,如果想要获取SErrorIRQFIQ,必须设置路由规则,并清除掉屏蔽。

另外,想要使能中断,还应该初始化中断控制器,使其发送中断请求给处理器,但这不是本文的范围。


3.1 中断路由规则


中断的路由规则,决定了中断发生时,哪个异常级别处理该中断。如果要路由到EL3,需要设置SCR_EL3.{EA,IRQ,FIQ}

  • 示例3:展示了如何将SErrorIRQFIQ路由到EL3异常级别的设置
MRS X0, SCR_EL3
ORR X0, X0, #(1<<3) // 设置EA位
ORR X0, X0, #(1<<1) // 设置IRQ位
ORR X0, X0, #(1<<2) // 设置FIQ位
MSR SCR_EL3, X0

想把中断路由到EL2而不是EL3,必须设置HCR_EL2.{AMO,FMO,IMO}并清除SCR_EL3.{EA,IRQ,FIQ}

  • 示例4:展示如何将SErrorIRQFIQ路由到EL2异常级别的设置
MRS X0, HCR_EL2
ORR X0, X0, #(1<<5) // 设置AMO位
ORR X0, X0, #(1<<4) // 设置IMO位
ORR X0, X0, #(1<<3) // 设置FMO位
MSR HCR_EL2, X0

如果中断没有设置路由到EL3或EL2,默认路由到EL1。


3.2 中断的掩码


中断是否被屏蔽,取决于下面的因素:

  • 中断被路由到的目标异常级别
  • PSTATE.{A,I,F}的值

目标异常级别低于当前异常级别,不管PSTATE.{A,I,F}的值是多少,该中断都被屏蔽(隐含规则);

目标异常级别等于当前异常级别,如果PSTATE.{A,I,F}设置为1,则异常被屏蔽;

目标异常级别高于当前异常级别,且目标异常级别是EL2或EL3,不管PSTATE.{A,I,F}的值是多少,异常都会被接收;

目标异常级别高于当前异常级别,且目标异常级别是EL1, 如果PSTATE.{A,I,F}设置为1,则异常被屏蔽;

  • 示例5:展示如何在PSTATE中清除SErrorIRQFIQ的掩码
// 使能SError, IRQ和FIQ
MSR DAIFClr, #0x7

更多关于使能中断的细节,查看ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture规范中的异步异常的类型、路由、屏蔽和优先级部分。

相关文章
|
4月前
|
Linux 网络安全 开发工具
内核实验(二):自定义一个迷你Linux ARM系统,基于Kernel v5.15.102, Busybox,Qemu
本文介绍了如何基于Linux Kernel 5.15.102版本和BusyBox创建一个自定义的迷你Linux ARM系统,并使用QEMU进行启动和调试,包括内核和BusyBox的编译配置、根文件系统的制作以及运行QEMU时的命令和参数设置。
367 0
内核实验(二):自定义一个迷你Linux ARM系统,基于Kernel v5.15.102, Busybox,Qemu
|
3月前
|
Go 开发工具 git
在Qemu+ARM上运行Minix3内核
在Qemu+ARM上运行Minix3内核
|
7月前
|
NoSQL Linux 开发工具
百度搜索:蓝易云【VSCode+GDB+Qemu调试ARM64 linux内核教程。】
请注意,根据你的具体环境和需求,上述步骤可能会有所调整和修改。建议参考相关文档和资源,以获得更详细的配置和调试指南。
102 0
|
传感器 资源调度 安全
ARM异常
ARM异常
111 0
|
NoSQL 安全 Linux
ARM深入理解-hypervisor调试方法一(异常寄存器分析)
ARM深入理解-hypervisor调试方法一(异常寄存器分析)
|
缓存 安全 测试技术
ARM深入理解-AArch64启动过程
ARM深入理解-AArch64启动过程
|
人工智能 安全
ARM深入理解-5.3-通往内核的大门(异常向量表_AArch32)
ARM深入理解-5.3-通往内核的大门(异常向量表_AArch32)
|
23天前
|
机器学习/深度学习 弹性计算 人工智能
阿里云服务器架构有啥区别?X86计算、Arm、GPU异构、裸金属和高性能计算对比
阿里云ECS涵盖x86、ARM、GPU/FPGA/ASIC、弹性裸金属及高性能计算等多种架构。x86架构采用Intel/AMD处理器,适用于广泛企业级应用;ARM架构低功耗,适合容器与微服务;GPU/FPGA/ASIC专为AI、图形处理设计;弹性裸金属提供物理机性能;高性能计算则针对大规模并行计算优化。
|
2月前
|
编解码 弹性计算 应用服务中间件
阿里云服务器Arm计算架构解析:Arm计算架构云服务器租用收费标准价格参考
阿里云服务器架构分为X86计算、Arm计算、高性能计算等多种架构,其中Arm计算架构以其低功耗、高效率的特点受到广泛关注。本文将深入解析阿里云Arm计算架构云服务器的技术特点、适用场景以及包年包月与按量付费的收费标准与最新活动价格情况,以供选择参考。
|
2月前
|
机器学习/深度学习 弹性计算 编解码
阿里云服务器计算架构X86/ARM/GPU/FPGA/ASIC/裸金属/超级计算集群有啥区别?
阿里云服务器ECS提供了多种计算架构,包括X86、ARM、GPU/FPGA/ASIC、弹性裸金属服务器及超级计算集群。X86架构常见且通用,适合大多数应用场景;ARM架构具备低功耗优势,适用于长期运行环境;GPU/FPGA/ASIC则针对深度学习、科学计算、视频处理等高性能需求;弹性裸金属服务器与超级计算集群则分别提供物理机级别的性能和高速RDMA互联,满足高性能计算和大规模训练需求。