* [Qemu-devel] [PATCH v2 2/4] RTC:Add RTC update-ended interrupt logic
@ 2012-02-20 0:25 Zhang, Yang Z
2012-02-20 7:38 ` Paolo Bonzini
0 siblings, 1 reply; 3+ messages in thread
From: Zhang, Yang Z @ 2012-02-20 0:25 UTC (permalink / raw)
To: qemu-devel@nongnu.org
Cc: Paolo Bonzini, aliguori@us.ibm.com, Marcelo Tosatti, Jan Kiszka,
kvm@vger.kernel.org
Use timer to emulate RTC update-ended interrupt. The timer is enabled
only when UIE is setting.
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
---
hw/mc146818rtc.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index b6655ae..bb1873b 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -93,9 +93,14 @@ typedef struct RTCState {
qemu_irq irq;
qemu_irq sqw_irq;
int it_shift;
+
/* periodic timer */
QEMUTimer *periodic_timer;
int64_t next_periodic_time;
+
+ /* update-ended timer */
+ QEMUTimer *update_timer;
+
uint16_t irq_reinject_on_ack_count;
uint32_t irq_coalesced;
uint32_t period;
@@ -140,7 +145,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;
@@ -178,7 +184,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;
@@ -205,6 +211,40 @@ static void rtc_periodic_timer(void *opaque)
}
}
+/* handle update-ended timer */
+static void update_ended_timer_update(RTCState *s)
+{
+ struct timeval tv_now;
+ uint64_t next_update_time;
+ uint64_t expire_time;
+
+ if ((s->cmos_data[RTC_REG_B] & REG_B_UIE) &&
+ !(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+ gettimeofday(&tv_now, NULL);
+ next_update_time = USEC_PER_SEC -
+ (tv_now.tv_usec + s->offset_usec) % 1000000;
+ expire_time = (get_ticks_per_sec() / USEC_PER_SEC) * next_update_time +
+ qemu_get_clock_ns(rtc_clock);
+ qemu_mod_timer(s->update_timer, expire_time);
+ } else {
+ qemu_del_timer(s->update_timer);
+ }
+}
+
+static void rtc_update_timer(void *opaque)
+{
+ RTCState *s = opaque;
+
+ update_ended_timer_update(s);
+ if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+ s->cmos_data[RTC_REG_C] |= REG_C_UF;
+ if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
+ s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
+ qemu_irq_raise(s->irq);
+ }
+ }
+}
+
static void rtc_set_offset(RTCState *s)
{
struct tm *tm = &s->current_tm;
@@ -256,7 +296,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
/* 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) {
@@ -279,7 +319,8 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
} else {
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));
+ update_ended_timer_update(s);
break;
case RTC_REG_C:
case RTC_REG_D:
@@ -493,6 +534,7 @@ 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_UINT32_V(irq_coalesced, RTCState, 2),
VMSTATE_UINT32_V(period, RTCState, 2),
VMSTATE_END_OF_LIST()
@@ -505,7 +547,7 @@ 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);
#ifdef TARGET_I386
if (s->lost_tick_policy == LOST_TICK_SLEW) {
rtc_coalesced_timer_update(s);
@@ -589,6 +631,7 @@ 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->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] 3+ messages in thread
* Re: [Qemu-devel] [PATCH v2 2/4] RTC:Add RTC update-ended interrupt logic
2012-02-20 0:25 [Qemu-devel] [PATCH v2 2/4] RTC:Add RTC update-ended interrupt logic Zhang, Yang Z
@ 2012-02-20 7:38 ` Paolo Bonzini
2012-02-20 23:55 ` Zhang, Yang Z
0 siblings, 1 reply; 3+ messages in thread
From: Paolo Bonzini @ 2012-02-20 7:38 UTC (permalink / raw)
To: Zhang, Yang Z
Cc: aliguori@us.ibm.com, Marcelo Tosatti, Jan Kiszka,
qemu-devel@nongnu.org, kvm@vger.kernel.org
On 02/20/2012 01:25 AM, Zhang, Yang Z wrote:
> Use timer to emulate RTC update-ended interrupt. The timer is enabled
> only when UIE is setting.
The timer needs to be enabled when UF is clear, not when UIE is set. If
UIE is set but the update interrupt is masked you do not need to do
anything; on the other hand you need to update UF in case the guest is
observing interrupts with polling.
Paolo
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Qemu-devel] [PATCH v2 2/4] RTC:Add RTC update-ended interrupt logic
2012-02-20 7:38 ` Paolo Bonzini
@ 2012-02-20 23:55 ` Zhang, Yang Z
0 siblings, 0 replies; 3+ messages in thread
From: Zhang, Yang Z @ 2012-02-20 23:55 UTC (permalink / raw)
To: Paolo Bonzini
Cc: aliguori@us.ibm.com, Marcelo Tosatti, Jan Kiszka,
qemu-devel@nongnu.org, kvm@vger.kernel.org
> -----Original Message-----
> From: Paolo Bonzini [mailto:paolo.bonzini@gmail.com] On Behalf Of Paolo
> Bonzini
> Sent: Monday, February 20, 2012 3:38 PM
> To: Zhang, Yang Z
> Cc: qemu-devel@nongnu.org; Jan Kiszka; kvm@vger.kernel.org;
> aliguori@us.ibm.com; Marcelo Tosatti
> Subject: Re: [PATCH v2 2/4] RTC:Add RTC update-ended interrupt logic
>
> On 02/20/2012 01:25 AM, Zhang, Yang Z wrote:
> > Use timer to emulate RTC update-ended interrupt. The timer is enabled
> > only when UIE is setting.
>
> The timer needs to be enabled when UF is clear, not when UIE is set. If UIE is
> set but the update interrupt is masked you do not need to do anything; on the
> other hand you need to update UF in case the guest is observing interrupts with
> polling.
Good point.
best regards
yang
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2012-02-20 23:57 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-02-20 0:25 [Qemu-devel] [PATCH v2 2/4] RTC:Add RTC update-ended interrupt logic Zhang, Yang Z
2012-02-20 7:38 ` Paolo Bonzini
2012-02-20 23:55 ` Zhang, Yang Z
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).