switch_to

arch/arm/kernel/entry-armv.S

arm架构相关的 swtich_to代码

/*
 * Register switch for ARMv3 and ARMv4 processors
 * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
 * previous and next are guaranteed not to be the same.
 */

ENTRY(__switch_to)
 UNWIND(.fnstart    )
 UNWIND(.cantunwind    )
    add    ip, r1, #TI_CPU_SAVE
    ldr    r3, [r2, #TI_TP_VALUE]
 ARM(    stmia    ip!, {r4 - sl, fp, sp, lr} )     @ Store most regs on stack
 THUMB(    stmia    ip!, {r4 - sl, fp}       )    @ Store most regs on stack
 THUMB(    str    sp, [ip], #4           )
 THUMB(    str    lr, [ip], #4           )
#ifdef CONFIG_CPU_USE_DOMAINS
    ldr    r6, [r2, #TI_CPU_DOMAIN]
#endif
    set_tls    r3, r4, r5
#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
    ldr    r7, [r2, #TI_TASK]
    ldr    r8, =__stack_chk_guard
    ldr    r7, [r7, #TSK_STACK_CANARY]
#endif
#ifdef CONFIG_CPU_USE_DOMAINS
    mcr    p15, 0, r6, c3, c0, 0        @ Set domain register
#endif
    mov    r5, r0
    add    r4, r2, #TI_CPU_SAVE
    ldr    r0, =thread_notify_head
    mov    r1, #THREAD_NOTIFY_SWITCH
    bl    atomic_notifier_call_chain
#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
    str    r7, [r8]
#endif
 THUMB(    mov    ip, r4               )
    mov    r0, r5
 ARM(    ldmia    r4, {r4 - sl, fp, sp, pc}  )    @ Load all regs saved previously
 THUMB(    ldmia    ip!, {r4 - sl, fp}       )    @ Load all regs saved previously
 THUMB(    ldr    sp, [ip], #4           )
 THUMB(    ldr    pc, [ip]           )
 UNWIND(.fnend        )

ENDPROC(__switch_to)


从生成的代码看

/*
 * Register switch for ARMv3 and ARMv4 processors
 * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
 * previous and next are guaranteed not to be the same.
 */
crash> dis -l __switch_to
../arch/arm/kernel/entry-armv.S

/*1. 保存上下文

 **/
0xc000dfe8 <__switch_to>:       add     r12, r1, #28
0xc000dfec <__switch_to+4>:     ldr     r3, [r2, #96]   ; 0x60
0xc000dff0 <__switch_to+8>:     stmia   r12!, {r4, r5, r6, r7, r8, r9, r10, r11, sp, lr}

/*2. 设置next 进程的domain

 **/
0xc000dff4 <__switch_to+12>:    mcr     15, 0, r3, cr13, cr0, {3}
0xc000dff8 <__switch_to+16>:    mov     r4, #0
0xc000dffc <__switch_to+20>:    mcr     15, 0, r4, cr13, cr0, {2}

/*3. 调用函数 atomic_notifier_call_chain

 **/
0xc000e000 <__switch_to+24>:    mov     r5, r0
0xc000e004 <__switch_to+28>:    add     r4, r2, #28
0xc000e008 <__switch_to+32>:    ldr     r0, [pc, #12]   ; 0xc000e01c
0xc000e00c <__switch_to+36>:    mov     r1, #2
0xc000e010 <__switch_to+40>:    bl      0xc0048ef8 <atomic_notifier_call_chain>

/*4. 设置新的上下文

 **/
0xc000e014 <__switch_to+44>:    mov     r0, r5
0xc000e018 <__switch_to+48>:    ldm     r4, {r4, r5, r6, r7, r8, r9, r10, r11, sp, pc}
0xc000e01c <__switch_to+52>:    rsbsgt  r1, r7, r12, lsr r1
0xc000e020 <__switch_to+56>:    nop     {0}
0xc000e024 <__switch_to+60>:    nop     {0}
0xc000e028 <__switch_to+64>:    nop     {0}
0xc000e02c <__switch_to+68>:    nop     {0}
0xc000e030 <__switch_to+72>:    nop     {0}
0xc000e034 <__switch_to+76>:    nop     {0}
0xc000e038 <__switch_to+80>:    nop     {0}
0xc000e03c <__switch_to+84>:    nop     {0}

add     r12, r1, #28
为什么是28?就是偏移到struct cpu_context_save

struct thread_info {
    [0] unsigned long flags;
    [4] int preempt_count;
    [8] mm_segment_t addr_limit;
   [12] struct task_struct *task;
   [16] struct exec_domain *exec_domain;
   [20] __u32 cpu;
   [24] __u32 cpu_domain;
   [28] struct cpu_context_save cpu_context;
   [76] __u32 syscall;
   [80] __u8 used_cp[16];
   [96] unsigned long tp_value;
  [100] struct crunch_state crunchstate;
  [288] union fp_state fpstate;
  [432] union vfp_state vfpstate;
  [712] struct restart_block restart_block;
}

crash> cpu_context_save
struct cpu_context_save {
    __u32 r4;
    __u32 r5;
    __u32 r6;
    __u32 r7;
    __u32 r8;
    __u32 r9;
    __u32 sl;[r10]
    __u32 fp;[r11]
    __u32 sp;[r13]
    __u32 pc; [r15/r14]/*保存的是lr,恢复到pc*/
    __u32 extra[2];
}

add     r12, r1, #28
ldr     r3, [r2, #96]; 0x60
偏移量 96

struct thread_info {
   [96] unsigned long tp_value;
这个数值和后面的mcr有关系,进而对domain的操作。

总结:

switch_to的操作主要是thread_info的cpu_context_save的保存和恢复。

且保存的并不是所以的寄存器,其中就不包括: r0/1/2/3/12.

你可能感兴趣的:(switch_to)