From patchwork Fri Jan 6 07:37:31 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: 134615 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 8398FB6FC5 for ; Fri, 6 Jan 2012 18:38:04 +1100 (EST) Received: from localhost ([::1]:50837 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rj4NC-0005BT-Oy for incoming@patchwork.ozlabs.org; Fri, 06 Jan 2012 02:37:58 -0500 Received: from eggs.gnu.org ([140.186.70.92]:38092) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rj4Mx-0004m0-B0 for qemu-devel@nongnu.org; Fri, 06 Jan 2012 02:37:45 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Rj4Mv-0004oa-9Y for qemu-devel@nongnu.org; Fri, 06 Jan 2012 02:37:43 -0500 Received: from mga03.intel.com ([143.182.124.21]:34895) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rj4Mu-0004oT-L9 for qemu-devel@nongnu.org; Fri, 06 Jan 2012 02:37:41 -0500 Received: from azsmga002.ch.intel.com ([10.2.17.35]) by azsmga101.ch.intel.com with ESMTP; 05 Jan 2012 23:37:39 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.71,315,1320652800"; d="scan'208";a="53836212" Received: from pgsmsx602.gar.corp.intel.com ([10.221.43.81]) by AZSMGA002.ch.intel.com with ESMTP; 05 Jan 2012 23:37:38 -0800 Received: from shsmsx151.ccr.corp.intel.com (10.239.6.50) by pgsmsx602.gar.corp.intel.com (10.221.43.81) with Microsoft SMTP Server (TLS) id 8.2.255.0; Fri, 6 Jan 2012 15:37:32 +0800 Received: from shsmsx101.ccr.corp.intel.com ([169.254.1.38]) by SHSMSX151.ccr.corp.intel.com ([169.254.3.223]) with mapi id 14.01.0355.002; Fri, 6 Jan 2012 15:37:31 +0800 From: "Zhang, Yang Z" To: "qemu-devel@nongnu.org" Thread-Topic: [PATCH 3/3] stop the periodic RTC update timer Thread-Index: AczMRgv3otEY5qI5SoqQWE/rZjOJlw== Date: Fri, 6 Jan 2012 07:37:31 +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: 143.182.124.21 Cc: "aliguori@us.ibm.com" , "Shan, Haitao" , "avi@redhat.com" , "kvm@vger.kernel.org" Subject: [Qemu-devel] [PATCH 3/3] stop the periodic RTC update timer 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 change the RTC update logic to use host time with offset to calculate RTC clock. There have no need to use two periodic timers to maintain an internal timer for RTC clock update and alarm check. Instead, we calculate the real RTC time by the host time with an offset. For alarm and updated-end interrupt, if guest enabled it, then we setup a timer, or else, stop it. Signed-off-by: Yang Zhang diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index 9cbd052..ac1854e 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -84,7 +84,7 @@ typedef struct RTCState { MemoryRegion io; uint8_t cmos_data[128]; uint8_t cmos_index; - struct tm current_tm; + int64_t offset; int32_t base_year; qemu_irq irq; qemu_irq sqw_irq; @@ -93,19 +93,18 @@ typedef struct RTCState { QEMUTimer *periodic_timer; int64_t next_periodic_time; /* second update */ - int64_t next_second_time; + QEMUTimer *update_timer; + int64_t next_update_time; + /* alarm */ + QEMUTimer *alarm_timer; + int64_t next_alarm_time; uint16_t irq_reinject_on_ack_count; uint32_t irq_coalesced; uint32_t period; QEMUTimer *coalesced_timer; - QEMUTimer *second_timer; - QEMUTimer *second_timer2; Notifier clock_reset_notifier; } RTCState; -static void rtc_set_time(RTCState *s); -static void rtc_copy_date(RTCState *s); - #ifdef TARGET_I386 static void rtc_coalesced_timer_update(RTCState *s) { @@ -140,6 +139,72 @@ static void rtc_coalesced_timer(void *opaque) } #endif +static inline int rtc_to_bcd(RTCState *s, int a) +{ + if (s->cmos_data[RTC_REG_B] & REG_B_DM) { + return a; + } else { + return ((a / 10) << 4) | (a % 10); + } +} + +static inline int rtc_from_bcd(RTCState *s, int a) +{ + if (s->cmos_data[RTC_REG_B] & REG_B_DM) { + return a; + } else { + return ((a >> 4) * 10) + (a & 0x0f); + } +} + +static void rtc_set_time(RTCState *s) +{ + struct tm tm ; + + tm.tm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]); + tm.tm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]); + tm.tm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f); + if (!(s->cmos_data[RTC_REG_B] & REG_B_24H) && + (s->cmos_data[RTC_HOURS] & 0x80)) { + tm.tm_hour += 12; + } + tm.tm_wday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1; + tm.tm_mday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]); + tm.tm_mon = rtc_from_bcd(s, s->cmos_data[RTC_MONTH]) - 1; + tm.tm_year = rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900; + + s->offset = qemu_timedate_diff(&tm); + + rtc_change_mon_event(&tm); +} + +static void rtc_update_time(RTCState *s) +{ + struct tm tm; + int year; + + qemu_get_timedate(&tm, s->offset); + + s->cmos_data[RTC_SECONDS] = rtc_to_bcd(s, tm.tm_sec); + s->cmos_data[RTC_MINUTES] = rtc_to_bcd(s, tm.tm_min); + if (s->cmos_data[RTC_REG_B] & REG_B_24H) { + /* 24 hour format */ + s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm.tm_hour); + } else { + /* 12 hour format */ + s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm.tm_hour % 12); + if (tm.tm_hour >= 12) + s->cmos_data[RTC_HOURS] |= 0x80; + } + s->cmos_data[RTC_DAY_OF_WEEK] = rtc_to_bcd(s, tm.tm_wday + 1); + s->cmos_data[RTC_DAY_OF_MONTH] = rtc_to_bcd(s, tm.tm_mday); + s->cmos_data[RTC_MONTH] = rtc_to_bcd(s, tm.tm_mon + 1); + year = (tm.tm_year - s->base_year) % 100; + if (year < 0) + year += 100; + s->cmos_data[RTC_YEAR] = rtc_to_bcd(s, year); +} + static void rtc_timer_update(RTCState *s, int64_t current_time) { int period_code, period; @@ -174,7 +239,7 @@ static void rtc_timer_update(RTCState *s, int64_t current_time) } } -static void rtc_periodic_timer(void *opaque) +static void rtc_periodic_interrupt(void *opaque) { RTCState *s = opaque; @@ -204,6 +269,92 @@ static void rtc_periodic_timer(void *opaque) } } +static void rtc_enable_update_interrupt(void *opaque) +{ + RTCState *s = opaque; + + s->next_update_time = qemu_get_clock_ns(rtc_clock) + get_ticks_per_sec(); + qemu_mod_timer(s->update_timer, s->next_update_time); +} + +static void rtc_disable_update_interrupt(void *opaque) +{ + RTCState *s = opaque; + + qemu_del_timer(s->update_timer); +} + +static void rtc_update_interrupt(void *opaque) +{ + RTCState *s = opaque; + + /* update ended interrupt */ + 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); + + s->next_update_time += get_ticks_per_sec(); + qemu_mod_timer(s->update_timer, s->next_update_time); + } else + rtc_disable_update_interrupt(s); +} + +static void rtc_enable_alarm(void *opaque) +{ + RTCState *s = opaque; + + s->next_alarm_time = qemu_get_clock_ns(rtc_clock) + get_ticks_per_sec(); + s->next_alarm_time /= get_ticks_per_sec(); + s->next_alarm_time *= get_ticks_per_sec(); + + qemu_mod_timer(s->alarm_timer, s->next_alarm_time); +} + +static void rtc_disable_alarm(void *opaque) +{ + RTCState *s = opaque; + + qemu_del_timer(s->alarm_timer); +} + +static void rtc_alarm_interrupt(void *opaque) +{ + RTCState *s = opaque; + struct tm tm; + int hour = 0; + + qemu_get_timedate(&tm, s->offset); + + if ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) != 0xc0) { + hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM] & 0x7f); + if (!(s->cmos_data[RTC_REG_B] & REG_B_24H) && + (s->cmos_data[RTC_HOURS_ALARM] & 0x80)) { + hour += 12; + } + } + + /* check alarm */ + if (s->cmos_data[RTC_REG_B] & REG_B_AIE) { + if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 || + rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]) == tm.tm_sec) && + ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 || + rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]) == tm.tm_min) && + ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 || + hour == tm.tm_hour)) { + + printf("raise irq\n"); + s->cmos_data[RTC_REG_C] |= 0xa0; + qemu_irq_raise(s->irq); + } + + s->next_alarm_time += get_ticks_per_sec(); + qemu_mod_timer(s->alarm_timer, s->next_alarm_time); + } else + rtc_disable_alarm(s); + +} + static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) { RTCState *s = opaque; @@ -239,26 +390,37 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) rtc_timer_update(s, qemu_get_clock_ns(rtc_clock)); break; case RTC_REG_B: - if (data & REG_B_SET) { - /* set mode: reset UIP mode */ - s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; - data &= ~REG_B_UIE; - } else { + if (data & REG_B_SET) + rtc_update_time(s); + else { /* if disabling set mode, update the time */ if (s->cmos_data[RTC_REG_B] & REG_B_SET) { rtc_set_time(s); } } + if (((s->cmos_data[RTC_REG_B] ^ data) & (REG_B_DM | REG_B_24H)) && !(data & REG_B_SET)) { /* If the time format has changed and not in set mode, update the registers immediately. */ s->cmos_data[RTC_REG_B] = data; - rtc_copy_date(s); - } else { + rtc_update_time(s); + } else s->cmos_data[RTC_REG_B] = data; - } + + /* check alarm interrupt */ + if ((s->cmos_data[RTC_REG_B] & REG_B_AIE) && + !(s->cmos_data[RTC_REG_B] & REG_B_SET) ) + rtc_enable_alarm(s); + + /* check update-ended interrupt */ + if ((s->cmos_data[RTC_REG_B] & REG_B_UIE) && + !(s->cmos_data[RTC_REG_B] & REG_B_SET)) + rtc_enable_update_interrupt(s); + + /* check periodic interrupt or square-wave */ rtc_timer_update(s, qemu_get_clock_ns(rtc_clock)); + break; case RTC_REG_C: case RTC_REG_D: @@ -271,184 +433,6 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) } } -static inline int rtc_to_bcd(RTCState *s, int a) -{ - if (s->cmos_data[RTC_REG_B] & REG_B_DM) { - return a; - } else { - return ((a / 10) << 4) | (a % 10); - } -} - -static inline int rtc_from_bcd(RTCState *s, int a) -{ - if (s->cmos_data[RTC_REG_B] & REG_B_DM) { - return a; - } else { - return ((a >> 4) * 10) + (a & 0x0f); - } -} - -static void rtc_set_time(RTCState *s) -{ - struct tm *tm = &s->current_tm; - - tm->tm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]); - tm->tm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]); - tm->tm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f); - if (!(s->cmos_data[RTC_REG_B] & REG_B_24H) && - (s->cmos_data[RTC_HOURS] & 0x80)) { - tm->tm_hour += 12; - } - tm->tm_wday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1; - tm->tm_mday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]); - tm->tm_mon = rtc_from_bcd(s, s->cmos_data[RTC_MONTH]) - 1; - tm->tm_year = rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900; - - rtc_change_mon_event(tm); -} - -static void rtc_copy_date(RTCState *s) -{ - const struct tm *tm = &s->current_tm; - int year; - - s->cmos_data[RTC_SECONDS] = rtc_to_bcd(s, tm->tm_sec); - s->cmos_data[RTC_MINUTES] = rtc_to_bcd(s, tm->tm_min); - if (s->cmos_data[RTC_REG_B] & REG_B_24H) { - /* 24 hour format */ - s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour); - } else { - /* 12 hour format */ - s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour % 12); - if (tm->tm_hour >= 12) - s->cmos_data[RTC_HOURS] |= 0x80; - } - s->cmos_data[RTC_DAY_OF_WEEK] = rtc_to_bcd(s, tm->tm_wday + 1); - s->cmos_data[RTC_DAY_OF_MONTH] = rtc_to_bcd(s, tm->tm_mday); - s->cmos_data[RTC_MONTH] = rtc_to_bcd(s, tm->tm_mon + 1); - year = (tm->tm_year - s->base_year) % 100; - if (year < 0) - year += 100; - s->cmos_data[RTC_YEAR] = rtc_to_bcd(s, year); -} - -/* month is between 0 and 11. */ -static int get_days_in_month(int month, int year) -{ - static const int days_tab[12] = { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 - }; - int d; - if ((unsigned )month >= 12) - return 31; - d = days_tab[month]; - if (month == 1) { - if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) - d++; - } - return d; -} - -/* update 'tm' to the next second */ -static void rtc_next_second(struct tm *tm) -{ - int days_in_month; - - tm->tm_sec++; - if ((unsigned)tm->tm_sec >= 60) { - tm->tm_sec = 0; - tm->tm_min++; - if ((unsigned)tm->tm_min >= 60) { - tm->tm_min = 0; - tm->tm_hour++; - if ((unsigned)tm->tm_hour >= 24) { - tm->tm_hour = 0; - /* next day */ - tm->tm_wday++; - if ((unsigned)tm->tm_wday >= 7) - tm->tm_wday = 0; - days_in_month = get_days_in_month(tm->tm_mon, - tm->tm_year + 1900); - tm->tm_mday++; - if (tm->tm_mday < 1) { - tm->tm_mday = 1; - } else if (tm->tm_mday > days_in_month) { - tm->tm_mday = 1; - tm->tm_mon++; - if (tm->tm_mon >= 12) { - tm->tm_mon = 0; - tm->tm_year++; - } - } - } - } - } -} - - -static void rtc_update_second(void *opaque) -{ - RTCState *s = opaque; - int64_t delay; - - /* if the oscillator is not in normal operation, we do not update */ - if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) { - s->next_second_time += get_ticks_per_sec(); - qemu_mod_timer(s->second_timer, s->next_second_time); - } else { - rtc_next_second(&s->current_tm); - - if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { - /* update in progress bit */ - s->cmos_data[RTC_REG_A] |= REG_A_UIP; - } - /* should be 244 us = 8 / 32768 seconds, but currently the - timers do not have the necessary resolution. */ - delay = (get_ticks_per_sec() * 1) / 100; - if (delay < 1) - delay = 1; - qemu_mod_timer(s->second_timer2, - s->next_second_time + delay); - } -} - -static void rtc_update_second2(void *opaque) -{ - RTCState *s = opaque; - - if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { - rtc_copy_date(s); - } - - /* check alarm */ - if (s->cmos_data[RTC_REG_B] & REG_B_AIE) { - if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 || - rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]) == s->current_tm.tm_sec) && - ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 || - rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]) == s->current_tm.tm_min) && - ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 || - rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]) == s->current_tm.tm_hour)) { - - s->cmos_data[RTC_REG_C] |= 0xa0; - qemu_irq_raise(s->irq); - } - } - - /* update ended interrupt */ - 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); - } - - /* clear update in progress bit */ - s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; - - s->next_second_time += get_ticks_per_sec(); - qemu_mod_timer(s->second_timer, s->next_second_time); -} - static uint32_t cmos_ioport_read(void *opaque, uint32_t addr) { RTCState *s = opaque; @@ -464,9 +448,9 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr) case RTC_DAY_OF_MONTH: case RTC_MONTH: case RTC_YEAR: - ret = s->cmos_data[s->cmos_index]; - break; - case RTC_REG_A: + /* if not in set mode, update the time before read */ + if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) + rtc_update_time(s); ret = s->cmos_data[s->cmos_index]; break; case RTC_REG_C: @@ -507,13 +491,6 @@ void rtc_set_memory(ISADevice *dev, int addr, int val) s->cmos_data[addr] = val; } -void rtc_set_date(ISADevice *dev, const struct tm *tm) -{ - RTCState *s = DO_UPCAST(RTCState, dev, dev); - s->current_tm = *tm; - rtc_copy_date(s); -} - /* PC cmos mappings */ #define REG_IBM_CENTURY_BYTE 0x32 #define REG_IBM_PS2_CENTURY_BYTE 0x37 @@ -524,10 +501,11 @@ static void rtc_set_date_from_host(ISADevice *dev) struct tm tm; int val; + s->offset = 0; /* set the CMOS date */ - qemu_get_timedate(&tm, 0); - rtc_set_date(dev, &tm); + rtc_update_time(s); + qemu_get_timedate(&tm, s->offset); val = rtc_to_bcd(s, (tm.tm_year / 100) + 19); rtc_set_memory(dev, REG_IBM_CENTURY_BYTE, val); rtc_set_memory(dev, REG_IBM_PS2_CENTURY_BYTE, val); @@ -556,18 +534,13 @@ static const VMStateDescription vmstate_rtc = { .fields = (VMStateField []) { VMSTATE_BUFFER(cmos_data, RTCState), VMSTATE_UINT8(cmos_index, RTCState), - VMSTATE_INT32(current_tm.tm_sec, RTCState), - VMSTATE_INT32(current_tm.tm_min, RTCState), - VMSTATE_INT32(current_tm.tm_hour, RTCState), - VMSTATE_INT32(current_tm.tm_wday, RTCState), - VMSTATE_INT32(current_tm.tm_mday, RTCState), - VMSTATE_INT32(current_tm.tm_mon, RTCState), - VMSTATE_INT32(current_tm.tm_year, RTCState), + VMSTATE_INT64(offset, RTCState), VMSTATE_TIMER(periodic_timer, RTCState), VMSTATE_INT64(next_periodic_time, RTCState), - VMSTATE_INT64(next_second_time, RTCState), - VMSTATE_TIMER(second_timer, RTCState), - VMSTATE_TIMER(second_timer2, RTCState), + VMSTATE_TIMER(update_timer, RTCState), + VMSTATE_INT64(next_update_time, RTCState), + VMSTATE_TIMER(alarm_timer, RTCState), + VMSTATE_INT64(next_alarm_time, RTCState), VMSTATE_UINT32_V(irq_coalesced, RTCState, 2), VMSTATE_UINT32_V(period, RTCState, 2), VMSTATE_END_OF_LIST() @@ -580,8 +553,6 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data) int64_t now = *(int64_t *)data; rtc_set_date_from_host(&s->dev); - s->next_second_time = now + (get_ticks_per_sec() * 99) / 100; - qemu_mod_timer(s->second_timer2, s->next_second_time); rtc_timer_update(s, now); #ifdef TARGET_I386 if (rtc_td_hack) { @@ -627,13 +598,15 @@ static void rtc_get_date(DeviceState *dev, Visitor *v, void *opaque, ISADevice *isa = DO_UPCAST(ISADevice, qdev, dev); RTCState *s = DO_UPCAST(RTCState, dev, isa); + struct tm tm; + qemu_get_timedate(&tm, s->offset); visit_start_struct(v, NULL, "struct tm", name, 0, errp); - visit_type_int32(v, &s->current_tm.tm_year, "tm_year", errp); - visit_type_int32(v, &s->current_tm.tm_mon, "tm_mon", errp); - visit_type_int32(v, &s->current_tm.tm_mday, "tm_mday", errp); - visit_type_int32(v, &s->current_tm.tm_hour, "tm_hour", errp); - visit_type_int32(v, &s->current_tm.tm_min, "tm_min", errp); - visit_type_int32(v, &s->current_tm.tm_sec, "tm_sec", errp); + visit_type_int32(v, &tm.tm_year, "tm_year", errp); + visit_type_int32(v, &tm.tm_mon, "tm_mon", errp); + visit_type_int32(v, &tm.tm_mday, "tm_mday", errp); + visit_type_int32(v, &tm.tm_hour, "tm_hour", errp); + visit_type_int32(v, &tm.tm_min, "tm_min", errp); + visit_type_int32(v, &tm.tm_sec, "tm_sec", errp); visit_end_struct(v, errp); } @@ -649,22 +622,18 @@ static int rtc_initfn(ISADevice *dev) rtc_set_date_from_host(dev); - s->periodic_timer = qemu_new_timer_ns(rtc_clock, rtc_periodic_timer, s); + s->periodic_timer = qemu_new_timer_ns(rtc_clock, rtc_periodic_interrupt, s); #ifdef TARGET_I386 if (rtc_td_hack) s->coalesced_timer = qemu_new_timer_ns(rtc_clock, rtc_coalesced_timer, s); #endif - s->second_timer = qemu_new_timer_ns(rtc_clock, rtc_update_second, s); - s->second_timer2 = qemu_new_timer_ns(rtc_clock, rtc_update_second2, s); + s->update_timer = qemu_new_timer_ns(rtc_clock, rtc_update_interrupt, s); + s->alarm_timer = qemu_new_timer_ns(rtc_clock, rtc_alarm_interrupt, s); s->clock_reset_notifier.notify = rtc_notify_clock_reset; qemu_register_clock_reset_notifier(rtc_clock, &s->clock_reset_notifier); - s->next_second_time = - qemu_get_clock_ns(rtc_clock) + (get_ticks_per_sec() * 99) / 100; - qemu_mod_timer(s->second_timer2, s->next_second_time); - memory_region_init_io(&s->io, &cmos_ops, s, "rtc", 2); isa_register_ioport(dev, &s->io, base);