[PATCH] MIPS: Fix MIPS_O32_FP64_SUPPORT for 64bit CPUs before R2

From: Jiaxun Yang
Date: Fri May 19 2023 - 12:30:45 EST


MIPS_O32_FP64_SUPPORT enables possibility of using all 32 FPRs on 32bit
kernel in case CPU implemented FR1. As FR1 is present on all 64bit CPUs
following R4000's priviliged spec, there is no reason to limit such support
to R2+ CPUs.

Fix it by remove architecture reversion conditions in FR1 context switch
code and enable relevant bits in kernel's FIR copy.

Signed-off-by: Jiaxun Yang <jiaxun.yang@xxxxxxxxxxx>
---
arch/mips/include/asm/asmmacro.h | 6 ++----
arch/mips/include/asm/fpu.h | 3 +--
arch/mips/kernel/elf.c | 5 ++---
arch/mips/kernel/fpu-probe.c | 17 +++++++++++++++++
arch/mips/kernel/r4k_fpu.S | 16 ++++++----------
5 files changed, 28 insertions(+), 19 deletions(-)

diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 067a635d3bc8..3e7c19ee6a90 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -130,8 +130,7 @@
.endm

.macro fpu_save_double thread status tmp
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPSR2) || \
- defined(CONFIG_CPU_MIPSR5) || defined(CONFIG_CPU_MIPSR6)
+#if defined(CONFIG_64BIT) || defined(CONFIG_MIPS_O32_FP64_SUPPORT)
sll \tmp, \status, 5
bgez \tmp, 10f
fpu_save_16odd \thread
@@ -189,8 +188,7 @@
.endm

.macro fpu_restore_double thread status tmp
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPSR2) || \
- defined(CONFIG_CPU_MIPSR5) || defined(CONFIG_CPU_MIPSR6)
+#if defined(CONFIG_64BIT) || defined(CONFIG_MIPS_O32_FP64_SUPPORT)
sll \tmp, \status, 5
bgez \tmp, 10f # 16 register mode?

diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index 86310d6e1035..1cd820e79f77 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -71,8 +71,7 @@ static inline int __enable_fpu(enum fpu_mode mode)
goto fr_common;

case FPU_64BIT:
-#if !(defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5) || \
- defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_64BIT))
+#if !(defined(CONFIG_64BIT) || defined(CONFIG_MIPS_O32_FP64_SUPPORT))
/* we only have a 32-bit FPU */
return SIGFPE;
#endif
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c
index 5582a4ca1e9e..0895bc9b5dd7 100644
--- a/arch/mips/kernel/elf.c
+++ b/arch/mips/kernel/elf.c
@@ -250,9 +250,8 @@ int arch_check_elf(void *_ehdr, bool has_interpreter, void *_interp_ehdr,
state->overall_fp_mode = FP_FRE;
else if ((prog_req.fr1 && prog_req.frdefault) ||
(prog_req.single && !prog_req.frdefault))
- /* Make sure 64-bit MIPS III/IV/64R1 will not pick FR1 */
- state->overall_fp_mode = ((raw_current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
- cpu_has_mips_r2_r6) ?
+ /* Make sure CPUs without FR1 will not pick FR1 */
+ state->overall_fp_mode = (raw_current_cpu_data.fpu_id & MIPS_FPIR_F64) ?
FP_FR1 : FP_FR0;
else if (prog_req.fr1)
state->overall_fp_mode = FP_FR1;
diff --git a/arch/mips/kernel/fpu-probe.c b/arch/mips/kernel/fpu-probe.c
index e689d6a83234..383c43e5c86a 100644
--- a/arch/mips/kernel/fpu-probe.c
+++ b/arch/mips/kernel/fpu-probe.c
@@ -289,6 +289,23 @@ void cpu_set_fpu_opts(struct cpuinfo_mips *c)
c->options |= MIPS_CPU_FRE;
}

+ /* Fix up FIR for FPU earlier than R2 */
+ if (!cpu_has_mips_r2_r6) {
+ c->fpu_id |= MIPS_FPIR_S;
+#ifdef CONFIG_CPU_R4K_FPU
+ /* All known R4000 class FPU implemented double */
+ c->fpu_id |= MIPS_FPIR_D;
+#endif
+ if (cpu_has_64bits) {
+ /* Try to enable FR1 */
+ change_c0_status(ST0_FR, ST0_FR);
+ if (read_c0_status() & ST0_FR) {
+ c->fpu_id |= MIPS_FPIR_F64;
+ c->options |= MIPS_CPU_32FPR;
+ }
+ }
+ }
+
cpu_set_fpu_fcsr_mask(c);
cpu_set_fpu_2008(c);
cpu_set_nan_2008(c);
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index 4e8c98517d9d..eeef115fc39e 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -40,8 +40,7 @@
*/
LEAF(_save_fp)
EXPORT_SYMBOL(_save_fp)
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPSR2) || \
- defined(CONFIG_CPU_MIPSR5) || defined(CONFIG_CPU_MIPSR6)
+#if defined(CONFIG_64BIT) || defined(CONFIG_MIPS_O32_FP64_SUPPORT)
mfc0 t0, CP0_STATUS
#endif
fpu_save_double a0 t0 t1 # clobbers t1
@@ -52,8 +51,7 @@ EXPORT_SYMBOL(_save_fp)
* Restore a thread's fp context.
*/
LEAF(_restore_fp)
-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPSR2) || \
- defined(CONFIG_CPU_MIPSR5) || defined(CONFIG_CPU_MIPSR6)
+#if defined(CONFIG_64BIT) || defined(CONFIG_MIPS_O32_FP64_SUPPORT)
mfc0 t0, CP0_STATUS
#endif
fpu_restore_double a0 t0 t1 # clobbers t1
@@ -102,11 +100,10 @@ LEAF(_save_fp_context)
cfc1 t1, fcr31
.set pop

-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPSR2) || \
- defined(CONFIG_CPU_MIPSR5) || defined(CONFIG_CPU_MIPSR6)
+#if defined(CONFIG_64BIT) || defined(CONFIG_MIPS_O32_FP64_SUPPORT)
.set push
.set hardfloat
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5)
+#if MIPS_ISA_REV < 6
.set mips32r2
.set fp=64
mfc0 t0, CP0_STATUS
@@ -170,11 +167,10 @@ LEAF(_save_fp_context)
LEAF(_restore_fp_context)
EX lw t1, 0(a1)

-#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPSR2) || \
- defined(CONFIG_CPU_MIPSR5) || defined(CONFIG_CPU_MIPSR6)
+#if defined(CONFIG_64BIT) || defined(CONFIG_MIPS_O32_FP64_SUPPORT)
.set push
.set hardfloat
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5)
+#if MIPS_ISA_REV < 6
.set mips32r2
.set fp=64
mfc0 t0, CP0_STATUS
--
2.39.2 (Apple Git-143)