微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM Linux系统调用的原理

ARM Linux系统调用的原理

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

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

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

网站地图

Top