mips: add o32_fp64 boot param to disable FP64 support
diff mbox series

Message ID 20200528231628.120171-1-syq@debian.org
State New
Headers show
Series
  • mips: add o32_fp64 boot param to disable FP64 support
Related show

Commit Message

YunQiang Su May 28, 2020, 11:16 p.m. UTC
When build with CONFIG_O32_FP64_SUPPORTS, even all of the userland
is FPXX, we cannot run any FP32 binary.

Then we need to disable FP64 support temporarily with a boot param:
   o32_fp64=no/disable

Signed-off-by: YunQiang Su <syq@debian.org>
---
 arch/mips/include/asm/abi.h |  2 ++
 arch/mips/include/asm/elf.h |  4 +++-
 arch/mips/kernel/elf.c      |  5 +++--
 arch/mips/kernel/process.c  |  2 +-
 arch/mips/kernel/setup.c    | 15 +++++++++++++++
 arch/mips/math-emu/cp1emu.c |  3 ++-
 6 files changed, 26 insertions(+), 5 deletions(-)

Comments

Thomas Bogendoerfer May 29, 2020, 11:09 a.m. UTC | #1
On Fri, May 29, 2020 at 07:16:28AM +0800, YunQiang Su wrote:
> When build with CONFIG_O32_FP64_SUPPORTS, even all of the userland
> is FPXX, we cannot run any FP32 binary.

I don't understand what this means. Can you explain what the problem
is ? 

> Then we need to disable FP64 support temporarily with a boot param:
>    o32_fp64=no/disable

A boot parameter should IMHO be last resort. But I need to understand
the problem first to think about different ways to solve this.

Thomas.
YunQiang Su May 29, 2020, 2:26 p.m. UTC | #2
Thomas Bogendoerfer <tsbogend@alpha.franken.de> 于2020年5月29日周五 下午7:09写道:
>
> On Fri, May 29, 2020 at 07:16:28AM +0800, YunQiang Su wrote:
> > When build with CONFIG_O32_FP64_SUPPORTS, even all of the userland
> > is FPXX, we cannot run any FP32 binary.
>
> I don't understand what this means. Can you explain what the problem
> is ?
>

Some or most CPU cannot run FP32 application if
CONFIG_O32_FP64_SUPPORTS is enabled.
So we switch the whole Debian archive to FPXX. But the golang cannot
support FP32 now.

So I wish provides a way to support FP32 and FP64 with a single kernel image.

> > Then we need to disable FP64 support temporarily with a boot param:
> >    o32_fp64=no/disable
>
> A boot parameter should IMHO be last resort. But I need to understand
> the problem first to think about different ways to solve this.
>

Yes, I guess that we have a better solution, but I have no idea how to:
   1. switch by /sys or /proc ?
   2. support per-process mode switch.

I think that the 2) should be better.

https://web.archive.org/web/20180828210612/https://dmz-
portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking




> Thomas.
>
> --
> Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
> good idea.                                                [ RFC1925, 2.3 ]
Maciej W. Rozycki June 4, 2020, 12:19 a.m. UTC | #3
On Fri, 29 May 2020, YunQiang Su wrote:

> > > When build with CONFIG_O32_FP64_SUPPORTS, even all of the userland
> > > is FPXX, we cannot run any FP32 binary.
> >
> > I don't understand what this means. Can you explain what the problem
> > is ?
> >
> 
> Some or most CPU cannot run FP32 application if
> CONFIG_O32_FP64_SUPPORTS is enabled.
> So we switch the whole Debian archive to FPXX. But the golang cannot
> support FP32 now.
> 
> So I wish provides a way to support FP32 and FP64 with a single kernel image.

 Well, FP32 and FP64 (and FPXX) are per-program attributes set in the ELF 
headers of o32 binaries and CP0.Status.FR is a per-process property.  At 
program execution an FP64-enabled kernel will set CP0.Status.FR in the 
program's user context according to the FP32/FP64 setting in the program's 
ELF structures, or fail if hardware does not support the requested mode.  

 The FPXX hybrid mode is there to permit running with either CP0.Status.FR 
