/branches/18.06.1/target/linux/generic/pending-4.14/304-mips_disable_fpu.patch |
@@ -0,0 +1,137 @@ |
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 |
@@ -2894,6 +2894,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 |
@@ -315,7 +315,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__ */ |