- 论坛徽章:
- 0
|
switch_mm中是进行页表的切换,即将下一个的pgd的开始物理地址放入CP15中的C2寄存器。进程的pgd的虚拟地址存放在task_struct结构中的pgd指针中,通过__virt_to_phys宏可以转变成成物理地址。
static inline voidswitch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned int cpu){ if (prev != next) cpu_switch_mm(next->pgd, tsk);} #define cpu_switch_mm(pgd,tsk) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd))) #define cpu_get_pgd() \ ({ \ unsigned long pg; \ __asm__("mrc p15, 0, %0, c2, c0, 0" \ : "=r" (pg)); \ pg &= ~0x3fff; \ (pgd_t *)phys_to_virt(pg); \ })
switch_to()完成进程上下文的切换,通过调用汇编函数__switch_to完成,其实现比较简单,也就是保存prev进程的上下文信息,该上下文信息由context_save_struct结构描述,包括主要的寄存器,然后将next的上下文信息读出,信息保存在task_struct中的thread.save中TSS_SAVE标识了thread.save在task_struct中的位置。
/* * Register switch for ARMv3 and ARMv4 processors * r0 = previous, r1 = next, return previous. * previous and next are guaranteed not to be the same. */ ENTRY(__switch_to) stmfd sp!, {r4 - sl, fp, lr} @ Store most regs on stack mrs ip, cpsr str ip, [sp, #-4]! @ Save cpsr_SVC str sp, [r0, #TSS_SAVE] @ Save sp_SVC ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC ldr r2, [r1, #TSS_DOMAIN] ldr ip, [sp], #4 mcr p15, 0, r2, c3, c0 @ Set domain register msr spsr, ip @ Save tasks CPSR into SPSR for this return ldmfd sp!, {r4 - sl, fp, pc}^ @ Load all regs saved previously
struct context_save_struct { unsigned long cpsr; unsigned long r4; unsigned long r5; unsigned long r6; unsigned long r7; unsigned long r8; unsigned long r9; unsigned long sl; unsigned long fp; unsigned long pc;};
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/51591/showart_454715.html |
|