setting, by tightening the FP ABI and forbidding the use of some code that 
is allowed with both FP32 and FP64.  This mode also permits the use of 
either FP32 or FP64 modules (but not both at a time) in dynamic loading, 
by switching CP0.Status.FR accordingly as long as supported by the piece 
of hardware being run on.

 If you have software that only supports a certain FPxx setting, then 
build it accordingly and the kernel will do the rest.  If the setting 
required is not compatible with what hardware supports, then you can't run 
your software on your hardware, and if you override the checks by patching 
the kernel, then you'll get incorrect results.

 So what problem are you trying to solve?  Why do you need FP32 support if 
all your software is FPXX (which will run with any CP0.Status.FR setting), 
and why does Go have issues (what kind of issues?) with any particular 
FPxx setting given that it uses the same MIPS backend as all the other 
language frontends do?

  Maciej
YunQiang Su June 11, 2020, 4:54 a.m. UTC | #4
Maciej W. Rozycki <macro@wdc.com> 于2020年6月4日周四 上午8:19写道:
>
> On Fri, 29 May 2020, YunQiang Su wrote:
>
> > > > When build with CONFIG_O32_FP64_SUPPORTS, even all of the userland
> > > > is FPXX, we cannot run any FP32 binary.
> > >
> > > I don't understand what this means. Can you explain what the problem
> > > is ?
> > >
> >
> > Some or most CPU cannot run FP32 application if
> > CONFIG_O32_FP64_SUPPORTS is enabled.
> > So we switch the whole Debian archive to FPXX. But the golang cannot
> > support FP32 now.
> >
> > So I wish provides a way to support FP32 and FP64 with a single kernel image.
>
>  Well, FP32 and FP64 (and FPXX) are per-program attributes set in the ELF
> headers of o32 binaries and CP0.Status.FR is a per-process property.  At
> program execution an FP64-enabled kernel will set CP0.Status.FR in the
> program's user context according to the FP32/FP64 setting in the program's
> ELF structures, or fail if hardware does not support the requested mode.

Yes. It is a bug of golang. It is FP32 while claims that it is FPXX,
due to it use gcc,
while doesn't pass -mfp32 to it.

https://go-review.googlesource.com/c/go/+/237058

>
>  The FPXX hybrid mode is there to permit running with either CP0.Status.FR
> setting, by tightening the FP ABI and forbidding the use of some code that
> is allowed with both FP32 and FP64.  This mode also permits the use of
> either FP32 or FP64 modules (but not both at a time) in dynamic loading,
> by switching CP0.Status.FR accordingly as long as supported by the piece
> of hardware being run on.
>
>  If you have software that only supports a certain FPxx setting, then
> build it accordingly and the kernel will do the rest.  If the setting
> required is not compatible with what hardware supports, then you can't run
> your software on your hardware, and if you override the checks by patching
> the kernel, then you'll get incorrect results.
>
>  So what problem are you trying to solve?  Why do you need FP32 support if

The problem is that I enabled CONFIG_O32_FP64_SUPPORT for Debian buster
while now golang cannot work with it.

I don't want to switch it off again, by instead, I *was* preferring to
provides a
boot-time option for sysadmin. So I can keep this option open, and the
kernel of DSA (debian official sysadmin) can turn it off on boot-time.

> all your software is FPXX (which will run with any CP0.Status.FR setting),
> and why does Go have issues (what kind of issues?) with any particular
> FPxx setting given that it uses the same MIPS backend as all the other
> language frontends do?
>
>   Maciej

Patch
diff mbox series

diff --git a/arch/mips/include/asm/abi.h b/arch/mips/include/asm/abi.h
index dba7f4b6bebf..c5d297c67a9c 100644
--- a/arch/mips/include/asm/abi.h
+++ b/arch/mips/include/asm/abi.h
@@ -29,4 +29,6 @@  struct mips_abi {
 	struct mips_vdso_image *vdso;
 };
 
