diff options
author | Matt Lupfer <mlupfer@ddn.com> | 2014-02-21 21:37:23 -0700 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2014-03-27 17:48:11 +0200 |
commit | c36ad13fe9ece9a21a8c1dd082473a2b182298ee (patch) | |
tree | d8cdb0993f0fb271eb5b1a473b911f107768d7bd /hw/timer/hpet.c | |
parent | 5c312079417908381ffca44d18150b6a990c4f0b (diff) | |
download | qemu-c36ad13fe9ece9a21a8c1dd082473a2b182298ee.tar.gz qemu-c36ad13fe9ece9a21a8c1dd082473a2b182298ee.tar.bz2 qemu-c36ad13fe9ece9a21a8c1dd082473a2b182298ee.zip |
Don't enable a HPET timer if HPET is disabled
A HPET timer can be started when HPET is not yet
enabled. This will not generate an interrupt
to the guest, but causes problems when HPET is later
enabled.
A timer that is created and expires at least once before
HPET is enabled will have an initialized comparator based
on a hpet_offset of 0 (uninitialized). When HPET is
enabled, hpet_set_timer() is called a second time, which
modifies the timer expiry to a time based on the
difference between current ticks (measured with the
newly initialized hpet_offset) and the timer's
comparator (which was generated before hpet_offset was
initialized). This results in a long period of no HPET
timer ticks.
When this occurs with a CentOS 5.x guest, the guest
may not receive timer interrupts during its narrow
timer check window and panic on boot.
Signed-off-by: Matt Lupfer <mlupfer@ddn.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw/timer/hpet.c')
-rw-r--r-- | hw/timer/hpet.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c index 1264dfd46a..e15d6bcac7 100644 --- a/hw/timer/hpet.c +++ b/hw/timer/hpet.c @@ -506,7 +506,8 @@ static void hpet_ram_write(void *opaque, hwaddr addr, timer->cmp = (uint32_t)timer->cmp; timer->period = (uint32_t)timer->period; } - if (activating_bit(old_val, new_val, HPET_TN_ENABLE)) { + if (activating_bit(old_val, new_val, HPET_TN_ENABLE) && + hpet_enabled(s)) { hpet_set_timer(timer); } else if (deactivating_bit(old_val, new_val, HPET_TN_ENABLE)) { hpet_del_timer(timer); |