diff options
Diffstat (limited to 'hw/core/ptimer.c')
-rw-r--r-- | hw/core/ptimer.c | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c index ed3fb6c66d..2a69dafca6 100644 --- a/hw/core/ptimer.c +++ b/hw/core/ptimer.c @@ -48,7 +48,7 @@ static void ptimer_reload(ptimer_state *s, int delta_adjust) ptimer_trigger(s); } - if (delta == 0) { + if (delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_RELOAD)) { delta = s->delta = s->limit; } @@ -79,6 +79,12 @@ static void ptimer_reload(ptimer_state *s, int delta_adjust) } } + if (delta == 0 && (s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_RELOAD)) { + if (s->enabled == 1 && s->limit != 0) { + delta = 1; + } + } + if (delta == 0) { if (!qtest_enabled()) { fprintf(stderr, "Timer with delta zero, disabling\n"); @@ -113,21 +119,36 @@ static void ptimer_reload(ptimer_state *s, int delta_adjust) static void ptimer_tick(void *opaque) { ptimer_state *s = (ptimer_state *)opaque; - ptimer_trigger(s); - s->delta = 0; + bool trigger = true; + if (s->enabled == 2) { + s->delta = 0; s->enabled = 0; } else { int delta_adjust = DELTA_ADJUST; - if (s->limit == 0) { + if (s->delta == 0 || s->limit == 0) { /* If a "continuous trigger" policy is not used and limit == 0, - we should error out. */ + we should error out. delta == 0 means that this tick is + caused by a "no immediate reload" policy, so it shouldn't + be adjusted. */ delta_adjust = DELTA_NO_ADJUST; } + if (!(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)) { + /* Avoid re-trigger on deferred reload if "no immediate trigger" + policy isn't used. */ + trigger = (delta_adjust == DELTA_ADJUST); + } + + s->delta = s->limit; + ptimer_reload(s, delta_adjust); } + + if (trigger) { + ptimer_trigger(s); + } } uint64_t ptimer_get_count(ptimer_state *s) |