ARM Linux内核解压阶段切换至Thumb2模式的原理疑问(4.15+主线版)
为什么跳转到PC低0x300偏移能切换到Thumb-2模式?
这个问题问得挺深入的,刚好我对ARM内核启动这块比较熟悉,给你拆解一下背后的逻辑:
1. ARM/Thumb模式切换的核心逻辑
ARM CPU切换到Thumb-2模式的关键是CPSR寄存器的T位:当T位为1时,CPU运行在Thumb/Thumb-2模式;为0时则处于ARM模式。
而触发T位自动设置的核心是跳转指令(比如BX或BLX)的目标地址最低位:
- 如果目标地址最低位是
1,跳转后CPU会自动把T位置1,进入Thumb模式 - 如果最低位是
0,则T位清0,切换回ARM模式
这里要注意:Thumb指令本身是2字节对齐的,实际代码地址的最低位肯定是0,所以这个最低位是链接器设置的虚拟标识位,专门用来告诉CPU要切换模式。
2. 为什么PC - 0x300这个偏移有效?
在arch/arm/boot/compressed/head.S的上下文里,这段代码是运行在ARM模式下的,此时PC的取值有个特殊规则:ARM模式下CPU是三级流水线,执行当前指令时,PC的值是当前指令地址 + 8(因为已经预取了后面两条指令)。
内核的链接脚本已经提前把Thumb-2模式的启动代码,安排在了相对于这段ARM代码的PC偏移-0x300的位置,并且这个Thumb入口地址的最低位被链接器置为1。所以当执行跳转到PC - 0x300的指令时,本质就是触发了一个带最低位1的跳转,CPU自动把CPSR的T位置1,完成Thumb-2模式切换。
3. adr/xadr指令的作用
你提到的adr或xadr是另一种实现方式,本质逻辑和直接跳转完全一致:
adr r0, thumb_entry:把Thumb入口的地址(带最低位1)加载到r0寄存器,adr只能处理小范围的地址偏移xadr r0, thumb_entry:是adr的扩展版本,支持更大范围的地址偏移- 之后执行
bx r0,通过r0里的地址最低位触发模式切换
而直接跳转到PC - 0x300是一种更紧凑的写法,前提是偏移量固定,且链接器已经确保该位置是合法的Thumb入口地址(带最低位1)。
内容的提问来源于stack exchange,提问作者CrisMison
相关产品推荐
相关产品推荐

