示例#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);
}
示例#2
0
文件: hpet.c 项目: CrazyXen/XEN_CODE
static uint64_t hpet_get_comparator(HPETState *h, unsigned int tn)
{
    uint64_t comparator;
    uint64_t elapsed;

    comparator = h->hpet.comparator64[tn];
    if ( timer_is_periodic(h, tn) )
    {
        /* update comparator by number of periods elapsed since last update */
        uint64_t period = h->hpet.period[tn];
        if (period)
        {
            elapsed = hpet_read_maincounter(h) + period - 1 - comparator;
            comparator += (elapsed / period) * period;
            h->hpet.comparator64[tn] = comparator;
        }
    }
    
    /* truncate if timer is in 32 bit mode */
    if ( timer_is_32bit(h, tn) )
        comparator = (uint32_t)comparator;
    h->hpet.timers[tn].cmp = comparator;
    return comparator;
}