ARM Linux系统调用的原理
474switch (no & 0xffff) {
475case 0: /* branch through 0 */
476 info.si_signo = SIGSEGV;
477 info.si_errno = 0;
478 info.si_code = SEGV_MAPERR;
479 info.si_addr = NULL;
480
481 arm_notify_die("branch throughzero", regs, &info, 0, 0);
482 return 0;
483
484case NR(breakpoint): /* SWI BREAK_POINT */
485 regs->ARM_pc -= thumb_mode(regs) ? 2: 4;
486 ptrace_break(current, regs);
487 return regs->ARM_r0;
488
489/*
490* Flush a region from virtual address r0 to virtual address r1
491 * _exclusive_. There is no alignment requirement on eitheraddress;
492* user space does not need to know the hardware cache layout.
493*
494* r2 contains flags. It shouldALWAYS be passed as ZERO until it
495* is defined to be something else.For now we ignore it, but may
496* the fires of hell burn in your belly if you break this rule. ;)
497*
498* (at a later date, we may want to allow this call to not flush
499* various aspects of the cache.Passing will guarantee that
500* everything necessary gets flushed to maintain consistency in
501* the specified region).
502*/
503case NR(cacheflush):
504 do_cache_op(regs->ARM_r0,regs->ARM_r1, regs->ARM_r2);
505 return 0;
506
507case NR(usr26):
508 if (!(elf_hwcap & HWCAP_26BIT))
509 break;
510 regs->ARM_cpsr &= ~MODE32_BIT;
511 return regs->ARM_r0;
512
513case NR(usr32):
514 if (!(elf_hwcap & HWCAP_26BIT))
515 break;
516 regs->ARM_cpsr = MODE32_BIT;
517 return regs->ARM_r0;
518
519case NR(set_tls):
520 thread->tp_value = regs->ARM_r0;
521 #if defined(CONFIG_HAS_TLS_REG)
522 asm ("mcr p15, 0, %0, c13, c0,3" : : "r" (regs->ARM_r0) );
523 #elif !defined(CONFIG_TLS_REG_EMUL)
524 /*
525 * User space must never try to accessthis directly.
526 * Expect your app to break eventuallyif you do so.
527 * The user helper at 0xffff0fe0 mustbe used instead.
528 * (see entry-armv.S for details)
529 */
530 *((unsigned int *)0xffff0ff0) =regs->ARM_r0;
531 #endif
532 return 0;
533
534 #ifdef CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG
535/*
536* Atomically store r1 in*r2 if *r2 is equal to r0 for user space.
537* Return zero in r0 if *MEM was changed or non-zero if no exchange
538* happened. Also set the user Cflag accordingly.
539* If access permissions have to be fixed up then non-zero is
540* returned and the operation has to be re-attempted.
541*
542* *NOTE*: This is a ghost syscall private to the kernel. Only the
543* __kuser_cmpxchg code in entry-armv.S should be aware of its
544* existence. Dont ever use thisfrom user code.
545*/
546case NR(cmpxchg):
547for (;;) {
548extern void do_DataAbort(unsigned long addr, unsigned int fsr,
549 struct pt_regs*regs);
550unsigned long val;
551unsigned long addr = regs->ARM_r2;
552struct mm_struct *mm = current->mm;
553pgd_t *pgd; pmd_t *pmd; pte_t *pte;
554spinlock_t *ptl;
556regs->ARM_cpsr &= ~PSR_C_BIT;
557down_read(&mm->mmap_sem);
558pgd = pgd_offset(mm, addr);
559if (!pgd_present(*pgd))
560goto bad_access;
561pmd = pmd_offset(pgd, addr);
562if (!pmd_present(*pmd))
563 goto bad_access;
564pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
565if (!pte_present(*pte) !pte_dirty(*pte)) {
566 pte_unmap_unlock(pte, ptl);
567 goto bad_access;
568}
569val = *(unsigned long *)addr;
570val -= regs->ARM_r0;
571if (val == 0) {
572 *(unsigned long *)addr =regs->ARM_r1;
573 regs->ARM_cpsr = PSR_C_BIT;
574}
575pte_unmap_unlock(pte, ptl);
576up_read(&mm->mmap_sem);
577return val;
578
579bad_access:
580up_read(&mm->mmap_sem);
581/* simulate a write access fault */
582do_DataAbort(addr, 15 + (1 < 11), regs);
583}
584 #endif
585
586default:
587 /* Calls 9f00xx..9f07ff are defined to return -ENOSYS
588 if not implemented, rather thanraising SIGILL. This
589 way the calling program can gracefullydetermine whether
590 a feature is suppor
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)
