[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Revert 25843:51090fe1ab97 (x86/HVM: assorted RTC emulation adjustments)
# HG changeset patch # User Jan Beulich # Date 1347449068 -7200 # Node ID 05d82fb18335ecf4abf5ab9483d2f9929e478a54 # Parent 35fa512c60b2bb8e907e4c7cd3a3ef98bc671cfb Revert 25843:51090fe1ab97 (x86/HVM: assorted RTC emulation adjustments) This was found to cause RHEL6 HVM guests to hang during shutdown. --- diff -r 35fa512c60b2 -r 05d82fb18335 xen/arch/x86/hvm/rtc.c --- a/xen/arch/x86/hvm/rtc.c Wed Sep 12 10:21:21 2012 +0200 +++ b/xen/arch/x86/hvm/rtc.c Wed Sep 12 13:24:28 2012 +0200 @@ -50,24 +50,11 @@ static void rtc_set_time(RTCState *s); static inline int from_bcd(RTCState *s, int a); static inline int convert_hour(RTCState *s, int hour); -static void rtc_toggle_irq(RTCState *s) -{ - struct domain *d = vrtc_domain(s); - - ASSERT(spin_is_locked(&s->lock)); - s->hw.cmos_data[RTC_REG_C] |= RTC_IRQF; - hvm_isa_irq_deassert(d, RTC_IRQ); - hvm_isa_irq_assert(d, RTC_IRQ); -} - -void rtc_periodic_interrupt(void *opaque) +static void rtc_periodic_cb(struct vcpu *v, void *opaque) { RTCState *s = opaque; - spin_lock(&s->lock); - s->hw.cmos_data[RTC_REG_C] |= RTC_PF; - if ( s->hw.cmos_data[RTC_REG_B] & RTC_PIE ) - rtc_toggle_irq(s); + s->hw.cmos_data[RTC_REG_C] |= 0xc0; spin_unlock(&s->lock); } @@ -81,25 +68,19 @@ static void rtc_timer_update(RTCState *s ASSERT(spin_is_locked(&s->lock)); period_code = s->hw.cmos_data[RTC_REG_A] & RTC_RATE_SELECT; - switch ( s->hw.cmos_data[RTC_REG_A] & RTC_DIV_CTL ) + if ( (period_code != 0) && (s->hw.cmos_data[RTC_REG_B] & RTC_PIE) ) { - case RTC_REF_CLCK_32KHZ: - if ( (period_code != 0) && (period_code <= 2) ) + if ( 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 */ - create_periodic_time(v, &s->pt, period, period, RTC_IRQ, NULL, s); - break; - } - /* fall through */ - default: + + 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); - break; } } @@ -121,7 +102,7 @@ static void check_update_timer(RTCState guest_usec = get_localtime_us(d) % USEC_PER_SEC; if (guest_usec >= (USEC_PER_SEC - 244)) { - /* RTC is in update cycle */ + /* RTC is in update cycle when enabling UIE */ s->hw.cmos_data[RTC_REG_A] |= RTC_UIP; next_update_time = (USEC_PER_SEC - guest_usec) * NS_PER_USEC; expire_time = NOW() + next_update_time; @@ -163,6 +144,7 @@ static void rtc_update_timer(void *opaqu static void rtc_update_timer2(void *opaque) { RTCState *s = opaque; + struct domain *d = vrtc_domain(s); spin_lock(&s->lock); if (!(s->hw.cmos_data[RTC_REG_B] & RTC_SET)) @@ -170,7 +152,11 @@ static void rtc_update_timer2(void *opaq s->hw.cmos_data[RTC_REG_C] |= RTC_UF; s->hw.cmos_data[RTC_REG_A] &= ~RTC_UIP; if ((s->hw.cmos_data[RTC_REG_B] & RTC_UIE)) - rtc_toggle_irq(s); + { + s->hw.cmos_data[RTC_REG_C] |= RTC_IRQF; + hvm_isa_irq_deassert(d, RTC_IRQ); + hvm_isa_irq_assert(d, RTC_IRQ); + } check_update_timer(s); } spin_unlock(&s->lock); @@ -189,18 +175,21 @@ static void alarm_timer_update(RTCState stop_timer(&s->alarm_timer); - if ( !(s->hw.cmos_data[RTC_REG_B] & RTC_SET) ) + if ((s->hw.cmos_data[RTC_REG_B] & RTC_AIE) && + !(s->hw.cmos_data[RTC_REG_B] & RTC_SET)) { s->current_tm = gmtime(get_localtime(d)); rtc_copy_date(s); alarm_sec = from_bcd(s, s->hw.cmos_data[RTC_SECONDS_ALARM]); alarm_min = from_bcd(s, s->hw.cmos_data[RTC_MINUTES_ALARM]); - alarm_hour = convert_hour(s, s->hw.cmos_data[RTC_HOURS_ALARM]); + alarm_hour = from_bcd(s, s->hw.cmos_data[RTC_HOURS_ALARM]); + alarm_hour = convert_hour(s, alarm_hour); cur_sec = from_bcd(s, s->hw.cmos_data[RTC_SECONDS]); cur_min = from_bcd(s, s->hw.cmos_data[RTC_MINUTES]); - cur_hour = convert_hour(s, s->hw.cmos_data[RTC_HOURS]); + cur_hour = from_bcd(s, s->hw.cmos_data[RTC_HOURS]); + cur_hour = convert_hour(s, cur_hour); next_update_time = USEC_PER_SEC - (get_localtime_us(d) % USEC_PER_SEC); next_update_time = next_update_time * NS_PER_USEC + NOW(); @@ -354,6 +343,7 @@ static void alarm_timer_update(RTCState static void rtc_alarm_cb(void *opaque) { RTCState *s = opaque; + struct domain *d = vrtc_domain(s); spin_lock(&s->lock); if (!(s->hw.cmos_data[RTC_REG_B] & RTC_SET)) @@ -361,7 +351,11 @@ static void rtc_alarm_cb(void *opaque) s->hw.cmos_data[RTC_REG_C] |= RTC_AF; /* alarm interrupt */ if (s->hw.cmos_data[RTC_REG_B] & RTC_AIE) - rtc_toggle_irq(s); + { + s->hw.cmos_data[RTC_REG_C] |= RTC_IRQF; + hvm_isa_irq_deassert(d, RTC_IRQ); + hvm_isa_irq_assert(d, RTC_IRQ); + } alarm_timer_update(s); } spin_unlock(&s->lock); @@ -371,7 +365,7 @@ static int rtc_ioport_write(void *opaque { RTCState *s = opaque; struct domain *d = vrtc_domain(s); - uint32_t orig, mask; + uint32_t orig; spin_lock(&s->lock); @@ -423,7 +417,7 @@ static int rtc_ioport_write(void *opaque /* set mode: reset UIP mode */ s->hw.cmos_data[RTC_REG_A] &= ~RTC_UIP; /* adjust cmos before stopping */ - if (!(orig & RTC_SET)) + if (!(s->hw.cmos_data[RTC_REG_B] & RTC_SET)) { s->current_tm = gmtime(get_localtime(d)); rtc_copy_date(s); @@ -432,26 +426,22 @@ static int rtc_ioport_write(void *opaque else { /* if disabling set mode, update the time */ - if ( orig & RTC_SET ) + if ( s->hw.cmos_data[RTC_REG_B] & RTC_SET ) rtc_set_time(s); } - /* - * If the interrupt is already set when the interrupt becomes - * enabled, raise an interrupt immediately. - * NB: RTC_{A,P,U}IE == RTC_{A,P,U}F respectively. - */ - for ( mask = RTC_UIE; mask <= RTC_PIE; mask <<= 1 ) - if ( (data & mask) && !(orig & mask) && - (s->hw.cmos_data[RTC_REG_C] & mask) ) + /* if the interrupt is already set when the interrupt become + * enabled, raise an interrupt immediately*/ + if ((data & RTC_UIE) && !(s->hw.cmos_data[RTC_REG_B] & RTC_UIE)) + if (s->hw.cmos_data[RTC_REG_C] & RTC_UF) { - rtc_toggle_irq(s); - break; + hvm_isa_irq_deassert(d, RTC_IRQ); + hvm_isa_irq_assert(d, RTC_IRQ); } s->hw.cmos_data[RTC_REG_B] = data; - if ( (data ^ orig) & RTC_SET ) - check_update_timer(s); - if ( (data ^ orig) & (RTC_24H | RTC_DM_BINARY | RTC_SET) ) - alarm_timer_update(s); + if ( (data ^ orig) & RTC_PIE ) + rtc_timer_update(s); + check_update_timer(s); + alarm_timer_update(s); break; case RTC_REG_C: case RTC_REG_D: @@ -466,7 +456,7 @@ static int rtc_ioport_write(void *opaque static inline int to_bcd(RTCState *s, int a) { - if ( s->hw.cmos_data[RTC_REG_B] & RTC_DM_BINARY ) + if ( s->hw.cmos_data[RTC_REG_B] & 0x04 ) return a; else return ((a / 10) << 4) | (a % 10); @@ -474,7 +464,7 @@ static inline int to_bcd(RTCState *s, in static inline int from_bcd(RTCState *s, int a) { - if ( s->hw.cmos_data[RTC_REG_B] & RTC_DM_BINARY ) + if ( s->hw.cmos_data[RTC_REG_B] & 0x04 ) return a; else return ((a >> 4) * 10) + (a & 0x0f); @@ -482,14 +472,12 @@ static inline int from_bcd(RTCState *s, /* Hours in 12 hour mode are in 1-12 range, not 0-11. * So we need convert it before using it*/ -static inline int convert_hour(RTCState *s, int raw) +static inline int convert_hour(RTCState *s, int hour) { - int hour = from_bcd(s, raw & 0x7f); - if (!(s->hw.cmos_data[RTC_REG_B] & RTC_24H)) { hour %= 12; - if (raw & 0x80) + if (s->hw.cmos_data[RTC_HOURS] & 0x80) hour += 12; } return hour; @@ -508,7 +496,8 @@ static void rtc_set_time(RTCState *s) tm->tm_sec = from_bcd(s, s->hw.cmos_data[RTC_SECONDS]); tm->tm_min = from_bcd(s, s->hw.cmos_data[RTC_MINUTES]); - tm->tm_hour = convert_hour(s, s->hw.cmos_data[RTC_HOURS]); + tm->tm_hour = from_bcd(s, s->hw.cmos_data[RTC_HOURS] & 0x7f); + tm->tm_hour = convert_hour(s, tm->tm_hour); tm->tm_wday = from_bcd(s, s->hw.cmos_data[RTC_DAY_OF_WEEK]); tm->tm_mday = from_bcd(s, s->hw.cmos_data[RTC_DAY_OF_MONTH]); tm->tm_mon = from_bcd(s, s->hw.cmos_data[RTC_MONTH]) - 1; diff -r 35fa512c60b2 -r 05d82fb18335 xen/arch/x86/hvm/vpt.c --- a/xen/arch/x86/hvm/vpt.c Wed Sep 12 10:21:21 2012 +0200 +++ b/xen/arch/x86/hvm/vpt.c Wed Sep 12 13:24:28 2012 +0200 @@ -22,7 +22,6 @@ #include <asm/hvm/vpt.h> #include <asm/event.h> #include <asm/apic.h> -#include <asm/mc146818rtc.h> #define mode_is(d, name) \ ((d)->arch.hvm_domain.params[HVM_PARAM_TIMER_MODE] == HVMPTM_##name) @@ -219,7 +218,6 @@ void pt_update_irq(struct vcpu *v) struct periodic_time *pt, *temp, *earliest_pt = NULL; uint64_t max_lag = -1ULL; int irq, is_lapic; - void *pt_priv; spin_lock(&v->arch.hvm_vcpu.tm_lock); @@ -253,14 +251,13 @@ void pt_update_irq(struct vcpu *v) earliest_pt->irq_issued = 1; irq = earliest_pt->irq; is_lapic = (earliest_pt->source == PTSRC_lapic); - pt_priv = earliest_pt->priv; spin_unlock(&v->arch.hvm_vcpu.tm_lock); if ( is_lapic ) + { vlapic_set_irq(vcpu_vlapic(v), irq, 0); - else if ( irq == RTC_IRQ && pt_priv ) - rtc_periodic_interrupt(pt_priv); + } else { hvm_isa_irq_deassert(v->domain, irq); diff -r 35fa512c60b2 -r 05d82fb18335 xen/include/asm-x86/hvm/vpt.h --- a/xen/include/asm-x86/hvm/vpt.h Wed Sep 12 10:21:21 2012 +0200 +++ b/xen/include/asm-x86/hvm/vpt.h Wed Sep 12 13:24:28 2012 +0200 @@ -181,7 +181,6 @@ void rtc_migrate_timers(struct vcpu *v); void rtc_deinit(struct domain *d); void rtc_reset(struct domain *d); void rtc_update_clock(struct domain *d); -void rtc_periodic_interrupt(void *); void pmtimer_init(struct vcpu *v); void pmtimer_deinit(struct domain *d); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |