From: Manuel Lauss 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 --- 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 @@ -2893,6 +2893,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 @@ -323,7 +323,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 #include +#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__ */