Skip to content

Commit

Permalink
BACKPORT: MIPS: Implement ieee754 NAN2008 emulation mode
Browse files Browse the repository at this point in the history
Implement ieee754 NAN2008 emulation mode.

When this mode is enabled, kernel will accept ELF file
compiled for both NaN 2008 and NaN legacy, but if hardware
does not have capability to match ELF's NaN mode, __own_fpu
will fail for corresponding thread and fpuemu will then kick
in.

This mode trade performance for correctness, while maintaining
support for both NaN mode regardless of hardware capability.
It is useful for multilib installation that have both types
of binary exist in system.

Reviewed-by: Philippe Mathieu-Daudé <[email protected]>
Signed-off-by: Jiaxun Yang <[email protected]>
Signed-off-by: Thomas Bogendoerfer <[email protected]>
  • Loading branch information
FlyGoat authored and opsiff committed Dec 25, 2024
1 parent c7a0793 commit 9d22d8e
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 2 deletions.
4 changes: 3 additions & 1 deletion Documentation/admin-guide/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1933,7 +1933,7 @@
for the device. By default it is set to false (0).

ieee754= [MIPS] Select IEEE Std 754 conformance mode
Format: { strict | legacy | 2008 | relaxed }
Format: { strict | legacy | 2008 | relaxed | emulated }
Default: strict

Choose which programs will be accepted for execution
Expand All @@ -1953,6 +1953,8 @@
by the FPU
relaxed accept any binaries regardless of whether
supported by the FPU
emulated accept any binaries but enable FPU emulator
if binary mode is unsupported by the FPU.

The FPU emulator is always able to support both NaN
encodings, so if no FPU hardware is present or it has
Expand Down
15 changes: 15 additions & 0 deletions arch/mips/include/asm/fpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,18 @@ static inline int __own_fpu(void)
if (ret)
return ret;

if (current->thread.fpu.fcr31 & FPU_CSR_NAN2008) {
if (!cpu_has_nan_2008) {
ret = SIGFPE;
goto failed;
}
} else {
if (!cpu_has_nan_legacy) {
ret = SIGFPE;
goto failed;
}
}

KSTK_STATUS(current) |= ST0_CU1;
if (mode == FPU_64BIT || mode == FPU_HYBRID)
KSTK_STATUS(current) |= ST0_FR;
Expand All @@ -137,6 +149,9 @@ static inline int __own_fpu(void)

set_thread_flag(TIF_USEDFPU);
return 0;
failed:
__disable_fpu();
return ret;
}

static inline int own_fpu_inatomic(int restore)
Expand Down
4 changes: 4 additions & 0 deletions arch/mips/kernel/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,10 @@ void mips_set_personality_nan(struct arch_elf_state *state)
t->thread.fpu.fcr31 = c->fpu_csr31;
switch (state->nan_2008) {
case 0:
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;
case 1:
if (!(c->fpu_msk31 & FPU_CSR_NAN2008))
Expand Down
9 changes: 8 additions & 1 deletion arch/mips/kernel/fpu-probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ static void cpu_set_fpu_2008(struct cpuinfo_mips *c)
* IEEE 754 conformance mode to use. Affects the NaN encoding and the
* ABS.fmt/NEG.fmt execution mode.
*/
static enum { STRICT, LEGACY, STD2008, RELAXED } ieee754 = STRICT;
static enum { STRICT, EMULATED, LEGACY, STD2008, RELAXED } ieee754 = STRICT;

/*
* Set the IEEE 754 NaN encodings and the ABS.fmt/NEG.fmt execution modes
Expand All @@ -160,6 +160,7 @@ static void cpu_set_nofpu_2008(struct cpuinfo_mips *c)

switch (ieee754) {
case STRICT:
case EMULATED:
if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
MIPS_CPU_ISA_M32R5 | MIPS_CPU_ISA_M64R5 |
Expand Down Expand Up @@ -204,6 +205,10 @@ static void cpu_set_nan_2008(struct cpuinfo_mips *c)
mips_use_nan_legacy = !cpu_has_nan_2008;
mips_use_nan_2008 = !!cpu_has_nan_2008;
break;
case EMULATED:
/* Pretend ABS2008/NAN2008 options are dynamic */
c->fpu_msk31 &= ~(FPU_CSR_NAN2008 | FPU_CSR_ABS2008);
fallthrough;
case RELAXED:
mips_use_nan_legacy = true;
mips_use_nan_2008 = true;
Expand All @@ -226,6 +231,8 @@ static int __init ieee754_setup(char *s)
return -1;
else if (!strcmp(s, "strict"))
ieee754 = STRICT;
else if (!strcmp(s, "emulated"))
ieee754 = EMULATED;
else if (!strcmp(s, "legacy"))
ieee754 = LEGACY;
else if (!strcmp(s, "2008"))
Expand Down

0 comments on commit 9d22d8e

Please sign in to comment.