Patch "MIPS: fix FP mode selection in lieu of .MIPS.abiflags data" has been added to the 4.0-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
MIPS: fix FP mode selection in lieu of .MIPS.abiflags data
to the 4.0-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
mips-fix-fp-mode-selection-in-lieu-of-.mips.abiflags-data.patch
and it can be found in the queue-4.0 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
620b155034570f577470cf5309f741bac6a6e32bMon Sep 17 00:00:00 2001
From: Paul Burton <[email protected]>
Date: Wed, 6 May 2015 11:52:32 +0100
Subject: MIPS: fix FP mode selection in lieu of .MIPS.abiflags data
From: Paul Burton <[email protected]>
commit 620b155034570f577470cf5309f741bac6a6e32b upstream.
Commit 46490b572544 ("MIPS: kernel: elf: Improve the overall ABI and FPU mode checks") reworked the ELF FP ABI mode selection logic, but when CONFIG_MIPS_O32_FP64_SUPPORT is enabled it breaks the use of binaries which have no PT_MIPS_ABIFLAGS program header & associated .MIPS.abiflags section.
A default mode is selected based upon whether the ELF contains MIPS32 or MIPS64 code, but that selection is made in arch_elf_pt_proc. arch_elf_pt_proc only executes when a PT_MIPS_ABIFLAGS program header is found. If one is not found then arch_elf_pt_proc is never called, and no default overall_fp_mode value is selected. When arch_check_elf is called, both abi0 & abi1 are MIPS_ABI_FP_UNKNOWN which leads to both prog_req & interp_req being set to none_req. none_req matches none of the conditions for mode selection at the end of arch_check_elf, so overall_fp_mode is left untouched. Finally once mips_set_personality_fp is called the BUG() in the default case is then hit & the kernel likely panics.
Fix this by moving the selection of a default overall mode to the start of arch_check_elf, which runs once per ELF executed regardless of whether it has a PT_MIPS_ABIFLAGS program header.
Patchwork: http://patchwork.linux-mips.org/patch/9978/
--- arch/mips/kernel/elf.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-)
arch/mips/kernel/elf.c +17 -15
@@ -76,14 +76,6 @@ int arch_elf_pt_proc(void *_ehdr, void */* Lets see if this is an O32 ELF */ if (ehdr32->e_ident[EI_CLASS ] ==ELFCLASS32 ) { -/* FR = 1 for N32 */ -if (ehdr32->e_flags &EF_MIPS_ABI2 ) - state->overall_fp_mode =FP_FR1 ; -else -/* Set a good default FPU mode for O32 */ - state->overall_fp_mode = cpu_has_mips_r6 ? -FP_FRE :FP_FR0 ; -if (ehdr32->e_flags &EF_MIPS_FP64 ) {/* * Set MIPS_ABI_FP_OLD_64 for EF_MIPS_FP64. We will override it
@@ -104,9 +96,6 @@ int arch_elf_pt_proc(void *_ehdr, void * (char *)&abiflags, sizeof(abiflags)); }else { -/* FR=1 is really the only option for 64-bit */ - state->overall_fp_mode =FP_FR1 ; -if (phdr64->p_type !=PT_MIPS_ABIFLAGS )return 0 ;if (phdr64->p_filesz <sizeof (abiflags))
@@ -147,6 +136,7 @@ int arch_check_elf(void *_ehdr, bool hasstruct elf32_hdr *ehdr = _ehdr;struct mode_req prog_req, interp_req;int fp_abi, interp_fp_abi, abi0, abi1, max_abi; +bool is_mips64;if (!config_enabled (CONFIG_MIPS_O32_FP64_SUPPORT ))return 0 ;
@@ -162,10 +152,22 @@ int arch_check_elf(void *_ehdr, bool has abi0 = abi1 = fp_abi; } -/* ABI limits. O32 = FP_64A, N32/N64 = FP_SOFT */ - max_abi = ((ehdr->e_ident[EI_CLASS ] ==ELFCLASS32 ) && - (!(ehdr->e_flags &EF_MIPS_ABI2 ))) ? -MIPS_ABI_FP_64A :MIPS_ABI_FP_SOFT ; + is_mips64 = (ehdr->e_ident[EI_CLASS ] ==ELFCLASS64 ) || + (ehdr->e_flags &EF_MIPS_ABI2 ); + +if (is_mips64) { +/* MIPS64 code always uses FR=1, thus the default is easy */ + state->overall_fp_mode =FP_FR1 ; + +/* Disallow access to the various FPXX & FP64 ABIs */ + max_abi =MIPS_ABI_FP_SOFT ; + }else { +/* Default to a mode capable of running code expecting FR=0 */ + state->overall_fp_mode = cpu_has_mips_r6 ?FP_FRE :FP_FR0 ; + +/* Allow all ABIs we know about */ + max_abi =MIPS_ABI_FP_64A ; + }if ((abi0 > max_abi && abi0 !=MIPS_ABI_FP_UNKNOWN ) || (abi1 > max_abi && abi1 !=MIPS_ABI_FP_UNKNOWN ))
Patches currently in stable-queue which might be from [email protected] are
queue-4.0/mips-fix-fp-mode-selection-in-lieu-of-.mips.abiflags-data.patch