Patchwork hpet: fix infinite loop in qemu_run_timers with -icount enabled

login
register
mail settings
Submitter Max Filippov
Date Nov. 9, 2011, 1:18 a.m.
Message ID <1320801489-18193-1-git-send-email-jcmvbkbc@gmail.com>
Download mbox | patch
Permalink /patch/124463/
State New
Headers show

Comments

Max Filippov - Nov. 9, 2011, 1:18 a.m.
hpet_timer timer callback rearms itself based on difference between
current HPET tick counter and comparator value. Difference calculated by
the hpet_calculate_diff function is limited to non-negative values.

cur_tick is calculated via hpet_get_ticks that uses qemu_get_clock_ns(vm_clock).

With -icount enabled vm_clock doesn't advance during qemu_run_timers
loop thus once difference is zero, qemu_run_timers loops forever
handling hpet_timer.

Limit hpet_calculate_diff results to positive only values to avoid that
infinite loop.

This fixes the following qemu-system-x86_64 hang when it reaches
timer_irq_works() in the linux bootup:

[    0.000000] Fast TSC calibration using PIT
[    0.000000] Detected 1000.054 MHz processor.
[    0.000031] Calibrating delay loop (skipped), value calculated using timer frequency.. 2000.10 BogoMIPS (lpj=10000540)
[    0.000404] pid_max: default: 32768 minimum: 301
[    0.001138] Mount-cache hash table entries: 256
[    0.003883] Initializing cgroup subsys ns
[    0.004035] Initializing cgroup subsys cpuacct
[    0.004280] Initializing cgroup subsys freezer
[    0.004790] Performance Events: AMD PMU driver.
[    0.004985] ... version:                0
[    0.005134] ... bit width:              48
[    0.005285] ... generic registers:      4
[    0.005437] ... value mask:             0000ffffffffffff
[    0.005625] ... max period:             00007fffffffffff
[    0.005807] ... fixed-purpose events:   0
[    0.005957] ... event mask:             000000000000000f
[    0.006275] SMP alternatives: switching to UP code

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 hw/hpet.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
Anthony Liguori - Nov. 9, 2011, 7:44 p.m.
On 11/08/2011 07:18 PM, Max Filippov wrote:
> hpet_timer timer callback rearms itself based on difference between
> current HPET tick counter and comparator value. Difference calculated by
> the hpet_calculate_diff function is limited to non-negative values.
>
> cur_tick is calculated via hpet_get_ticks that uses qemu_get_clock_ns(vm_clock).
>
> With -icount enabled vm_clock doesn't advance during qemu_run_timers
> loop thus once difference is zero, qemu_run_timers loops forever
> handling hpet_timer.
>
> Limit hpet_calculate_diff results to positive only values to avoid that
> infinite loop.
>
> This fixes the following qemu-system-x86_64 hang when it reaches
> timer_irq_works() in the linux bootup:
>
> [    0.000000] Fast TSC calibration using PIT
> [    0.000000] Detected 1000.054 MHz processor.
> [    0.000031] Calibrating delay loop (skipped), value calculated using timer frequency.. 2000.10 BogoMIPS (lpj=10000540)
> [    0.000404] pid_max: default: 32768 minimum: 301
> [    0.001138] Mount-cache hash table entries: 256
> [    0.003883] Initializing cgroup subsys ns
> [    0.004035] Initializing cgroup subsys cpuacct
> [    0.004280] Initializing cgroup subsys freezer
> [    0.004790] Performance Events: AMD PMU driver.
> [    0.004985] ... version:                0
> [    0.005134] ... bit width:              48
> [    0.005285] ... generic registers:      4
> [    0.005437] ... value mask:             0000ffffffffffff
> [    0.005625] ... max period:             00007fffffffffff
> [    0.005807] ... fixed-purpose events:   0
> [    0.005957] ... event mask:             000000000000000f
> [    0.006275] SMP alternatives: switching to UP code
>
> Signed-off-by: Max Filippov<jcmvbkbc@gmail.com>

Applied.  Thanks.

Regards,

Anthony Liguori

> ---
>   hw/hpet.c |    4 ++--
>   1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/hw/hpet.c b/hw/hpet.c
> index 12bd64d..6e6ea52 100644
> --- a/hw/hpet.c
> +++ b/hw/hpet.c
> @@ -157,14 +157,14 @@ static inline uint64_t hpet_calculate_diff(HPETTimer *t, uint64_t current)
>
>           cmp = (uint32_t)t->cmp;
>           diff = cmp - (uint32_t)current;
> -        diff = (int32_t)diff>  0 ? diff : (uint32_t)0;
> +        diff = (int32_t)diff>  0 ? diff : (uint32_t)1;
>           return (uint64_t)diff;
>       } else {
>           uint64_t diff, cmp;
>
>           cmp = t->cmp;
>           diff = cmp - current;
> -        diff = (int64_t)diff>  0 ? diff : (uint64_t)0;
> +        diff = (int64_t)diff>  0 ? diff : (uint64_t)1;
>           return diff;
>       }
>   }

Patch

diff --git a/hw/hpet.c b/hw/hpet.c
index 12bd64d..6e6ea52 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -157,14 +157,14 @@  static inline uint64_t hpet_calculate_diff(HPETTimer *t, uint64_t current)
 
         cmp = (uint32_t)t->cmp;
         diff = cmp - (uint32_t)current;
-        diff = (int32_t)diff > 0 ? diff : (uint32_t)0;
+        diff = (int32_t)diff > 0 ? diff : (uint32_t)1;
         return (uint64_t)diff;
     } else {
         uint64_t diff, cmp;
 
         cmp = t->cmp;
         diff = cmp - current;
-        diff = (int64_t)diff > 0 ? diff : (uint64_t)0;
+        diff = (int64_t)diff > 0 ? diff : (uint64_t)1;
         return diff;
     }
 }