aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2023-08-08 14:19:51 +1000
committerMichael Tokarev <mjt@tls.msk.ru>2023-09-25 23:43:49 +0300
commit270bf7977fbda35d1bb63decd8c670f16c30602e (patch)
tree41c6a6e2d40f7c447a22c2c58a6028e8b950cb24
parente916d29608c83f4dc521c58fe9c57b17affcc943 (diff)
hw/ppc: Always store the decrementer value
When writing a value to the decrementer that raises an exception, the irq is raised, but the value is not stored so the store doesn't appear to have changed the register when it is read again. Always store the write value to the register. Fixes: e81a982aa53 ("PPC: Clean up DECR implementation") Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Cédric Le Goater <clg@kaod.org> (cherry picked from commit febb71d543a8f747b2f8aaf0182d0a385c6a02c3) Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
-rw-r--r--hw/ppc/ppc.c20
1 files changed, 10 insertions, 10 deletions
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index dfa3945454..b17804fc17 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -843,6 +843,16 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
}
/*
+ * Calculate the next decrementer event and set a timer.
+ * decr_next is in timebase units to keep rounding simple. Note it is
+ * not adjusted by tb_offset because if TB changes via tb_offset changing,
+ * decrementer does not change, so not directly comparable with TB.
+ */
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ next = ns_to_tb(tb_env->decr_freq, now) + value;
+ *nextp = next; /* nextp is in timebase units */
+
+ /*
* Going from 1 -> 0 or 0 -> -1 is the event to generate a DEC interrupt.
*
* On MSB level based DEC implementations the MSB always means the interrupt
@@ -863,16 +873,6 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
(*lower_excp)(cpu);
}
- /*
- * Calculate the next decrementer event and set a timer.
- * decr_next is in timebase units to keep rounding simple. Note it is
- * not adjusted by tb_offset because if TB changes via tb_offset changing,
- * decrementer does not change, so not directly comparable with TB.
- */
- now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- next = ns_to_tb(tb_env->decr_freq, now) + value;
- *nextp = next;
-
/* Adjust timer */
timer_mod(timer, tb_to_ns_round_up(tb_env->decr_freq, next));
}