飞腾CPU体系结构之系统调用(异常入口分析)
异常向量表
/*
* Exception vectors.
*/
.pushsection ".entry.text", "ax" //异常向量表专属代码段
.align 11 //地址对齐要求, 地址低11为0
ENTRY(vectors)
kernel_ventry 1, sync_invalid // Synchronous EL1t
kernel_ventry 1, irq_invalid // IRQ EL1t
kernel_ventry 1, fiq_invalid // FIQ EL1t
kernel_ventry 1, error_invalid // Error EL1t
kernel_ventry 1, sync // Synchronous EL1h
kernel_ventry 1, irq // IRQ EL1h
kernel_ventry 1, fiq_invalid // FIQ EL1h
kernel_ventry 1, error // Error EL1h
kernel_ventry 0, sync // Synchronous 64-bit EL0
kernel_ventry 0, irq // IRQ 64-bit EL0
kernel_ventry 0, fiq_invalid // FIQ 64-bit EL0
kernel_ventry 0, error // Error 64-bit EL0
#ifdef CONFIG_COMPAT
kernel_ventry 0, sync_compat, 32 // Synchronous 32-bit EL0
kernel_ventry 0, irq_compat, 32 // IRQ 32-bit EL0
kernel_ventry 0, fiq_invalid_compat, 32 // FIQ 32-bit EL0
kernel_ventry 0, error_compat, 32 // Error 32-bit EL0
#else
kernel_ventry 0, sync_invalid, 32 // Synchronous 32-bit EL0
kernel_ventry 0, irq_invalid, 32 // IRQ 32-bit EL0
kernel_ventry 0, fiq_invalid, 32 // FIQ 32-bit EL0
kernel_ventry 0, error_invalid, 32 // Error 32-bit EL0
#endif
END(vectors)
上面是EL1操作系统响应的异常向量表格式,AArch64 EL1t模式下能可以响应来自AArch64 EL1t、AArch64 EL1h、AArch64 EL0t和AArch32 EL0四个模式下触发的异常。由于异常又分为同步、IRQ、FIQ和系统错误四种类型,因此EL1操作系统响应的异常向量有4x4=16个入口点。
根据代码可以看出
- Linux操作系统FIQ异常全部处理为invalid;
- Linux操作系统不支持来自AArch64 EL1t模式触发的异常,全部处理为invalid。
- 来自AArch32的异常需要专门配置内核选项参数COMPAT,否则也全部处理为invalid。
每个处理器的异常向量表基地址寄存器设置
//第一个CPU的vbar_el1寄存器设置代码
__primary_switched:
...//省去其他代码
adr_l x8, vectors // load VBAR_EL1 with virtual
msr vbar_el1, x8 // vector table address
isb
//第二/三/.../个CPU的bar_el1寄存器设置代码
__secondary_switched:
adr_l x5, vectors
msr vbar_el1, x5
isb
adr_l是伪汇编代码,主要是获取变量vectors的虚拟地址(MMU已经初始化完成),并赋值给x8。
adrp x8, vectors //以4K页为粒度的地址偏移量
add x8, x8, :lo12:vectors //再加上4K页内部地址偏移量
系统调用入口点
系统调用属于EL0下的同步类型异常,不考虑AArch32 EL0情况下,也就是
第九个入口点
kernel_ventry 0, sync