- 论坛徽章:
- 0
|
static void rest_init(void)
{
kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
//CLONE_FS | CLONE_FILES | CLONE_SIGNAL == 0x00010e00
unlock_kernel();
current->need_resched = 1;
cpu_idle();
}
pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{
pid_t __ret;
__asm__ __volatile__(
"orr r0, %1, %2 @ kernel_thread sys_clone
//r0 = CLONE_FS | CLONE_FILES | CLONE_SIGNAL | CLONE_VM == 0x00010f00
mov r1, #0
//r1 = 0
"__syscall(clone)" //后面注释
movs %0, r0 @ if we are the child
bne 1f
mov fp, #0 @ ensure that fp is zero
mov r0, %4
mov lr, pc
mov pc, %3
b sys_exit
1: "
: "=r" (__ret)
: "Ir" (flags), "I" (CLONE_VM), "r" (fn), "r" (arg)
: "r0", "r1", "lr");
return __ret;
}
//----------------------------------------------------------
语句"__syscall(clone)" 在unistd.h中,可以转化为:"swi\t #(0x900000+120)\t\n",即调用swi软中断指令。
背景知识:
一旦发生中断:
1、自动把cpsr保存到相应异常模式下的spsr;
2、自动把pc保存到相应异常模式下的lr;
3、自动设置cpsr为相应的异常模式;
4、自动设置pc为相应异常处理程序的入口。
寄存器分布:
r0
r1
r2
r3
r4
r5
r6
r7
r8 r8_fiq
r9 r9_fiq
r10(sl) r10_fiq
r11(fp) r11_fiq
r12(ip) r12_fiq
r13(sp) r13_fiq r13_irq r13_svc r13_undef r13_abt
r14(lr) r14_fiq r14_irq r14_svc r14_undef r14_abt
r15(pc)
cpsr
spsr_fiq spsr_irq spsr_svc spsr_undef spsr_abt
user/sys fiq irq svc undef abt
中断向量表(entry-armV.s)
.LCvectors: swi SYS_ERROR0
b __real_stubs_start + (vector_undefinstr - __stubs_start)
ldr pc, __real_stubs_start + (.LCvswi - __stubs_start)
b __real_stubs_start + (vector_prefetch - __stubs_start)
b __real_stubs_start + (vector_data - __stubs_start)
b __real_stubs_start + (vector_addrexcptn - __stubs_start)
b __real_stubs_start + (vector_IRQ - __stubs_start)
b __real_stubs_start + (vector_FIQ - __stubs_start)
//----------------------------------------------------------
//swi指令触发软中断,程序指令最后跳转到
ENTRY(vector_swi)
save_user_regs
//该宏主要用来保存寄存器,及相关参数,栈指针变化如下:
sp-->r0
spsr
lr
lr
sp
r12
r11
r10
r9
r8
r7
r6
r5
r4
r3
r2
r1
sp=sp-18 -->r0
×
sp=sp-2 -->r4
zero_fp
get_scno
//取得swi指令码 r7 = swi指令码。
//在entry-header.S中有:
// scno .req r7
// tbl .req r8
// why .req r8
// tsk .req r9
arm710_bug_check scno, ip
#ifdef CONFIG_ALIGNMENT_TRAP
ldr ip, __cr_alignment
ldr ip, [ip]
mcr p15, 0, ip, c1, c0 @ update control register
#endif
enable_irqs ip
str r4, [sp, #-S_OFF]! @ push fifth arg
//该语句改变了sp指针,见上图
get_current_task tsk //r9 = current
ldr ip, [tsk, #TSK_PTRACE] @ check for syscall tracing
bic scno, scno, #0xff000000 @ mask off SWI op-code
eor scno, scno, #OS_NUMBER
//sys_call_table 即__syscall_start 在文件calls.S中
tst ip, #PT_TRACESYS @ are we tracing syscalls? //tst指令是按位与操作
bne __sys_trace
adrsvc al, lr, ret_fast_syscall @ return address
//adr\cond \reg, \label lr = ret_fast_syscall
cmp scno, #NR_syscalls @ check upper syscall limit
ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
//转向程序sys_clone_wapper
:
:
//在entry-common.S中:
sys_clone_wapper:
add r2, sp, #S_OFF
b SYMBOL_NAME(sys_clone)
在分析sys_clone之前,回顾一下现在主要寄存器中的值:
r0 = 0x00010f00 = CLONE_FS | CLONE_FILES | CLONE_SIGNAL | CLONE_VM;
r1 = 0;
r2 = sp + 8; //具体位置见上图
r14 = ret_fast_syscall
asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct pt_regs *regs)
{
if (!newsp) // newsp = r1
newsp = regs->ARM_sp;
// “听说该赋值,因为是在系统模式下,同时返回系统模式,用户模式下的sp无效”
return do_fork(clone_flags, newsp, regs, 0);
}
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/60314/showart_483934.html |
|