diff options
Diffstat (limited to 'arch/powerpc/kernel/signal_64.c')
-rw-r--r-- | arch/powerpc/kernel/signal_64.c | 16 |
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; |