From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KvCsm-0003Xo-Vy for qemu-devel@nongnu.org; Wed, 29 Oct 2008 11:22:53 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KvCsk-0003W1-MX for qemu-devel@nongnu.org; Wed, 29 Oct 2008 11:22:52 -0400 Received: from [199.232.76.173] (port=56326 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KvCsk-0003Vj-6A for qemu-devel@nongnu.org; Wed, 29 Oct 2008 11:22:50 -0400 Received: from mx2.redhat.com ([66.187.237.31]:49522) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1KvCsj-0004Ur-KH for qemu-devel@nongnu.org; Wed, 29 Oct 2008 11:22:49 -0400 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id m9TFMm2X021916 for ; Wed, 29 Oct 2008 11:22:48 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id m9TFMmSG004626 for ; Wed, 29 Oct 2008 11:22:48 -0400 Received: from dhcp-1-237.tlv.redhat.com (dhcp-1-237.tlv.redhat.com [10.35.1.237]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id m9TFMlrG017677 for ; Wed, 29 Oct 2008 11:22:47 -0400 Received: from dhcp-1-237.local (localhost [127.0.0.1]) by dhcp-1-237.tlv.redhat.com (Postfix) with ESMTP id 119A118D4AF for ; Wed, 29 Oct 2008 17:22:47 +0200 (IST) From: Gleb Natapov Date: Wed, 29 Oct 2008 17:22:47 +0200 Message-ID: <20081029152247.14831.41835.stgit@dhcp-1-237.local> In-Reply-To: <20081029152236.14831.15193.stgit@dhcp-1-237.local> References: <20081029152236.14831.15193.stgit@dhcp-1-237.local> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH 2/3] Fix time drift problem under high load when PIT is in use. Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org 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 pit is used as a time source. Signed-off-by: Gleb Natapov --- hw/i8254.c | 23 ++++++++++++++++++++++- 1 files changed, 22 insertions(+), 1 deletions(-) diff --git a/hw/i8254.c b/hw/i8254.c index 4813b03..1a43ffc 100644 --- a/hw/i8254.c +++ b/hw/i8254.c @@ -49,6 +49,7 @@ typedef struct PITChannelState { int64_t count_load_time; /* irq handling */ int64_t next_transition_time; + uint32_t irq_coalesced; QEMUTimer *irq_timer; qemu_irq irq; } PITChannelState; @@ -228,6 +229,9 @@ static inline void pit_load_count(PITChannelState *s, int val) { if (val == 0) val = 0x10000; + /* recalculate how much IRQs to inject based on new timer value */ + if(s->irq_coalesced) + s->irq_coalesced = (s->irq_coalesced * s->count) / val; s->count_load_time = qemu_get_clock(vm_clock); s->count = val; pit_irq_timer_update(s, s->count_load_time); @@ -369,12 +373,28 @@ static void pit_irq_timer_update(PITChannelState *s, int64_t current_time) return; expire_time = pit_get_next_transition_time(s, current_time); irq_level = pit_get_out1(s, current_time); - qemu_set_irq(s->irq, irq_level); + if(irq_level) { + if(!qemu_irq_raise(s->irq)) + s->irq_coalesced++; + } else { + qemu_irq_lower(s->irq); + if(s->irq_coalesced > 0) { + if(qemu_irq_raise(s->irq)) + s->irq_coalesced--; + qemu_irq_lower(s->irq); + } + } + #ifdef DEBUG_PIT printf("irq_level=%d next_delay=%f\n", irq_level, (double)(expire_time - current_time) / ticks_per_sec); #endif + if(s->irq_coalesced && expire_time != -1) { + uint32_t div = ((s->irq_coalesced >> 10) & 0x7f) + 2; + expire_time -= ((expire_time - current_time) / div); + } + s->next_transition_time = expire_time; if (expire_time != -1) qemu_mod_timer(s->irq_timer, expire_time); @@ -459,6 +479,7 @@ static void pit_reset(void *opaque) s = &pit->channels[i]; s->mode = 3; s->gate = (i != 2); + s->irq_coalesced = 0; pit_load_count(s, 0); } }