Skip to content

Commit

Permalink
ARM: 9044/1: vfp: use undef hook for VFP support detection
Browse files Browse the repository at this point in the history
[ Upstream commit 3cce9d4 ]

Commit f77ac2e ("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.

Fixes: f77ac2e ("ARM: 9030/1: entry: omit FP emulation for UND ...")
Reported-by: "kernelci.org bot" <bot@kernelci.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
ardbiesheuvel authored and gregkh committed Dec 30, 2020
1 parent 3f27cb2 commit bf7b8c1
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 22 deletions.
17 changes: 0 additions & 17 deletions arch/arm/vfp/entry.S
Expand Up @@ -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
25 changes: 20 additions & 5 deletions arch/arm/vfp/vfpmodule.c
Expand Up @@ -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);

Expand All @@ -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 __initdata VFP_arch;

/*
* The pointer to the vfpstate structure of the thread which currently
Expand Down Expand Up @@ -437,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__);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
*/
Expand All @@ -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: ");
Expand Down

0 comments on commit bf7b8c1

Please sign in to comment.