summaryrefslogtreecommitdiff
path: root/hw/ppc/ppc_booke.c
diff options
context:
space:
mode:
authorBharat Bhushan <r65777@freescale.com>2013-06-12 18:00:50 +0530
committerAlexander Graf <agraf@suse.de>2013-07-01 01:11:16 +0200
commitab8131afee34d6aa427bd56ac18c4d3b6df80728 (patch)
treea058046b9d6d557926841306dee6536c279b0164 /hw/ppc/ppc_booke.c
parentf1ff0e89c8287de79c804ec7a50d43f39a9f65dc (diff)
downloadqemu-ab8131afee34d6aa427bd56ac18c4d3b6df80728.tar.gz
booke_ppc: limit booke timer to max when timeout overflow
Limit watchdog and fit timer to maximum timeout value which qemu timer can support (INT64_MAX). This maximum timeout will be hundreds of years, so limiting to max timeout is pretty safe. Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'hw/ppc/ppc_booke.c')
-rw-r--r--hw/ppc/ppc_booke.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/hw/ppc/ppc_booke.c b/hw/ppc/ppc_booke.c
index e41b036b8e..000c27f2e8 100644
--- a/hw/ppc/ppc_booke.c
+++ b/hw/ppc/ppc_booke.c
@@ -131,17 +131,33 @@ static void booke_update_fixed_timer(CPUPPCState *env,
struct QEMUTimer *timer)
{
ppc_tb_t *tb_env = env->tb_env;
- uint64_t lapse;
+ uint64_t delta_tick, ticks = 0;
uint64_t tb;
- uint64_t period = 1 << (target_bit + 1);
+ uint64_t period;
uint64_t now;
now = qemu_get_clock_ns(vm_clock);
tb = cpu_ppc_get_tb(tb_env, now, tb_env->tb_offset);
+ period = 1ULL << target_bit;
+ delta_tick = period - (tb & (period - 1));
- lapse = period - ((tb - (1 << target_bit)) & (period - 1));
+ /* the timer triggers only when the selected bit toggles from 0 to 1 */
+ if (tb & period) {
+ ticks = period;
+ }
- *next = now + muldiv64(lapse, get_ticks_per_sec(), tb_env->tb_freq);
+ if (ticks + delta_tick < ticks) {
+ /* Overflow, so assume the biggest number we can express. */
+ ticks = UINT64_MAX;
+ } else {
+ ticks += delta_tick;
+ }
+
+ *next = now + muldiv64(ticks, get_ticks_per_sec(), tb_env->tb_freq);
+ if ((*next < now) || (*next > INT64_MAX)) {
+ /* Overflow, so assume the biggest number the qemu timer supports. */
+ *next = INT64_MAX;
+ }
/* XXX: If expire time is now. We can't run the callback because we don't
* have access to it. So we just set the timer one nanosecond later.