diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h index 68374ba6a943e9d029246d927b64a52913ea525e..c79f61faa3a55e81ae773b6d9d83532821b24c33 100644 --- a/arch/arm/include/asm/atomic.h +++ b/arch/arm/include/asm/atomic.h @@ -243,7 +243,7 @@ typedef struct { #define ATOMIC64_INIT(i) { (i) } -static inline u64 atomic64_read(atomic64_t *v) +static inline u64 atomic64_read(const atomic64_t *v) { u64 result; diff --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h index 3d2220498abc2db2d98378c94a3309c71e91ccee..6ddbe446425e11524d927b5cd8b479bcd2419238 100644 --- a/arch/arm/include/asm/domain.h +++ b/arch/arm/include/asm/domain.h @@ -60,13 +60,13 @@ #ifndef __ASSEMBLY__ #ifdef CONFIG_CPU_USE_DOMAINS -#define set_domain(x) \ - do { \ - __asm__ __volatile__( \ - "mcr p15, 0, %0, c3, c0 @ set domain" \ - : : "r" (x)); \ - isb(); \ - } while (0) +static inline void set_domain(unsigned val) +{ + asm volatile( + "mcr p15, 0, %0, c3, c0 @ set domain" + : : "r" (val)); + isb(); +} #define modify_domain(dom,type) \ do { \ @@ -78,8 +78,8 @@ } while (0) #else -#define set_domain(x) do { } while (0) -#define modify_domain(dom,type) do { } while (0) +static inline void set_domain(unsigned val) { } +static inline void modify_domain(unsigned dom, unsigned type) { } #endif /* diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index b79f8e97f7755f22d82ae20ee00442cd11f7af02..af7b0bda3355d9af850ae722b2b1f55277ef6e67 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -148,7 +148,6 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ #define TIF_SYSCALL_TRACE 8 #define TIF_SYSCALL_AUDIT 9 -#define TIF_SYSCALL_RESTARTSYS 10 #define TIF_POLLING_NRFLAG 16 #define TIF_USING_IWMMXT 17 #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ @@ -164,11 +163,9 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT) #define _TIF_SECCOMP (1 << TIF_SECCOMP) -#define _TIF_SYSCALL_RESTARTSYS (1 << TIF_SYSCALL_RESTARTSYS) /* Checks for any syscall work in entry-common.S */ -#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ - _TIF_SYSCALL_RESTARTSYS) +#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT) /* * Change these and you break ASM code in entry-common.S diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/kernel/kprobes-test-arm.c index ba32b393b3f0c514c83799687348d52655bfe1da..38c1a3b103a0684b5b579bb74ca07f38bb91eb13 100644 --- a/arch/arm/kernel/kprobes-test-arm.c +++ b/arch/arm/kernel/kprobes-test-arm.c @@ -187,8 +187,8 @@ void kprobe_arm_test_cases(void) TEST_BF_R ("mov pc, r",0,2f,"") TEST_BF_RR("mov pc, r",0,2f,", asl r",1,0,"") TEST_BB( "sub pc, pc, #1b-2b+8") -#if __LINUX_ARM_ARCH__ >= 6 - TEST_BB( "sub pc, pc, #1b-2b+8-2") /* UNPREDICTABLE before ARMv6 */ +#if __LINUX_ARM_ARCH__ == 6 && !defined(CONFIG_CPU_V7) + TEST_BB( "sub pc, pc, #1b-2b+8-2") /* UNPREDICTABLE before and after ARMv6 */ #endif TEST_BB_R( "sub pc, pc, r",14, 1f-2f+8,"") TEST_BB_R( "rsb pc, r",14,1f-2f+8,", pc") diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 186c8cb982c543a2cc1631796b34376151b33702..a02eada3aa5d06036027ac1241e652d5032781bd 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -503,7 +503,7 @@ __hw_perf_event_init(struct perf_event *event) event_requires_mode_exclusion(&event->attr)) { pr_debug("ARM performance counters do not support " "mode exclusion\n"); - return -EPERM; + return -EOPNOTSUPP; } /* diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 5700a7ae7f0bc1511ae048d7a3f025c401e5729c..14e38261cd31db9d852db2eb0b8046251a04613d 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -918,8 +917,6 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3); - if (why == 0 && test_and_clear_thread_flag(TIF_SYSCALL_RESTARTSYS)) - scno = __NR_restart_syscall - __NR_SYSCALL_BASE; if (!test_thread_flag(TIF_SYSCALL_TRACE)) return scno; diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index fd2392a17ac1befb3464b5a0e77960a0f862b4ca..536c5d6b340b7fca2aee9c770000372c38be98bb 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -27,6 +27,7 @@ */ #define SWI_SYS_SIGRETURN (0xef000000|(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE)) #define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE)) +#define SWI_SYS_RESTART (0xef000000|__NR_restart_syscall|__NR_OABI_SYSCALL_BASE) /* * With EABI, the syscall number has to be loaded into r7. @@ -46,6 +47,18 @@ const unsigned long sigreturn_codes[7] = { MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, }; +/* + * Either we support OABI only, or we have EABI with the OABI + * compat layer enabled. In the later case we don't know if + * user space is EABI or not, and if not we must not clobber r7. + * Always using the OABI syscall solves that issue and works for + * all those cases. + */ +const unsigned long syscall_restart_code[2] = { + SWI_SYS_RESTART, /* swi __NR_restart_syscall */ + 0xe49df004, /* ldr pc, [sp], #4 */ +}; + /* * atomically swap in the new signal mask, and wait for a signal. */ @@ -592,10 +605,12 @@ static void do_signal(struct pt_regs *regs, int syscall) case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: - case -ERESTART_RESTARTBLOCK: regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc = restart_addr; break; + case -ERESTART_RESTARTBLOCK: + regs->ARM_r0 = -EINTR; + break; } } @@ -611,14 +626,12 @@ static void do_signal(struct pt_regs *regs, int syscall) * debugger has chosen to restart at a different PC. */ if (regs->ARM_pc == restart_addr) { - if (retval == -ERESTARTNOHAND || - retval == -ERESTART_RESTARTBLOCK + if (retval == -ERESTARTNOHAND || (retval == -ERESTARTSYS && !(ka.sa.sa_flags & SA_RESTART))) { regs->ARM_r0 = -EINTR; regs->ARM_pc = continue_addr; } - clear_thread_flag(TIF_SYSCALL_RESTARTSYS); } handle_signal(signr, &ka, &info, regs); @@ -632,8 +645,29 @@ static void do_signal(struct pt_regs *regs, int syscall) * ignore the restart. */ if (retval == -ERESTART_RESTARTBLOCK - && regs->ARM_pc == restart_addr) - set_thread_flag(TIF_SYSCALL_RESTARTSYS); + && regs->ARM_pc == continue_addr) { + if (thumb_mode(regs)) { + regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; + regs->ARM_pc -= 2; + } else { +#if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT) + regs->ARM_r7 = __NR_restart_syscall; + regs->ARM_pc -= 4; +#else + u32 __user *usp; + + regs->ARM_sp -= 4; + usp = (u32 __user *)regs->ARM_sp; + + if (put_user(regs->ARM_pc, usp) == 0) { + regs->ARM_pc = KERN_RESTART_CODE; + } else { + regs->ARM_sp += 4; + force_sigsegv(0, current); + } +#endif + } + } } restore_saved_sigmask(); diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h index 5ff067b7c7522f428b4343832ecb759b7ccf16de..6fcfe8398aa473051fbf72396986a84dc700978f 100644 --- a/arch/arm/kernel/signal.h +++ b/arch/arm/kernel/signal.h @@ -8,5 +8,7 @@ * published by the Free Software Foundation. */ #define KERN_SIGRETURN_CODE (CONFIG_VECTORS_BASE + 0x00000500) +#define KERN_RESTART_CODE (KERN_SIGRETURN_CODE + sizeof(sigreturn_codes)) extern const unsigned long sigreturn_codes[7]; +extern const unsigned long syscall_restart_code[2]; diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 4928d89758f4ce0dea767acdf9fcf2299dff7833..3647170e9a16ba3aa8838218ed99e74dbc5b7c59 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -820,6 +820,8 @@ void __init early_trap_init(void *vectors_base) */ memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE), sigreturn_codes, sizeof(sigreturn_codes)); + memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE), + syscall_restart_code, sizeof(syscall_restart_code)); flush_icache_range(vectors, vectors + PAGE_SIZE); modify_domain(DOMAIN_USER, DOMAIN_CLIENT); diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c index bec933b04ef04bebcac7d312b46f710b9ce3a9e3..e95bf84cc837550650ccc053e5afc72486d6682a 100644 --- a/arch/arm/mach-versatile/pci.c +++ b/arch/arm/mach-versatile/pci.c @@ -339,7 +339,6 @@ void __init pci_versatile_preinit(void) static int __init versatile_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { int irq; - int devslot = PCI_SLOT(dev->devfn); /* slot, pin, irq * 24 1 27 diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index c471436c79522d7722ba08a2baec7223e4c663d5..2e8a1efdf7b85f3443294b396ec5673496dd635d 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -64,7 +64,7 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page #ifdef CONFIG_ZONE_DMA extern phys_addr_t arm_dma_limit; #else -#define arm_dma_limit ((u32)~0) +#define arm_dma_limit ((phys_addr_t)~0) #endif extern phys_addr_t arm_lowmem_limit;