|
[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 |