qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 5/7] RTC:Add RTC update-ended interrupt support
@ 2012-03-19  6:14 Zhang, Yang Z
  2012-03-20 18:04 ` Stefano Stabellini
  0 siblings, 1 reply; 10+ messages in thread
From: Zhang, Yang Z @ 2012-03-19  6:14 UTC (permalink / raw)
  To: qemu-devel@nongnu.org
  Cc: Paolo Bonzini, aliguori@us.ibm.com, kvm@vger.kernel.org

Use a timer to emulate update cycle. When update cycle ended and UIE is setting, then raise an interrupt. The timer runs only when UF or AF is cleared.

Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com>
---
 hw/mc146818rtc.c |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 80 insertions(+), 6 deletions(-)

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 5e7fbb5..fae049e 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -97,6 +97,11 @@ typedef struct RTCState {
     /* periodic timer */
     QEMUTimer *periodic_timer;
     int64_t next_periodic_time;
+    /* update-ended timer */
+    QEMUTimer *update_timer;
+    QEMUTimer *update_timer2;
+    uint64_t next_update_time;
+    uint32_t use_timer;
     uint16_t irq_reinject_on_ack_count;
     uint32_t irq_coalesced;
     uint32_t period;
@@ -157,7 +162,8 @@ static void rtc_coalesced_timer(void *opaque)
 }
 #endif

-static void rtc_timer_update(RTCState *s, int64_t current_time)
+/* handle periodic timer */
+static void periodic_timer_update(RTCState *s, int64_t current_time)
 {
     int period_code, period;
     int64_t cur_clock, next_irq_clock;
@@ -195,7 +201,7 @@ static void rtc_periodic_timer(void *opaque)
 {
     RTCState *s = opaque;

-    rtc_timer_update(s, s->next_periodic_time);
+    periodic_timer_update(s, s->next_periodic_time);
     s->cmos_data[RTC_REG_C] |= REG_C_PF;
     if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
         s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
@@ -222,6 +228,58 @@ static void rtc_periodic_timer(void *opaque)
     }
 }

+/* handle update-ended timer */
+static void check_update_timer(RTCState *s)
+{
+    uint64_t next_update_time, expire_time;
+    uint64_t guest_usec;
+    qemu_del_timer(s->update_timer);
+    qemu_del_timer(s->update_timer2);
+
+    if (!((s->cmos_data[RTC_REG_C] & (REG_C_UF | REG_C_AF)) ==
+            (REG_C_UF | REG_C_AF)) && !(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+        s->use_timer = 1;
+        guest_usec = get_guest_rtc_us(s) % USEC_PER_SEC;
+        if (guest_usec >= (USEC_PER_SEC - 244)) {
+            /* RTC is in update cycle when enabling UIE */
+            s->cmos_data[RTC_REG_A] |= REG_A_UIP;
+            next_update_time = (USEC_PER_SEC - guest_usec) * NS_PER_USEC;
+            expire_time = qemu_get_clock_ns(rtc_clock) + next_update_time;
+            qemu_mod_timer(s->update_timer2, expire_time);
+        } else {
+            next_update_time = (USEC_PER_SEC - guest_usec - 244) * NS_PER_USEC;
+            expire_time = qemu_get_clock_ns(rtc_clock) + next_update_time;
+            s->next_update_time = expire_time;
+            qemu_mod_timer(s->update_timer, expire_time);
+        }
+    } else {
+        s->use_timer = 0;
+    }
+}
+
+static void rtc_update_timer(void *opaque)
+{
+    RTCState *s = opaque;
+
+    if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+        s->cmos_data[RTC_REG_A] |= REG_A_UIP;
+        qemu_mod_timer(s->update_timer2, s->next_update_time + 244000UL);
+    }
+}
+
+static void rtc_update_timer2(void *opaque)
+{
+    RTCState *s = opaque;
+
+    if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+        s->cmos_data[RTC_REG_C] |= REG_C_UF;
+        s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
+        s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
+        qemu_irq_raise(s->irq);
+    }
+    check_update_timer(s);
+}
+
 static void rtc_set_offset(RTCState *s, int32_t start_usec)
 {
     struct tm *tm = &s->current_tm;
@@ -283,13 +341,14 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
                     rtc_calibrate_time(s);
                     rtc_set_offset(s, 500000);
                     s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
+                    check_update_timer(s);
                     divider_reset = 0;
                 }
             }
             /* UIP bit is read only */
             s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
                 (s->cmos_data[RTC_REG_A] & REG_A_UIP);
-            rtc_timer_update(s, qemu_get_clock_ns(rtc_clock));
+            periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
             break;
         case RTC_REG_B:
             if (data & REG_B_SET) {
@@ -315,7 +374,8 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
                 }
             }
             s->cmos_data[RTC_REG_B] = data;
-            rtc_timer_update(s, qemu_get_clock_ns(rtc_clock));
+            periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
+            check_update_timer(s);
             break;
         case RTC_REG_C:
         case RTC_REG_D:
@@ -445,7 +505,7 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
             break;
         case RTC_REG_A:
             ret = s->cmos_data[s->cmos_index];
-            if (update_in_progress(s)) {
+            if ((s->use_timer == 0) && update_in_progress(s)) {
                 ret |= REG_A_UIP;
             }
             break;
@@ -453,6 +513,12 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
             ret = s->cmos_data[s->cmos_index];
             qemu_irq_lower(s->irq);
             s->cmos_data[RTC_REG_C] = 0x00;
+            if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+                rtc_calibrate_time(s);
+            }
+            if (ret & (REG_C_UF | REG_C_AF)) {
+                check_update_timer(s);
+            }
 #ifdef TARGET_I386
             if(s->irq_coalesced &&
                     (s->cmos_data[RTC_REG_B] & REG_B_PIE) &&
@@ -545,6 +611,9 @@ static const VMStateDescription vmstate_rtc = {
         VMSTATE_INT32(offset_usec, RTCState),
         VMSTATE_TIMER(periodic_timer, RTCState),
         VMSTATE_INT64(next_periodic_time, RTCState),
+        VMSTATE_TIMER(update_timer, RTCState),
+        VMSTATE_TIMER(update_timer2, RTCState),
+        VMSTATE_UINT64(next_update_time, RTCState),
         VMSTATE_UINT32_V(irq_coalesced, RTCState, 2),
         VMSTATE_UINT32_V(period, RTCState, 2),
         VMSTATE_END_OF_LIST()
@@ -557,7 +626,8 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data)
     int64_t now = *(int64_t *)data;

     rtc_set_date_from_host(&s->dev);
-    rtc_timer_update(s, now);
+    periodic_timer_update(s, now);
+    check_update_timer(s);
 #ifdef TARGET_I386
     if (s->lost_tick_policy == LOST_TICK_SLEW) {
         rtc_coalesced_timer_update(s);
@@ -579,6 +649,7 @@ static void rtc_reset(void *opaque)

     s->cmos_data[RTC_REG_B] &= ~(REG_B_PIE | REG_B_AIE | REG_B_SQWE);
     s->cmos_data[RTC_REG_C] &= ~(REG_C_UF | REG_C_IRQF | REG_C_PF | REG_C_AF);
+    check_update_timer(s);

     qemu_irq_lower(s->irq);

@@ -649,6 +720,9 @@ static int rtc_initfn(ISADevice *dev)
 #endif

     s->periodic_timer = qemu_new_timer_ns(rtc_clock, rtc_periodic_timer, s);
+    s->update_timer = qemu_new_timer_ns(rtc_clock, rtc_update_timer, s);
+    s->update_timer2 = qemu_new_timer_ns(rtc_clock, rtc_update_timer2, s);
+    check_update_timer(s);

     s->clock_reset_notifier.notify = rtc_notify_clock_reset;
     qemu_register_clock_reset_notifier(rtc_clock, &s->clock_reset_notifier);
--
1.7.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v4 5/7] RTC:Add RTC update-ended interrupt support
  2012-03-19  6:14 [Qemu-devel] [PATCH v4 5/7] RTC:Add RTC update-ended interrupt support Zhang, Yang Z
@ 2012-03-20 18:04 ` Stefano Stabellini
  2012-03-20 18:35   ` Stefano Stabellini
  2012-03-22  0:04   ` Zhang, Yang Z
  0 siblings, 2 replies; 10+ messages in thread
