| 2009年4月25日
#define CFI_STARTPROC .cfi_startproc //用在每个函数的开始,用于初始化一些内部数据结构
#define CFI_ENDPROC .cfi_endproc //在函数结束的时候使用与.cfi_startproc相配套使用
#define CFI_DEF_CFA .cfi_def_cfa //定义计算CFA的规则
#define CFI_DEF_CFA_REGISTER .cfi_def_cfa_register //xx reg ,offset reg中的值保存在offset中,offset是CFA的
#define CFI_DEF_CFA_OFFSET .cfi_def_cfa_offset //xx offset 修改计算CFA的规则,reg中的值不发生变化,之改变offset
#define CFI_ADJUST_CFA_OFFSET .cfi_adjust_cfa_offset //与上面相似但是修改前面一个offset
#define CFI_OFFSET .cfi_offset //xx reg ,offset reg中的值保存在offset中,offset是CFA的
#define CFI_REL_OFFSET .cfi_rel_offset
#define CFI_REGISTER .cfi_register
#define CFI_RESTORE .cfi_restore
#define CFI_REMEMBER_STATE .cfi_remember_state
#define CFI_RESTORE_STATE .cfi_restore_state
#define CFI_UNDEFINED .cfi_undefined
.macro RING0_INT_FRAME
CFI_STARTPROC simple
CFI_SIGNAL_FRAME
CFI_DEF_CFA esp, 3*4
/*CFI_OFFSET cs, -2*4;*/
CFI_OFFSET eip, -3*4
.endm
# system call handler stub
ENTRY(system_call)
RING0_INT_FRAME # can't unwind into user space anyway
pushl %eax # save orig_eax //保存原来的eax中的值
CFI_ADJUST_CFA_OFFSET 4
SAVE_ALL //保存系统寄存器信息
GET_THREAD_INFO(%ebp) //获取thread_info结构的地址
# system call tracing in operation / emulation
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) //检测thread_info中的相关标志看是否有系统跟踪
jnz syscall_trace_entry //有系统跟踪则先执行系统跟踪的代码,然后转跳回来(这在syscall_trace_entry中有写的)
cmpl $(nr_syscalls), %eax //比较请求的系统调用号和最大系统调用号(验证系统调用号是否有效)
jae syscall_badsys //如果请求系统调用号无效则退出
syscall_call:
call *sys_call_table(,%eax,4) //跳转到系统调用表中,系统调用表是4字节对齐。
movl %eax,PT_EAX(%esp) # store the return value
syscall_exit:
LOCKDEP_SYS_EXIT //用于调试使用,只有在开启调试的时候才会去检测系统调用深度
DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt
# setting need_resched or sigpending
# between sampling and the iret
//#define ENABLE_INTERRUPTS(x) sti
//#define DISABLE_INTERRUPTS(x) cli
TRACE_IRQS_OFF //关闭中断跟踪
movl TI_flags(%ebp), %ecx //
testl $_TIF_ALLWORK_MASK, %ecx # current->work //检测是否可以返回用户空间
jne syscall_exit_work
syscall_exit_work:
testl $_TIF_WORK_SYSCALL_EXIT, %ecx
jz work_pending
TRACE_IRQS_ON //开启系统中断跟踪
ENABLE_INTERRUPTS(CLBR_ANY) # could let syscall_trace_leave() call
# schedule() instead
//允许中断
movl %esp, %eax
call syscall_trace_leave
jmp resume_userspace
END(syscall_exit_work)
关注「黑光技术」,关注大数据+微服务