展示代码
adr_l x8, vectors // load VBAR_EL1 with virtual
msr vbar_el1, x8 // vector table address
isb
stp xzr, x30, [sp, #-16]!
mov x29, sp
#ifdef CONFIG_SHADOW_CALL_STACK
adr_l scs_sp, init_shadow_call_stack // Set shadow call stack
#endif
分析代码
第1行将 vectors 的地址存放在 x8
vectors 定义在 arch/arm64/kernel 目录下
/*
* Exception vectors.
*/
.pushsection ".entry.text", "ax"
.align 11
SYM_CODE_START(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
SYM_CODE_END(vectors)
第2行将 x8,也就是 vectors 的地址加载到 vbar_el1
前2行综合起来看,含义如下
dr_l x8, vectors 这条指令用于将中断向量表的地址加载到寄存器 x8 中。vectors 是一个符号,它代表中断向量表在内核中的地址。
中断向量表包含了处理器在不同的异常情况下跳转到的处理函数的地址,例如,当发生中断、异常或系统调用时,处理器会跳转到这个表中指定的地址去执行相应的处理函数。
在ARM64架构中,有一个名为VBAR_EL1的系统寄存器,它用于存储异常向量表的基地址。msr vbar_el1, x8 这条指令就是将寄存器 x8 中存储的地址值写入到VBAR_EL1寄存器中,从而设置处理器的异常向量表地址。
这个设置是在内核启动过程中完成的,确保了当内核开始处理中断和异常时,能够正确地跳转到内核定义的处理函数。这是内核初始化过程中的一个重要步骤,它为内核提供了处理各种硬件生成的中断和异常的能力。
第5行的含义是将 xzr 和 x30 寄存器的值存储到栈指针 sp 当前指向的内存地址,然后栈指针 sp 减去16字节。这通常用于在函数调用之前将寄存器的值压入栈中保存起来,以便之后可以恢复。由于 xzr 总是存储0,所以这个操作实际上是将0和 x30 寄存器的值压栈。
第6行的含义是将 sp 存储在 x29
第8到第10行受条件编译宏 CONFIG_SHADOW_CALL_STACK 控制,暂时不分析
2833

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



