target-mips: indicate presence of IEEE 754-2008 FPU in R6/R5+MSA CPUs

MIPS Release 6 and MIPS SIMD Architecture make it mandatory to have IEEE
754-2008 FPU which is indicated by CP1 FIR.HAS2008, FCSR.ABS2008 and
FCSR.NAN2008 bits set to 1.

In QEMU we still keep these bits cleared as there is no 2008-NaN support.
However, this now causes problems preventing from running R6 Linux with
the v4.5 kernel. Kernel refuses to execute 2008-NaN ELFs on a CPU
whose FPU does not support 2008-NaN encoding:

(...)
VFS: Mounted root (ext4 filesystem) readonly on device 8:0.
devtmpfs: mounted
Freeing unused kernel memory: 256K (ffffffff806f0000 - ffffffff80730000)
request_module: runaway loop modprobe binfmt-464c
Starting init: /sbin/init exists but couldn't execute it (error -8)
request_module: runaway loop modprobe binfmt-464c
Starting init: /bin/sh exists but couldn't execute it (error -8)
Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/init.txt for guidance.

Therefore always indicate presence of 2008-NaN support in R6 as well as in
R5+MSA CPUs, even though this feature is not yet supported by MIPS in QEMU.

Backports commit ba5c79f26221c0fd7139c883a34a4e75d993f732 from qemu
This commit is contained in:
Leon Alrae 2018-02-22 11:29:49 -05:00 committed by Lioncash
parent eb29ff04ca
commit 224cbb008a
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
3 changed files with 51 additions and 20 deletions

View file

