异常向量与VBAR_ELx:Linux entry.S 中的vectors 布局

当 CPU 发生同步异常、IRQ、FIQ 或 SError 时,硬件根据当前异常级别(EL)和异常类型,跳转到 VBAR_ELx 指向的向量表条目。Linux 内核在 entry.S 中构造这张表,并在 setup_arch 早期通过 cpu_setup() 把物理地址写入 VBAR_EL1。理解 vectors 的分区与 kernel_ventry 宏,是分析缺页、系统调用、中断入口的第一把钥匙------本文聚焦向量表本身,不重复 EL 权限模型与 head.S 早期启动流程。

源码锚点

路径 作用
arch/arm64/kernel/entry.S vectors 表、kernel_ventry、kernel_entry
arch/arm64/kernel/entry-common.c C 侧异常处理、do_el0_svc 等
arch/arm64/kernel/traps.c 非法指令、undef、panic 路径
arch/arm64/kernel/irq.c handle_arch_irq 函数指针
arch/arm64/kernel/setup.c cpu_setup() 设置 VBAR
arch/arm64/include/asm/exception.h struct pt_regs、异常帧布局

向量表主体(每个 slot 128 字节对齐):

asm 复制代码
/* arch/arm64/kernel/entry.S */
	.align	11
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				// 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				// FIQ 64-bit EL0
	kernel_ventry	0, error			// Error 64-bit EL0

kernel_ventry 在栈上分配 struct pt_regs 并保存通用寄存器:

asm 复制代码
	.macro kernel_ventry, el, label, regsize = 64
	.align 7
.Lventry_start\@:
	sub	sp, sp, #S_FRAME_SIZE
	/* 保存 x0-x29、lr、elr_el1、spsr_el1 等到 pt_regs */
	b	\label
	.endm

VBAR 安装(每 CPU 在 bring-up 时执行):

c 复制代码
/* arch/arm64/kernel/setup.c --- cpu_setup 概念路径 */
void __init cpu_setup(char *fdt)
{
	/* ... */
	write_sysreg((u64)vectors, vbar_el1);
	isb();
}

EL0 系统调用从 sync 向量进入 el0_svc_common:

asm 复制代码
/* entry.S --- el0_svc 附近 */
el0_svc:
	adrp	x16, vectors
	b	el0_svc_common

调用链

text 复制代码
硬件异常(例:EL0 发 svc #0)
  → PC 跳至 VBAR_EL1 + offset(EL0 sync slot)
      → kernel_ventry 0, sync
          → 构造 pt_regs,b el0_sync
              → el0_svc / el0_da / el0_ia / el0_ti ...
                  → do_el0_svc(regs)     /* 系统调用 */
                  → do_mem_abort()       /* 缺页/权限 fault */
              → ret_to_user → eret

硬件 IRQ(EL0/EL1)
  → vectors → kernel_ventry → el0_irq / el1_irq
      → enter_el1_irq_or_nmi
          → irq_handler(regs)
              → handle_arch_irq(regs)   /* 由 GIC driver 注册 */
                  → generic_handle_domain_irq()
              → irq_exit()
          → ret_to_user / ret_to_kernel

VBAR 变更场景:

text 复制代码
cpu_startup_entry() / secondary_start_kernel()
  → cpu_setup() 或 smp 路径再次确认 vbar_el1
KVM/VHE:host 可能在 EL2 使用 vbar_el2(与本篇 EL1 Linux 主路径分离)

重点知识

16 个向量 slot: AArch64 规定每个异常类型 ×(当前 EL + SP 选择)共 16 组入口;Linux 主要使用 EL1h(内核用 SP_EL1)与 EL0(用户态)四组;EL1t 多为 *_invalid 陷阱误用 SP_EL0 的内核代码。

128 字节对齐: 每条 kernel_ventry 占 128 字节(.align 7),便于 VBAR 基址低 11 位为零;修改向量表需保证链接脚本不把 vectors 拆散。

pt_regs 与 eret: 异常返回依赖 elr_el1(返回 PC)与 spsr_el1(返回 PSTATE);内核 patch 这些字段可实现信号 delivery、ptrace 单步。

IRQ 与 preempt: el0_irq 路径在 irq_exit() 中检查 TIF_NEED_RESCHED;理解向量入口栈(sync 用 task 内核栈 vs IRQ stack)对 lockdep 与 stack overflow 排障至关重要。

SError: error 向量处理异步外部 abort(如 AXI 错误);未注册 handler 时可能 panic;设备驱动 DMA 错误有时经此上报。

与 VBAR_EL3 区别: TF-A BL31 在 EL3 有自己的 vbar_el3 处理 SMC;Linux 运行在 EL1,仅写 vbar_el1。EL2 存在时(KVM nVHE)另有独立向量表。

调试: crash 中 dis vectors;ftrace function_graph 从 el0_svc 跟踪;/proc/kallsyms 查 vectors 符号地址应与 VBAR_EL1 一致。

Checklist

  • VBAR_EL1 指向 vectors 符号,16 组入口地址随内核版本与配置(KASLR)变化
  • 用户 syscall、缺页、IRQ 分别对应 EL0 sync/irq 路径,而非 EL1t invalid
  • 修改 entry.S 后检查 128 字节对齐与 S_FRAME_SIZE 栈布局
  • IRQ 处理经 handle_arch_irq,与 GICv3 驱动注册一致
  • SError 路径有平台 arm64_serror_panic 或自定义 handler
  • secondary CPU 启动后 VBAR 与 primary 一致,无旧 Bootloader 残留
相关推荐
KaiwuDB2 分钟前
KaiwuDB 运维实战06:数据库备份与恢复:从理论到实战
运维·数据库·时序数据库·kaiwudb
无人生还别怕14 分钟前
如何搭建k8s服务(containerd部署)
linux·云原生·容器·kubernetes·openanolisos
智购科技自动售货机厂家22 分钟前
让AI经营自动售货机:从Project Vend看工具权限与业务规则~YH
大数据·服务器·单片机·嵌入式硬件·深度学习
jnrjian24 分钟前
delete file shell 让 AI 写脚本
服务器·开发语言
数字新视界28 分钟前
空调控制器AIRC800的智能化管理与应用实践
大数据·服务器·数据库·动环监控系统·动力与环境监控系统
知已难寻35 分钟前
01 · OpenStack的认证管理 Keystone
运维·服务器·云原生·云计算·openstack
ai_xiaogui1 小时前
私有化部署大模型实战:PanelAI 一键搭建、Token 计费与多用户隔离
运维·私有化部署·大模型部署·大模型 token 计费·api key 统一管理·多用户实例隔离·应用市场一键部署
企鹅侠客1 小时前
Linux CPU 负载平均值(Load Average)详解:从原理到实践
linux·运维·服务器·服务器负载
易点云徐源1 小时前
HP 暗影精灵 PRO 16 安装双系统后,开机直接进入 Windows,按 F9 才能进入 Ubuntu:GRUB 菜单不显示的处理方法
linux·运维·ubuntu
吃一碗粉只付一碗钱1 小时前
10-令牌里的用户主键不要明文
服务器·数据库·sql·sqlserver·c#