aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/timer/mc146818rtc.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 93de3e1cc5..7d78391b62 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -391,6 +391,7 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
uint64_t data, unsigned size)
{
RTCState *s = opaque;
+ bool update_periodic_timer;
if ((addr & 1) == 0) {
s->cmos_index = data & 0x7f;
@@ -423,6 +424,8 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
}
break;
case RTC_REG_A:
+ update_periodic_timer = (s->cmos_data[RTC_REG_A] ^ data) & 0x0f;
+
if ((data & 0x60) == 0x60) {
if (rtc_running(s)) {
rtc_update_time(s);
@@ -445,10 +448,17 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
/* UIP bit is read only */
s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
(s->cmos_data[RTC_REG_A] & REG_A_UIP);
- periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+
+ if (update_periodic_timer) {
+ periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+ }
+
check_update_timer(s);
break;
case RTC_REG_B:
+ update_periodic_timer = (s->cmos_data[RTC_REG_B] ^ data)
+ & REG_B_PIE;
+
if (data & REG_B_SET) {
/* update cmos to when the rtc was stopping */
if (rtc_running(s)) {
@@ -475,7 +485,11 @@ static void cmos_ioport_write(void *opaque, hwaddr addr,
qemu_irq_lower(s->irq);
}
s->cmos_data[RTC_REG_B] = data;
- periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+
+ if (update_periodic_timer) {
+ periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+ }
+
check_update_timer(s);
break;
case RTC_REG_C: