static void hpet_set_timer(HPETState *h, unsigned int tn) { uint64_t tn_cmp, cur_tick, diff; unsigned int irq; unsigned int oneshot; ASSERT(tn < HPET_TIMER_NUM); ASSERT(spin_is_locked(&h->lock)); if ( (tn == 0) && (h->hpet.config & HPET_CFG_LEGACY) ) { /* HPET specification requires PIT shouldn't generate * interrupts if LegacyReplacementRoute is set for timer0 */ PITState *pit = &vhpet_domain(h)->arch.hvm_domain.pl_time.vpit; pit_stop_channel0_irq(pit); } if ( !timer_enabled(h, tn) ) return; tn_cmp = hpet_get_comparator(h, tn); cur_tick = hpet_read_maincounter(h); if ( timer_is_32bit(h, tn) ) { tn_cmp = (uint32_t)tn_cmp; cur_tick = (uint32_t)cur_tick; } diff = tn_cmp - cur_tick; /* * Detect time values set in the past. This is hard to do for 32-bit * comparators as the timer does not have to be set that far in the future * for the counter difference to wrap a 32-bit signed integer. We fudge * by looking for a 'small' time value in the past. */ if ( (int64_t)diff < 0 ) diff = (timer_is_32bit(h, tn) && (-diff > HPET_TINY_TIME_SPAN)) ? (uint32_t)diff : 0; if ( (tn <= 1) && (h->hpet.config & HPET_CFG_LEGACY) ) /* if LegacyReplacementRoute bit is set, HPET specification requires timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC, timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC. */ irq = (tn == 0) ? 0 : 8; else irq = timer_int_route(h, tn); /* * diff is the time from now when the timer should fire, for a periodic * timer we also need the period which may be different because time may * have elapsed between the time the comparator was written and the timer * being enabled (now). */ oneshot = !timer_is_periodic(h, tn); create_periodic_time(vhpet_vcpu(h), &h->pt[tn], hpet_tick_to_ns(h, diff), oneshot ? 0 : hpet_tick_to_ns(h, h->hpet.period[tn]), irq, NULL, NULL); }
static void aspeed_timer_expire(void *opaque) { AspeedTimer *t = opaque; bool interrupt = false; uint32_t ticks; if (!timer_enabled(t)) { return; } ticks = calculate_ticks(t, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); if (!ticks) { interrupt = timer_overflow_interrupt(t) || !t->match[0] || !t->match[1]; } else if (ticks <= MIN(t->match[0], t->match[1])) { interrupt = true; } else if (ticks <= MAX(t->match[0], t->match[1])) { interrupt = true; } if (interrupt) { t->level = !t->level; qemu_set_irq(t->irq, t->level); } aspeed_timer_mod(t); }
static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg, uint32_t value) { AspeedTimer *t; uint32_t old_reload; trace_aspeed_timer_set_value(timer, reg, value); t = &s->timers[timer]; switch (reg) { case TIMER_REG_RELOAD: old_reload = t->reload; t->reload = value; /* If the reload value was not previously set, or zero, and * the current value is valid, try to start the timer if it is * enabled. */ if (old_reload || !t->reload) { break; } case TIMER_REG_STATUS: if (timer_enabled(t)) { uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); int64_t delta = (int64_t) value - (int64_t) calculate_ticks(t, now); uint32_t rate = calculate_rate(t); t->start += muldiv64(delta, NANOSECONDS_PER_SECOND, rate); aspeed_timer_mod(t); } break; case TIMER_REG_MATCH_FIRST: case TIMER_REG_MATCH_SECOND: t->match[reg - 2] = value; if (timer_enabled(t)) { aspeed_timer_mod(t); } break; default: qemu_log_mask(LOG_UNIMP, "%s: Programming error: unexpected reg: %d\n", __func__, reg); break; } }
void Timer::update(uint cycles) { update_divider(cycles); if (timer_enabled()) { // Should this be here, or updated when TAC is written to in Memory? // Only update the frequency when counter reaches 0 / set counter to zero // when we update the frequency? update_clock_freq(); if (interrupt_pending) { // An overflow occured on the previous cycle // Reset TIMA and raise an interrupt memory.set8(Memory::IO::TIMA, memory.get8(Memory::IO::TMA)); cpu.raise_interrupt(LR35902::Interrupt::TIMER); interrupt_pending = false; } counter -= cycles; if (counter <= 0) { counter += cycles_per_tick; u8 TIMA = memory.get8(Memory::IO::TIMA); if (TIMA == 0xff) { // Overflow - raise an interrupt and reset TIMA on the next cycle interrupt_pending = true; } // 8-bit overflow expected: memory.set8(Memory::IO::TIMA, TIMA+1); } } }
int timer_device_enabled(const device_config *timer) { timer_state *state = get_safe_token(timer); return timer_enabled(state->timer); }
int timer_device_enabled(running_device *timer) { timer_state *state = get_safe_token(timer); return timer_enabled(state->timer); }