All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ARM: vfp: use undef hook for VFP support detection
@ 2020-12-18 15:54 Ard Biesheuvel
  2020-12-18 16:34 ` Ard Biesheuvel
  0 siblings, 1 reply; 2+ messages in thread
From: Ard Biesheuvel @ 2020-12-18 15:54 UTC (permalink / raw)
  To: linux; +Cc: guillaume.tucker, linus.walleij, Ard Biesheuvel, linux-arm-kernel

Commit f77ac2e378be9dd6 ("ARM: 9030/1: entry: omit FP emulation for UND
exceptions taken in kernel mode") failed to take into account that there
is in fact a case where we relied on this code path: during boot, the
VFP detection code issues a read of FPSID, which will trigger an undef
exception on cores that lack VFP support.

So let's reinstate this logic using an undef hook which is registered
only for the duration of the initcall to vpf_init(), and which sets
VFP_arch to a non-zero value - as before - if no VFP support is present.

Reported-by: "kernelci.org bot" <bot@kernelci.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm/vfp/entry.S     | 17 -----------------
 arch/arm/vfp/vfpmodule.c | 23 +++++++++++++++++++----
 2 files changed, 19 insertions(+), 21 deletions(-)

diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
index 0186cf9da890..27b0a1f27fbd 100644
--- a/arch/arm/vfp/entry.S
+++ b/arch/arm/vfp/entry.S
@@ -37,20 +37,3 @@ ENDPROC(vfp_null_entry)
 	.align	2
 .LCvfp:
 	.word	vfp_vector
-
-@ This code is called if the VFP does not exist. It needs to flag the
-@ failure to the VFP initialisation code.
-
-	__INIT
-ENTRY(vfp_testing_entry)
-	dec_preempt_count_ti r10, r4
-	ldr	r0, VFP_arch_address
-	str	r0, [r0]		@ set to non-zero value
-	ret	r9			@ we have handled the fault
-ENDPROC(vfp_testing_entry)
-
-	.align	2
-VFP_arch_address:
-	.word	VFP_arch
-
-	__FINIT
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index c3b6451c18bd..285a1c7e7a3f 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -32,7 +32,6 @@
 /*
  * Our undef handlers (in entry.S)
  */
-asmlinkage void vfp_testing_entry(void);
 asmlinkage void vfp_support_entry(void);
 asmlinkage void vfp_null_entry(void);
 
@@ -43,7 +42,7 @@ asmlinkage void (*vfp_vector)(void) = vfp_null_entry;
  * Used in startup: set to non-zero if VFP checks fail
  * After startup, holds VFP architecture
  */
-unsigned int VFP_arch;
+static unsigned int VFP_arch;
 
 /*
  * The pointer to the vfpstate structure of the thread which currently
@@ -707,7 +706,7 @@ static int __init vfp_kmode_exception_hook_init(void)
 		register_undef_hook(&vfp_kmode_exception_hook[i]);
 	return 0;
 }
-core_initcall(vfp_kmode_exception_hook_init);
+subsys_initcall(vfp_kmode_exception_hook_init);
 
 /*
  * Kernel-side NEON support functions
@@ -753,6 +752,21 @@ EXPORT_SYMBOL(kernel_neon_end);
 
 #endif /* CONFIG_KERNEL_MODE_NEON */
 
+static int __init vfp_detect(struct pt_regs *regs, unsigned int instr)
+{
+	VFP_arch = UINT_MAX;	/* mark as not present */
+	regs->ARM_pc += 4;
+	return 0;
+}
+
+static struct undef_hook vfp_detect_hook __initdata = {
+	.instr_mask	= 0x0c000e00,
+	.instr_val	= 0x0c000a00,
+	.cpsr_mask	= MODE_MASK,
+	.cpsr_val	= SVC_MODE,
+	.fn		= vfp_detect,
+};
+
 /*
  * VFP support code initialisation.
  */
@@ -773,10 +787,11 @@ static int __init vfp_init(void)
 	 * The handler is already setup to just log calls, so
 	 * we just need to read the VFPSID register.
 	 */
-	vfp_vector = vfp_testing_entry;
+	register_undef_hook(&vfp_detect_hook);
 	barrier();
 	vfpsid = fmrx(FPSID);
 	barrier();
+	unregister_undef_hook(&vfp_detect_hook);
 	vfp_vector = vfp_null_entry;
 
 	pr_info("VFP support v0.3: ");
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] ARM: vfp: use undef hook for VFP support detection
  2020-12-18 15:54 [PATCH] ARM: vfp: use undef hook for VFP support detection Ard Biesheuvel
@ 2020-12-18 16:34 ` Ard Biesheuvel
  0 siblings, 0 replies; 2+ messages in thread
From: Ard Biesheuvel @ 2020-12-18 16:34 UTC (permalink / raw)
  To: Russell King; +Cc: Guillaume Tucker, Linus Walleij, Linux ARM

