@@ -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
@@ -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
@@ -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);
@@ -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;
A side effect is that coalesced irq handling is extended to seconds alarm and irq reinjection. Signed-off-by: Blue Swirl <blauwirbel@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(-)