Benjamin Herrenschmidt <[email protected]> writes:

> On Thu, 2016-07-07 at 23:21 +1000, Benjamin Herrenschmidt wrote:
>> 
>> I think the right fix is that if a restore_sigcontext() has the MSR
>> bits set,
>> it should set the corresponding used_* flag.
>
> Something like this:
>
> (totally untested)

Simon/Laurent, can you guys test this and let me know if it works for
your usecase.

Cyril, can you give this a review, you've been touching this code the
most lately.

cheers

> diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
> index b6aa378..1bf074e 100644
> --- a/arch/powerpc/kernel/signal_32.c
> +++ b/arch/powerpc/kernel/signal_32.c
> @@ -698,6 +698,7 @@ static long restore_user_regs(struct pt_regs *regs,
>               if (__copy_from_user(&current->thread.vr_state, &sr->mc_vregs,
>                                    sizeof(sr->mc_vregs)))
>                       return 1;
> +             current->thread.used_vr = true;
>       } else if (current->thread.used_vr)
>               memset(&current->thread.vr_state, 0,
>                      ELF_NVRREG * sizeof(vector128));
> @@ -724,6 +725,7 @@ static long restore_user_regs(struct pt_regs *regs,
>                */
>               if (copy_vsx_from_user(current, &sr->mc_vsregs))
>                       return 1;
> +             current->thread.used_vsr = true;
>       } else if (current->thread.used_vsr)
>               for (i = 0; i < 32 ; i++)
>                       current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0;
> @@ -743,6 +745,7 @@ static long restore_user_regs(struct pt_regs *regs,
>               if (__copy_from_user(current->thread.evr, &sr->mc_vregs,
>                                    ELF_NEVRREG * sizeof(u32)))
>                       return 1;
> +             current->thread.used_spe = true;
>       } else if (current->thread.used_spe)
>               memset(current->thread.evr, 0, ELF_NEVRREG * sizeof(u32));
>  
> @@ -799,6 +802,7 @@ static long restore_tm_user_regs(struct pt_regs *regs,
>                                    &tm_sr->mc_vregs,
>                                    sizeof(sr->mc_vregs)))
>                       return 1;
> +             current->thread.used_vr = true;
>       } else if (current->thread.used_vr) {
>               memset(&current->thread.vr_state, 0,
>                      ELF_NVRREG * sizeof(vector128));
> @@ -832,6 +836,7 @@ static long restore_tm_user_regs(struct pt_regs *regs,
>               if (copy_vsx_from_user(current, &sr->mc_vsregs) ||
>                   copy_transact_vsx_from_user(current, &tm_sr->mc_vsregs))
>                       return 1;
> +             current->thread.used_vsr = true;
>       } else if (current->thread.used_vsr)
>               for (i = 0; i < 32 ; i++) {
>                       current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0;
> @@ -848,6 +853,7 @@ static long restore_tm_user_regs(struct pt_regs *regs,
>               if (__copy_from_user(current->thread.evr, &sr->mc_vregs,
>                                    ELF_NEVRREG * sizeof(u32)))
>                       return 1;
> +             current->thread.used_spe = true;
>       } else if (current->thread.used_spe)
>               memset(current->thread.evr, 0, ELF_NEVRREG * sizeof(u32));
>  
> diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
> index 2552079..8704269 100644
> --- a/arch/powerpc/kernel/signal_64.c
> +++ b/arch/powerpc/kernel/signal_64.c
> @@ -363,9 +363,11 @@ static long restore_sigcontext(struct pt_regs *regs, 
> sigset_t *set, int sig,
>       if (v_regs && !access_ok(VERIFY_READ, v_regs, 34 * sizeof(vector128)))
>               return -EFAULT;
>       /* Copy 33 vec registers (vr0..31 and vscr) from the stack */
> -     if (v_regs != NULL && (msr & MSR_VEC) != 0)
> +     if (v_regs != NULL && (msr & MSR_VEC) != 0) {
>               err |= __copy_from_user(&current->thread.vr_state, v_regs,
>                                       33 * sizeof(vector128));
> +             current->thread.used_vr = true;
> +     }
>       else if (current->thread.used_vr)
>               memset(&current->thread.vr_state, 0, 33 * sizeof(vector128));
>       /* Always get VRSAVE back */
> @@ -385,9 +387,10 @@ static long restore_sigcontext(struct pt_regs *regs, 
> sigset_t *set, int sig,
>        * buffer for formatting, then into the taskstruct.
>        */
>       v_regs += ELF_NVRREG;
> -     if ((msr & MSR_VSX) != 0)
> +     if ((msr & MSR_VSX) != 0) {
>               err |= copy_vsx_from_user(current, v_regs);
> -     else
> +             current->thread.used_vsr = true;
> +     } else
>               for (i = 0; i < 32 ; i++)
>                       current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0;
>  #endif
> @@ -482,6 +485,7 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
>                                       33 * sizeof(vector128));
>               err |= __copy_from_user(&current->thread.transact_vr, tm_v_regs,
>                                       33 * sizeof(vector128));
> +             current->thread.used_vr = true;
>       }
>       else if (current->thread.used_vr) {
>               memset(&current->thread.vr_state, 0, 33 * sizeof(vector128));
> @@ -515,6 +519,7 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
>               tm_v_regs += ELF_NVRREG;
>               err |= copy_vsx_from_user(current, v_regs);
>               err |= copy_transact_vsx_from_user(current, tm_v_regs);
> +             current->thread.used_vsr = true;
>       } else {
>               for (i = 0; i < 32 ; i++) {
>                       current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0;
_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to