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


  • To: xen-changelog@xxxxxxxxxxxxxxxxxxx
  • From: Xen patchbot-unstable <patchbot@xxxxxxx>
  • Date: Fri, 14 Sep 2012 10:55:30 +0000
  • Delivery-date: Fri, 14 Sep 2012 10:55:54 +0000
  • List-id: "Change log for Mercurial \(receive only\)" <xen-changelog.lists.xen.org>

# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.