From patchwork Mon Feb 20 00:25:26 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Yang Z" X-Patchwork-Id: 142093 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 34F43B6FA5 for ; Mon, 20 Feb 2012 11:26:26 +1100 (EST) Received: from localhost ([::1]:60577 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RzH5D-0002Cr-Ci for incoming@patchwork.ozlabs.org; Sun, 19 Feb 2012 19:26:23 -0500 Received: from eggs.gnu.org ([140.186.70.92]:47303) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RzH4f-0000zn-8k for qemu-devel@nongnu.org; Sun, 19 Feb 2012 19:25:51 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RzH4d-0007Pz-U4 for qemu-devel@nongnu.org; Sun, 19 Feb 2012 19:25:49 -0500 Received: from mga02.intel.com ([134.134.136.20]:27724) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RzH4d-0007Pu-KH for qemu-devel@nongnu.org; Sun, 19 Feb 2012 19:25:47 -0500 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP; 19 Feb 2012 16:25:31 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.67,351,1309762800"; d="scan'208";a="112166935" Received: from pgsmsx101.gar.corp.intel.com ([10.221.44.78]) by orsmga002.jf.intel.com with ESMTP; 19 Feb 2012 16:25:29 -0800 Received: from pgsmsx151.gar.corp.intel.com (172.30.236.41) by PGSMSX101.gar.corp.intel.com (10.221.44.78) with Microsoft SMTP Server (TLS) id 14.1.355.2; Mon, 20 Feb 2012 08:25:28 +0800 Received: from shsmsx102.ccr.corp.intel.com (10.239.4.154) by PGSMSX151.gar.corp.intel.com (172.30.236.41) with Microsoft SMTP Server (TLS) id 14.1.355.2; Mon, 20 Feb 2012 08:25:28 +0800 Received: from shsmsx101.ccr.corp.intel.com ([169.254.1.142]) by SHSMSX102.ccr.corp.intel.com ([169.254.2.36]) with mapi id 14.01.0355.002; Mon, 20 Feb 2012 08:25:27 +0800 From: "Zhang, Yang Z" To: "qemu-devel@nongnu.org" Thread-Topic: [PATCH v2 2/4] RTC:Add RTC update-ended interrupt logic Thread-Index: AczvZiNIbSlL/U6ZTgeMwKLCpBz05g== Date: Mon, 20 Feb 2012 00:25:26 +0000 Message-ID: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.20 Cc: Paolo Bonzini , "aliguori@us.ibm.com" , Marcelo Tosatti , Jan Kiszka , "kvm@vger.kernel.org" Subject: [Qemu-devel] [PATCH v2 2/4] RTC:Add RTC update-ended interrupt logic X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Use timer to emulate RTC update-ended interrupt. The timer is enabled only when UIE is setting. Signed-off-by: Yang Zhang --- hw/mc146818rtc.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 48 insertions(+), 5 deletions(-) -- 1.7.1 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);