Linux arm 进程切换 Linux进程切换的函数是在函数schedule()中实现的,其中主要的函数是: schedule(void) { …… context_switch(rq, prev, next); …… } 在函数context_switch()中主要实现两个功能:1.切换页全局目录,生成进程的新的地址空间;2.切换硬件的上下文,即切换寄存器的值。以下主要分析这两个功能。 context_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next) { …… switch_mm(oldmm, mm, next); …… switch_to(prev, next, prev); …… } 一.切换全局目录 switch_mm(oldmm, mm, next) { …… cpu_switch_mm(next->pgd, next); …… } #define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm) #define cpu_do_switch_mm(pgd,mm) processor.switch_mm(pgd,mm) .align 5 ENTRY(cpu_arm920_switch_mm) //suyi processor.switch_mm(pgd,mm) #ifdef CONFIG_MMU mov ip, #0 …… mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache mcr p15, 0, ip, c7, c10, 4 @ drain WB mcr p15, 0, r0, c2, c0, 0 @ load page table pointer //此处切换MMU的全局页表 mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs #endif mov pc, lr 二.切换硬件的上下文 switch_to(prev, next, prev) #define switch_to(prev,next,last) \ do { \ last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \ } while (0) ENTRY(__switch_to) add ip, r1, #TI_CPU_SAVE //DEFINE(TI_CPU_SAVE,offsetof(struct thread_info, cpu_context)); //struct cpu_context_save { // __u32 r4; // __u32 r5; // __u32 r6; // __u32 r7; // __u32 r8; // __u32 r9; // __u32 sl; // __u32 fp; // __u32 sp; // __u32 pc; // __u32 extra[2]; /* Xscale 'acc' register, etc */ //}; ldr r3, [r2, #TI_TP_VALUE] stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack// 保存prev寄存器状态 #ifdef CONFIG_MMU ldr r6, [r2, #TI_CPU_DOMAIN] #endif #if __LINUX_ARM_ARCH__ >= 6 #ifdef CONFIG_CPU_32v6K clrex #else strex r5, r4, [ip] @ Clear exclusive monitor #endif #endif #if defined(CONFIG_HAS_TLS_REG) mcr p15, 0, r3, c13, c0, 3 @ set TLS register #elif !defined(CONFIG_TLS_REG_EMUL) mov r4, #0xffff0fff str r3, [r4, #-15] @ TLS val at 0xffff0ff0 #endif #ifdef CONFIG_MMU mcr p15, 0, r6, c3, c0, 0 @ Set domain register #endif mov r5, r0 add r4, r2, #TI_CPU_SAVE //next进程的寄存器状态值 ldr r0, =thread_notify_head mov r1, #THREAD_NOTIFY_SWITCH bl atomic_notifier_call_chain mov r0, r5 ldmia r4, {r4 - sl, fp, sp, pc} @ Load all regs saved previously //加载next进程的寄存器值 (责任编辑:IT) |