qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] fix rtc-td-hack on host without high-res timers


From: Gleb Natapov
Subject: [Qemu-devel] [PATCH] fix rtc-td-hack on host without high-res timers
Date: Tue, 8 Dec 2009 15:50:54 +0200

On hosts without high-res timers it is impossible to inject rtc interrupt
faster then 1kHz. Windows sometimes configures RTC to generate 1kHz
interrupts, so we can't inject missed interrupts when running on such
hosts. Always injecting an interrupt on REG_C read is also not an option
since Windows wait for REG_C to become zero with interrupt disabled
during boot. This patch uses mixed approach: accelerate timer + inject
up to 1000 interrupts on REG_C read.

Signed-off-by: Gleb Natapov <address@hidden>
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index b8c7b0c..e4d55c7 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -30,6 +30,8 @@
 
 //#define DEBUG_CMOS
 
+#define RTC_REINJECT_ON_ACK_COUNT 1000
+
 #define RTC_SECONDS             0
 #define RTC_SECONDS_ALARM       1
 #define RTC_MINUTES             2
@@ -76,6 +78,7 @@ struct RTCState {
     int64_t next_periodic_time;
     /* second update */
     int64_t next_second_time;
+    uint16_t irq_reinject_on_ack_count;
     uint32_t irq_coalesced;
     uint32_t period;
     QEMUTimer *coalesced_timer;
@@ -180,6 +183,8 @@ static void rtc_periodic_timer(void *opaque)
         s->cmos_data[RTC_REG_C] |= 0xc0;
 #ifdef TARGET_I386
         if(rtc_td_hack) {
+            if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
+                s->irq_reinject_on_ack_count = 0;              
             apic_reset_irq_delivered();
             rtc_irq_raise(s->irq);
             if (!apic_get_irq_delivered()) {
@@ -458,6 +463,18 @@ 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);
+#ifdef TARGET_I386
+            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
+
             s->cmos_data[RTC_REG_C] = 0x00;
             break;
         default:
--
                        Gleb.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]