From: Stefano Stabellini @ 2012-03-20 18:04 UTC (permalink / raw)
  To: Zhang, Yang Z
  Cc: Paolo Bonzini, aliguori@us.ibm.com, qemu-devel@nongnu.org,
	kvm@vger.kernel.org

On Mon, 19 Mar 2012, Zhang, Yang Z wrote:
> Use a timer to emulate update cycle. When update cycle ended and UIE is setting, then raise an interrupt. The timer runs only when UF or AF is cleared.

The idea is that if the user requests the update-ended interrupt (UIE)
we setup a timer to inject it at the right time into the guest and
another timer to update the UIP bit, correct?
But do we actually need the second timer? Why can't we just update the
UIP bit whenever the user tries to read reg A, as we do when UIE is not set?


Also I am not sure it is a great idea to rename rtc_timer_update into
periodic_timer_update in the same patch where you introduce this new
logic.


> Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com>
> ---
>  hw/mc146818rtc.c |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++----
>  1 files changed, 80 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
> index 5e7fbb5..fae049e 100644
> --- a/hw/mc146818rtc.c
> +++ b/hw/mc146818rtc.c
> @@ -97,6 +97,11 @@ typedef struct RTCState {
>      /* periodic timer */
>      QEMUTimer *periodic_timer;
>      int64_t next_periodic_time;
> +    /* update-ended timer */
> +    QEMUTimer *update_timer;
> +    QEMUTimer *update_timer2;
> +    uint64_t next_update_time;
> +    uint32_t use_timer;
>      uint16_t irq_reinject_on_ack_count;
>      uint32_t irq_coalesced;
>      uint32_t period;
> @@ -157,7 +162,8 @@ static void rtc_coalesced_timer(void *opaque)
>  }
>  #endif
> 
> -static void rtc_timer_update(RTCState *s, int64_t current_time)
> +/* handle periodic timer */
> +static void periodic_timer_update(RTCState *s, int64_t current_time)
>  {
>      int period_code, period;
>      int64_t cur_clock, next_irq_clock;
> @@ -195,7 +201,7 @@ static void rtc_periodic_timer(void *opaque)
>  {
>      RTCState *s = opaque;
> 
> -    rtc_timer_update(s, s->next_periodic_time);
> +    periodic_timer_update(s, s->next_periodic_time);
>      s->cmos_data[RTC_REG_C] |= REG_C_PF;
>      if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
>          s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
> @@ -222,6 +228,58 @@ static void rtc_periodic_timer(void *opaque)
>      }
>  }
> 
> +/* handle update-ended timer */
> +static void check_update_timer(RTCState *s)
> +{
> +    uint64_t next_update_time, expire_time;
> +    uint64_t guest_usec;
> +    qemu_del_timer(s->update_timer);
> +    qemu_del_timer(s->update_timer2);
> +
> +    if (!((s->cmos_data[RTC_REG_C] & (REG_C_UF | REG_C_AF)) ==
> +            (REG_C_UF | REG_C_AF)) && !(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
> +        s->use_timer = 1;
> +        guest_usec = get_guest_rtc_us(s) % USEC_PER_SEC;
> +        if (guest_usec >= (USEC_PER_SEC - 244)) {
> +            /* RTC is in update cycle when enabling UIE */
> +            s->cmos_data[RTC_REG_A] |= REG_A_UIP;
> +            next_update_time = (USEC_PER_SEC - guest_usec) * NS_PER_USEC;
> +            expire_time = qemu_get_clock_ns(rtc_clock) + next_update_time;
> +            qemu_mod_timer(s->update_timer2, expire_time);
> +        } else {
> +            next_update_time = (USEC_PER_SEC - guest_usec - 244) * NS_PER_USEC;
> +            expire_time = qemu_get_clock_ns(rtc_clock) + next_update_time;
> +            s->next_update_time = expire_time;
> +            qemu_mod_timer(s->update_timer, expire_time);
> +        }
> +    } else {
> +        s->use_timer = 0;
> +    }
> +}
> +static void rtc_update_timer(void *opaque)
> +{
> +    RTCState *s = opaque;
> +
> +    if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
> +        s->cmos_data[RTC_REG_A] |= REG_A_UIP;
> +        qemu_mod_timer(s->update_timer2, s->next_update_time + 244000UL);
> +    }
> +}
> +
> +static void rtc_update_timer2(void *opaque)
> +{
> +    RTCState *s = opaque;
> +
> +    if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
> +        s->cmos_data[RTC_REG_C] |= REG_C_UF;
> +        s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
> +        s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
> +        qemu_irq_raise(s->irq);
> +    }
> +    check_update_timer(s);
> +}
> +
>  static void rtc_set_offset(RTCState *s, int32_t start_usec)
>  {
>      struct tm *tm = &s->current_tm;
> @@ -283,13 +341,14 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
>                      rtc_calibrate_time(s);
>                      rtc_set_offset(s, 500000);
>                      s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
> +                    check_update_timer(s);
>                      divider_reset = 0;
>                  }
>              }
>              /* UIP bit is read only */
>              s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
>                  (s->cmos_data[RTC_REG_A] & REG_A_UIP);
> -            rtc_timer_update(s, qemu_get_clock_ns(rtc_clock));
> +            periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
>              break;
>          case RTC_REG_B:
>              if (data & REG_B_SET) {
> @@ -315,7 +374,8 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
>                  }
>              }
>              s->cmos_data[RTC_REG_B] = data;
> -            rtc_timer_update(s, qemu_get_clock_ns(rtc_clock));
> +            periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
> +            check_update_timer(s);
>              break;
>          case RTC_REG_C:
>          case RTC_REG_D:
> @@ -445,7 +505,7 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
>              break;
>          case RTC_REG_A:
>              ret = s->cmos_data[s->cmos_index];
> -            if (update_in_progress(s)) {
> +            if ((s->use_timer == 0) && update_in_progress(s)) {
>                  ret |= REG_A_UIP;
>              }
>              break;
> @@ -453,6 +513,12 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
>              ret = s->cmos_data[s->cmos_index];
>              qemu_irq_lower(s->irq);
>              s->cmos_data[RTC_REG_C] = 0x00;
> +            if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
> +                rtc_calibrate_time(s);
> +            }
> +            if (ret & (REG_C_UF | REG_C_AF)) {
> +                check_update_timer(s);
> +            }
>  #ifdef TARGET_I386
>              if(s->irq_coalesced &&
>                      (s->cmos_data[RTC_REG_B] & REG_B_PIE) &&
> @@ -545,6 +611,9 @@ static const VMStateDescription vmstate_rtc = {
>          VMSTATE_INT32(offset_usec, RTCState),
>          VMSTATE_TIMER(periodic_timer, RTCState),
>          VMSTATE_INT64(next_periodic_time, RTCState),
> +        VMSTATE_TIMER(update_timer, RTCState),
> +        VMSTATE_TIMER(update_timer2, RTCState),
> +        VMSTATE_UINT64(next_update_time, RTCState),
>          VMSTATE_UINT32_V(irq_coalesced, RTCState, 2),
>          VMSTATE_UINT32_V(period, RTCState, 2),
>          VMSTATE_END_OF_LIST()
> @@ -557,7 +626,8 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data)
>      int64_t now = *(int64_t *)data;
> 
>      rtc_set_date_from_host(&s->dev);
> -    rtc_timer_update(s, now);
> +    periodic_timer_update(s, now);
> +    check_update_timer(s);
>  #ifdef TARGET_I386
>      if (s->lost_tick_policy == LOST_TICK_SLEW) {
>          rtc_coalesced_timer_update(s);
> @@ -579,6 +649,7 @@ static void rtc_reset(void *opaque)
> 
>      s->cmos_data[RTC_REG_B] &= ~(REG_B_PIE | REG_B_AIE | REG_B_SQWE);
>      s->cmos_data[RTC_REG_C] &= ~(REG_C_UF | REG_C_IRQF | REG_C_PF | REG_C_AF);
> +    check_update_timer(s);
> 
>      qemu_irq_lower(s->irq);
> 
> @@ -649,6 +720,9 @@ static int rtc_initfn(ISADevice *dev)
>  #endif
> 
>      s->periodic_timer = qemu_new_timer_ns(rtc_clock, rtc_periodic_timer, s);
> +    s->update_timer = qemu_new_timer_ns(rtc_clock, rtc_update_timer, s);
> +    s->update_timer2 = qemu_new_timer_ns(rtc_clock, rtc_update_timer2, s);
> +    check_update_timer(s);
> 
>      s->clock_reset_notifier.notify = rtc_notify_clock_reset;
>      qemu_register_clock_reset_notifier(rtc_clock, &s->clock_reset_notifier);
> --
> 1.7.1
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v4 5/7] RTC:Add RTC update-ended interrupt support
  2012-03-20 18:04 ` Stefano Stabellini
@ 2012-03-20 18:35   ` Stefano Stabellini
  2012-03-21  7:49     ` Paolo Bonzini
  2012-03-22  0:04   ` Zhang, Yang Z
  1 sibling, 1 reply; 10+ messages in thread
From: Stefano Stabellini @ 2012-03-20 18:35 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Zhang, Yang Z, Paolo Bonzini, aliguori@us.ibm.com,
	qemu-devel@nongnu.org, kvm@vger.kernel.org

> +/* handle update-ended timer */
> +static void check_update_timer(RTCState *s)
> +{
> +    uint64_t next_update_time, expire_time;
> +    uint64_t guest_usec;
> +    qemu_del_timer(s->update_timer);
> +    qemu_del_timer(s->update_timer2);
> +
> +    if (!((s->cmos_data[RTC_REG_C] & (REG_C_UF | REG_C_AF)) ==
> +            (REG_C_UF | REG_C_AF)) && !(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
> +        s->use_timer = 1;
> +        guest_usec = get_guest_rtc_us(s) % USEC_PER_SEC;
> +        if (guest_usec >= (USEC_PER_SEC - 244)) {
> +            /* RTC is in update cycle when enabling UIE */
> +            s->cmos_data[RTC_REG_A] |= REG_A_UIP;
> +            next_update_time = (USEC_PER_SEC - guest_usec) * NS_PER_USEC;
> +            expire_time = qemu_get_clock_ns(rtc_clock) + next_update_time;
> +            qemu_mod_timer(s->update_timer2, expire_time);
> +        } else {
> +            next_update_time = (USEC_PER_SEC - guest_usec - 244) * NS_PER_USEC;
> +            expire_time = qemu_get_clock_ns(rtc_clock) + next_update_time;
> +            s->next_update_time = expire_time;
> +            qemu_mod_timer(s->update_timer, expire_time);
> +        }
> +    } else {
> +        s->use_timer = 0;
> +    }
> +}

This is the function that is used to figure out whether we need the
timers or not, the condition seems to be:

(Not (REG_C_UF | REG_C_AF)) And (Not (REG_B_SET))

Shouldn't actually check for UIE being enabled?

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v4 5/7] RTC:Add RTC update-ended interrupt support
  2012-03-20 18:35   ` Stefano Stabellini
@ 2012-03-21  7:49     ` Paolo Bonzini
  2012-03-21 16:54       ` Stefano Stabellini
  0 siblings, 1 reply; 10+ messages in thread
From: Paolo Bonzini @ 2012-03-21  7:49 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Zhang, Yang Z, aliguori@us.ibm.com, qemu-devel@nongnu.org,
	kvm@vger.kernel.org

Il 20/03/2012 19:35, Stefano Stabellini ha scritto:
> This is the function that is used to figure out whether we need the
> timers or not, the condition seems to be:
> 
> (Not (REG_C_UF | REG_C_AF)) And (Not (REG_B_SET))
> 
> Shouldn't actually check for UIE being enabled?

No, you need to set UF in case the code observes it without actually
enabling interrupt delivery on the ISA bus.

Paolo

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v4 5/7] RTC:Add RTC update-ended interrupt support
  2012-03-21  7:49     ` Paolo Bonzini
@ 2012-03-21 16:54       ` Stefano Stabellini
  2012-03-21 21:16         ` Paolo Bonzini
  0 siblings, 1 reply; 10+ messages in thread
From: Stefano Stabellini @ 2012-03-21 16:54 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Zhang, Yang Z, aliguori@us.ibm.com, qemu-devel@nongnu.org,
	kvm@vger.kernel.org, Stefano Stabellini

On Wed, 21 Mar 2012, Paolo Bonzini wrote:
> Il 20/03/2012 19:35, Stefano Stabellini ha scritto:
> > This is the function that is used to figure out whether we need the
> > timers or not, the condition seems to be:
> > 
> > (Not (REG_C_UF | REG_C_AF)) And (Not (REG_B_SET))
> > 
> > Shouldn't actually check for UIE being enabled?
> 
> No, you need to set UF in case the code observes it without actually
> enabling interrupt delivery on the ISA bus.
 
Well, if it is just about updating UF, can we do it only when the user
reads REG_C?
I am just trying to limit the need for the update_timers...

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v4 5/7] RTC:Add RTC update-ended interrupt support
  2012-03-21 16:54       ` Stefano Stabellini
@ 2012-03-21 21:16         ` Paolo Bonzini
  2012-03-22 10:29           ` Stefano Stabellini
  0 siblings, 1 reply; 10+ messages in thread
From: Paolo Bonzini @ 2012-03-21 21:16 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Zhang, Yang Z, aliguori@us.ibm.com, qemu-devel@nongnu.org,
	kvm@vger.kernel.org

Il 21/03/2012 17:54, Stefano Stabellini ha scritto:
>> > 
>> > No, you need to set UF in case the code observes it without actually
>> > enabling interrupt delivery on the ISA bus.
>  
> Well, if it is just about updating UF, can we do it only when the user
> reads REG_C?

Perhaps, but for AF it is much harder.  Note that if the guest does not
care, this will run just once.

Paolo

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v4 5/7] RTC:Add RTC update-ended interrupt support
  2012-03-20 18:04 ` Stefano Stabellini
  2012-03-20 18:35   ` Stefano Stabellini
@ 2012-03-22  0:04   ` Zhang, Yang Z
  2012-03-22 10:29     ` Stefano Stabellini
  1 sibling, 1 reply; 10+ messages in thread
From: Zhang, Yang Z @ 2012-03-22  0:04 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Paolo Bonzini, aliguori@us.ibm.com, qemu-devel@nongnu.org,
	kvm@vger.kernel.org

> -----Original Message-----
> From: Stefano Stabellini [mailto:stefano.stabellini@eu.citrix.com]
> Sent: Wednesday, March 21, 2012 2:04 AM
> 
> On Mon, 19 Mar 2012, Zhang, Yang Z wrote:
> > Use a timer to emulate update cycle. When update cycle ended and UIE is
> setting, then raise an interrupt. The timer runs only when UF or AF is cleared.
> 
> The idea is that if the user requests the update-ended interrupt (UIE)
> we setup a timer to inject it at the right time into the guest and
> another timer to update the UIP bit, correct?
No, the timer runs whenever the UF and AF is cleared, not only UIE or AIE is set.

> But do we actually need the second timer? Why can't we just update the
> UIP bit whenever the user tries to read reg A, as we do when UIE is not set?
The purpose of using two timer is trying to keep the UF, AF and UIP synchronous. User can poll UIP to check UF and AF bit. If we use timer for UF/AF bit track and check UIP by another way, since the timer will be fired with delay, then the problem is encountered: the UIP is cleared, but due to the delay of timer, the UF/AF bit is not set. So we need to check them on a same level. Although we can update UF/AF when reading it, the logic is too complicated, especially for AF bit. 

> 
> Also I am not sure it is a great idea to rename rtc_timer_update into
> periodic_timer_update in the same patch where you introduce this new
> logic.
Ok, it make sense.

best regards
yang

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v4 5/7] RTC:Add RTC update-ended interrupt support
  2012-03-22  0:04   ` Zhang, Yang Z
