Linux arm 进程切换
时间:2019-05-05 13:39 来源:linux.it.net.cn 作者:IT
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)
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) |