summaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/elf.c
diff options
context:
space:
mode:
authorMaciej W. Rozycki2015-11-13 01:48:02 +0100
committerRalf Baechle2016-01-20 00:39:20 +0100
commit2b5e869ecfcb3112f7e1267cb0328f3ff6d49b18 (patch)
tree668568711a9ffbd41ad288bb038ec851a59a58c7 /arch/mips/kernel/elf.c
parentELF: Also pass any interpreter's file header to `arch_check_elf' (diff)
downloadkernel-qcow2-linux-2b5e869ecfcb3112f7e1267cb0328f3ff6d49b18.tar.gz
kernel-qcow2-linux-2b5e869ecfcb3112f7e1267cb0328f3ff6d49b18.tar.xz
kernel-qcow2-linux-2b5e869ecfcb3112f7e1267cb0328f3ff6d49b18.zip
MIPS: ELF: Interpret the NAN2008 file header flag
Handle the EF_MIPS_NAN2008 ELF file header flag and refuse execution where there is no support in the FPU for the NaN encoding mode requested by a binary invoked. Ensure that the setting of the bit in the binary matches one in any intepreter used. Set the thread's initial FCSR contents according to the value of the EF_MIPS_NAN2008. Set the values of the FCSR ABS2008 and NAN2008 bits both to the same value if possible, to take the approach taken with existing FPU hardware into account. As of now all implementations have both bits hardwired to the same value, that is both are fixed at 0 or both are fixed at 1, even though the architecture allows for implementations where the amount of control implemented with each of these two individual bits is independent of each other. Signed-off-by: Maciej W. Rozycki <macro@imgtec.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Matthew Fortune <Matthew.Fortune@imgtec.com> Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11479/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/elf.c')
-rw-r--r--arch/mips/kernel/elf.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c
index 7d1a90903e4b..f36a261b275c 100644
--- a/arch/mips/kernel/elf.c
+++ b/arch/mips/kernel/elf.c
@@ -11,6 +11,8 @@
#include <linux/elf.h>
#include <linux/sched.h>
+#include <asm/cpu-info.h>
+
/* FPU modes */
enum {
FP_FRE,
@@ -135,6 +137,10 @@ int arch_check_elf(void *_ehdr, bool has_interpreter, void *_interp_ehdr,
struct elf32_hdr e32;
struct elf64_hdr e64;
} *ehdr = _ehdr;
+ union {
+ struct elf32_hdr e32;
+ struct elf64_hdr e64;
+ } *iehdr = _interp_ehdr;
struct mode_req prog_req, interp_req;
int fp_abi, interp_fp_abi, abi0, abi1, max_abi;
bool elf32;
@@ -143,6 +149,32 @@ int arch_check_elf(void *_ehdr, bool has_interpreter, void *_interp_ehdr,
elf32 = ehdr->e32.e_ident[EI_CLASS] == ELFCLASS32;
flags = elf32 ? ehdr->e32.e_flags : ehdr->e64.e_flags;
+ /*
+ * Determine the NaN personality, reject the binary if no hardware
+ * support. Also ensure that any interpreter matches the executable.
+ */
+ if (flags & EF_MIPS_NAN2008) {
+ if (cpu_has_nan_2008)
+ state->nan_2008 = 1;
+ else
+ return -ENOEXEC;
+ } else {
+ if (cpu_has_nan_legacy)
+ state->nan_2008 = 0;
+ else
+ return -ENOEXEC;
+ }
+ if (has_interpreter) {
+ bool ielf32;
+ u32 iflags;
+
+ ielf32 = iehdr->e32.e_ident[EI_CLASS] == ELFCLASS32;
+ iflags = ielf32 ? iehdr->e32.e_flags : iehdr->e64.e_flags;
+
+ if ((flags ^ iflags) & EF_MIPS_NAN2008)
+ return -ELIBBAD;
+ }
+
if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
return 0;
@@ -266,3 +298,27 @@ void mips_set_personality_fp(struct arch_elf_state *state)
BUG();
}
}
+
+/*
+ * Select the IEEE 754 NaN encoding and ABS.fmt/NEG.fmt execution mode
+ * in FCSR according to the ELF NaN personality.
+ */
+void mips_set_personality_nan(struct arch_elf_state *state)
+{
+ struct cpuinfo_mips *c = &boot_cpu_data;
+ struct task_struct *t = current;
+
+ t->thread.fpu.fcr31 = c->fpu_csr31;
+ switch (state->nan_2008) {
+ case 0:
+ break;
+ case 1:
+ if (!(c->fpu_msk31 & FPU_CSR_NAN2008))
+ t->thread.fpu.fcr31 |= FPU_CSR_NAN2008;
+ if (!(c->fpu_msk31 & FPU_CSR_ABS2008))
+ t->thread.fpu.fcr31 |= FPU_CSR_ABS2008;
+ break;
+ default:
+ BUG();
+ }
+}