aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/traps.c
diff options
context:
space:
mode:
authorAnton Altaparmakov <aia21@cantab.net>2005-06-23 06:26:22 -0400
committerAnton Altaparmakov <aia21@cantab.net>2005-06-23 06:26:22 -0400
commit3357d4c75f1fb67e7304998c4ad4e9a9fed66fa4 (patch)
treeceba46966a5a1112a05d257d8ecb25ae5eee95e0 /arch/arm/kernel/traps.c
parent364f6c717deef4a3ac4982e670fa9846b43cd060 (diff)
parentee98689be1b054897ff17655008c3048fe88be94 (diff)
Automatic merge with /usr/src/ntfs-2.6.git.
Diffstat (limited to 'arch/arm/kernel/traps.c')
-rw-r--r--arch/arm/kernel/traps.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 14df16b983f4..2fb0a4cfb37a 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -30,6 +30,7 @@
30#include <asm/traps.h> 30#include <asm/traps.h>
31 31
32#include "ptrace.h" 32#include "ptrace.h"
33#include "signal.h"
33 34
34const char *processor_modes[]= 35const char *processor_modes[]=
35{ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , 36{ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
@@ -464,6 +465,55 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
464#endif 465#endif
465 return 0; 466 return 0;
466 467
468#ifdef CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG
469 /*
470 * Atomically store r1 in *r2 if *r2 is equal to r0 for user space.
471 * Return zero in r0 if *MEM was changed or non-zero if no exchange
472 * happened. Also set the user C flag accordingly.
473 * If access permissions have to be fixed up then non-zero is
474 * returned and the operation has to be re-attempted.
475 *
476 * *NOTE*: This is a ghost syscall private to the kernel. Only the
477 * __kuser_cmpxchg code in entry-armv.S should be aware of its
478 * existence. Don't ever use this from user code.
479 */
480 case 0xfff0:
481 {
482 extern void do_DataAbort(unsigned long addr, unsigned int fsr,
483 struct pt_regs *regs);
484 unsigned long val;
485 unsigned long addr = regs->ARM_r2;
486 struct mm_struct *mm = current->mm;
487 pgd_t *pgd; pmd_t *pmd; pte_t *pte;
488
489 regs->ARM_cpsr &= ~PSR_C_BIT;
490 spin_lock(&mm->page_table_lock);
491 pgd = pgd_offset(mm, addr);
492 if (!pgd_present(*pgd))
493 goto bad_access;
494 pmd = pmd_offset(pgd, addr);
495 if (!pmd_present(*pmd))
496 goto bad_access;
497 pte = pte_offset_map(pmd, addr);
498 if (!pte_present(*pte) || !pte_write(*pte))
499 goto bad_access;
500 val = *(unsigned long *)addr;
501 val -= regs->ARM_r0;
502 if (val == 0) {
503 *(unsigned long *)addr = regs->ARM_r1;
504 regs->ARM_cpsr |= PSR_C_BIT;
505 }
506 spin_unlock(&mm->page_table_lock);
507 return val;
508
509 bad_access:
510 spin_unlock(&mm->page_table_lock);
511 /* simulate a read access fault */
512 do_DataAbort(addr, 15 + (1 << 11), regs);
513 return -1;
514 }
515#endif
516
467 default: 517 default:
468 /* Calls 9f00xx..9f07ff are defined to return -ENOSYS 518 /* Calls 9f00xx..9f07ff are defined to return -ENOSYS
469 if not implemented, rather than raising SIGILL. This 519 if not implemented, rather than raising SIGILL. This
@@ -634,6 +684,14 @@ void __init trap_init(void)
634 memcpy((void *)0xffff0000, __vectors_start, __vectors_end - __vectors_start); 684 memcpy((void *)0xffff0000, __vectors_start, __vectors_end - __vectors_start);
635 memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start); 685 memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start);
636 memcpy((void *)0xffff1000 - kuser_sz, __kuser_helper_start, kuser_sz); 686 memcpy((void *)0xffff1000 - kuser_sz, __kuser_helper_start, kuser_sz);
687
688 /*
689 * Copy signal return handlers into the vector page, and
690 * set sigreturn to be a pointer to these.
691 */
692 memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
693 sizeof(sigreturn_codes));
694
637 flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE); 695 flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE);
638 modify_domain(DOMAIN_USER, DOMAIN_CLIENT); 696 modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
639} 697}