Beispiel #1
0
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);
}
Beispiel #2
0
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);
}
Beispiel #3
0
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;
    }
}
Beispiel #4
0
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);
    }
  }
}
Beispiel #5
0
int timer_device_enabled(const device_config *timer)
{
	timer_state *state = get_safe_token(timer);
	return timer_enabled(state->timer);
}
Beispiel #6
0
int timer_device_enabled(running_device *timer)
{
	timer_state *state = get_safe_token(timer);
	return timer_enabled(state->timer);
}