@ -100,6 +100,7 @@ struct CPUMIPSFPUContext {
uint32_t fcr0;
#define FCR0_FREP 29
#define FCR0_UFRP 28
#define FCR0_HAS2008 23
#define FCR0_F64 22
#define FCR0_L 21
#define FCR0_W 20
@ -111,6 +112,8 @@ struct CPUMIPSFPUContext {
#define FCR0_REV 0
/* fcsr */
uint32_t fcr31;
#define FCR31_ABS2008 19
#define FCR31_NAN2008 18
#define SET_FP_COND(num,env) do { ((env).fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
#define CLEAR_FP_COND(num,env) do { ((env).fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
#define GET_FP_COND(env) ((((env).fcr31 >> 24) & 0xfe) | (((env).fcr31 >> 23) & 0x1))

View file

@ -20263,6 +20263,7 @@ void cpu_state_reset(CPUMIPSState *env)
env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
env->msair = env->cpu_model->MSAIR;
env->insn_flags = env->cpu_model->insn_flags;

View file

@ -84,6 +84,7 @@ struct mips_def_t {
int32_t CP0_TCStatus_rw_bitmask;
int32_t CP0_SRSCtl;
int32_t CP1_fcr0;
int32_t CP1_fcr31;
int32_t MSAIR;
int32_t SEGBITS;
int32_t PABITS;
@ -128,7 +129,8 @@ static const mips_def_t mips_defs[] =
0x1278FF17,
0,
0,
0,
0, // CP1_fcr0
0, // CP1_fcr31
0,
32,
32,
@ -161,7 +163,8 @@ static const mips_def_t mips_defs[] =
0,
0,
0,
0, // CP1_fcr0
0, // CP1_fcr31
0,
32,
32,
@ -190,7 +193,8 @@ static const mips_def_t mips_defs[] =
0x1278FF17,
0,
0,
0,
0, // CP1_fcr0
0, // CP1_fcr31
0,
32,
32,
@ -219,7 +223,8 @@ static const mips_def_t mips_defs[] =
0x1258FF17,
0,
0,
0,
0, // CP1_fcr0
0, // CP1_fcr31
0,
32,
32,
@ -249,7 +254,8 @@ static const mips_def_t mips_defs[] =
0x1278FF17,
0,
0,
0,
0, // CP1_fcr0
0, // CP1_fcr31
0,
32,
32,
@ -279,7 +285,8 @@ static const mips_def_t mips_defs[] =
0x1258FF17,
0,
0,
0,
0, // CP1_fcr0
0, // CP1_fcr31
0,
32,
32,
@ -310,6 +317,8 @@ static const mips_def_t mips_defs[] =
0x1278FF1F,
0,
0,
0, // CP1_fcr0
0, // CP1_fcr31
0,
32,
32,
@ -343,6 +352,7 @@ static const mips_def_t mips_defs[] =
(1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
(1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
0,
0,
32,
32,
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
@ -378,6 +388,7 @@ static const mips_def_t mips_defs[] =
32,
(1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
(1 << FCR0_D) | (1 << FCR0_S) | (0x95 << FCR0_PRID),
0,
0x3fffffff,
(1U << CP0SRSC0_M) | (0x3fe << CP0SRSC0_SRS3) |
(0x3fe << CP0SRSC0_SRS2) | (0x3fe << CP0SRSC0_SRS1),
@ -423,6 +434,7 @@ static const mips_def_t mips_defs[] =
(1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
(1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
0,
0,
32,
32,
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
@ -450,7 +462,8 @@ static const mips_def_t mips_defs[] =
0x1258FF17,
0,
0,
0,
0, // CP1_fcr0
0, // CP1_fcr31
0,
32,
32,
@ -480,7 +493,8 @@ static const mips_def_t mips_defs[] =
0x1278FF17,
0,
0,
0,
0, // CP1_fcr0
0, // CP1_fcr31
0,
32,
32,
@ -523,9 +537,10 @@ static const mips_def_t mips_defs[] =
0x3C68FF1F,
0,
0,
(1 << FCR0_FREP) | (1 << FCR0_UFRP) | (1 << FCR0_F64) |
(1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
(1 << FCR0_S) | (0x03 << FCR0_PRID),
(1 << FCR0_FREP) | (1 << FCR0_UFRP) | (1 << FCR0_HAS2008) |
(1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
(1 << FCR0_D) | (1 << FCR0_S) | (0x03 << FCR0_PRID),
(1 << FCR31_ABS2008) | (1 << FCR31_NAN2008),
0,
32,
40,
@ -564,9 +579,10 @@ static const mips_def_t mips_defs[] =
0x3058FF1F,
0,
0,
(1 << FCR0_FREP) | (1 << FCR0_F64) | (1 << FCR0_L) |
(1 << FCR0_FREP) | (1 << FCR0_F64) | (1 << FCR0_HAS2008) | (1 << FCR0_L) |
(1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) |
(0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
(1 << FCR31_ABS2008) | (1 << FCR31_NAN2008),
0,
32,
32,
@ -604,6 +620,7 @@ static const mips_def_t mips_defs[] =
/* The R4000 has a full 64bit FPU but doesn't use the fcr0 bits. */
(0x5 << FCR0_PRID) | (0x0 << FCR0_REV),
0,
0,
40,
36,
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
@ -632,6 +649,7 @@ static const mips_def_t mips_defs[] =
/* The VR5432 has a full 64bit FPU but doesn't use the fcr0 bits. */
(0x54 << FCR0_PRID) | (0x0 << FCR0_REV),
0,
0,
40,
32,
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
@ -660,7 +678,8 @@ static const mips_def_t mips_defs[] =
0x12F8FFFF,
0,
0,
0,
0, // CP1_fcr0
0, // CP1_fcr31
0,
42,
36,
@ -695,6 +714,7 @@ static const mips_def_t mips_defs[] =
(1 << FCR0_D) | (1 << FCR0_S) |
(0x81 << FCR0_PRID) | (0x0 << FCR0_REV),
0,
0,
42,
36,
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
@ -730,6 +750,7 @@ static const mips_def_t mips_defs[] =
(1 << FCR0_D) | (1 << FCR0_S) |
(0x82 << FCR0_PRID) | (0x0 << FCR0_REV),
0,
0,
40,
36,
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
@ -764,6 +785,7 @@ static const mips_def_t mips_defs[] =
(1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
(1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
0,
0,
42,
36,
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
@ -802,9 +824,10 @@ static const mips_def_t mips_defs[] =
0x30D8FFFF,
0,
0,
(1 << FCR0_FREP) | (1 << FCR0_F64) | (1 << FCR0_L) |
(1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) |
(0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
(1 << FCR0_FREP) | (1 << FCR0_HAS2008) | (1 << FCR0_F64) |
(1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
(1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
(1 << FCR31_ABS2008) | (1 << FCR31_NAN2008),
0,
48,
48,
@ -839,7 +862,8 @@ static const mips_def_t mips_defs[] =
0x12F8FFFF,
0,
0,
0,
0, // CP1_fcr0
0, // CP1_fcr31
0,
42,
36,
@ -875,6 +899,7 @@ static const mips_def_t mips_defs[] =
(1 << FCR0_D) | (1 << FCR0_S) |
(0x89 << FCR0_PRID) | (0x0 << FCR0_REV),
0,
0,
42,
36,
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
@ -904,6 +929,7 @@ static const mips_def_t mips_defs[] =
0,
(0x5 << FCR0_PRID) | (0x1 << FCR0_REV),
0,
0,
40,
40,
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
@ -933,6 +959,7 @@ static const mips_def_t mips_defs[] =
0,
(0x5 << FCR0_PRID) | (0x1 << FCR0_REV),
0,
0,
40,
40,
0,0, 0,0, 0,0, 0,0, 0,0, 0,0,
@ -968,6 +995,7 @@ static const mips_def_t mips_defs[] =
(1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
(1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
0,
0,
42,
/* The architectural limit is 59, but we have hardcoded 36 bit
in some places...
@ -977,7 +1005,6 @@ static const mips_def_t mips_defs[] =
CPU_MIPS64R2 | ASE_DSP | ASE_DSPR2,
MMU_TYPE_R4000,
},
#endif
};