diff options
-rw-r--r-- | hw/core/ptimer.c | 20 | ||||
-rw-r--r-- | include/hw/ptimer.h | 4 |
2 files changed, 20 insertions, 4 deletions
diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c index 1aa019447f..ed3fb6c66d 100644 --- a/hw/core/ptimer.c +++ b/hw/core/ptimer.c @@ -13,7 +13,8 @@ #include "sysemu/replay.h" #include "sysemu/qtest.h" -#define DELTA_ADJUST 1 +#define DELTA_ADJUST 1 +#define DELTA_NO_ADJUST -1 struct ptimer_state { @@ -43,8 +44,11 @@ static void ptimer_reload(ptimer_state *s, int delta_adjust) uint64_t period = s->period; uint64_t delta = s->delta; - if (delta == 0) { + if (delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)) { ptimer_trigger(s); + } + + if (delta == 0) { delta = s->delta = s->limit; } @@ -58,7 +62,9 @@ static void ptimer_reload(ptimer_state *s, int delta_adjust) } if (s->policy_mask & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD) { - delta += delta_adjust; + if (delta_adjust != DELTA_NO_ADJUST) { + delta += delta_adjust; + } } if (delta == 0 && (s->policy_mask & PTIMER_POLICY_CONTINUOUS_TRIGGER)) { @@ -67,6 +73,12 @@ static void ptimer_reload(ptimer_state *s, int delta_adjust) } } + if (delta == 0 && (s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)) { + if (delta_adjust != DELTA_NO_ADJUST) { + delta = 1; + } + } + if (delta == 0) { if (!qtest_enabled()) { fprintf(stderr, "Timer with delta zero, disabling\n"); @@ -111,7 +123,7 @@ static void ptimer_tick(void *opaque) if (s->limit == 0) { /* If a "continuous trigger" policy is not used and limit == 0, we should error out. */ - delta_adjust = 0; + delta_adjust = DELTA_NO_ADJUST; } ptimer_reload(s, delta_adjust); diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h index b2fb4f9864..911cc11bac 100644 --- a/include/hw/ptimer.h +++ b/include/hw/ptimer.h @@ -43,6 +43,10 @@ * re-trigger every period. */ #define PTIMER_POLICY_CONTINUOUS_TRIGGER (1 << 1) +/* Starting to run with/setting counter to "0" won't trigger immediately, + * but after a one period for both oneshot and periodic modes. */ +#define PTIMER_POLICY_NO_IMMEDIATE_TRIGGER (1 << 2) + /* ptimer.c */ typedef struct ptimer_state ptimer_state; typedef void (*ptimer_cb)(void *opaque); |