/* 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; } }
/* 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 ) { if ( period_code != s->pt_code ) { s->pt_code = period_code; period = 1 << (period_code - 1); /* period in 32 Khz cycles */ period = DIV_ROUND(period * 1000000000ULL, 32768); /* in ns */ if ( v->domain->arch.hvm_domain.params[HVM_PARAM_VPT_ALIGN] ) delta = 0; else delta = period - ((NOW() - s->start_time) % period); create_periodic_time(v, &s->pt, delta, period, RTC_IRQ, NULL, s); } break; } /* fall through */ default: destroy_periodic_time(&s->pt); s->pt_code = 0; break; } }
/* 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; struct vcpu *v = vrtc_vcpu(s); ASSERT(spin_is_locked(&s->lock)); period_code = s->hw.cmos_data[RTC_REG_A] & RTC_RATE_SELECT; if ( (period_code != 0) && (s->hw.cmos_data[RTC_REG_B] & RTC_PIE) ) { if ( period_code <= 2 ) period_code += 7; period = 1 << (period_code - 1); /* period in 32 Khz cycles */ period = DIV_ROUND((period * 1000000000ULL), 32768); /* period in ns */ create_periodic_time(v, &s->pt, period, period, RTC_IRQ, rtc_periodic_cb, s); } else { destroy_periodic_time(&s->pt); } }