系统调用流程梳理

linux-3.5/arch/arm/include/asm/unistd.h
#define __NR_OABI_SYSCALL_BASE  0x900000
#define __NR_SYSCALL_BASE   __NR_OABI_SYSCALL_BASE
//提供给应用层使用
#define __NR_restart_syscall        (__NR_SYSCALL_BASE+  0)
#define __NR_exit           (__NR_SYSCALL_BASE+  1)
#define __NR_fork           (__NR_SYSCALL_BASE+  2)
#define __NR_read           (__NR_SYSCALL_BASE+  3)
#define __NR_write          (__NR_SYSCALL_BASE+  4)
#define __NR_open           (__NR_SYSCALL_BASE+  5)
#define __NR_close          (__NR_SYSCALL_BASE+  6)
                         ......
#define __NR_setns          (__NR_SYSCALL_BASE+375)
#define __NR_process_vm_readv       (__NR_SYSCALL_BASE+376)
#define __NR_process_vm_writev      (__NR_SYSCALL_BASE+377)
 
linux-3.5/arch/arm/kernel/entry-header.S
scno    .req    r7      @ syscall number
tbl .req    r8      @ syscall table pointer
why .req    r8      @ Linux syscall (!= 0)
tsk .req    r9      @ current thread_info
 
linux-3.5/include/generated/asm-offsets.h
#define S_R0 0 /* offsetof(struct pt_regs, ARM_r0)  @ */
#define S_R1 4 /* offsetof(struct pt_regs, ARM_r1)  @ */
#define S_R2 8 /* offsetof(struct pt_regs, ARM_r2)  @ */
#define S_R3 12 /* offsetof(struct pt_regs, ARM_r3) @ */
#define S_R4 16 /* offsetof(struct pt_regs, ARM_r4) @ */
#define S_R5 20 /* offsetof(struct pt_regs, ARM_r5) @ */
#define S_R6 24 /* offsetof(struct pt_regs, ARM_r6) @ */
#define S_R7 28 /* offsetof(struct pt_regs, ARM_r7) @ */
#define S_R8 32 /* offsetof(struct pt_regs, ARM_r8) @ */
#define S_R9 36 /* offsetof(struct pt_regs, ARM_r9) @ */
#define S_R10 40 /* offsetof(struct pt_regs, ARM_r10)   @ */
#define S_FP 44 /* offsetof(struct pt_regs, ARM_fp) @ */
#define S_IP 48 /* offsetof(struct pt_regs, ARM_ip) @ */
#define S_SP 52 /* offsetof(struct pt_regs, ARM_sp) @ */
#define S_LR 56 /* offsetof(struct pt_regs, ARM_lr) @ */
#define S_PC 60 /* offsetof(struct pt_regs, ARM_pc) @ */
#define S_PSR 64 /* offsetof(struct pt_regs, ARM_cpsr)  @ */
#define S_OLD_R0 68 /* offsetof(struct pt_regs, ARM_ORIG_r0)    @ */
#define S_FRAME_SIZE 72 /* sizeof(struct pt_regs)   @ */

linux-3.5/arch/arm/include/asm/ptrace.h
struct pt_regs {
    unsigned long uregs[18];

#define ARM_cpsr    uregs[16]
#define ARM_pc      uregs[15]
#define ARM_lr      uregs[14]
#define ARM_sp      uregs[13]
#define ARM_ip      uregs[12]
#define ARM_fp      uregs[11]
#define ARM_r10     uregs[10]
#define ARM_r9      uregs[9]
#define ARM_r8      uregs[8]
#define ARM_r7      uregs[7]
#define ARM_r6      uregs[6]
#define ARM_r5      uregs[5]
#define ARM_r4      uregs[4]
#define ARM_r3      uregs[3]
#define ARM_r2      uregs[2]
#define ARM_r1      uregs[1]
#define ARM_r0      uregs[0]
#define ARM_ORIG_r0 uregs[17]
 
linux/arch/arm/kernel/calls.S
/* 0 */     CALL(sys_restart_syscall)
        CALL(sys_exit)
        CALL(sys_fork_wrapper)
        CALL(sys_read)
        CALL(sys_write)
/* 5 */     CALL(sys_open)

          ......
         
/* 375 */   CALL(sys_setns)
        CALL(sys_process_vm_readv)
        CALL(sys_process_vm_writev)
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls     @第一次才会执行(NR_syscalls==1),syscalls_padding=3,保证以4对齐
#define syscalls_counted
#endif
.rept syscalls_padding
        CALL(sys_ni_syscall)
.endr
 
linux-3.5/arch/arm/kernel/entry-common.S
.equ NR_syscalls,0
#define CALL(x) .equ NR_syscalls,NR_syscalls+1
#include "calls.S"
#undef CALL
#define CALL(x) .long x
 
/*
* This is the syscall table declaration for native ABI syscalls.
* With EABI a couple syscalls are obsolete and defined as sys_ni_syscall.
*/
#define ABI(native, compat) native
#ifdef CONFIG_AEABI      
#define OBSOLETE(syscall) sys_ni_syscall
#else
#define OBSOLETE(syscall) syscall
#endif

.type   sys_call_table, #object
ENTRY(sys_call_table)    
#include "calls.S"
#undef ABI
#undef OBSOLETE
 

