aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/signal_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/signal_64.c')
-rw-r--r--arch/powerpc/kernel/signal_64.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index c2db642f4cdd..6e75d7ab6d4d 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -141,9 +141,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
141 unsigned long err = 0; 141 unsigned long err = 0;
142 unsigned long save_r13 = 0; 142 unsigned long save_r13 = 0;
143 elf_greg_t *gregs = (elf_greg_t *)regs; 143 elf_greg_t *gregs = (elf_greg_t *)regs;
144#ifdef CONFIG_ALTIVEC
145 unsigned long msr; 144 unsigned long msr;
146#endif
147 int i; 145 int i;
148 146
149 /* If this is not a signal return, we preserve the TLS in r13 */ 147 /* If this is not a signal return, we preserve the TLS in r13 */
@@ -154,7 +152,12 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
154 err |= __copy_from_user(regs, &sc->gp_regs, 152 err |= __copy_from_user(regs, &sc->gp_regs,
155 PT_MSR*sizeof(unsigned long)); 153 PT_MSR*sizeof(unsigned long));
156 154
157 /* skip MSR and SOFTE */ 155 /* get MSR separately, transfer the LE bit if doing signal return */
156 err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
157 if (sig)
158 regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE);
159
160 /* skip SOFTE */
158 for (i = PT_MSR+1; i <= PT_RESULT; i++) { 161 for (i = PT_MSR+1; i <= PT_RESULT; i++) {
159 if (i == PT_SOFTE) 162 if (i == PT_SOFTE)
160 continue; 163 continue;
@@ -179,7 +182,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
179 182
180#ifdef CONFIG_ALTIVEC 183#ifdef CONFIG_ALTIVEC
181 err |= __get_user(v_regs, &sc->v_regs); 184 err |= __get_user(v_regs, &sc->v_regs);
182 err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
183 if (err) 185 if (err)
184 return err; 186 return err;
185 if (v_regs && !access_ok(VERIFY_READ, v_regs, 34 * sizeof(vector128))) 187 if (v_regs && !access_ok(VERIFY_READ, v_regs, 34 * sizeof(vector128)))
@@ -396,8 +398,8 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
396 current->thread.fpscr.val = 0; 398 current->thread.fpscr.val = 0;
397 399
398 /* Set up to return from userspace. */ 400 /* Set up to return from userspace. */
399 if (vdso64_rt_sigtramp && current->thread.vdso_base) { 401 if (vdso64_rt_sigtramp && current->mm->context.vdso_base) {
400 regs->link = current->thread.vdso_base + vdso64_rt_sigtramp; 402 regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp;
401 } else { 403 } else {
402 err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); 404 err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
403 if (err) 405 if (err)
@@ -412,6 +414,8 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
412 414
413 /* Set up "regs" so we "return" to the signal handler. */ 415 /* Set up "regs" so we "return" to the signal handler. */
414 err |= get_user(regs->nip, &funct_desc_ptr->entry); 416 err |= get_user(regs->nip, &funct_desc_ptr->entry);
417 /* enter the signal handler in big-endian mode */
418 regs->msr &= ~MSR_LE;
415 regs->gpr[1] = newsp; 419 regs->gpr[1] = newsp;
416 err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); 420 err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
417 regs->gpr[3] = signr; 421 regs->gpr[3] = signr;