On Fri, 18 Dec 2020 at 16:54, Ard Biesheuvel <ardb@kernel.org> wrote:
>
> Commit f77ac2e378be9dd6 ("ARM: 9030/1: entry: omit FP emulation for UND
> exceptions taken in kernel mode") failed to take into account that there
> is in fact a case where we relied on this code path: during boot, the
> VFP detection code issues a read of FPSID, which will trigger an undef
> exception on cores that lack VFP support.
>
> So let's reinstate this logic using an undef hook which is registered
> only for the duration of the initcall to vpf_init(), and which sets
> VFP_arch to a non-zero value - as before - if no VFP support is present.
>
> Reported-by: "kernelci.org bot" <bot@kernelci.org>
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> ---
>  arch/arm/vfp/entry.S     | 17 -----------------
>  arch/arm/vfp/vfpmodule.c | 23 +++++++++++++++++++----
>  2 files changed, 19 insertions(+), 21 deletions(-)
>
> diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
> index 0186cf9da890..27b0a1f27fbd 100644
> --- a/arch/arm/vfp/entry.S
> +++ b/arch/arm/vfp/entry.S
> @@ -37,20 +37,3 @@ ENDPROC(vfp_null_entry)
>         .align  2
>  .LCvfp:
>         .word   vfp_vector
> -
> -@ This code is called if the VFP does not exist. It needs to flag the
> -@ failure to the VFP initialisation code.
> -
> -       __INIT
> -ENTRY(vfp_testing_entry)
> -       dec_preempt_count_ti r10, r4
> -       ldr     r0, VFP_arch_address
> -       str     r0, [r0]                @ set to non-zero value
> -       ret     r9                      @ we have handled the fault
> -ENDPROC(vfp_testing_entry)
> -
> -       .align  2
> -VFP_arch_address:
> -       .word   VFP_arch
> -
> -       __FINIT
> diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
> index c3b6451c18bd..285a1c7e7a3f 100644
> --- a/arch/arm/vfp/vfpmodule.c
> +++ b/arch/arm/vfp/vfpmodule.c
> @@ -32,7 +32,6 @@
>  /*
>   * Our undef handlers (in entry.S)
>   */
> -asmlinkage void vfp_testing_entry(void);
>  asmlinkage void vfp_support_entry(void);
>  asmlinkage void vfp_null_entry(void);
>
> @@ -43,7 +42,7 @@ asmlinkage void (*vfp_vector)(void) = vfp_null_entry;
>   * Used in startup: set to non-zero if VFP checks fail
>   * After startup, holds VFP architecture
>   */
> -unsigned int VFP_arch;
> +static unsigned int VFP_arch;
>
>  /*
>   * The pointer to the vfpstate structure of the thread which currently
> @@ -707,7 +706,7 @@ static int __init vfp_kmode_exception_hook_init(void)
>                 register_undef_hook(&vfp_kmode_exception_hook[i]);
>         return 0;
>  }
> -core_initcall(vfp_kmode_exception_hook_init);
> +subsys_initcall(vfp_kmode_exception_hook_init);
>
>  /*
>   * Kernel-side NEON support functions
> @@ -753,6 +752,21 @@ EXPORT_SYMBOL(kernel_neon_end);
>
>  #endif /* CONFIG_KERNEL_MODE_NEON */
>
> +static int __init vfp_detect(struct pt_regs *regs, unsigned int instr)
> +{
> +       VFP_arch = UINT_MAX;    /* mark as not present */
> +       regs->ARM_pc += 4;
> +       return 0;
> +}
> +
> +static struct undef_hook vfp_detect_hook __initdata = {
> +       .instr_mask     = 0x0c000e00,
> +       .instr_val      = 0x0c000a00,
> +       .cpsr_mask      = MODE_MASK,
> +       .cpsr_val       = SVC_MODE,
> +       .fn             = vfp_detect,
> +};
> +
>  /*
>   * VFP support code initialisation.
>   */
> @@ -773,10 +787,11 @@ static int __init vfp_init(void)
>          * The handler is already setup to just log calls, so
>          * we just need to read the VFPSID register.
>          */
> -       vfp_vector = vfp_testing_entry;
> +       register_undef_hook(&vfp_detect_hook);
>         barrier();
>         vfpsid = fmrx(FPSID);
>         barrier();
> +       unregister_undef_hook(&vfp_detect_hook);
>         vfp_vector = vfp_null_entry;
>
>         pr_info("VFP support v0.3: ");
> --
> 2.17.1
>

Assuming this patch fixes the issue, and nobody minds, I will fold in
the below before dropping it into the patch system.

diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 285a1c7e7a3f..2cb355c1b5b7 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -42,7 +42,7 @@ asmlinkage void (*vfp_vector)(void) = vfp_null_entry;
  * Used in startup: set to non-zero if VFP checks fail
  * After startup, holds VFP architecture
  */
-static unsigned int VFP_arch;
+static unsigned int __initdata VFP_arch;

 /*
  * The pointer to the vfpstate structure of the thread which currently
@@ -436,7 +436,7 @@ static void vfp_enable(void *unused)
  * present on all CPUs within a SMP complex. Needs to be called prior to
  * vfp_init().
  */
-void vfp_disable(void)
+void __init vfp_disable(void)
 {
        if (VFP_arch) {
                pr_debug("%s: should be called prior to vfp_init\n", __func__);

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-12-18 17:49 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-18 15:54 [PATCH] ARM: vfp: use undef hook for VFP support detection Ard Biesheuvel
2020-12-18 16:34 ` Ard Biesheuvel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.