Count the number of interrupts that was lost due to interrupt coalescing and re-inject them back when possible. This fixes time drift problem when RTC is used as a time source.
Signed-off-by: Gleb Natapov <[EMAIL PROTECTED]> --- hw/mc146818rtc.c | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-) diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index 30bb044..64e4c11 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -72,6 +72,7 @@ struct RTCState { static void rtc_set_time(RTCState *s); static void rtc_copy_date(RTCState *s); +static uint32_t rtc_irq_coalesced; static void rtc_timer_update(RTCState *s, int64_t current_time) { @@ -101,7 +102,8 @@ static void rtc_periodic_timer(void *opaque) rtc_timer_update(s, s->next_periodic_time); s->cmos_data[RTC_REG_C] |= 0xc0; - qemu_irq_raise(s->irq); + if(!qemu_irq_raise(s->irq)) + rtc_irq_coalesced++; } static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) @@ -360,7 +362,12 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr) case RTC_REG_C: ret = s->cmos_data[s->cmos_index]; qemu_irq_lower(s->irq); - s->cmos_data[RTC_REG_C] = 0x00; + if(!rtc_irq_coalesced) { + s->cmos_data[RTC_REG_C] = 0x00; + } else { + if(qemu_irq_raise(s->irq)) + rtc_irq_coalesced--; + } break; default: ret = s->cmos_data[s->cmos_index]; -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html