Setting the CP0 clock simply on CPU init is incorrect. First
because the clock can not be yet propagated. Second because
we aimed to support dynamic frequencies in commit a0713e85bfa,
so the CPU frequency can be changed *after* init time.

The correct way is to register a ClockCallback, which will
update the CP0 period when the clock changes.

Fixes: a0713e85bfa ("target/mips/cpu: Allow the CPU to use dynamic frequencies")
Signed-off-by: Philippe Mathieu-Daudé <f4...@amsat.org>
---
 target/mips/cpu.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index aa0b00256e6..db93d19c49a 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -604,6 +604,13 @@ static void mips_cp0_period_set(MIPSCPU *cpu)
     assert(env->cp0_count_ns);
 }
 
+static void mips_cpu_clk_update(void *opaque, ClockEvent event)
+{
+    MIPSCPU *cpu = opaque;
+
+    mips_cp0_period_set(cpu);
+}
+
 static void mips_cpu_realizefn(DeviceState *dev, Error **errp)
 {
     CPUState *cs = CPU(dev);
@@ -624,7 +631,6 @@ static void mips_cpu_realizefn(DeviceState *dev, Error 
**errp)
         /* Initialize the frequency in case the clock remains unconnected. */
         clock_set_hz(cpu->clock, CPU_FREQ_HZ_DEFAULT);
     }
-    mips_cp0_period_set(cpu);
 
     cpu_exec_realizefn(cs, &local_err);
     if (local_err != NULL) {
@@ -653,7 +659,8 @@ static void mips_cpu_initfn(Object *obj)
     MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(obj);
 
     cpu_set_cpustate_pointers(cpu);
-    cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, cpu, 0);
+    cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in",
+                                    mips_cpu_clk_update, cpu, ClockUpdate);
     env->cpu_model = mcc->cpu_def;
 }
 
-- 
2.26.3


Reply via email to