@ 2012-03-22 10:29     ` Stefano Stabellini
  2012-03-22 10:32       ` Paolo Bonzini
  0 siblings, 1 reply; 10+ messages in thread
From: Stefano Stabellini @ 2012-03-22 10:29 UTC (permalink / raw)
  To: Zhang, Yang Z
  Cc: Paolo Bonzini, aliguori@us.ibm.com, qemu-devel@nongnu.org,
	kvm@vger.kernel.org, Stefano Stabellini

On Thu, 22 Mar 2012, Zhang, Yang Z wrote:
> > -----Original Message-----
> > From: Stefano Stabellini [mailto:stefano.stabellini@eu.citrix.com]
> > Sent: Wednesday, March 21, 2012 2:04 AM
> > 
> > On Mon, 19 Mar 2012, Zhang, Yang Z wrote:
> > > Use a timer to emulate update cycle. When update cycle ended and UIE is
> > setting, then raise an interrupt. The timer runs only when UF or AF is cleared.
> > 
> > The idea is that if the user requests the update-ended interrupt (UIE)
> > we setup a timer to inject it at the right time into the guest and
> > another timer to update the UIP bit, correct?
> No, the timer runs whenever the UF and AF is cleared, not only UIE or AIE is set.
> 
> > But do we actually need the second timer? Why can't we just update the
> > UIP bit whenever the user tries to read reg A, as we do when UIE is not set?
> The purpose of using two timer is trying to keep the UF, AF and UIP synchronous. User can poll UIP to check UF and AF bit. If we use timer for UF/AF bit track and check UIP by another way, since the timer will be fired with delay, then the problem is encountered: the UIP is cleared, but due to the delay of timer, the UF/AF bit is not set. So we need to check them on a same level. Although we can update UF/AF when reading it, the logic is too complicated, especially for AF bit. 

