From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Jpljr-00029M-Nf for qemu-devel@nongnu.org; Sat, 26 Apr 2008 10:50:55 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Jpljq-00028b-P6 for qemu-devel@nongnu.org; Sat, 26 Apr 2008 10:50:55 -0400 Received: from [199.232.76.173] (port=43878 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Jpljq-00028J-7h for qemu-devel@nongnu.org; Sat, 26 Apr 2008 10:50:54 -0400 Received: from savannah.gnu.org ([199.232.41.3] helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Jpljp-0005sV-Mg for qemu-devel@nongnu.org; Sat, 26 Apr 2008 10:50:53 -0400 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.63) (envelope-from ) id 1Jpljl-0006VK-9k for qemu-devel@nongnu.org; Sat, 26 Apr 2008 14:50:49 +0000 Received: from balrog by cvs.savannah.gnu.org with local (Exim 4.63) (envelope-from ) id 1Jpljl-0006VE-1p for qemu-devel@nongnu.org; Sat, 26 Apr 2008 14:50:49 +0000 MIME-Version: 1.0 Errors-To: balrog Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Andrzej Zaborowski Message-Id: Date: Sat, 26 Apr 2008 14:50:49 +0000 Subject: [Qemu-devel] [4258] Fix sci irq set when acpi timer about to wrap (Dor Laor, Yaniv Kamay ). 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 Revision: 4258 http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4258 Author: balrog Date: 2008-04-26 14:50:48 +0000 (Sat, 26 Apr 2008) Log Message: ----------- Fix sci irq set when acpi timer about to wrap (Dor Laor, Yaniv Kamay). Modified Paths: -------------- trunk/hw/acpi.c Modified: trunk/hw/acpi.c =================================================================== --- trunk/hw/acpi.c 2008-04-26 14:44:49 UTC (rev 4257) +++ trunk/hw/acpi.c 2008-04-26 14:50:48 UTC (rev 4258) @@ -50,12 +50,15 @@ uint8_t smb_data[32]; uint8_t smb_index; qemu_irq irq; + int64_t pmtmr; } PIIX4PMState; #define RTC_EN (1 << 10) #define PWRBTN_EN (1 << 8) #define GBL_EN (1 << 5) #define TMROF_EN (1 << 0) +#define TIMER_OVERFLOW_CNT (1 << 23) +#define TIMER_MASK 0xffffffLL #define SCI_EN (1 << 0) @@ -74,47 +77,61 @@ PIIX4PMState *pm_state; +static void update_pmtmr(PIIX4PMState *s) +{ + int64_t pmtmr; + + pmtmr = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec) + & TIMER_MASK; + + if (!(s->pmsts & TMROF_EN)) { + if ((pmtmr ^ s->pmtmr) & TIMER_OVERFLOW_CNT) { + s->pmsts |= TMROF_EN; + if (s->pmen & TMROF_EN) + qemu_set_irq(s->irq, 1); + } else { + /* Calculate when the timer will neet to set + * the overflow bit again */ + uint64_t delta = TIMER_OVERFLOW_CNT - + (pmtmr & (TIMER_OVERFLOW_CNT - 1)); + + delta = muldiv64(delta, ticks_per_sec, PM_FREQ); + qemu_mod_timer(s->tmr_timer, qemu_get_clock(vm_clock) + delta); + } + } + + s->pmtmr = pmtmr; +} + static uint32_t get_pmtmr(PIIX4PMState *s) { - uint32_t d; - d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec); - return d & 0xffffff; + update_pmtmr(s); + return s->pmtmr & TIMER_MASK; } + static int get_pmsts(PIIX4PMState *s) { - int64_t d; - int pmsts; - pmsts = s->pmsts; - d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec); - if (d >= s->tmr_overflow_time) - s->pmsts |= TMROF_EN; - return pmsts; + /* Just increase the accurancy by double computing the timer value */ + update_pmtmr(s); + + return s->pmsts; } static void pm_update_sci(PIIX4PMState *s) { - int sci_level, pmsts; - int64_t expire_time; + int sci_level; - pmsts = get_pmsts(s); - sci_level = (((pmsts & s->pmen) & - (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0); - qemu_set_irq(s->irq, sci_level); - /* schedule a timer interruption if needed */ - if ((s->pmen & TMROF_EN) && !(pmsts & TMROF_EN)) { - expire_time = muldiv64(s->tmr_overflow_time, ticks_per_sec, PM_FREQ); - qemu_mod_timer(s->tmr_timer, expire_time); - s->tmr_overflow_time += 0x800000; - } else { - qemu_del_timer(s->tmr_timer); - } + sci_level = (((s->pmsts & s->pmen) & + (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0); + if (!sci_level) + qemu_set_irq(s->irq, sci_level); } static void pm_tmr_timer(void *opaque) { PIIX4PMState *s = opaque; - pm_update_sci(s); + update_pmtmr(s); } static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) @@ -123,18 +140,9 @@ addr &= 0x3f; switch(addr) { case 0x00: - { - int64_t d; - int pmsts; - pmsts = get_pmsts(s); - if (pmsts & val & TMROF_EN) { - /* if TMRSTS is reset, then compute the new overflow time */ - d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec); - s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL; - } - s->pmsts &= ~val; - pm_update_sci(s); - } + s->pmsts &= ~val; + update_pmtmr(s); + pm_update_sci(s); break; case 0x02: s->pmen = val;