微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Arm Linux系统调用流程详细解析

Arm Linux系统调用流程详细解析

时间:11-09 来源:互联网 点击:

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 #include  here,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

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top