fair enough

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v4 5/7] RTC:Add RTC update-ended interrupt support
  2012-03-21 21:16         ` Paolo Bonzini
@ 2012-03-22 10:29           ` Stefano Stabellini
  0 siblings, 0 replies; 10+ messages in thread
From: Stefano Stabellini @ 2012-03-22 10:29 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Zhang, Yang Z, aliguori@us.ibm.com, qemu-devel@nongnu.org,
	kvm@vger.kernel.org, Stefano Stabellini

On Wed, 21 Mar 2012, Paolo Bonzini wrote:
> Il 21/03/2012 17:54, Stefano Stabellini ha scritto:
> >> > 
> >> > No, you need to set UF in case the code observes it without actually
> >> > enabling interrupt delivery on the ISA bus.
> >  
> > Well, if it is just about updating UF, can we do it only when the user
> > reads REG_C?
> 
> Perhaps, but for AF it is much harder.  Note that if the guest does not
> care, this will run just once.

Right, probably not worth the effort.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v4 5/7] RTC:Add RTC update-ended interrupt support
  2012-03-22 10:29     ` Stefano Stabellini
@ 2012-03-22 10:32       ` Paolo Bonzini
  0 siblings, 0 replies; 10+ messages in thread
From: Paolo Bonzini @ 2012-03-22 10:32 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Zhang, Yang Z, aliguori@us.ibm.com, qemu-devel@nongnu.org,
	kvm@vger.kernel.org

