Skip to content

Commit 59649de

Browse files
FlyGoattsbogend
authored andcommitted
MIPS: Implement ieee754 NAN2008 emulation mode
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]>
1 parent 9c7a86c commit 59649de

File tree

4 files changed

+30
-2
lines changed

4 files changed

+30
-2
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2022,7 +2022,7 @@
20222022
for the device. By default it is set to false (0).
20232023

20242024
ieee754= [MIPS] Select IEEE Std 754 conformance mode
2025-
Format: { strict | legacy | 2008 | relaxed }
2025+
Format: { strict | legacy | 2008 | relaxed | emulated }
20262026
Default: strict
20272027

20282028
Choose which programs will be accepted for execution
@@ -2042,6 +2042,8 @@
20422042
by the FPU
20432043
relaxed accept any binaries regardless of whether
20442044
supported by the FPU
2045+
emulated accept any binaries but enable FPU emulator
2046+
if binary mode is unsupported by the FPU.
20452047

20462048
The FPU emulator is always able to support both NaN
20472049
encodings, so if no FPU hardware is present or it has

arch/mips/include/asm/fpu.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,18 @@ static inline int __own_fpu(void)
129129
if (ret)
130130
return ret;
131131

132+
if (current->thread.fpu.fcr31 & FPU_CSR_NAN2008) {
133+
if (!cpu_has_nan_2008) {
134+
ret = SIGFPE;
135+
goto failed;
136+
}
137+
} else {
138+
if (!cpu_has_nan_legacy) {
139+
ret = SIGFPE;
140+
goto failed;
141+
}
142+
}
143+
132144
KSTK_STATUS(current) |= ST0_CU1;
133145
if (mode == FPU_64BIT || mode == FPU_HYBRID)
134146
KSTK_STATUS(current) |= ST0_FR;
@@ -137,6 +149,9 @@ static inline int __own_fpu(void)
137149

138150
set_thread_flag(TIF_USEDFPU);
139151
return 0;
152+
failed:
153+
__disable_fpu();
154+
return ret;
140155
}
141156

142157
static inline int own_fpu_inatomic(int restore)

arch/mips/kernel/elf.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,10 @@ void mips_set_personality_nan(struct arch_elf_state *state)
318318
t->thread.fpu.fcr31 = c->fpu_csr31;
319319
switch (state->nan_2008) {
320320
case 0:
321+
if (!(c->fpu_msk31 & FPU_CSR_NAN2008))
322+
t->thread.fpu.fcr31 &= ~FPU_CSR_NAN2008;
323+
if (!(c->fpu_msk31 & FPU_CSR_ABS2008))
324+
t->thread.fpu.fcr31 &= ~FPU_CSR_ABS2008;
321325
break;
322326
case 1:
323327
if (!(c->fpu_msk31 & FPU_CSR_NAN2008))

arch/mips/kernel/fpu-probe.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ static void cpu_set_fpu_2008(struct cpuinfo_mips *c)
144144
* IEEE 754 conformance mode to use. Affects the NaN encoding and the
145145
* ABS.fmt/NEG.fmt execution mode.
146146
*/
147-
static enum { STRICT, LEGACY, STD2008, RELAXED } ieee754 = STRICT;
147+
static enum { STRICT, EMULATED, LEGACY, STD2008, RELAXED } ieee754 = STRICT;
148148

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

161161
switch (ieee754) {
162162
case STRICT:
163+
case EMULATED:
163164
if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
164165
MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
165166
MIPS_CPU_ISA_M32R5 | MIPS_CPU_ISA_M64R5 |
@@ -204,6 +205,10 @@ static void cpu_set_nan_2008(struct cpuinfo_mips *c)
204205
mips_use_nan_legacy = !cpu_has_nan_2008;
205206
mips_use_nan_2008 = !!cpu_has_nan_2008;
206207
break;
208+
case EMULATED:
209+
/* Pretend ABS2008/NAN2008 options are dynamic */
210+
c->fpu_msk31 &= ~(FPU_CSR_NAN2008 | FPU_CSR_ABS2008);
211+
fallthrough;
207212
case RELAXED:
208213
mips_use_nan_legacy = true;
209214
mips_use_nan_2008 = true;
@@ -226,6 +231,8 @@ static int __init ieee754_setup(char *s)
226231
return -1;
227232
else if (!strcmp(s, "strict"))
228233
ieee754 = STRICT;
234+
else if (!strcmp(s, "emulated"))
235+
ieee754 = EMULATED;
229236
else if (!strcmp(s, "legacy"))
230237
ieee754 = LEGACY;
231238
else if (!strcmp(s, "2008"))

0 commit comments

Comments
 (0)