]> xenbits.xensource.com Git - qemu-xen.git/commitdiff
target-mips: Fix CP0.Config3.ISAOnExc write accesses
authorMaciej W. Rozycki <macro@codesourcery.com>
Tue, 18 Nov 2014 03:59:07 +0000 (03:59 +0000)
committerLeon Alrae <leon.alrae@imgtec.com>
Tue, 16 Dec 2014 12:45:20 +0000 (12:45 +0000)
Fix CP0.Config3.ISAOnExc write accesses on microMIPS processors.  This
bit is mandatory for any processor that implements the microMIPS
instruction set.  This bit is r/w for processors that implement both the
standard MIPS and the microMIPS instruction set.  This bit is r/o and
hardwired to 1 if only the microMIPS instruction set is implemented.

There is no other bit ever writable in CP0.Config3 so defining a
corresponding `CP0_Config3_rw_bitmask' member in `CPUMIPSState' is I
think an overkill.  Therefore make the ability to write the bit rely on
the presence of ASE_MICROMIPS set in the instruction flags.

The read-only case of the microMIPS instruction set being implemented
only can be added when we add support for such a configuration.  We do
not currently have such support, we have no instruction flag that would
control the presence of the standard MIPS instruction set nor any
associated code in instruction decoding.

This change is needed to boot a microMIPS Linux kernel successfully,
otherwise it hangs early on as interrupts are enabled and then the
exception handler invoked loops as its first instruction is interpreted
in the wrong execution mode and triggers another exception right away.
And then over and over again.

We already check the current setting of the CP0.Config3.ISAOnExc in
`set_hflags_for_handler' to set the ISA bit correctly on the exception
handler entry so it is the ability to set it that is missing only.

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
target-mips/helper.h
target-mips/op_helper.c
target-mips/translate.c

index 9d0275891cfc0740549ed33457c8c579c4499036..3bd0b029e487fa319936d6ef3dc887d3f2905995 100644 (file)
@@ -137,6 +137,7 @@ DEF_HELPER_2(mtc0_ebase, void, env, tl)
 DEF_HELPER_2(mttc0_ebase, void, env, tl)
 DEF_HELPER_2(mtc0_config0, void, env, tl)
 DEF_HELPER_2(mtc0_config2, void, env, tl)
+DEF_HELPER_2(mtc0_config3, void, env, tl)
 DEF_HELPER_2(mtc0_config4, void, env, tl)
 DEF_HELPER_2(mtc0_config5, void, env, tl)
 DEF_HELPER_2(mtc0_lladdr, void, env, tl)
index 1ec2756373fa8c1209edcdfcc47930e55d290391..1267ef297cf7b181f794cc163f1f182a16c828bc 100644 (file)
@@ -1503,6 +1503,14 @@ void helper_mtc0_config2(CPUMIPSState *env, target_ulong arg1)
     env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
 }
 
+void helper_mtc0_config3(CPUMIPSState *env, target_ulong arg1)
+{
+    if (env->insn_flags & ASE_MICROMIPS) {
+        env->CP0_Config3 = (env->CP0_Config3 & ~(1 << CP0C3_ISA_ON_EXC)) |
+                           (arg1 & (1 << CP0C3_ISA_ON_EXC));
+    }
+}
+
 void helper_mtc0_config4(CPUMIPSState *env, target_ulong arg1)
 {
     env->CP0_Config4 = (env->CP0_Config4 & (~env->CP0_Config4_rw_bitmask)) |
index 70da66f9581b3aaa23047fe9d99b5fd63f0469ff..d4fedfbd4511e6ba81402f0fce53fbfd379734ca 100644 (file)
@@ -5846,8 +5846,10 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             ctx->bstate = BS_STOP;
             break;
         case 3:
-            /* ignored, read only */
+            gen_helper_mtc0_config3(cpu_env, arg);
             rn = "Config3";
+            /* Stop translation as we may have switched the execution mode */
+            ctx->bstate = BS_STOP;
             break;
         case 4:
             gen_helper_mtc0_config4(cpu_env, arg);
@@ -7097,8 +7099,10 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             ctx->bstate = BS_STOP;
             break;
         case 3:
-            /* ignored */
+            gen_helper_mtc0_config3(cpu_env, arg);
             rn = "Config3";
+            /* Stop translation as we may have switched the execution mode */
+            ctx->bstate = BS_STOP;
             break;
         case 4:
             /* currently ignored */