From 4a9d32d377e1facca204cc1c6856406be8b53fa3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 23 Dec 2012 03:08:53 -0500 Subject: microblaze: switch to generic sigaltstack Signed-off-by: Al Viro --- arch/microblaze/Kconfig | 1 + arch/microblaze/kernel/signal.c | 17 ++--------------- 2 files changed, 3 insertions(+), 15 deletions(-) (limited to 'arch/microblaze') diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index ba3b7c8c04b8..5e30d75c74ed 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -27,6 +27,7 @@ config MICROBLAZE select GENERIC_CLOCKEVENTS select MODULES_USE_ELF_RELA select CLONE_BACKWARDS + select GENERIC_SIGALTSTACK config SWAP def_bool n diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index ac3d0a0f4814..dfd61e2f1189 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -41,13 +41,6 @@ #include #include -asmlinkage long -sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, - struct pt_regs *regs) -{ - return do_sigaltstack(uss, uoss, regs->r1); -} - /* * Do a signal return; undo the signal stack. */ @@ -109,9 +102,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval)) goto badframe; - /* It is more difficult to avoid calling this function than to - call it and ignore errors. */ - if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->r1) == -EFAULT) + if (restore_altstack(&frame->uc.uc_stack)) goto badframe; return rval; @@ -194,11 +185,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(NULL, &frame->uc.uc_link); - err |= __put_user((void __user *)current->sas_ss_sp, - &frame->uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->r1), - &frame->uc.uc_stack.ss_flags); - err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= __save_altstack(&frame->uc.uc_stack, regs->r1); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); -- cgit v1.2.3 From c886a9fc1f69c0e53788a9c4a780b6b8825bd4ab Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 29 Apr 2012 03:35:29 -0400 Subject: microblaze: evict the check for kernel_mode(regs) from do_notify_resume() Only one caller hasn't done it in assembler - work_pending on !MMU. Everything else can't reach do_notify_resume() if we are returning to kernel mode, so move that check to that sole caller and make do_notify_resume() reachable only when returning to userland. Signed-off-by: Al Viro --- arch/microblaze/kernel/entry-nommu.S | 3 +++ arch/microblaze/kernel/signal.c | 9 --------- 2 files changed, 3 insertions(+), 9 deletions(-) (limited to 'arch/microblaze') diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 70da83a49670..29a05d62ec1a 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S @@ -482,6 +482,8 @@ ENTRY(ret_from_kernel_thread) addk r3, r0, r0 work_pending: + lwi r11, r1, PT_MODE + bneid r11, 2f enable_irq andi r11, r19, _TIF_NEED_RESCHED @@ -507,6 +509,7 @@ ENTRY(ret_to_user) no_work_pending: disable_irq +2: /* save r31 */ swi r31, r0, PER_CPU(CURRENT_SAVE) /* save mode indicator */ diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index dfd61e2f1189..9f7a8bde0686 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -343,15 +343,6 @@ static void do_signal(struct pt_regs *regs, int in_syscall) asmlinkage void do_notify_resume(struct pt_regs *regs, int in_syscall) { - /* - * 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 (kernel_mode(regs)) - return; - if (test_thread_flag(TIF_SIGPENDING)) do_signal(regs, in_syscall); -- cgit v1.2.3 From 14203e19cbc562a79f49117c45c80639a1e65bdd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 29 Apr 2012 04:11:34 -0400 Subject: microblaze: fix the horror with restarts of sigreturn() solution a-la arm one - pick a callee-saved register (r30), set it non-zero when entering a syscall, have sigreturn wrapper zero it out and pass the value in it to do_notify_resume() as "in_syscall" (actually, "restarts allowed") argument. Note that we don't give a damn about ret_from_fork() - return value is not restart-worthy anyway. Possible remaining bug: on !MMU we still have _debug_exception() restartable. If it hits with -ERESTART_... accidentally in r3, fun happens. MMU does _not_ have _debug_exception() restartable. If that's decided to be a bug (as I strongly suspect it to be), we'll just need to replace setting r30 to 1 with setting r30 to 0 in !MMU _debug_exception(). Up to microblaze maintainers... [folded a fix from Michal] Signed-off-by: Al Viro --- arch/microblaze/kernel/entry-nommu.S | 5 ++++- arch/microblaze/kernel/entry.S | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'arch/microblaze') diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 29a05d62ec1a..96f97f845495 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S @@ -280,6 +280,7 @@ ENTRY(_user_exception) /* Figure out which function to use for this system call. */ /* Note Microblaze barrel shift is optional, so don't rely on it */ add r12, r12, r12 /* convert num -> ptr */ + addik r30, r0, 1 /* restarts allowed */ add r12, r12, r12 lwi r12, r12, sys_call_table /* Get function pointer */ addik r15, r0, ret_to_user-8 /* set return address */ @@ -369,6 +370,7 @@ ENTRY(_debug_exception) bralid r15, send_sig add r7, r0, r0 /* 3rd param zero */ + addik r30, r0, 1 /* restarts allowed ??? */ /* Restore r3/r4 to work around how ret_to_user works */ lwi r3, r1, PT_R3 lwi r4, r1, PT_R4 @@ -492,7 +494,7 @@ work_pending: nop 1: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME beqi r11, no_work_pending - addk r5, r1, r0 + addk r5, r30, r0 bralid r15, do_notify_resume addik r6, r0, 1 bri no_work_pending @@ -562,6 +564,7 @@ no_work_pending: nop sys_rt_sigreturn_wrapper: + addk r30, r0, r0 /* no restarts for this one */ brid sys_rt_sigreturn addk r5, r1, r0 diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index c217367dfc7b..18908d29248b 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -353,6 +353,7 @@ C_ENTRY(_user_exception): /* Figure out which function to use for this system call. */ /* Note Microblaze barrel shift is optional, so don't rely on it */ add r12, r12, r12; /* convert num -> ptr */ + addi r30, r0, 1 /* restarts allowed */ add r12, r12, r12; #ifdef DEBUG @@ -417,7 +418,7 @@ C_ENTRY(ret_from_trap): addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ bralid r15, do_notify_resume; /* Handle any signals */ - addi r6, r0, 1; /* Arg 2: int in_syscall */ + add r6, r30, r0; /* Arg 2: int in_syscall */ /* Finally, return to user state. */ 1: set_bip; /* Ints masked for state restore */ @@ -464,6 +465,7 @@ C_ENTRY(ret_from_kernel_thread): add r3, r0, r0 C_ENTRY(sys_rt_sigreturn_wrapper): + addik r30, r0, 0 /* no restarts */ brid sys_rt_sigreturn /* Do real work */ addik r5, r1, 0; /* add user context as 1st arg */ -- cgit v1.2.3 From e9f9252667e383c0ccfd3570b358ccb72cd51359 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 29 Apr 2012 04:43:50 -0400 Subject: microblaze: fix handling of multiple pending signals We need to keep building sigframes until no pending signals remain. Wrap do_notify_resume() calls into loops; do _not_ allow syscall restart logics to trigger after the first iteration. Incidentally, comments about pending signals that should (somehow) be in r18 are pure BS. Doesn't work that way and cannot work that way, sorry... Signed-off-by: Al Viro --- arch/microblaze/kernel/entry-nommu.S | 13 ++++++-- arch/microblaze/kernel/entry.S | 58 +++++++++++++++++++----------------- 2 files changed, 42 insertions(+), 29 deletions(-) (limited to 'arch/microblaze') diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 96f97f845495..7e394fc2c439 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S @@ -124,6 +124,7 @@ ret_from_intr: lwi r11, r1, PT_MODE bneid r11, no_intr_resched +3: lwi r6, r31, TS_THREAD_INFO /* get thread info */ lwi r19, r6, TI_FLAGS /* get flags in thread info */ /* do an extra work if any bits are set */ @@ -132,11 +133,13 @@ ret_from_intr: beqi r11, 1f bralid r15, schedule nop + bri 3b 1: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME beqid r11, no_intr_resched addk r5, r1, r0 bralid r15, do_notify_resume addk r6, r0, r0 + bri 3b no_intr_resched: /* Disable interrupts, we are now committed to the state restore */ @@ -486,18 +489,24 @@ ENTRY(ret_from_kernel_thread) work_pending: lwi r11, r1, PT_MODE bneid r11, 2f +3: enable_irq - andi r11, r19, _TIF_NEED_RESCHED beqi r11, 1f bralid r15, schedule nop + bri 4f 1: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME beqi r11, no_work_pending addk r5, r30, r0 bralid r15, do_notify_resume addik r6, r0, 1 - bri no_work_pending + addk r30, r0, r0 /* no restarts from now on */ +4: + disable_irq + lwi r6, r31, TS_THREAD_INFO /* get thread info */ + lwi r19, r6, TI_FLAGS /* get flags in thread info */ + bri 3b ENTRY(ret_to_user) disable_irq diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 18908d29248b..85b6b5d80c99 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -402,26 +402,27 @@ C_ENTRY(ret_from_trap): * trigger rescheduling. */ /* get thread info from current task */ lwi r11, CURRENT_TASK, TS_THREAD_INFO; - lwi r11, r11, TI_FLAGS; /* get flags in thread info */ - andi r11, r11, _TIF_NEED_RESCHED; + lwi r19, r11, TI_FLAGS; /* get flags in thread info */ + andi r11, r19, _TIF_NEED_RESCHED; beqi r11, 5f; bralid r15, schedule; /* Call scheduler */ nop; /* delay slot */ + bri 1b /* Maybe handle a signal */ -5: /* get thread info from current task*/ - lwi r11, CURRENT_TASK, TS_THREAD_INFO; - lwi r11, r11, TI_FLAGS; /* get flags in thread info */ - andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; - beqi r11, 1f; /* Signals to handle, handle them */ +5: + andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; + beqi r11, 4f; /* Signals to handle, handle them */ addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ bralid r15, do_notify_resume; /* Handle any signals */ add r6, r30, r0; /* Arg 2: int in_syscall */ + add r30, r0, r0 /* no more restarts */ + bri 1b /* Finally, return to user state. */ -1: set_bip; /* Ints masked for state restore */ +4: set_bip; /* Ints masked for state restore */ swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ VM_OFF; tophys(r1,r1); @@ -573,20 +574,20 @@ C_ENTRY(ret_from_exc): /* We're returning to user mode, so check for various conditions that trigger rescheduling. */ +1: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ - lwi r11, r11, TI_FLAGS; /* get flags in thread info */ - andi r11, r11, _TIF_NEED_RESCHED; + lwi r19, r11, TI_FLAGS; /* get flags in thread info */ + andi r11, r19, _TIF_NEED_RESCHED; beqi r11, 5f; /* Call the scheduler before returning from a syscall/trap. */ bralid r15, schedule; /* Call scheduler */ nop; /* delay slot */ + bri 1b /* Maybe handle a signal */ -5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ - lwi r11, r11, TI_FLAGS; /* get flags in thread info */ - andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; - beqi r11, 1f; /* Signals to handle, handle them */ +5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; + beqi r11, 4f; /* Signals to handle, handle them */ /* * Handle a signal return; Pending signals should be in r18. @@ -602,9 +603,10 @@ C_ENTRY(ret_from_exc): addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ bralid r15, do_notify_resume; /* Handle any signals */ addi r6, r0, 0; /* Arg 2: int in_syscall */ + bri 1b /* Finally, return to user state. */ -1: set_bip; /* Ints masked for state restore */ +4: set_bip; /* Ints masked for state restore */ swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ VM_OFF; tophys(r1,r1); @@ -684,22 +686,23 @@ ret_from_irq: lwi r11, r1, PT_MODE; bnei r11, 2f; +1: lwi r11, CURRENT_TASK, TS_THREAD_INFO; - lwi r11, r11, TI_FLAGS; /* MS: get flags from thread info */ - andi r11, r11, _TIF_NEED_RESCHED; + lwi r19, r11, TI_FLAGS; /* MS: get flags from thread info */ + andi r11, r19, _TIF_NEED_RESCHED; beqi r11, 5f bralid r15, schedule; nop; /* delay slot */ + bri 1b /* Maybe handle a signal */ -5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get thread info */ - lwi r11, r11, TI_FLAGS; /* get flags in thread info */ - andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; +5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; beqid r11, no_intr_resched /* Handle a signal return; Pending signals should be in r18. */ addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ bralid r15, do_notify_resume; /* Handle any signals */ addi r6, r0, 0; /* Arg 2: int in_syscall */ + bri 1b /* Finally, return to user state. */ no_intr_resched: @@ -817,28 +820,29 @@ dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */ lwi r11, r1, PT_MODE; bnei r11, 2f; /* MS: Return to user space - gdb */ +1: /* Get current task ptr into r11 */ lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ - lwi r11, r11, TI_FLAGS; /* get flags in thread info */ - andi r11, r11, _TIF_NEED_RESCHED; + lwi r19, r11, TI_FLAGS; /* get flags in thread info */ + andi r11, r19, _TIF_NEED_RESCHED; beqi r11, 5f; /* Call the scheduler before returning from a syscall/trap. */ bralid r15, schedule; /* Call scheduler */ nop; /* delay slot */ + bri 1b /* Maybe handle a signal */ -5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ - lwi r11, r11, TI_FLAGS; /* get flags in thread info */ - andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; - beqi r11, 1f; /* Signals to handle, handle them */ +5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; + beqi r11, 4f; /* Signals to handle, handle them */ addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ bralid r15, do_notify_resume; /* Handle any signals */ addi r6, r0, 0; /* Arg 2: int in_syscall */ + bri 1b /* Finally, return to user state. */ -1: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ +4: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ VM_OFF; tophys(r1,r1); /* MS: Restore all regs */ -- cgit v1.2.3 From 4de6ba68c9f52a361c89ea16c9c55eda2669253b Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 17 Sep 2012 11:18:24 +0200 Subject: microblaze: Move restart allowed out of block Better not to break block which do work together. Signed-off-by: Michal Simek Signed-off-by: Al Viro --- arch/microblaze/kernel/entry.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/microblaze') diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 85b6b5d80c99..0536bc021cc6 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -353,8 +353,8 @@ C_ENTRY(_user_exception): /* Figure out which function to use for this system call. */ /* Note Microblaze barrel shift is optional, so don't rely on it */ add r12, r12, r12; /* convert num -> ptr */ - addi r30, r0, 1 /* restarts allowed */ add r12, r12, r12; + addi r30, r0, 1 /* restarts allowed */ #ifdef DEBUG /* Trac syscalls and stored them to syscall_debug_table */ -- cgit v1.2.3 From de2bfce30e1abda837c613d1ed5aaecb648c7e8f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 7 Dec 2012 19:01:58 -0500 Subject: microblaze: remove debris in ptrace.c Signed-off-by: Al Viro --- arch/microblaze/kernel/ptrace.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'arch/microblaze') diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c index ab1b9db661f3..b050219c42e6 100644 --- a/arch/microblaze/kernel/ptrace.c +++ b/arch/microblaze/kernel/ptrace.c @@ -164,29 +164,6 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) tracehook_report_syscall_exit(regs, step); } -#if 0 -static asmlinkage void syscall_trace(void) -{ - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; - if (!(current->ptrace & PT_PTRACED)) - return; - /* The 0x80 provides a way for the tracing parent to distinguish - between a syscall stop and SIGTRAP delivery */ - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } -} -#endif - void ptrace_disable(struct task_struct *child) { /* nothing to do */ -- cgit v1.2.3 From d64008a8f30e0b381b292788ec6f3ee509b3bb40 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 25 Nov 2012 23:12:10 -0500 Subject: burying unused conditionals __ARCH_WANT_SYS_RT_SIGACTION, __ARCH_WANT_SYS_RT_SIGSUSPEND, __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND, __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL - not used anymore CONFIG_GENERIC_{SIGALTSTACK,COMPAT_RT_SIG{ACTION,QUEUEINFO,PENDING,PROCMASK}} - can be assumed always set. --- arch/microblaze/Kconfig | 1 - arch/microblaze/include/asm/unistd.h | 2 -- 2 files changed, 3 deletions(-) (limited to 'arch/microblaze') diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 5e30d75c74ed..ba3b7c8c04b8 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -27,7 +27,6 @@ config MICROBLAZE select GENERIC_CLOCKEVENTS select MODULES_USE_ELF_RELA select CLONE_BACKWARDS - select GENERIC_SIGALTSTACK config SWAP def_bool n diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index 10f8ac186855..b3778391d9cc 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h @@ -33,8 +33,6 @@ #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK -#define __ARCH_WANT_SYS_RT_SIGACTION -#define __ARCH_WANT_SYS_RT_SIGSUSPEND #define __ARCH_WANT_SYS_CLONE #define __ARCH_WANT_SYS_VFORK #define __ARCH_WANT_SYS_FORK -- cgit v1.2.3