Il 22/03/2012 11:29, Stefano Stabellini ha scritto:
>> The purpose of using two timer is trying to keep the UF, AF and UIP
>> synchronous. User can poll UIP to check UF and AF bit. If we use
>> timer for UF/AF bit track and check UIP by another way, since the
>> timer will be fired with delay, then the problem is encountered:
>> the UIP is cleared, but due to the delay of timer, the UF/AF bit is
>> not set. So we need to check them on a same level. Although we can
>> update UF/AF when reading it, the logic is too complicated,
>> especially for AF bit.

FWIW, the solution I used when I removed the second timer from the
current code (not yet posted, I do hope your patches can be fixed!) was
to set UIP when reading A, and clear it in the timer.  You have
something like that, but keep the two timers.

Paolo

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2012-03-22 10:32 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-19  6:14 [Qemu-devel] [PATCH v4 5/7] RTC:Add RTC update-ended interrupt support Zhang, Yang Z
2012-03-20 18:04 ` Stefano Stabellini
2012-03-20 18:35   ` Stefano Stabellini
2012-03-21  7:49     ` Paolo Bonzini
2012-03-21 16:54       ` Stefano Stabellini
2012-03-21 21:16         ` Paolo Bonzini
2012-03-22 10:29           ` Stefano Stabellini
2012-03-22  0:04   ` Zhang, Yang Z
2012-03-22 10:29     ` Stefano Stabellini
2012-03-22 10:32       ` Paolo Bonzini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).