Linux 内核的异常(1)
一、Linux 4.19内核的异常向量表
上一期中我们提到,异常向量被保存在异常向量表中。在 /openeuler/kernel/blob/kernel-4.19/arch/arm64/kernel/entry.S
文件中我们可以找到定义异常向量表的汇编代码:
以上异常向量表共16项并被分为四组,每组包含四项并对应不同的异常处理情形。这四组表项从上到下对应的四种情形分别是[1,2]:
异常级别 EL1 生成的异常,使用 SP_EL0 寄存器;内核不支持带有 invalid 后缀的异常处理,在 entry.S 文件中,我们可以找到,通过带有 invalid 后缀的异常向量可以调用 inv_entry 宏:
这段代码保存三个参数到 X0、X1和X2 寄存器,然后跳转到 bad_mode 函数。bad_mode 函数在 /openeuler/kernel/blob/kernel-4.19/arch/arm64/kernel/traps.c 文件中可以找到:
该函数打印了异常发生的相关信息并调用 local_daif_mask()函数设置调试掩码位D、系统错误掩码位A、中断掩码位I和快速中断掩码位F来禁止调试异常、系统错误异常、外部中断和快速中断。
异常级别 EL1 生成的异常,使用当前异常级别的 SP_ELx 寄存器;
64位应用程序在异常级别 EL0 生成的异常。例如64位用户态程序发生系统调用,处理器从异常级别 EL0 切换到异常级别 EL1,并且使用 aarch64 执行状态处理异常;
32位应用程序在异常级别 EL0 生成的异常。例如32位用户态程序发生系统调用,处理器从异常级别 EL0 切换到异常级别 EL1,并且使用 aarch32 执行状态处理异常;
其中 kernel_ventry 的定义在同一个文件中可以找到:
该宏的输入是当前异常级别 el、跳转入口地址 label 和寄存器宽度 regsize;寄存器宽度用来标识执行状态,regsize = 64标识 aarch64 执行状态,regsize = 32标识 aarch32 执行状态。.align 7表示把下一条指令对齐到27 byte。该宏的主要作用是跳转到 label 所对应的地址处。
二、结语
[1]https://blog.csdn.net/rikeyone/article/details/79919019
[2]《Linux内核深度解析》,余华兵著,2019
- 点赞
- 收藏
- 关注作者
评论(0)