主要内容:理解AArch64的异常机制和系统调用机制。
1 AArch64中的异常
异常是指低特权级软件(如用户程序)请求高特权级软件(例如内核中的异常处理程序)采取某些措施以确保程序平稳运行的系统事件。
异常分类:
- 同步异常
- 同步中止(取值或数值访问失败)
- 异常生成指令(svc,hvc,smc)
- 异布异常
- IRQ,FIQ,SError
异常向量表
每个异常级别有自己独立的异常向量表(EBAR_EL3, EBAR_EL2, EBAR_EL1),每个异常向量表有16个条目。
设置异常向量表:
1 | BEGIN_FUNC(set_exception_vector) |
异常处理相关寄存器
- ESR_ELx:存储有关异常原因的信息
- FAR_ELx:存储所有同步指令中止、同步数据中止和对齐异常所对应的虚拟地址
- ELR_ELx:异常的首选返回地址
2 异步处理流程
触发同步异常
以svc系统调用为例分析异常处理流程:
1 | u64 syscall(u64 sys_no, u64 arg0, u64 arg1, u64 arg2, u64 arg3, u64 arg4, |
svc #0
指令会出发同步异常,于是发生特权级别切换。
处理器自动保存
- PC保存在ELR_EL1
- 异常事件的原因保存在ESR_EL1
- 当前状态保存在SPSR_EL1
- 异常信息保存在FAR_EL1
- 栈寄存器开始使用SP_EL1,不在使用SP_EL0
- 修改PSTATE中的特权级标志位,设置为内核态(EL1)
- 根据VBAR_EL1寄存器中保存的异常向量表基地址,以及异常事件发生的类型,找到异常处理函数的入口地址,并把该地址设置到PC,开始运行操作系统的代码
异常进入、处理和退出
操作系统在异常处理函数会做异常处理的一些上下文保存、函数调用和上下文恢复动作。
操作系统在特权级切换过程中的动作:
保存x0-x31,sp_el0,elr_el1,spsr_el1等寄存器到内核栈中(切换到EL1时自动使用SP_EL1)
做系统调用或其他异常处理
恢复应用程序的处理器上下文
调用eret返回应用程序
异常返回eret
调用eret时,处理器自动完成:
- SPSR_EL1写入到PSTATE
- 开始使用SP_EL0
- ELR_EL1写入PC,并执行应用程序的代码
1 | .align 11 |
1 | sync_el0_64: |
1 | .macro exception_enter |
1 | el0_syscall: |
1 | .macro exception_exit |