Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: cpu-probe: move fpu probing/handling into its own file

cpu-probe.c has grown when supporting more and more CPUs and there
are use cases where probing for all the CPUs isn't useful like
running on a R3k system. But still the fpu handling is nearly
the same. For sharing put the fpu code into it's own file.

Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>

+364 -324
+1
arch/mips/kernel/Makefile
··· 42 42 sw-$(CONFIG_CPU_CAVIUM_OCTEON) := octeon_switch.o 43 43 obj-y += $(sw-y) 44 44 45 + obj-$(CONFIG_MIPS_FP_SUPPORT) += fpu-probe.o 45 46 obj-$(CONFIG_CPU_R2300_FPU) += r2300_fpu.o 46 47 obj-$(CONFIG_CPU_R4K_FPU) += r4k_fpu.o 47 48
+2 -324
arch/mips/kernel/cpu-probe.c
··· 28 28 #include <asm/spram.h> 29 29 #include <linux/uaccess.h> 30 30 31 + #include "fpu-probe.h" 32 + 31 33 #include <asm/mach-loongson64/cpucfg-emul.h> 32 34 33 35 /* Hardware capabilities */ 34 36 unsigned int elf_hwcap __read_mostly; 35 37 EXPORT_SYMBOL_GPL(elf_hwcap); 36 - 37 - #ifdef CONFIG_MIPS_FP_SUPPORT 38 - 39 - /* 40 - * Get the FPU Implementation/Revision. 41 - */ 42 - static inline unsigned long cpu_get_fpu_id(void) 43 - { 44 - unsigned long tmp, fpu_id; 45 - 46 - tmp = read_c0_status(); 47 - __enable_fpu(FPU_AS_IS); 48 - fpu_id = read_32bit_cp1_register(CP1_REVISION); 49 - write_c0_status(tmp); 50 - return fpu_id; 51 - } 52 - 53 - /* 54 - * Check if the CPU has an external FPU. 55 - */ 56 - static inline int __cpu_has_fpu(void) 57 - { 58 - return (cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE; 59 - } 60 - 61 - /* 62 - * Determine the FCSR mask for FPU hardware. 63 - */ 64 - static inline void cpu_set_fpu_fcsr_mask(struct cpuinfo_mips *c) 65 - { 66 - unsigned long sr, mask, fcsr, fcsr0, fcsr1; 67 - 68 - fcsr = c->fpu_csr31; 69 - mask = FPU_CSR_ALL_X | FPU_CSR_ALL_E | FPU_CSR_ALL_S | FPU_CSR_RM; 70 - 71 - sr = read_c0_status(); 72 - __enable_fpu(FPU_AS_IS); 73 - 74 - fcsr0 = fcsr & mask; 75 - write_32bit_cp1_register(CP1_STATUS, fcsr0); 76 - fcsr0 = read_32bit_cp1_register(CP1_STATUS); 77 - 78 - fcsr1 = fcsr | ~mask; 79 - write_32bit_cp1_register(CP1_STATUS, fcsr1); 80 - fcsr1 = read_32bit_cp1_register(CP1_STATUS); 81 - 82 - write_32bit_cp1_register(CP1_STATUS, fcsr); 83 - 84 - write_c0_status(sr); 85 - 86 - c->fpu_msk31 = ~(fcsr0 ^ fcsr1) & ~mask; 87 - } 88 - 89 - /* 90 - * Determine the IEEE 754 NaN encodings and ABS.fmt/NEG.fmt execution modes 91 - * supported by FPU hardware. 92 - */ 93 - static void cpu_set_fpu_2008(struct cpuinfo_mips *c) 94 - { 95 - if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 | 96 - MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | 97 - MIPS_CPU_ISA_M32R5 | MIPS_CPU_ISA_M64R5 | 98 - MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) { 99 - unsigned long sr, fir, fcsr, fcsr0, fcsr1; 100 - 101 - sr = read_c0_status(); 102 - __enable_fpu(FPU_AS_IS); 103 - 104 - fir = read_32bit_cp1_register(CP1_REVISION); 105 - if (fir & MIPS_FPIR_HAS2008) { 106 - fcsr = read_32bit_cp1_register(CP1_STATUS); 107 - 108 - /* 109 - * MAC2008 toolchain never landed in real world, so we're only 110 - * testing wether it can be disabled and don't try to enabled 111 - * it. 112 - */ 113 - fcsr0 = fcsr & ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008 | FPU_CSR_MAC2008); 114 - write_32bit_cp1_register(CP1_STATUS, fcsr0); 115 - fcsr0 = read_32bit_cp1_register(CP1_STATUS); 116 - 117 - fcsr1 = fcsr | FPU_CSR_ABS2008 | FPU_CSR_NAN2008; 118 - write_32bit_cp1_register(CP1_STATUS, fcsr1); 119 - fcsr1 = read_32bit_cp1_register(CP1_STATUS); 120 - 121 - write_32bit_cp1_register(CP1_STATUS, fcsr); 122 - 123 - if (c->isa_level & (MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2)) { 124 - /* 125 - * The bit for MAC2008 might be reused by R6 in future, 126 - * so we only test for R2-R5. 127 - */ 128 - if (fcsr0 & FPU_CSR_MAC2008) 129 - c->options |= MIPS_CPU_MAC_2008_ONLY; 130 - } 131 - 132 - if (!(fcsr0 & FPU_CSR_NAN2008)) 133 - c->options |= MIPS_CPU_NAN_LEGACY; 134 - if (fcsr1 & FPU_CSR_NAN2008) 135 - c->options |= MIPS_CPU_NAN_2008; 136 - 137 - if ((fcsr0 ^ fcsr1) & FPU_CSR_ABS2008) 138 - c->fpu_msk31 &= ~FPU_CSR_ABS2008; 139 - else 140 - c->fpu_csr31 |= fcsr & FPU_CSR_ABS2008; 141 - 142 - if ((fcsr0 ^ fcsr1) & FPU_CSR_NAN2008) 143 - c->fpu_msk31 &= ~FPU_CSR_NAN2008; 144 - else 145 - c->fpu_csr31 |= fcsr & FPU_CSR_NAN2008; 146 - } else { 147 - c->options |= MIPS_CPU_NAN_LEGACY; 148 - } 149 - 150 - write_c0_status(sr); 151 - } else { 152 - c->options |= MIPS_CPU_NAN_LEGACY; 153 - } 154 - } 155 - 156 - /* 157 - * IEEE 754 conformance mode to use. Affects the NaN encoding and the 158 - * ABS.fmt/NEG.fmt execution mode. 159 - */ 160 - static enum { STRICT, LEGACY, STD2008, RELAXED } ieee754 = STRICT; 161 - 162 - /* 163 - * Set the IEEE 754 NaN encodings and the ABS.fmt/NEG.fmt execution modes 164 - * to support by the FPU emulator according to the IEEE 754 conformance 165 - * mode selected. Note that "relaxed" straps the emulator so that it 166 - * allows 2008-NaN binaries even for legacy processors. 167 - */ 168 - static void cpu_set_nofpu_2008(struct cpuinfo_mips *c) 169 - { 170 - c->options &= ~(MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY); 171 - c->fpu_csr31 &= ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008); 172 - c->fpu_msk31 &= ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008); 173 - 174 - switch (ieee754) { 175 - case STRICT: 176 - if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 | 177 - MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | 178 - MIPS_CPU_ISA_M32R5 | MIPS_CPU_ISA_M64R5 | 179 - MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) { 180 - c->options |= MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY; 181 - } else { 182 - c->options |= MIPS_CPU_NAN_LEGACY; 183 - c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008; 184 - } 185 - break; 186 - case LEGACY: 187 - c->options |= MIPS_CPU_NAN_LEGACY; 188 - c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008; 189 - break; 190 - case STD2008: 191 - c->options |= MIPS_CPU_NAN_2008; 192 - c->fpu_csr31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008; 193 - c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008; 194 - break; 195 - case RELAXED: 196 - c->options |= MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY; 197 - break; 198 - } 199 - } 200 - 201 - /* 202 - * Override the IEEE 754 NaN encoding and ABS.fmt/NEG.fmt execution mode 203 - * according to the "ieee754=" parameter. 204 - */ 205 - static void cpu_set_nan_2008(struct cpuinfo_mips *c) 206 - { 207 - switch (ieee754) { 208 - case STRICT: 209 - mips_use_nan_legacy = !!cpu_has_nan_legacy; 210 - mips_use_nan_2008 = !!cpu_has_nan_2008; 211 - break; 212 - case LEGACY: 213 - mips_use_nan_legacy = !!cpu_has_nan_legacy; 214 - mips_use_nan_2008 = !cpu_has_nan_legacy; 215 - break; 216 - case STD2008: 217 - mips_use_nan_legacy = !cpu_has_nan_2008; 218 - mips_use_nan_2008 = !!cpu_has_nan_2008; 219 - break; 220 - case RELAXED: 221 - mips_use_nan_legacy = true; 222 - mips_use_nan_2008 = true; 223 - break; 224 - } 225 - } 226 - 227 - /* 228 - * IEEE 754 NaN encoding and ABS.fmt/NEG.fmt execution mode override 229 - * settings: 230 - * 231 - * strict: accept binaries that request a NaN encoding supported by the FPU 232 - * legacy: only accept legacy-NaN binaries 233 - * 2008: only accept 2008-NaN binaries 234 - * relaxed: accept any binaries regardless of whether supported by the FPU 235 - */ 236 - static int __init ieee754_setup(char *s) 237 - { 238 - if (!s) 239 - return -1; 240 - else if (!strcmp(s, "strict")) 241 - ieee754 = STRICT; 242 - else if (!strcmp(s, "legacy")) 243 - ieee754 = LEGACY; 244 - else if (!strcmp(s, "2008")) 245 - ieee754 = STD2008; 246 - else if (!strcmp(s, "relaxed")) 247 - ieee754 = RELAXED; 248 - else 249 - return -1; 250 - 251 - if (!(boot_cpu_data.options & MIPS_CPU_FPU)) 252 - cpu_set_nofpu_2008(&boot_cpu_data); 253 - cpu_set_nan_2008(&boot_cpu_data); 254 - 255 - return 0; 256 - } 257 - 258 - early_param("ieee754", ieee754_setup); 259 - 260 - /* 261 - * Set the FIR feature flags for the FPU emulator. 262 - */ 263 - static void cpu_set_nofpu_id(struct cpuinfo_mips *c) 264 - { 265 - u32 value; 266 - 267 - value = 0; 268 - if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 | 269 - MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | 270 - MIPS_CPU_ISA_M32R5 | MIPS_CPU_ISA_M64R5 | 271 - MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) 272 - value |= MIPS_FPIR_D | MIPS_FPIR_S; 273 - if (c->isa_level & (MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | 274 - MIPS_CPU_ISA_M32R5 | MIPS_CPU_ISA_M64R5 | 275 - MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) 276 - value |= MIPS_FPIR_F64 | MIPS_FPIR_L | MIPS_FPIR_W; 277 - if (c->options & MIPS_CPU_NAN_2008) 278 - value |= MIPS_FPIR_HAS2008; 279 - c->fpu_id = value; 280 - } 281 - 282 - /* Determined FPU emulator mask to use for the boot CPU with "nofpu". */ 283 - static unsigned int mips_nofpu_msk31; 284 - 285 - /* 286 - * Set options for FPU hardware. 287 - */ 288 - static void cpu_set_fpu_opts(struct cpuinfo_mips *c) 289 - { 290 - c->fpu_id = cpu_get_fpu_id(); 291 - mips_nofpu_msk31 = c->fpu_msk31; 292 - 293 - if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 | 294 - MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | 295 - MIPS_CPU_ISA_M32R5 | MIPS_CPU_ISA_M64R5 | 296 - MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) { 297 - if (c->fpu_id & MIPS_FPIR_3D) 298 - c->ases |= MIPS_ASE_MIPS3D; 299 - if (c->fpu_id & MIPS_FPIR_UFRP) 300 - c->options |= MIPS_CPU_UFR; 301 - if (c->fpu_id & MIPS_FPIR_FREP) 302 - c->options |= MIPS_CPU_FRE; 303 - } 304 - 305 - cpu_set_fpu_fcsr_mask(c); 306 - cpu_set_fpu_2008(c); 307 - cpu_set_nan_2008(c); 308 - } 309 - 310 - /* 311 - * Set options for the FPU emulator. 312 - */ 313 - static void cpu_set_nofpu_opts(struct cpuinfo_mips *c) 314 - { 315 - c->options &= ~MIPS_CPU_FPU; 316 - c->fpu_msk31 = mips_nofpu_msk31; 317 - 318 - cpu_set_nofpu_2008(c); 319 - cpu_set_nan_2008(c); 320 - cpu_set_nofpu_id(c); 321 - } 322 - 323 - static int mips_fpu_disabled; 324 - 325 - static int __init fpu_disable(char *s) 326 - { 327 - cpu_set_nofpu_opts(&boot_cpu_data); 328 - mips_fpu_disabled = 1; 329 - 330 - return 1; 331 - } 332 - 333 - __setup("nofpu", fpu_disable); 334 - 335 - #else /* !CONFIG_MIPS_FP_SUPPORT */ 336 - 337 - #define mips_fpu_disabled 1 338 - 339 - static inline unsigned long cpu_get_fpu_id(void) 340 - { 341 - return FPIR_IMP_NONE; 342 - } 343 - 344 - static inline int __cpu_has_fpu(void) 345 - { 346 - return 0; 347 - } 348 - 349 - static void cpu_set_fpu_opts(struct cpuinfo_mips *c) 350 - { 351 - /* no-op */ 352 - } 353 - 354 - static void cpu_set_nofpu_opts(struct cpuinfo_mips *c) 355 - { 356 - /* no-op */ 357 - } 358 - 359 - #endif /* CONFIG_MIPS_FP_SUPPORT */ 360 38 361 39 static inline unsigned long cpu_get_msa_id(void) 362 40 {
+321
arch/mips/kernel/fpu-probe.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Processor capabilities determination functions. 4 + * 5 + * Copyright (C) xxxx the Anonymous 6 + * Copyright (C) 1994 - 2006 Ralf Baechle 7 + * Copyright (C) 2003, 2004 Maciej W. Rozycki 8 + * Copyright (C) 2001, 2004, 2011, 2012 MIPS Technologies, Inc. 9 + */ 10 + 11 + #include <linux/init.h> 12 + #include <linux/kernel.h> 13 + 14 + #include <asm/bugs.h> 15 + #include <asm/cpu.h> 16 + #include <asm/cpu-features.h> 17 + #include <asm/cpu-type.h> 18 + #include <asm/elf.h> 19 + #include <asm/fpu.h> 20 + #include <asm/mipsregs.h> 21 + 22 + #include "fpu-probe.h" 23 + 24 + /* 25 + * Get the FPU Implementation/Revision. 26 + */ 27 + static inline unsigned long cpu_get_fpu_id(void) 28 + { 29 + unsigned long tmp, fpu_id; 30 + 31 + tmp = read_c0_status(); 32 + __enable_fpu(FPU_AS_IS); 33 + fpu_id = read_32bit_cp1_register(CP1_REVISION); 34 + write_c0_status(tmp); 35 + return fpu_id; 36 + } 37 + 38 + /* 39 + * Check if the CPU has an external FPU. 40 + */ 41 + int __cpu_has_fpu(void) 42 + { 43 + return (cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE; 44 + } 45 + 46 + /* 47 + * Determine the FCSR mask for FPU hardware. 48 + */ 49 + static inline void cpu_set_fpu_fcsr_mask(struct cpuinfo_mips *c) 50 + { 51 + unsigned long sr, mask, fcsr, fcsr0, fcsr1; 52 + 53 + fcsr = c->fpu_csr31; 54 + mask = FPU_CSR_ALL_X | FPU_CSR_ALL_E | FPU_CSR_ALL_S | FPU_CSR_RM; 55 + 56 + sr = read_c0_status(); 57 + __enable_fpu(FPU_AS_IS); 58 + 59 + fcsr0 = fcsr & mask; 60 + write_32bit_cp1_register(CP1_STATUS, fcsr0); 61 + fcsr0 = read_32bit_cp1_register(CP1_STATUS); 62 + 63 + fcsr1 = fcsr | ~mask; 64 + write_32bit_cp1_register(CP1_STATUS, fcsr1); 65 + fcsr1 = read_32bit_cp1_register(CP1_STATUS); 66 + 67 + write_32bit_cp1_register(CP1_STATUS, fcsr); 68 + 69 + write_c0_status(sr); 70 + 71 + c->fpu_msk31 = ~(fcsr0 ^ fcsr1) & ~mask; 72 + } 73 + 74 + /* 75 + * Determine the IEEE 754 NaN encodings and ABS.fmt/NEG.fmt execution modes 76 + * supported by FPU hardware. 77 + */ 78 + static void cpu_set_fpu_2008(struct cpuinfo_mips *c) 79 + { 80 + if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 | 81 + MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | 82 + MIPS_CPU_ISA_M32R5 | MIPS_CPU_ISA_M64R5 | 83 + MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) { 84 + unsigned long sr, fir, fcsr, fcsr0, fcsr1; 85 + 86 + sr = read_c0_status(); 87 + __enable_fpu(FPU_AS_IS); 88 + 89 + fir = read_32bit_cp1_register(CP1_REVISION); 90 + if (fir & MIPS_FPIR_HAS2008) { 91 + fcsr = read_32bit_cp1_register(CP1_STATUS); 92 + 93 + /* 94 + * MAC2008 toolchain never landed in real world, so 95 + * we're only testing whether it can be disabled and 96 + * don't try to enabled it. 97 + */ 98 + fcsr0 = fcsr & ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008 | 99 + FPU_CSR_MAC2008); 100 + write_32bit_cp1_register(CP1_STATUS, fcsr0); 101 + fcsr0 = read_32bit_cp1_register(CP1_STATUS); 102 + 103 + fcsr1 = fcsr | FPU_CSR_ABS2008 | FPU_CSR_NAN2008; 104 + write_32bit_cp1_register(CP1_STATUS, fcsr1); 105 + fcsr1 = read_32bit_cp1_register(CP1_STATUS); 106 + 107 + write_32bit_cp1_register(CP1_STATUS, fcsr); 108 + 109 + if (c->isa_level & (MIPS_CPU_ISA_M32R2 | 110 + MIPS_CPU_ISA_M64R2)) { 111 + /* 112 + * The bit for MAC2008 might be reused by R6 113 + * in future, so we only test for R2-R5. 114 + */ 115 + if (fcsr0 & FPU_CSR_MAC2008) 116 + c->options |= MIPS_CPU_MAC_2008_ONLY; 117 + } 118 + 119 + if (!(fcsr0 & FPU_CSR_NAN2008)) 120 + c->options |= MIPS_CPU_NAN_LEGACY; 121 + if (fcsr1 & FPU_CSR_NAN2008) 122 + c->options |= MIPS_CPU_NAN_2008; 123 + 124 + if ((fcsr0 ^ fcsr1) & FPU_CSR_ABS2008) 125 + c->fpu_msk31 &= ~FPU_CSR_ABS2008; 126 + else 127 + c->fpu_csr31 |= fcsr & FPU_CSR_ABS2008; 128 + 129 + if ((fcsr0 ^ fcsr1) & FPU_CSR_NAN2008) 130 + c->fpu_msk31 &= ~FPU_CSR_NAN2008; 131 + else 132 + c->fpu_csr31 |= fcsr & FPU_CSR_NAN2008; 133 + } else { 134 + c->options |= MIPS_CPU_NAN_LEGACY; 135 + } 136 + 137 + write_c0_status(sr); 138 + } else { 139 + c->options |= MIPS_CPU_NAN_LEGACY; 140 + } 141 + } 142 + 143 + /* 144 + * IEEE 754 conformance mode to use. Affects the NaN encoding and the 145 + * ABS.fmt/NEG.fmt execution mode. 146 + */ 147 + static enum { STRICT, LEGACY, STD2008, RELAXED } ieee754 = STRICT; 148 + 149 + /* 150 + * Set the IEEE 754 NaN encodings and the ABS.fmt/NEG.fmt execution modes 151 + * to support by the FPU emulator according to the IEEE 754 conformance 152 + * mode selected. Note that "relaxed" straps the emulator so that it 153 + * allows 2008-NaN binaries even for legacy processors. 154 + */ 155 + static void cpu_set_nofpu_2008(struct cpuinfo_mips *c) 156 + { 157 + c->options &= ~(MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY); 158 + c->fpu_csr31 &= ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008); 159 + c->fpu_msk31 &= ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008); 160 + 161 + switch (ieee754) { 162 + case STRICT: 163 + if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 | 164 + MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | 165 + MIPS_CPU_ISA_M32R5 | MIPS_CPU_ISA_M64R5 | 166 + MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) { 167 + c->options |= MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY; 168 + } else { 169 + c->options |= MIPS_CPU_NAN_LEGACY; 170 + c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008; 171 + } 172 + break; 173 + case LEGACY: 174 + c->options |= MIPS_CPU_NAN_LEGACY; 175 + c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008; 176 + break; 177 + case STD2008: 178 + c->options |= MIPS_CPU_NAN_2008; 179 + c->fpu_csr31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008; 180 + c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008; 181 + break; 182 + case RELAXED: 183 + c->options |= MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY; 184 + break; 185 + } 186 + } 187 + 188 + /* 189 + * Override the IEEE 754 NaN encoding and ABS.fmt/NEG.fmt execution mode 190 + * according to the "ieee754=" parameter. 191 + */ 192 + static void cpu_set_nan_2008(struct cpuinfo_mips *c) 193 + { 194 + switch (ieee754) { 195 + case STRICT: 196 + mips_use_nan_legacy = !!cpu_has_nan_legacy; 197 + mips_use_nan_2008 = !!cpu_has_nan_2008; 198 + break; 199 + case LEGACY: 200 + mips_use_nan_legacy = !!cpu_has_nan_legacy; 201 + mips_use_nan_2008 = !cpu_has_nan_legacy; 202 + break; 203 + case STD2008: 204 + mips_use_nan_legacy = !cpu_has_nan_2008; 205 + mips_use_nan_2008 = !!cpu_has_nan_2008; 206 + break; 207 + case RELAXED: 208 + mips_use_nan_legacy = true; 209 + mips_use_nan_2008 = true; 210 + break; 211 + } 212 + } 213 + 214 + /* 215 + * IEEE 754 NaN encoding and ABS.fmt/NEG.fmt execution mode override 216 + * settings: 217 + * 218 + * strict: accept binaries that request a NaN encoding supported by the FPU 219 + * legacy: only accept legacy-NaN binaries 220 + * 2008: only accept 2008-NaN binaries 221 + * relaxed: accept any binaries regardless of whether supported by the FPU 222 + */ 223 + static int __init ieee754_setup(char *s) 224 + { 225 + if (!s) 226 + return -1; 227 + else if (!strcmp(s, "strict")) 228 + ieee754 = STRICT; 229 + else if (!strcmp(s, "legacy")) 230 + ieee754 = LEGACY; 231 + else if (!strcmp(s, "2008")) 232 + ieee754 = STD2008; 233 + else if (!strcmp(s, "relaxed")) 234 + ieee754 = RELAXED; 235 + else 236 + return -1; 237 + 238 + if (!(boot_cpu_data.options & MIPS_CPU_FPU)) 239 + cpu_set_nofpu_2008(&boot_cpu_data); 240 + cpu_set_nan_2008(&boot_cpu_data); 241 + 242 + return 0; 243 + } 244 + 245 + early_param("ieee754", ieee754_setup); 246 + 247 + /* 248 + * Set the FIR feature flags for the FPU emulator. 249 + */ 250 + static void cpu_set_nofpu_id(struct cpuinfo_mips *c) 251 + { 252 + u32 value; 253 + 254 + value = 0; 255 + if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 | 256 + MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | 257 + MIPS_CPU_ISA_M32R5 | MIPS_CPU_ISA_M64R5 | 258 + MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) 259 + value |= MIPS_FPIR_D | MIPS_FPIR_S; 260 + if (c->isa_level & (MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | 261 + MIPS_CPU_ISA_M32R5 | MIPS_CPU_ISA_M64R5 | 262 + MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) 263 + value |= MIPS_FPIR_F64 | MIPS_FPIR_L | MIPS_FPIR_W; 264 + if (c->options & MIPS_CPU_NAN_2008) 265 + value |= MIPS_FPIR_HAS2008; 266 + c->fpu_id = value; 267 + } 268 + 269 + /* Determined FPU emulator mask to use for the boot CPU with "nofpu". */ 270 + static unsigned int mips_nofpu_msk31; 271 + 272 + /* 273 + * Set options for FPU hardware. 274 + */ 275 + void cpu_set_fpu_opts(struct cpuinfo_mips *c) 276 + { 277 + c->fpu_id = cpu_get_fpu_id(); 278 + mips_nofpu_msk31 = c->fpu_msk31; 279 + 280 + if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 | 281 + MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | 282 + MIPS_CPU_ISA_M32R5 | MIPS_CPU_ISA_M64R5 | 283 + MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) { 284 + if (c->fpu_id & MIPS_FPIR_3D) 285 + c->ases |= MIPS_ASE_MIPS3D; 286 + if (c->fpu_id & MIPS_FPIR_UFRP) 287 + c->options |= MIPS_CPU_UFR; 288 + if (c->fpu_id & MIPS_FPIR_FREP) 289 + c->options |= MIPS_CPU_FRE; 290 + } 291 + 292 + cpu_set_fpu_fcsr_mask(c); 293 + cpu_set_fpu_2008(c); 294 + cpu_set_nan_2008(c); 295 + } 296 + 297 + /* 298 + * Set options for the FPU emulator. 299 + */ 300 + void cpu_set_nofpu_opts(struct cpuinfo_mips *c) 301 + { 302 + c->options &= ~MIPS_CPU_FPU; 303 + c->fpu_msk31 = mips_nofpu_msk31; 304 + 305 + cpu_set_nofpu_2008(c); 306 + cpu_set_nan_2008(c); 307 + cpu_set_nofpu_id(c); 308 + } 309 + 310 + int mips_fpu_disabled; 311 + 312 + static int __init fpu_disable(char *s) 313 + { 314 + cpu_set_nofpu_opts(&boot_cpu_data); 315 + mips_fpu_disabled = 1; 316 + 317 + return 1; 318 + } 319 + 320 + __setup("nofpu", fpu_disable); 321 +
+40
arch/mips/kernel/fpu-probe.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + 3 + #include <linux/kernel.h> 4 + 5 + #include <asm/cpu.h> 6 + #include <asm/cpu-info.h> 7 + 8 + #ifdef CONFIG_MIPS_FP_SUPPORT 9 + 10 + extern int mips_fpu_disabled; 11 + 12 + int __cpu_has_fpu(void); 13 + void cpu_set_fpu_opts(struct cpuinfo_mips *c); 14 + void cpu_set_nofpu_opts(struct cpuinfo_mips *c); 15 + 16 + #else /* !CONFIG_MIPS_FP_SUPPORT */ 17 + 18 + #define mips_fpu_disabled 1 19 + 20 + static inline unsigned long cpu_get_fpu_id(void) 21 + { 22 + return FPIR_IMP_NONE; 23 + } 24 + 25 + static inline int __cpu_has_fpu(void) 26 + { 27 + return 0; 28 + } 29 + 30 + static inline void cpu_set_fpu_opts(struct cpuinfo_mips *c) 31 + { 32 + /* no-op */ 33 + } 34 + 35 + static inline void cpu_set_nofpu_opts(struct cpuinfo_mips *c) 36 + { 37 + /* no-op */ 38 + } 39 + 40 + #endif /* CONFIG_MIPS_FP_SUPPORT */