Beispiel #1
0
Datei: rtc.c Projekt: Fantu/Xen
void rtc_reset(struct domain *d)
{
    RTCState *s = domain_vrtc(d);

    TRACE_0D(TRC_HVM_EMUL_RTC_STOP_TIMER);
    destroy_periodic_time(&s->pt);
    s->period = 0;
    s->pt.source = PTSRC_isa;
}
Beispiel #2
0
Datei: rtc.c Projekt: Fantu/Xen
void rtc_deinit(struct domain *d)
{
    RTCState *s = domain_vrtc(d);

    spin_barrier(&s->lock);

    TRACE_0D(TRC_HVM_EMUL_RTC_STOP_TIMER);
    destroy_periodic_time(&s->pt);
    kill_timer(&s->update_timer);
    kill_timer(&s->update_timer2);
    kill_timer(&s->alarm_timer);
}
Beispiel #3
0
Datei: rtc.c Projekt: 0day-ci/xen
/* Enable/configure/disable the periodic timer based on the RTC_PIE and
 * RTC_RATE_SELECT settings */
static void rtc_timer_update(RTCState *s)
{
    int period_code, period, delta;
    struct vcpu *v = vrtc_vcpu(s);

    ASSERT(spin_is_locked(&s->lock));

    s->pt_dead_ticks = 0;

    period_code = s->hw.cmos_data[RTC_REG_A] & RTC_RATE_SELECT;
    switch ( s->hw.cmos_data[RTC_REG_A] & RTC_DIV_CTL )
    {
    case RTC_REF_CLCK_32KHZ:
        if ( (period_code != 0) && (period_code <= 2) )
            period_code += 7;
        /* fall through */
    case RTC_REF_CLCK_1MHZ:
    case RTC_REF_CLCK_4MHZ:
        if ( period_code != 0 )
        {
            period = 1 << (period_code - 1); /* period in 32 Khz cycles */
            period = DIV_ROUND(period * 1000000000ULL, 32768); /* in ns */
            if ( period != s->period )
            {
                s_time_t now = NOW();

                s->period = period;
                if ( v->domain->arch.hvm_domain.params[HVM_PARAM_VPT_ALIGN] )
                    delta = 0;
                else
                    delta = period - ((now - s->start_time) % period);
                if ( s->hw.cmos_data[RTC_REG_B] & RTC_PIE )
                {
                    TRACE_2D(TRC_HVM_EMUL_RTC_START_TIMER, delta, period);
                    create_periodic_time(v, &s->pt, delta, period,
                                         RTC_IRQ, rtc_pf_callback, s);
                }
                else
                    s->check_ticks_since = now;
            }
            break;
        }
        /* fall through */
    default:
        TRACE_0D(TRC_HVM_EMUL_RTC_STOP_TIMER);
        destroy_periodic_time(&s->pt);
        s->period = 0;
        break;
    }
}
Beispiel #4
0
Datei: rtc.c Projekt: 0day-ci/xen
/* Called by the VPT code after it's injected a PF interrupt for us.
 * Fix up the register state to reflect what happened. */
static void rtc_pf_callback(struct vcpu *v, void *opaque)
{
    RTCState *s = opaque;

    spin_lock(&s->lock);

    if ( !rtc_mode_is(s, no_ack)
         && (s->hw.cmos_data[RTC_REG_C] & RTC_IRQF)
         && ++(s->pt_dead_ticks) >= 10 )
    {
        /* VM is ignoring its RTC; no point in running the timer */
        TRACE_0D(TRC_HVM_EMUL_RTC_STOP_TIMER);
        destroy_periodic_time(&s->pt);
        s->period = 0;
    }

    s->hw.cmos_data[RTC_REG_C] |= RTC_PF|RTC_IRQF;

    spin_unlock(&s->lock);
}
Beispiel #5
0
Datei: rtc.c Projekt: 0day-ci/xen
static int rtc_ioport_write(void *opaque, uint32_t addr, uint32_t data)
{
    RTCState *s = opaque;
    struct domain *d = vrtc_domain(s);
    uint32_t orig;

    spin_lock(&s->lock);

    if ( (addr & 1) == 0 )
    {
        data &= 0x7f;
        s->hw.cmos_index = data;
        spin_unlock(&s->lock);
        return (data < RTC_CMOS_SIZE);
    }

    if ( s->hw.cmos_index >= RTC_CMOS_SIZE )
    {
        spin_unlock(&s->lock);
        return 0;
    }

    orig = s->hw.cmos_data[s->hw.cmos_index];
    switch ( s->hw.cmos_index )
    {
    case RTC_SECONDS_ALARM:
    case RTC_MINUTES_ALARM:
    case RTC_HOURS_ALARM:
        s->hw.cmos_data[s->hw.cmos_index] = data;
        alarm_timer_update(s);
        break;
    case RTC_SECONDS:
    case RTC_MINUTES:
    case RTC_HOURS:
    case RTC_DAY_OF_WEEK:
    case RTC_DAY_OF_MONTH:
    case RTC_MONTH:
    case RTC_YEAR:
        /* if in set mode, just write the register */
        if ( (s->hw.cmos_data[RTC_REG_B] & RTC_SET) )
            s->hw.cmos_data[s->hw.cmos_index] = data;
        else
        {
            /* Fetch the current time and update just this field. */
            s->current_tm = gmtime(get_localtime(d));
            rtc_copy_date(s);
            s->hw.cmos_data[s->hw.cmos_index] = data;
            rtc_set_time(s);
        }
        alarm_timer_update(s);
        break;
    case RTC_REG_A:
        /* UIP bit is read only */
        s->hw.cmos_data[RTC_REG_A] = (data & ~RTC_UIP) | (orig & RTC_UIP);
        if ( (data ^ orig) & ~RTC_UIP )
            rtc_timer_update(s);
        break;
    case RTC_REG_B:
        if ( data & RTC_SET )
        {
            /* set mode: reset UIP mode */
            s->hw.cmos_data[RTC_REG_A] &= ~RTC_UIP;
            /* adjust cmos before stopping */
            if (!(orig & RTC_SET))
            {
                s->current_tm = gmtime(get_localtime(d));
                rtc_copy_date(s);
            }
        }
        else
        {
            /* if disabling set mode, update the time */
            if ( orig & RTC_SET )
                rtc_set_time(s);
        }
        check_for_pf_ticks(s);
        s->hw.cmos_data[RTC_REG_B] = data;
        /*
         * If the interrupt is already set when the interrupt becomes
         * enabled, raise an interrupt immediately.
         */
        rtc_update_irq(s);
        if ( (data ^ orig) & RTC_PIE )
        {
            TRACE_0D(TRC_HVM_EMUL_RTC_STOP_TIMER);
            destroy_periodic_time(&s->pt);
            s->period = 0;
            rtc_timer_update(s);
        }
        if ( (data ^ orig) & RTC_SET )
            check_update_timer(s);
        if ( (data ^ orig) & (RTC_24H | RTC_DM_BINARY | RTC_SET) )
            alarm_timer_update(s);
        break;
    case RTC_REG_C:
    case RTC_REG_D:
        /* cannot write to them */
        break;
    }

    spin_unlock(&s->lock);

    return 1;
}