OpenWrt – Rev 1

Subversion Repositories:
Rev:
From:   Manuel Lauss <manuel.lauss@gmail.com>
Subject: [RFC PATCH v4 2/2] MIPS: make FPU emulator optional

This small patch makes the MIPS FPU emulator optional. The kernel
kills float-users on systems without a hardware FPU by sending a SIGILL.

Disabling the emulator shrinks vmlinux by about 54kBytes (32bit,
optimizing for size).

Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com>
---
v4: rediffed because of patch 1/2, should now work with micromips as well
v3: updated patch description with size savings.
v2: incorporated changes suggested by Jonas Gorski
    force the fpu emulator on for micromips: relocating the parts
    of the mmips code in the emulator to other areas would be a
    much larger change; I went the cheap route instead with this.

 arch/mips/Kbuild                     |  2 +-
 arch/mips/Kconfig                    | 14 ++++++++++++++
 arch/mips/include/asm/fpu.h          |  5 +++--
 arch/mips/include/asm/fpu_emulator.h | 15 +++++++++++++++
 4 files changed, 33 insertions(+), 3 deletions(-)

--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2892,6 +2892,20 @@ config MIPS_O32_FP64_SUPPORT
 
          If unsure, say N.
 
+config MIPS_FPU_EMULATOR
+       bool "MIPS FPU Emulator"
+       default y
+       help
+         This option lets you disable the built-in MIPS FPU (Coprocessor 1)
+         emulator, which handles floating-point instructions on processors
+         without a hardware FPU.  It is generally a good idea to keep the
+         emulator built-in, unless you are perfectly sure you have a
+         complete soft-float environment.  With the emulator disabled, all
+         users of float operations will be killed with an illegal instr-
+         uction exception.
+
+         Say Y, please.
+
 config USE_OF
        bool
        select OF
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -322,7 +322,7 @@ OBJCOPYFLAGS                += --remove-section=.regin
 head-y := arch/mips/kernel/head.o
 
 libs-y                 += arch/mips/lib/
-libs-y                 += arch/mips/math-emu/
+libs-$(CONFIG_MIPS_FPU_EMULATOR)       += arch/mips/math-emu/
 
 # See arch/mips/Kbuild for content of core part of the kernel
 core-y += arch/mips/
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -230,8 +230,10 @@ static inline int init_fpu(void)
                /* Restore FRE */
                write_c0_config5(config5);
                enable_fpu_hazard();
-       } else
+       } else if (IS_ENABLED(CONFIG_MIPS_FPU_EMULATOR))
                fpu_emulator_init_fpu();
+       else
+               ret = SIGILL;
 
        return ret;
 }
--- a/arch/mips/include/asm/fpu_emulator.h
+++ b/arch/mips/include/asm/fpu_emulator.h
@@ -30,6 +30,7 @@
 #include <asm/local.h>
 #include <asm/processor.h>
 
+#ifdef CONFIG_MIPS_FPU_EMULATOR
 #ifdef CONFIG_DEBUG_FS
 
 struct mips_fpu_emulator_stats {
@@ -179,6 +180,16 @@ do {                                                                       \
 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
                                    struct mips_fpu_struct *ctx, int has_fpu,
                                    void __user **fault_addr);
+#else  /* no CONFIG_MIPS_FPU_EMULATOR */
+static inline int fpu_emulator_cop1Handler(struct pt_regs *xcp,
+                               struct mips_fpu_struct *ctx, int has_fpu,
+                               void __user **fault_addr)
+{
+       *fault_addr = NULL;
+       return SIGILL;  /* we don't speak MIPS FPU */
+}
+#endif /* CONFIG_MIPS_FPU_EMULATOR */
+
 void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr,
                     struct task_struct *tsk);
 int process_fpemu_return(int sig, void __user *fault_addr,
--- a/arch/mips/include/asm/dsemul.h
+++ b/arch/mips/include/asm/dsemul.h
@@ -41,6 +41,7 @@ struct task_struct;
 extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir,
                       unsigned long branch_pc, unsigned long cont_pc);
 
+#ifdef CONFIG_MIPS_FPU_EMULATOR
 /**
  * do_dsemulret() - Return from a delay slot 'emulation' frame
  * @xcp:       User thread register context.
@@ -88,5 +89,27 @@ extern bool dsemul_thread_rollback(struc
  * before @mm is freed in order to avoid memory leaks.
  */
 extern void dsemul_mm_cleanup(struct mm_struct *mm);
+#else
+static inline bool do_dsemulret(struct pt_regs *xcp)
+{
+       return false;
+}
+
+static inline bool dsemul_thread_cleanup(struct task_struct *tsk)
+{
+       return false;
+}
+
+static inline bool dsemul_thread_rollback(struct pt_regs *regs)
+{
+       return false;
+}
+
+static inline void dsemul_mm_cleanup(struct mm_struct *mm)
+{
+
+}
+
+#endif
 
 #endif /* __MIPS_ASM_DSEMUL_H__ */