0

The switch to assembly of arm32 in linux is like that: you coud see there are no cpsr reigister backup, compare to others arch, like mips or riscv, which corresponding mstatus and status register are all do the backup and restore during the _switch_to, so, why there are the differences?

  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
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • `_switch_to` is a function; the caller already assumes call-clobbered registers will be destroyed. If there's no long-term state (not just condition codes) in CSPR *that different kernel tasks are allowed to change*, there's no need to save/restore it. – Peter Cordes Feb 20 '20 at 03:25
  • can the status bit like "n", "c", "v" be long term? think about scenarios the prev task c flag still need after the task restore to run? – seiya seiya Feb 20 '20 at 03:45
  • 1
    No. From the POV of the compiler generating code that calls this function, it's a regular function call (which *eventually* returns). Like any non-inline opaque function call, it's assumed to destroy status bits, along with other call-clobbered registers like `r0..r3`. That's why switch_to only has to save call-preserved parts of the state with `stmia`. – Peter Cordes Feb 20 '20 at 03:47

1 Answers1

3

There are a few different uses of cpsr and it is not clear which one you are referring to.

  1. The supervisor mode cpsr.
  2. The user mode cpsr.
  3. Some exception cpsr.

These values are stored during an exception on an ARM cpu.

See: Linux kernel ARM exception stack

This makes all 'spsr' except the svc and user mode meaningless.

Note: The ARM has banked SP, cpsr and lr. Other referenced architectures may or may not have banked registers. For certain, all need to restore the user mode status register or user CPSR on ARM.

The switch_to assembler is used to switch kernel state for a process. The sp that is restored is an 8k page where the lower portion is a thread_info holding a copy of the user registers. The switch_to() function takes a from and to thread_info held in R1 and R2.

The code,

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

Is more like a longjmp() to a previous call to switch_to(); the code is not heading to the same place it was called from necessarily. The SPSR which is the return to user mode CPSR (and lr). These are saved in r1,r2 by the vector stubs. They are restored by the restore_user_regs macro. The instruction movs pc, lr will restore the user CPSR and return from an exception/syscall.

The cpsr (SVC) active with kernel code is protected by the 'C' ABI which says the status bits are not valid after a function call. It is also assumed the any svc code uses the same 'T' bit (all kernel code is either Thumb or ARM only) and the function needs to be called with 'F' and 'I' bits in a known state. switch_to callers should use the stacking mask functions OR never have interrupts masked. I think it is probably the last one. If you try to mix Thumb/ARM code or use/change interrupt masking with calls to switch_to, it would be an issue; otherwise, there is no need to save/restore this value.

artless noise
  • 21,212
  • 6
  • 68
  • 105
  • `__switch_to` is pretty much separate from restoring user-space state, right? I think talking about the details of restoring user-space state (from the task's kernel stack) might be a distraction here. That only happens after `return`ing out of some levels of function calls after `__switch_to`, at the earliest. And some tasks (kernel threads) don't have user-space. Anyway, despite the longjmp like behaviour, perhaps important to point out that from the caller's POV, a context switch is simply a normal function call that *eventually* returns. I think that's part of the key to grokking this. – Peter Cordes Feb 20 '20 at 15:46
  • No, the kernel is acting on behalf of a userspace process so these values need to be swap in a race safe way. This includes cpu state for returning to userspace. I uderstand it is not imediate but is happening. This may differ from an un-banked arch. – artless noise Feb 20 '20 at 22:25
  • It is not obvious because it is just switching sp to do this. – artless noise Feb 20 '20 at 22:27
  • Oh right, so `__switch_to` has to modify the user-space banked SP / LR / cspr, otherwise return to user-space would bank-switch to the wrong version of those regs. Or something like that; I don't know how ARM banked registers are controlled well enough to really grok what Linux does here. On x86-64 or other ISAs without banked registers, `__switch_to` doesn't care whether the new task is eventually returning to user-space or not. (Except maybe for FPU state, I forget.) – Peter Cordes Feb 20 '20 at 22:39
  • why i dont think this is related user-space restore, my be i am not think this as deep as @artlessnoise. as said above petercordes, __switch_to doesn't care whether the new task is eventually returning to user-space or not, so even a rtos kernel that permanently running in "svc" mode, then can do the same "longjmp" style switch to without caring about cpsr and spsr. and BTW, user mode and system mode didi not have spsr, so meaningless talk spsr on user mode, right? – seiya seiya Feb 21 '20 at 12:54