2.6 EL0_SYNC与EL1_SYNC 异常改造
在 entry.S 中,EL1_SYNC 相关代码并没有改动。
下面主要分析 EL0_SYNC 的代码变动。
2.6.1 el0_sync代码框架
沿着 vectors -> kernel_ventry 0,irq -> el0_sync 进行分析。
/*
* EL0 mode handlers.
*/
.align 6
el0_sync:
kernel_entry 0
mrs x25, esr_el1 // read the syndrome register
lsr x24, x25, #ESR_ELx_EC_SHIFT // exception class
cmp x24, #ESR_ELx_EC_SVC64 // SVC in 64-bit state
b.eq el0_svc
cmp x24, #ESR_ELx_EC_DABT_LOW // data abort in EL0
b.eq el0_da
cmp x24, #ESR_ELx_EC_IABT_LOW // instruction abort in EL0
b.eq el0_ia
cmp x24, #ESR_ELx_EC_FP_ASIMD // FP/ASIMD access
b.eq el0_fpsimd_acc
cmp x24, #ESR_ELx_EC_SVE // SVE access
b.eq el0_sve_acc
cmp x24, #ESR_ELx_EC_FP_EXC64 // FP/ASIMD exception
b.eq el0_fpsimd_exc
cmp x24, #ESR_ELx_EC_SYS64 // configurable trap
b.eq el0_sys
cmp x24, #ESR_ELx_EC_SP_ALIGN // stack alignment exception
b.eq el0_sp_pc
cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
b.eq el0_sp_pc
cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL0
b.eq el0_undef
cmp x24, #ESR_ELx_EC_BREAKPT_LOW // debug exception in EL0
b.ge el0_dbg
b el0_inv
首先读取ESR_EL1寄存器,向右移位ESR_ELx_EC_SHIFT(26)得到异常发生的原因(Bit 31-26),然后跳转到相应的分支继续处理。整个过程,类似于C语言中的switch case语句。
在entry.S中,引入I-pipe patch之后,el0_sync自身及其跳转的分支,都没有代码变化。唯一值得注意的是,所有的分支最终都是调用 ret_to_user 返回到用户层。
2.6.2 返回用户空间
1 ret_to_user:
2 #ifdef CONFIG_IPIPE
3 disable_daif
4 ldr x0, [tsk, #TSK_TI_IPIPE]
5 tst x0, #_TIP_HEAD
6 b.eq ret_to_user_noirq
7 kernel_exit 0
8 #endif
第3行,关闭daif共4个中断屏蔽标识
第4-5行,检查TSK_TI_IPIPE中是否设置了_TIP_HEAD标记。TSK_TI_IPIPE定义在arch/arm64/kernel/asm-offsets.c;_TIP_HEAD定义在arch/arm64/include/asm/thread_info.h。根据注释,它代表进程运行在HEAD域。
DEFINE(TSK_TI_IPIPE, offsetof(struct task_struct, thread_info.ipipe_flags));
第6行,如果TSK_TI_IPIPE中没有设置_TIP_HEAD标记,第14行tst指令(相当于ands)结果为0,则Z标志位为1,b.eq判断条件成立。说明当前进程处于ROOT域,跳转到ret_to_user_noirq。此后的流程与 EL0_IRQ 处理流程相同。
第7行,如果TSK_TI_IPIPE中设置_了TIP_HEAD标记,第14行tst指令(相当于ands)结果为1,则Z标志位为0,b.eq判断条件不成立。说明当前进程处于HEAD域即Xenomai实时进程,直接通过kernel_exit 0返回用户层。
612

被折叠的 条评论
为什么被折叠?