+extern bool o32_fp64_support;
+
 #endif /* _ASM_ABI_H */
diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index 5aa29ced6970..dc55815923b5 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -15,6 +15,7 @@ 
 #include <uapi/linux/elf.h>
 
 #include <asm/current.h>
+#include <asm/abi.h>
 
 /* ELF header e_flags defines. */
 /* MIPS architecture level. */
@@ -293,7 +294,8 @@  void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs);
 	if (((__h->e_flags & EF_MIPS_ABI) != 0) &&			\
 	    ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32))		\
 		__res = 0;						\
-	if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO)		\
+	if ((__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO) &&		\
+	    !o32_fp64_support)						\
 		__res = 0;						\
 									\
 	__res;								\
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c
index 7b045d2a0b51..3de15308971c 100644
--- a/arch/mips/kernel/elf.c
+++ b/arch/mips/kernel/elf.c
@@ -11,6 +11,7 @@ 
 
 #include <asm/cpu-features.h>
 #include <asm/cpu-info.h>
+#include <asm/abi.h>
 
 #ifdef CONFIG_MIPS_FP_SUPPORT
 
@@ -176,7 +177,7 @@  int arch_check_elf(void *_ehdr, bool has_interpreter, void *_interp_ehdr,
 			return -ELIBBAD;
 	}
 
-	if (!IS_ENABLED(CONFIG_MIPS_O32_FP64_SUPPORT))
+	if (!o32_fp64_support)
 		return 0;
 
 	fp_abi = state->fp_abi;
@@ -282,7 +283,7 @@  void mips_set_personality_fp(struct arch_elf_state *state)
 	 * not be worried about N32/N64 binaries.
 	 */
 
-	if (!IS_ENABLED(CONFIG_MIPS_O32_FP64_SUPPORT))
+	if (!o32_fp64_support)
 		return;
 
 	switch (state->overall_fp_mode) {
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index ff5320b79100..1bb93941c4c1 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -760,7 +760,7 @@  int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
 		return 0;
 
 	/* Only accept a mode change if 64-bit FP enabled for o32.  */
-	if (!IS_ENABLED(CONFIG_MIPS_O32_FP64_SUPPORT))
+	if (!o32_fp64_support)
 		return -EOPNOTSUPP;
 
 	/* And only for o32 tasks.  */
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 7b537fa2035d..2475843487aa 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -484,6 +484,21 @@  static int __init early_parse_elfcorehdr(char *p)
 early_param("elfcorehdr", early_parse_elfcorehdr);
 #endif
 
+#ifdef CONFIG_MIPS_O32_FP64_SUPPORT
+bool o32_fp64_support __read_mostly = true;
+static int __init early_parse_o32_fp64(char *p)
+{
+	if (strncmp(p, "no", 2) == 0 ||
+	    strncmp(p, "disable", 7) == 0
+	    strncmp(p, "off", 3) == 0)
+		o32_fp64_support = false;
+	return 0;
+}
+early_param("o32_fp64", early_parse_o32_fp64);
+#else
+bool o32_fp64_support __read_mostly;
+#endif
+
 #ifdef CONFIG_KEXEC
 static void __init mips_parse_crashkernel(void)
 {
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 587cf1d115e8..54d7a5122137 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -33,6 +33,7 @@ 
 #include <linux/uaccess.h>
 
 #include <asm/cpu-info.h>
+#include <asm/abi.h>
 #include <asm/processor.h>
 #include <asm/fpu_emulator.h>
 #include <asm/fpu.h>
@@ -784,7 +785,7 @@  static inline int cop1_64bit(struct pt_regs *xcp)
 	if (IS_ENABLED(CONFIG_64BIT) && !IS_ENABLED(CONFIG_MIPS32_O32))
 		return 1;
 	else if (IS_ENABLED(CONFIG_32BIT) &&
-		 !IS_ENABLED(CONFIG_MIPS_O32_FP64_SUPPORT))
+		 !o32_fp64_support)
 		return 0;
 
 	return !test_thread_flag(TIF_32BIT_FPREGS);