Subject: [PATCH v2 4/4] ARM: vfp: clear fpscr length and stride bits on entry to sig handler

From: [email-masked] (Dave Martin)
Date: Mon, 30 Jan 2012 17:07:03 +0000

On Mon, Jan 30, 2012 at 11:24:55AM +0000, Will Deacon wrote:
> The ARM PCS mandates that the length and stride bits of the fpscr are
> cleared on entry to and return from a public interface. Although signal
> handlers run asynchronously with respect to the interrupted function,
> the handler itself expects to run as though it has been called like a
> normal function.
> 
> This patch updates the state mirroring the VFP hardware before entry to
> a signal handler so that it adheres to the PCS. Furthermore, we disable
> VFP to ensure that we trap on any floating point operation performed by
> the signal handler and synchronise the hardware appropriately. A check
> is inserted after the signal handler to avoid redundant flushing if VFP
> was not used.

Hmmm, that looks more like it.  I've not tried this out, but it looks
sensible.

Ignore my stale comments on your previous post.

Cheers
---Dave

> 
> Reported-by: Peter Maydell <[email-masked]>
> Signed-off-by: Will Deacon <[email-masked]>
> ---
>  arch/arm/kernel/signal.c |   17 ++++++++++++++++-
>  1 files changed, 16 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
> index 9e617bd..3de59a0 100644
> --- a/arch/arm/kernel/signal.c
> +++ b/arch/arm/kernel/signal.c
> @@ -207,6 +207,20 @@ static int preserve_vfp_context(struct vfp_sigframe __user *frame)
>  	__put_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
>  	__put_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
>  
> +	vfp_flush_hwstate(thread);
> +
> +	/*
> +	 * As per the PCS, clear the length and stride bits before entry
> +	 * to the signal handler.
> +	 */
> +	h->fpscr &= ~(FPSCR_LENGTH_MASK | FPSCR_STRIDE_MASK);
> +
> +	/*
> +	 * Disable VFP so that we can detect if it was used by the
> +	 * signal handler.
> +	 */
> +	h->fpexc &= ~FPEXC_EN;
> +
>  	return err ? -EFAULT : 0;
>  }
>  
> @@ -227,7 +241,8 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame)
>  	if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
>  		return -EINVAL;
>  
> -	vfp_flush_hwstate(thread);
> +	if (h->fpexc & FPEXC_EN)
> +		vfp_flush_hwstate(thread);
>  
>  	/*
>  	 * Copy the floating point registers. There can be unused
> -- 
> 1.7.4.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel