0

在linux中切换arm32的汇编是这样的:你可以看到没有cpsr reigister备份,比较其他arch,如mips或riscv,其对应的mstatus和status寄存器都是_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
4

1 回答 1

3

有几种不同的用途,cpsr不清楚您指的是哪一种。

  1. 主管模式cpsr。
  2. 用户模式cpsr。
  3. 一些异常cpsr。

这些值在异常期间存储在 ARM cpu 上。

请参阅:Linux 内核 ARM 异常堆栈

这使得除了 svc 和用户模式之外的所有“spsr”都毫无意义。

注意:ARM 已存储 SP、cpsr 和 lr。其他参考架构可能有也可能没有存储寄存器。当然,ARM上都需要恢复用户模式状态寄存器或用户CPSR。

switch_to汇编器用于切换进程的内核状态。恢复的sp是一个 8k 页面,其中下部是thread_info保存用户寄存器的副本。该switch_to()函数接受R1 和 R2 中保存的fromto thread_info。

编码,

  add     r4, r2, #24
  ldm     r4, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc}

更像是longjmp()对先前的调用switch_to();代码不一定会指向它被调用的同一个地方。SPSR 即返回到用户模式 ​​CPSR(和 lr)。这些由向量存根保存在 r1,r2 中。它们由restore_user_regs宏恢复。该指令movs pc, lr将恢复用户 CPSR 并从异常/系统调用返回。

使用内核代码激活的 cpsr (SVC) 受“C”ABI 保护,该 ABI 表示状态位在函数调用后无效。还假设任何 svc 代码使用相同的“T”位(所有内核代码都是 Thumb 或 ARM),并且需要在已知状态下使用“F”和“I”位调用该函数。 switch_to调用者应该使用堆栈掩码函数,或者永远不要屏蔽中断。我想这可能是最后一个。如果您尝试混合使用 Thumb/ARM 代码或使用/更改中断屏蔽与对 的调用switch_to,这将是一个问题;否则,无需保存/恢复此值。

于 2020-02-20T14:46:43.113 回答