Include the new stack frame inside the user access block and set it up
using unsafe_put_user().

On an mpc 8321 (book3s/32) the improvment is about 4% on a process
sending a signal to itself.

Signed-off-by: Christophe Leroy <christophe.le...@csgroup.eu>
---
 arch/powerpc/kernel/signal_32.c | 29 +++++++++++++----------------
 arch/powerpc/kernel/signal_64.c | 14 +++++++-------
 2 files changed, 20 insertions(+), 23 deletions(-)

diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 0608581967f0..ff101e2b3bab 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -726,7 +726,7 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t 
*oldset,
        struct rt_sigframe __user *frame;
        struct mcontext __user *mctx;
        struct mcontext __user *tm_mctx = NULL;
-       unsigned long newsp = 0;
+       unsigned long __user *newsp;
        unsigned long tramp;
        struct pt_regs *regs = tsk->thread.regs;
        /* Save the thread's msr before get_tm_stackpointer() changes it */
@@ -734,6 +734,7 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t 
*oldset,
 
        /* Set up Signal Frame */
        frame = get_sigframe(ksig, tsk, sizeof(*frame), 1);
+       newsp = (unsigned long __user *)((unsigned long)frame - 
(__SIGNAL_FRAMESIZE + 16));
        mctx = &frame->uc.uc_mcontext;
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        tm_mctx = &frame->uc_transact.uc_mcontext;
@@ -743,7 +744,7 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t 
*oldset,
        else
                prepare_save_user_regs(1);
 
-       if (!user_access_begin(frame, sizeof(*frame)))
+       if (!user_access_begin(newsp, __SIGNAL_FRAMESIZE + 16 + sizeof(*frame)))
                goto badframe;
 
        /* Put the siginfo & fill in most of the ucontext */
@@ -779,6 +780,9 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t 
*oldset,
        }
        unsafe_put_sigset_t(&frame->uc.uc_sigmask, oldset, failed);
 
+       /* create a stack frame for the caller of the handler */
+       unsafe_put_user(regs->gpr[1], newsp, failed);
+
        user_access_end();
 
        if (copy_siginfo_to_user(&frame->info, &ksig->info))
@@ -790,13 +794,8 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t 
*oldset,
        tsk->thread.fp_state.fpscr = 0; /* turn off all fp exceptions */
 #endif
 
-       /* create a stack frame for the caller of the handler */
-       newsp = ((unsigned long)frame) - (__SIGNAL_FRAMESIZE + 16);
-       if (put_user(regs->gpr[1], (u32 __user *)newsp))
-               goto badframe;
-
        /* Fill registers for signal handler */
-       regs->gpr[1] = newsp;
+       regs->gpr[1] = (unsigned long)newsp;
        regs->gpr[3] = ksig->sig;
        regs->gpr[4] = (unsigned long)&frame->info;
        regs->gpr[5] = (unsigned long)&frame->uc;
@@ -826,7 +825,7 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
        struct sigframe __user *frame;
        struct mcontext __user *mctx;
        struct mcontext __user *tm_mctx = NULL;
-       unsigned long newsp = 0;
+       unsigned long __user *newsp;
        unsigned long tramp;
        struct pt_regs *regs = tsk->thread.regs;
        /* Save the thread's msr before get_tm_stackpointer() changes it */
@@ -834,6 +833,7 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
 
        /* Set up Signal Frame */
        frame = get_sigframe(ksig, tsk, sizeof(*frame), 1);
+       newsp = (unsigned long __user *)((unsigned long)frame - 
__SIGNAL_FRAMESIZE);
        mctx = &frame->mctx;
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        tm_mctx = &frame->mctx_transact;
@@ -843,7 +843,7 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
        else
                prepare_save_user_regs(1);
 
-       if (!user_access_begin(frame, sizeof(*frame)))
+       if (!user_access_begin(newsp, __SIGNAL_FRAMESIZE + sizeof(*frame)))
                goto badframe;
        sc = (struct sigcontext __user *) &frame->sctx;
 
@@ -873,6 +873,8 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
                unsafe_put_user(PPC_RAW_SC(), &mctx->mc_pad[1], failed);
                asm("dcbst %y0; sync; icbi %y0; sync" :: "Z" (mctx->mc_pad[0]));
        }
+       /* create a stack frame for the caller of the handler */
+       unsafe_put_user(regs->gpr[1], newsp, failed);
        user_access_end();
 
        regs->link = tramp;
@@ -881,12 +883,7 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
        tsk->thread.fp_state.fpscr = 0; /* turn off all fp exceptions */
 #endif
 
-       /* create a stack frame for the caller of the handler */
-       newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
-       if (put_user(regs->gpr[1], (u32 __user *)newsp))
-               goto badframe;
-
-       regs->gpr[1] = newsp;
+       regs->gpr[1] = (unsigned long)newsp;
        regs->gpr[3] = ksig->sig;
        regs->gpr[4] = (unsigned long) sc;
        regs_set_return_ip(regs, (unsigned long) ksig->ka.sa.sa_handler);
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 7b1cd50bc4fb..d80ff83cacb9 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -847,13 +847,14 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t 
*set,
                struct task_struct *tsk)
 {
        struct rt_sigframe __user *frame;
-       unsigned long newsp = 0;
+       unsigned long __user *newsp;
        long err = 0;
        struct pt_regs *regs = tsk->thread.regs;
        /* Save the thread's msr before get_tm_stackpointer() changes it */
        unsigned long msr = regs->msr;
 
        frame = get_sigframe(ksig, tsk, sizeof(*frame), 0);
+       newsp = (unsigned long __user *)((unsigned long)frame - 
__SIGNAL_FRAMESIZE);
 
        /*
         * This only applies when calling unsafe_setup_sigcontext() and must be
@@ -862,7 +863,7 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
        if (!MSR_TM_ACTIVE(msr))
                prepare_setup_sigcontext(tsk);
 
-       if (!user_write_access_begin(frame, sizeof(*frame)))
+       if (!user_write_access_begin(newsp, __SIGNAL_FRAMESIZE + 
sizeof(*frame)))
                goto badframe;
 
        unsafe_put_user(&frame->info, &frame->pinfo, badframe_block);
@@ -900,6 +901,9 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
        }
 
        unsafe_copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set), 
badframe_block);
+       /* Allocate a dummy caller frame for the signal handler. */
+       unsafe_put_user(regs->gpr[1], newsp, badframe_block);
+
        user_write_access_end();
 
        /* Save the siginfo outside of the unsafe block. */
@@ -919,10 +923,6 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
                regs_set_return_ip(regs, (unsigned long) &frame->tramp[0]);
        }
 
-       /* Allocate a dummy caller frame for the signal handler. */
-       newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
-       err |= put_user(regs->gpr[1], (unsigned long __user *)newsp);
-
        /* Set up "regs" so we "return" to the signal handler. */
        if (is_elf2_task()) {
                regs->ctr = (unsigned long) ksig->ka.sa.sa_handler;
@@ -947,7 +947,7 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
 
        /* enter the signal handler in native-endian mode */
        regs_set_return_msr(regs, (regs->msr & ~MSR_LE) | (MSR_KERNEL & 
MSR_LE));
-       regs->gpr[1] = newsp;
+       regs->gpr[1] = (unsigned long)newsp;
        regs->gpr[3] = ksig->sig;
        regs->result = 0;
        if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
-- 
2.31.1

Reply via email to