diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-30 03:21:44 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-30 03:21:44 +0200 |
commit | 227d1e4319ffd8729781941d92f4ae4d85beecd9 (patch) | |
tree | 22dd4d85386dd3bdd228b7be988bebbb9607d0fa /arch/arm | |
parent | Merge branch 'akpm' (Andrew's patch-bomb) (diff) | |
parent | Merge branch 'for-arm' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/... (diff) | |
download | linux-227d1e4319ffd8729781941d92f4ae4d85beecd9.tar.xz linux-227d1e4319ffd8729781941d92f4ae4d85beecd9.zip |
Merge branch 'for-linus' of git://git.linaro.org/people/rmk/linux-arm
Pull arm updates from Russell King:
"This contains both some fixes found when trying to get the
Assabet+neponset setup as a replacement firewall with a 3c589 PCMCIA
card, and a bunch of changes from Al to fix up the ARM signal
handling, particularly some of the restart behaviour."
* 'for-linus' of git://git.linaro.org/people/rmk/linux-arm:
ARM: neponset: make sure neponset_ncr_frob() is exported
ARM: fix out[bwl]()
arm: don't open-code ptrace_report_syscall()
arm: bury unused _TIF_RESTORE_SIGMASK
arm: remove unused restart trampoline
arm: new way of handling ERESTART_RESTARTBLOCK
arm: if we get into work_pending while returning to kernel mode, just go away
arm: don't call try_to_freeze() from do_signal()
arm: if there's no handler we need to restore sigmask, syscall or no syscall
arm: trim _TIF_WORK_MASK, get rid of useless test and branch...
arm: missing checks of __get_user()/__put_user() return values
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/include/asm/io.h | 24 | ||||
-rw-r--r-- | arch/arm/include/asm/thread_info.h | 8 | ||||
-rw-r--r-- | arch/arm/kernel/entry-common.S | 8 | ||||
-rw-r--r-- | arch/arm/kernel/ptrace.c | 3 | ||||
-rw-r--r-- | arch/arm/kernel/signal.c | 85 | ||||
-rw-r--r-- | arch/arm/kernel/signal.h | 2 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/neponset.c | 1 |
8 files changed, 44 insertions, 89 deletions
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 9af5563dd3eb..815c669fec0a 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -47,9 +47,9 @@ extern void __raw_readsb(const void __iomem *addr, void *data, int bytelen); extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen); extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); -#define __raw_writeb(v,a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a) = (v)) -#define __raw_writew(v,a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v)) -#define __raw_writel(v,a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v)) +#define __raw_writeb(v,a) ((void)(__chk_io_ptr(a), *(volatile unsigned char __force *)(a) = (v))) +#define __raw_writew(v,a) ((void)(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v))) +#define __raw_writel(v,a) ((void)(__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v))) #define __raw_readb(a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a)) #define __raw_readw(a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a)) @@ -229,11 +229,9 @@ extern void _memset_io(volatile void __iomem *, int, size_t); #define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \ __raw_readl(c)); __r; }) -#define writeb_relaxed(v,c) ((void)__raw_writeb(v,c)) -#define writew_relaxed(v,c) ((void)__raw_writew((__force u16) \ - cpu_to_le16(v),c)) -#define writel_relaxed(v,c) ((void)__raw_writel((__force u32) \ - cpu_to_le32(v),c)) +#define writeb_relaxed(v,c) __raw_writeb(v,c) +#define writew_relaxed(v,c) __raw_writew((__force u16) cpu_to_le16(v),c) +#define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c) #define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; }) #define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; }) @@ -281,12 +279,12 @@ extern void _memset_io(volatile void __iomem *, int, size_t); #define ioread16be(p) ({ unsigned int __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; }) #define ioread32be(p) ({ unsigned int __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; }) -#define iowrite8(v,p) ({ __iowmb(); (void)__raw_writeb(v, p); }) -#define iowrite16(v,p) ({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_le16(v), p); }) -#define iowrite32(v,p) ({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_le32(v), p); }) +#define iowrite8(v,p) ({ __iowmb(); __raw_writeb(v, p); }) +#define iowrite16(v,p) ({ __iowmb(); __raw_writew((__force __u16)cpu_to_le16(v), p); }) +#define iowrite32(v,p) ({ __iowmb(); __raw_writel((__force __u32)cpu_to_le32(v), p); }) -#define iowrite16be(v,p) ({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_be16(v), p); }) -#define iowrite32be(v,p) ({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_be32(v), p); }) +#define iowrite16be(v,p) ({ __iowmb(); __raw_writew((__force __u16)cpu_to_be16(v), p); }) +#define iowrite32be(v,p) ({ __iowmb(); __raw_writel((__force __u32)cpu_to_be32(v), p); }) #define ioread8_rep(p,d,c) __raw_readsb(p,d,c) #define ioread16_rep(p,d,c) __raw_readsw(p,d,c) diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index 68388eb4946b..b79f8e97f775 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -148,6 +148,7 @@ 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 */ @@ -162,16 +163,17 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT) -#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) #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) +#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ + _TIF_SYSCALL_RESTARTSYS) /* * Change these and you break ASM code in entry-common.S */ -#define _TIF_WORK_MASK 0x000000ff +#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_RESUME) #endif /* __KERNEL__ */ #endif /* __ASM_ARM_THREAD_INFO_H */ diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 7bd2d3cb8957..4afed88d250a 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -53,9 +53,13 @@ fast_work_pending: work_pending: tst r1, #_TIF_NEED_RESCHED bne work_resched - tst r1, #_TIF_SIGPENDING|_TIF_NOTIFY_RESUME - beq no_work_pending + /* + * TIF_SIGPENDING or TIF_NOTIFY_RESUME must've been set if we got here + */ + ldr r2, [sp, #S_PSR] mov r0, sp @ 'regs' + tst r2, #15 @ are we returning to user mode? + bne no_work_pending @ no? just leave, then... mov r2, why @ 'syscall' tst r1, #_TIF_SIGPENDING @ delivering a signal? movne why, #0 @ prevent further restarts diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 14e38261cd31..5700a7ae7f0b 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -25,6 +25,7 @@ #include <linux/regset.h> #include <linux/audit.h> #include <linux/tracehook.h> +#include <linux/unistd.h> #include <asm/pgtable.h> #include <asm/traps.h> @@ -917,6 +918,8 @@ 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 4e5fdd9bd9e3..17fc36c41cff 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -29,7 +29,6 @@ */ #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. @@ -50,18 +49,6 @@ const unsigned long sigreturn_codes[7] = { }; /* - * 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. */ asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask) @@ -82,10 +69,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, old_sigset_t mask; if (!access_ok(VERIFY_READ, act, sizeof(*act)) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags) || + __get_user(mask, &act->sa_mask)) return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); siginitset(&new_ka.sa.sa_mask, mask); } @@ -94,10 +81,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, if (!ret && oact) { if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } return ret; @@ -602,15 +589,6 @@ static void do_signal(struct pt_regs *regs, int syscall) int signr; /* - * We want the common case to go fast, which - * is why we may in certain cases get here from - * kernel mode. Just return without doing anything - * if so. - */ - if (!user_mode(regs)) - return; - - /* * If we were from a system call, check for system call restarting... */ if (syscall) { @@ -626,18 +604,13 @@ 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; } } - if (try_to_freeze()) - goto no_signal; - /* * Get the signal to deliver. When running under ptrace, at this * point the debugger may change all our registers ... @@ -652,12 +625,14 @@ 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 + if (retval == -ERESTARTNOHAND || + retval == -ERESTART_RESTARTBLOCK || (retval == -ERESTARTSYS && !(ka.sa.sa_flags & SA_RESTART))) { regs->ARM_r0 = -EINTR; regs->ARM_pc = continue_addr; } + clear_thread_flag(TIF_SYSCALL_RESTARTSYS); } if (test_thread_flag(TIF_RESTORE_SIGMASK)) @@ -677,7 +652,6 @@ static void do_signal(struct pt_regs *regs, int syscall) return; } - no_signal: if (syscall) { /* * Handle restarting a different system call. As above, @@ -685,38 +659,15 @@ static void do_signal(struct pt_regs *regs, int syscall) * ignore the restart. */ if (retval == -ERESTART_RESTARTBLOCK - && 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 - } - } - - /* If there's no signal to deliver, we just put the saved sigmask - * back. - */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); - } + && regs->ARM_pc == restart_addr) + set_thread_flag(TIF_SYSCALL_RESTARTSYS); } + + /* If there's no signal to deliver, we just put the saved sigmask + * back. + */ + if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) + set_current_blocked(¤t->saved_sigmask); } asmlinkage void diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h index 6fcfe8398aa4..5ff067b7c752 100644 --- a/arch/arm/kernel/signal.h +++ b/arch/arm/kernel/signal.h @@ -8,7 +8,5 @@ * 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 3647170e9a16..4928d89758f4 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -820,8 +820,6 @@ 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-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c index 6c58f01b358a..266db873a4e4 100644 --- a/arch/arm/mach-sa1100/neponset.c +++ b/arch/arm/mach-sa1100/neponset.c @@ -89,6 +89,7 @@ void neponset_ncr_frob(unsigned int mask, unsigned int val) WARN(1, "nep_base unset\n"); } } +EXPORT_SYMBOL(neponset_ncr_frob); static void neponset_set_mctrl(struct uart_port *port, u_int mctrl) { |