切换到linux中arm32的汇编如下:与其他arch(如mips或riscv(相比,您可以看到没有cpsr-register备份,哪个相应的mstatus和状态寄存器都在_switch_to期间进行备份和恢复,那么,为什么会有差异呢?
12948 8010d328 <__switch_to>:
12949 8010d328: e281c018 add ip, r1, #24
12950 8010d32c: e8ac6ff0 stmia ip!, {r4, r5, r6, r7, r8, r9, sl, fp, sp, lr}
12951 8010d330: e592405c ldr r4, [r2, #92] ; 0x5c
12952 8010d334: e5925060 ldr r5, [r2, #96] ; 0x60
12953 8010d338: ee1d7f50 mrc 15, 0, r7, cr13, cr0, {2}
12954 8010d33c: ee0d4f70 mcr 15, 0, r4, cr13, cr0, {3}
12955 8010d340: ee0d5f50 mcr 15, 0, r5, cr13, cr0, {2}
12956 8010d344: e5817060 str r7, [r1, #96] ; 0x60
12957 8010d348: e1a05000 mov r5, r0
12958 8010d34c: e2824018 add r4, r2, #24
12959 8010d350: e59f000c ldr r0, [pc, #12] ; 8010d364 <__switch_to+0x3c>
12960 8010d354: e3a01002 mov r1, #2
12961 8010d358: eb00c813 bl 8013f3ac <atomic_notifier_call_chain>
12962 8010d35c: e1a00005 mov r0, r5
12963 8010d360: e894aff0 ldm r4, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc}
12964 8010d364: 80b61200 .word 0x80b61200
12965 8010d368: e58d403c str r4, [sp, #60] ; 0x3c
12966 8010d36c: e1a0f009 mov pc, r9
cpsr
有几种不同的用途,不清楚您指的是哪一种。
- 监控器模式cpsr
- 用户模式cpsr
- 某些异常cpsr
这些值在ARM cpu上发生异常时存储。
请参阅:Linux内核ARM异常堆栈
这使得除svc和用户模式之外的所有"spsr"都变得毫无意义。
注:ARM已存储SP、cpsr和lr。其他参考体系结构可能有也可能没有存储寄存器。当然,所有的都需要恢复ARM上的用户模式状态寄存器或用户CPSR。
switch_to
汇编程序用于切换进程的内核状态。被恢复的sp
是8k页,其中下部是持有用户寄存器的副本的thread_info
。switch_to()
函数从R1和R2中的和到thread_info获取。
代码,
add r4, r2, #24
ldm r4, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc}
更像是对switch_to()
的先前呼叫的longjmp()
;代码不一定是从同一个地方调用的。SPSR是返回到用户模式的CPSR(和lr(。这些由矢量短截线保存在r1、r2中。它们由restore_user_regs宏恢复。指令movs pc, lr
将恢复用户CPSR并从异常/syscall返回。
带有内核代码的活动cpsr(SVC(受"C"ABI保护,该ABI表示在函数调用后状态位无效。还假设任何svc代码使用相同的"T"位(所有内核代码仅为Thumb或ARM(,并且需要在已知状态下使用"F"one_answers"I"位来调用函数。switch_to
调用方应该使用堆栈掩码函数,或者永远不要屏蔽中断。我想这可能是最后一个了。如果您尝试将Thumb/ARM代码与调用switch_to
混合使用或使用/更改中断屏蔽,这将是一个问题;否则,无需保存/恢复此值。