首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

ARM 软件中断指令SWI讲解(3)

ARM 软件中断指令SWI讲解(3)

举一个例子来说pen系统调用,库函数最终会调用__syscall(open),宏展开之后为swi #__NR_open,,swi #0x900005触发中断,中断号0x900005存放在[lr,#-4]地址中,处理器跳转到arch/arm/kernel/entry-common.Svector_swi读取[lr,#-4]地址中的中断号,之后查询arch/arm/kernel/entry-common.S中的sys_call_table系统调用表,该表内容在arch/arm/kernel/calls.S中定义,__NR_open在表中对应的顺序号为__syscall_start:




  • .long    SYMBOL_NAME(sys_open)                     //第5个
  • ...  
  • 将sys_call_table[5]中内容传给pc,系统进入sys_open函数,处理实质的open动作  

  • 注:用到的一些函数数据所在文件,如下所示  
  • arch/arm/kernel/calls.S声明了系统调用函数  
  • include/asm-arm/unistd.h定义了系统调用的调用号规则  

  • vector_swi定义在arch/arm/kernel/entry-common.S  
  • vector_IRQ定义在arch/arm/kernel/entry-armv.S  
  • vector_FIQ定义在arch/arm/kernel/entry-armv.S  

  • arch/arm/kernel/entry-common.S中对sys_call_table进行了定义:  
  •     .type    sys_call_table, #object  
  • ENTRY(sys_call_table)  
  • #include "calls.S"                                 //将calls.S中的内容顺序链接到这里


源程序:




  • ENTRY(vector_swi)  
  •     save_user_regs  
  •     zero_fp  
  •     get_scno                                        //将[lr,#-4]中的中断号转储到scno(r7)
  •     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_irq ip  

  •     str    r4, [sp, #-S_OFF]!                       @ push fifth arg  

  •     get_current_task tsk  
  •     ldr    ip, [tsk, #TSK_PTRACE]                   @ check for syscall tracing  
  •     bic    scno, scno, #0xff000000                  @ mask off SWI op-code  
  • //#define OS_NUMBER    9[entry-header.S]
  • //所以对于上面示例中open系统调用号scno=0x900005
  • //eor scno,scno,#0x900000
  • //之后scno=0x05
  •     eor    scno, scno, #OS_NUMBER << 20             @ check OS number  
  • //sys_call_table项为calls.S的内容
  •     adr    tbl, sys_call_table                      @ load syscall table pointer  
  •     tst    ip, #PT_TRACESYS                         @ are we tracing syscalls?  
  •     bne    __sys_trace  

  •     adrsvc    al, lr, ret_fast_syscall              @ return address  
  •     cmp    scno, #NR_syscalls                       @ check upper syscall limit  
  • //执行sys_open函数
  •     ldrcc    pc, [tbl, scno, lsl #2]                @ call sys_* routine  
  •     add    r1, sp, #S_OFF  
  • 2:  mov    why, #0                                  @ no longer a real syscall  
  •     cmp    scno, #ARMSWI_OFFSET  
  •     eor    r0, scno, #OS_NUMBER << 20               @ put OS number back  
  •     bcs    SYMBOL_NAME(arm_syscall)      
  •     b    SYMBOL_NAME(sys_ni_syscall)                @ not private func  
  •     /*
  •      * This is the really slow path. We're going to be doing
  •      * context switches, and waiting for our parent to respond.
  •      */
  • __sys_trace:  
  •     add    r1, sp, #S_OFF  
  •     mov    r0, #0                                   @ trace entry [IP = 0]  
  •     bl    SYMBOL_NAME(syscall_trace)  
  • /*
  • //2007-07-01 gliethttp [entry-header.S]
  • //Like adr, but force SVC mode (if required)
  •   .macro adrsvc, cond, reg, label
  •      adr\cond \reg, \label
  •   .endm
  • //对应反汇编:
  • //add lr, pc, #16 ; lr = __sys_trace_return
  • */
  •     adrsvc    al, lr, __sys_trace_return            @ return address  
  •     add    r1, sp, #S_R0 + S_OFF                    @ pointer to regs  
  •     cmp    scno, #NR_syscalls                       @ check upper syscall limit  
  •     ldmccia    r1, {r0 - r3}                        @ have to reload r0 - r3  
  •     ldrcc    pc, [tbl, scno, lsl #2]                @ call sys_* routine  
  •     b    2b  

  • __sys_trace_return:  
  •     str    r0, [sp, #S_R0 + S_OFF]!                 @ save returned r0  
  •     mov    r1, sp  
  •     mov    r0, #1                                   @ trace exit [IP = 1]  
  •     bl    SYMBOL_NAME(syscall_trace)  
  •     b    ret_disable_irq  

  •     .align    5  
  • #ifdef CONFIG_ALIGNMENT_TRAP
  •     .type    __cr_alignment, #object  
  • __cr_alignment:  
  •     .word    SYMBOL_NAME(cr_alignment)  
  • #endif

  •     .type    sys_call_table, #object  
  • ENTRY(sys_call_table)  
  • #include "calls.S"
返回列表