    .align  5
ENTRY(vector_swi)
/****************************将中断发生前的寄存器状态备份入栈**********/
    sub sp, sp, #S_FRAME_SIZE          @在栈上开辟18*4的空间备份跳转之前的寄存器值
    stmia   sp, {r0 - r12}          @ Calling r0 - r12,备份r0 - r12寄存器
     ARM(   add r8, sp, #S_PC       )                                              
     ARM(   stmdb   r8, {sp, lr}^       )   @ Calling sp, lr
     mrs r8, spsr            @ called from non-FIQ mode, so ok. 将CPSR的值存在r8中  
     str lr, [sp, #S_PC]         @ Save calling PC                         
     str r8, [sp, #S_PSR]        @ Save CPSR                                    
     str r0, [sp, #S_OLD_R0]     @ Save OLD_R0 备份r0到栈空间中r17的位置(因为没有SPSR 所以这里多备份了一个r0,估计是为了标准化)                                 
     zero_fp                            @清空fp寄存器r11
    
    /*
     * Get the system call number.
     */

#if defined(CONFIG_OABI_COMPAT)

    /*
     * If we have CONFIG_OABI_COMPAT then we need to look at the swi
     * value to determine if it is an EABI or an old ABI call.
     */
#ifdef CONFIG_ARM_THUMB
    tst r8, #PSR_T_BIT
    movne   r10, #0             @ no thumb OABI emulation
    ldreq   r10, [lr, #-4]          @ get SWI instruction
#else
    ldr r10, [lr, #-4]          @ get SWI instruction // get SWI instruction 利用lr取得swi指令的内容 
     //跳转前code段的内存{地址:内容:流水级},从下面的内存分布可以清楚看出lr - 4的含义 
    //{0x8:xxx:fetch<--pc},{0x4:xxx:decode<--lr},{0x0:swi num:exe}
#endif
#ifdef CONFIG_CPU_ENDIAN_BE8
    rev r10, r10            @ little endian instruction
#endif

#elif defined(CONFIG_AEABI)

    /*
     * Pure EABI user space always put syscall number into scno (r7).
     */
#elif defined(CONFIG_ARM_THUMB)
    /* Legacy ABI only, possibly thumb mode. */
    tst r8, #PSR_T_BIT          @ this is SPSR from save_user_regs
    addne   scno, r7, #__NR_SYSCALL_BASE    @ put OS number in
    ldreq   scno, [lr, #-4]
#else
    /* Legacy ABI only. */
    ldr scno, [lr, #-4]         @ get SWI instruction
#endif

/************为进入syscall具体函数做准备,主要是使调用符合ATPCS规范***********/
#ifdef CONFIG_ALIGNMENT_TRAP
    ldr ip, __cr_alignment
    ldr ip, [ip]                    //? 
    mcr p15, 0, ip, c1, c0      @ update control registe 读ip中的数据到c1
#endif
    enable_irq

    get_thread_info tsk
    adr tbl, sys_call_table     @ load syscall table pointer

#if defined(CONFIG_OABI_COMPAT)
    /*
     * If the swi argument is zero, this is an EABI call and we do nothing.
     *
     * If this is an old ABI call, get the syscall number into scno and
     * get the old ABI syscall table address.
     */
    bics    r10, r10, #0xff000000
    eorne   scno, r10, #__NR_OABI_SYSCALL_BASE
    ldrne   tbl, =sys_oabi_call_table
#elif !defined(CONFIG_AEABI)
    bic scno, scno, #0xff000000     @ mask off SWI op-code
    eor scno, scno, #__NR_SYSCALL_BASE  @ check OS number
#endif

    ldr r10, [tsk, #TI_FLAGS]       @ check for syscall tracing
    stmdb   sp!, {r4, r5}           @ push fifth and sixth args

#ifdef CONFIG_SECCOMP
    tst r10, #_TIF_SECCOMP
    beq 1f
    mov r0, scno
    bl  __secure_computing
    add r0, sp, #S_R0 + S_OFF       @ pointer to regs
    ldmia   r0, {r0 - r3}           @ have to reload r0 - r3
1:
#endif

    tst r10, #_TIF_SYSCALL_WORK     @ are we tracing syscalls?
    bne __sys_trace

    cmp scno, #NR_syscalls      @ check upper syscall limit
    adr lr, BSYM(ret_fast_syscall)  @ return address
    ldrcc   pc, [tbl, scno, lsl #2]     @ call sys_* routine PC = *(tbl+(scno<<2))

    add r1, sp, #S_OFF
2:  mov why, #0             @ no longer a real syscall
    cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
    eor r0, scno, #__NR_SYSCALL_BASE    @ put OS number back
    bcs arm_syscall
    b   sys_ni_syscall          @ not private func

ENDPROC(vector_swi) 
 
 
系统调用的主流程:
     API->swi>sys_*->driver(sys_*)
 
linux-3.5/fs/namei.c
linux-3.5/fs/open.c    
open()->SYSCALL_DEFINE3(open, ...)->do_sys_open()->do_filp_open()->
path_openat()->do_last()->nameidata_to_filp()->do_dentry_open()->open(inode, f)
 
1.获取系统调用号(ldr r10, [lr, #-4]);
2.根据tbl+scno来调用指定的系统调用接口。
posted @ 2015-12-14 00:15  suonikeyinsu  Views(880)  Comments(0Edit  收藏  举报