X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Farm%2Fkernel%2Ftraps.c;h=760191e3bd381aa1c4776420fa1b6a894d0816f8;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=3f28167930be4627bc6f75a0094a52e29e824f80;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 3f2816793..760191e3b 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -200,7 +200,7 @@ void show_stack(struct task_struct *tsk, unsigned long *sp) barrier(); } -spinlock_t die_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(die_lock); /* * This function is protected against re-entrancy. @@ -241,7 +241,7 @@ void die_if_kernel(const char *str, struct pt_regs *regs, int err) } static LIST_HEAD(undef_hook); -static spinlock_t undef_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(undef_lock); void register_undef_hook(struct undef_hook *hook) { @@ -263,7 +263,7 @@ asmlinkage void do_undefinstr(struct pt_regs *regs) unsigned int instr; struct undef_hook *hook; siginfo_t info; - void *pc; + void __user *pc; /* * According to the ARM ARM, PC is 2 or 4 bytes ahead, @@ -272,11 +272,11 @@ asmlinkage void do_undefinstr(struct pt_regs *regs) */ regs->ARM_pc -= correction; - pc = (void *)instruction_pointer(regs); + pc = (void __user *)instruction_pointer(regs); if (thumb_mode(regs)) { - get_user(instr, (u16 *)pc); + get_user(instr, (u16 __user *)pc); } else { - get_user(instr, (u32 *)pc); + get_user(instr, (u32 __user *)pc); } spin_lock_irq(&undef_lock); @@ -328,20 +328,11 @@ asmlinkage void do_unexp_fiq (struct pt_regs *regs) */ asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode) { - unsigned int vectors = vectors_base(); - console_verbose(); printk(KERN_CRIT "Bad mode in %s handler detected: mode %s\n", handler[reason], processor_modes[proc_mode]); - /* - * Dump out the vectors and stub routines. Maybe a better solution - * would be to dump them out only if we detect that they are corrupted. - */ - dump_mem(KERN_CRIT "Vectors: ", vectors, vectors + 0x40); - dump_mem(KERN_CRIT "Stubs: ", vectors + 0x200, vectors + 0x4b8); - die("Oops - bad mode", regs, 0); local_irq_disable(); panic("bad mode"); @@ -368,7 +359,7 @@ static int bad_syscall(int n, struct pt_regs *regs) info.si_signo = SIGILL; info.si_errno = 0; info.si_code = ILL_ILLTRP; - info.si_addr = (void *)instruction_pointer(regs) - + info.si_addr = (void __user *)instruction_pointer(regs) - (thumb_mode(regs) ? 2 : 4); force_sig_info(SIGILL, &info, current); @@ -381,7 +372,7 @@ do_cache_op(unsigned long start, unsigned long end, int flags) { struct vm_area_struct *vma; - if (end < start) + if (end < start || flags) return; vma = find_vma(current->active_mm, start); @@ -391,7 +382,7 @@ do_cache_op(unsigned long start, unsigned long end, int flags) if (end > vma->vm_end) end = vma->vm_end; - flush_cache_range(vma, start, end); + flush_cache_user_range(vma, start, end); } } @@ -402,6 +393,7 @@ do_cache_op(unsigned long start, unsigned long end, int flags) #define NR(x) ((__ARM_NR_##x) - __ARM_NR_BASE) asmlinkage int arm_syscall(int no, struct pt_regs *regs) { + struct thread_info *thread = current_thread_info(); siginfo_t info; if ((no >> 16) != 0x9f) @@ -426,7 +418,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) /* * Flush a region from virtual address 'r0' to virtual address 'r1' - * _inclusive_. There is no alignment requirement on either address; + * _exclusive_. There is no alignment requirement on either address; * user space does not need to know the hardware cache layout. * * r2 contains flags. It should ALWAYS be passed as ZERO until it @@ -454,6 +446,17 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) regs->ARM_cpsr |= MODE32_BIT; return regs->ARM_r0; + case NR(set_tls): + thread->tp_value = regs->ARM_r0; + /* + * Our user accessible TLS ptr is located at 0xffff0ffc. + * On SMP read access to this address must raise a fault + * and be emulated from the data abort handler. + * m + */ + *((unsigned long *)0xffff0ffc) = thread->tp_value; + return 0; + default: /* Calls 9f00xx..9f07ff are defined to return -ENOSYS if not implemented, rather than raising SIGILL. This @@ -481,7 +484,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) info.si_signo = SIGILL; info.si_errno = 0; info.si_code = ILL_ILLTRP; - info.si_addr = (void *)instruction_pointer(regs) - + info.si_addr = (void __user *)instruction_pointer(regs) - (thumb_mode(regs) ? 2 : 4); force_sig_info(SIGILL, &info, current); @@ -519,7 +522,7 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs) info.si_signo = SIGILL; info.si_errno = 0; info.si_code = ILL_ILLOPC; - info.si_addr = (void *)addr; + info.si_addr = (void __user *)addr; force_sig_info(SIGILL, &info, current); die_if_kernel("unknown data abort code", regs, instr); @@ -537,7 +540,7 @@ EXPORT_SYMBOL(__bug); void __readwrite_bug(const char *fn) { - printk("%s called, but not implemented", fn); + printk("%s called, but not implemented\n", fn); BUG(); } EXPORT_SYMBOL(__readwrite_bug); @@ -562,7 +565,7 @@ asmlinkage void __div0(void) printk("Division by zero in kernel.\n"); dump_stack(); } -EXPORT_SYMBOL_NOVERS(__div0); +EXPORT_SYMBOL(__div0); void abort(void) { @@ -575,13 +578,9 @@ EXPORT_SYMBOL(abort); void __init trap_init(void) { - extern void __trap_init(unsigned long); - unsigned long base = vectors_base(); - - __trap_init(base); - flush_icache_range(base, base + PAGE_SIZE); - if (base != 0) - printk(KERN_DEBUG "Relocating machine vectors to 0x%08lx\n", - base); + extern void __trap_init(void); + + __trap_init(); + flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE); modify_domain(DOMAIN_USER, DOMAIN_CLIENT); }