A side effect is that coalesced irq handling is extended to seconds alarm and irq reinjection.
Signed-off-by: Blue Swirl <blauwir...@gmail.com> --- hw/mc146818rtc.c | 20 ++++++++++---------- hw/mc146818rtc.h | 1 + hw/pc.c | 6 ++++++ hw/pc.h | 1 + 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index e0c33c5..93d72cc 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -25,7 +25,6 @@ #include "qemu-timer.h" #include "sysemu.h" #include "pc.h" -#include "apic.h" #include "isa.h" #include "mc146818rtc.h" @@ -115,16 +114,19 @@ static void rtc_coalesced_timer(void *opaque) RTCState *s = opaque; if (s->irq_coalesced != 0) { - apic_reset_irq_delivered(); s->cmos_data[RTC_REG_C] |= 0xc0; qemu_irq_raise(s->irq); - if (apic_get_irq_delivered()) { - s->irq_coalesced--; - } } rtc_coalesced_timer_update(s); } + +void rtc_dec_coalesced(ISADevice *dev) +{ + RTCState *s = DO_UPCAST(RTCState, dev, dev); + + s->irq_coalesced--; +} #endif static void rtc_timer_update(RTCState *s, int64_t current_time) @@ -168,11 +170,12 @@ static void rtc_periodic_timer(void *opaque) s->cmos_data[RTC_REG_C] |= 0xc0; #ifdef TARGET_I386 if(rtc_td_hack) { + uint32_t old_coalesced = s->irq_coalesced; + if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT) s->irq_reinject_on_ack_count = 0; - apic_reset_irq_delivered(); qemu_irq_raise(s->irq); - if (!apic_get_irq_delivered()) { + if (s->irq_coalesced == old_coalesced) { s->irq_coalesced++; rtc_coalesced_timer_update(s); } @@ -452,10 +455,7 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr) if(s->irq_coalesced && s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) { s->irq_reinject_on_ack_count++; - apic_reset_irq_delivered(); qemu_irq_raise(s->irq); - if (apic_get_irq_delivered()) - s->irq_coalesced--; break; } #endif diff --git a/hw/mc146818rtc.h b/hw/mc146818rtc.h index d630485..c496ecd 100644 --- a/hw/mc146818rtc.h +++ b/hw/mc146818rtc.h @@ -6,6 +6,7 @@ ISADevice *rtc_init(int base_year); void rtc_set_memory(ISADevice *dev, int addr, int val); void rtc_set_date(ISADevice *dev, const struct tm *tm); +void rtc_dec_coalesced(ISADevice *dev); #define RTC_ISA_IRQ 8 diff --git a/hw/pc.c b/hw/pc.c index 9f1a9d6..c6f28e1 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -78,6 +78,8 @@ static void isa_set_irq(IsaIrqState *isa, int n, int level) static void rtc_irq_handler(IsaIrqState *isa, int level) { + apic_reset_irq_delivered(); + /* When HPET is operating in legacy mode, RTC interrupts are disabled. * We block qemu_irq_raise, but not qemu_irq_lower, in case legacy * mode is established while interrupt is raised. We want it to @@ -85,6 +87,9 @@ static void rtc_irq_handler(IsaIrqState *isa, int level) */ if ((isa->hpet_state && !hpet_in_legacy_mode(isa->hpet_state)) || !level) { isa_set_irq(isa, RTC_ISA_IRQ, level); + if (apic_get_irq_delivered()) { + rtc_dec_coalesced(isa->rtc_state); + } } } @@ -961,6 +966,7 @@ void pc_basic_device_init(qemu_irq *isa_irq, IsaIrqState *isa, register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL); *rtc_state = rtc_init(2000); + isa->rtc_state = *rtc_state; qemu_register_boot_set(pc_boot_set, *rtc_state); diff --git a/hw/pc.h b/hw/pc.h index 3e085b9..e19dfe9 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -42,6 +42,7 @@ void irq_info(Monitor *mon); typedef struct isa_irq_state { qemu_irq *i8259; qemu_irq *ioapic; + ISADevice *rtc_state; void *hpet_state; } IsaIrqState; -- 1.6.2.4