Arm Linux系统调用流程详细解析
ons have to be fixed up then non-zero is* returned and the operation has to be re-attempted.** *NOTE*: This is a ghost syscall private to the kernel. Only the* __kuser_cmpxchg code in entry-armv.S should be aware of its* existence. Dont ever use this from user code.*/case NR(cmpxchg):for (;;) {extern void do_DataAbort(unsigned long addr, unsigned int fsr,struct pt_regs *regs);unsigned long val;unsigned long addr = regs->ARM_r2;struct mm_struct *mm = current->mm;pgd_t *pgd; pmd_t *pmd; pte_t *pte;spinlock_t *ptl;regs->ARM_cpsr &= ~PSR_C_BIT;down_read(&mm->mmap_sem);pgd = pgd_offset(mm, addr);if (!pgd_present(*pgd))goto bad_access;pmd = pmd_offset(pgd, addr);if (!pmd_present(*pmd))goto bad_access;pte = pte_offset_map_lock(mm, pmd, addr, &ptl);if (!pte_present(*pte) !pte_dirty(*pte)) {pte_unmap_unlock(pte, ptl);goto bad_access;}val = *(unsigned long *)addr;val -= regs->ARM_r0;if (val == 0) {*(unsigned long *)addr = regs->ARM_r1;regs->ARM_cpsr = PSR_C_BIT;}pte_unmap_unlock(pte, ptl);up_read(&mm->mmap_sem);return val;bad_access:up_read(&mm->mmap_sem);/* simulate a write access fault */do_DataAbort(addr, 15 + (1 < 11), regs);}#endifdefault:/* Calls 9f00xx..9f07ff are defined to return -ENOSYSif not implemented, rather than raising SIGILL. Thisway the calling program can gracefully determine whethera feature is supported. */if ((no & 0xffff) <= 0x7ff)return -ENOSYS;break;}#ifdef CONFIG_DEBUG_USER/** experience shows that these seem to indicate that* something catastrophic has happened*/if (user_debug & UDBG_SYSCALL) {printk("[%d] %s: arm syscall %d\n",task_pid_nr(current), current->comm, no);dump_instr("", regs);if (user_mode(regs)) {__show_regs(regs);c_backtrace(regs->ARM_fp, processor_mode(regs));}}#endifinfo.si_signo = SIGILL;info.si_errno = 0;info.si_code = ILL_ILLTRP;info.si_addr = (void __user *)instruction_pointer(regs) -(thumb_mode(regs) ? 2 : 4);arm_notify_die("Oops - bad syscall(2)", regs, &info, no, 0);return 0;}
还有那个sys_ni_syscall,这个函数在kernel/sys_ni.c中定义,它的作用似乎也仅仅是要给用户空间返回错误码ENOSYS。
/* we cant #includehere,but tell gcc to not warn with -Wmissing-prototypes */asmlinkage long sys_ni_syscall(void);/** Non-implemented system calls get redirected here.*/asmlinkage long sys_ni_syscall(void){return -ENOSYS;}
系统调用号正确也好不正确也好,最终都是通过ret_fast_syscall例程来返回,同样在arch/arm/kernel/entry-common.S文件中:
.align 5/** This is the fast syscall return path. We do as little as* possible here, and this includes saving r0 back into the SVC* stack.*/ret_fast_syscall:UNWIND(.fnstart )UNWIND(.cantunwind )disable_irq @ disable interruptsldr r1, [tsk, #TI_FLAGS]tst r1, #_TIF_WORK_MASKbne fast_work_pending#if defined(CONFIG_IRQSOFF_TRACER)asm_trace_hardirqs_on#endif/* perform architecture specific actions before user return */arch_ret_to_user r1, lrrestore_user_regs fast = 1, offset = S_OFFUNWIND(.fnend )
四.声明系统调用的相关宏
linux下的系统调用函数定义接口:
1.SYSCALL_DEFINE1~6(include/linux/syscalls.h)
#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
2.SYSCALL_DEFINEx
#ifdef CONFIG_FTRACE_SYSCALLS#define SYSCALL_DEFINEx(x, sname, ...) \static const char *types_##sname[] = { \__SC_STR_TDECL##x(__VA_ARGS__) \}; \static const char *args_##sname[] = { \__SC_STR_ADECL##x(__VA_ARGS__) \}; \SYSCALL_METADATA(sname, x); \__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)#else#define SYSCALL_DEFINEx(x, sname, ...) \__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)#endif
ArmLinux系统调 相关文章:
- ARM Linux下添加新的系统调用(11-21)
- 《ARM与Linux些许问题》第四章:ARM平台系统调用原理分析(11-09)
- Arm linux 系统调用分析(11-09)
- Android arm linux 系统调用实现(11-09)
- arm linux 系统调用实现(11-09)
- Arm Linux系统调用流程详细解析SWI(11-09)