From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1JZa0U-0005Ai-0h for qemu-devel@nongnu.org; Wed, 12 Mar 2008 19:05:10 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1JZa0T-0005AW-DQ for qemu-devel@nongnu.org; Wed, 12 Mar 2008 19:05:09 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JZa0T-0005AT-9p for qemu-devel@nongnu.org; Wed, 12 Mar 2008 19:05:09 -0400 Received: from nf-out-0910.google.com ([64.233.182.190]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1JZa0S-0003h6-GD for qemu-devel@nongnu.org; Wed, 12 Mar 2008 19:05:08 -0400 Received: by nf-out-0910.google.com with SMTP id 30so1366921nfu.12 for ; Wed, 12 Mar 2008 16:05:05 -0700 (PDT) Content-Type: multipart/mixed; boundary="=-BS4k9LxQef/kt1d/0J97" Date: Thu, 13 Mar 2008 01:00:38 +0200 Message-Id: <1205362838.3163.27.camel@localhost.localdomain> Mime-Version: 1.0 From: Dor Laor Subject: [Qemu-devel] [PATCH] Fix sci irq set when acpi timer about to wrap Reply-To: dor.laor@qumranet.com, qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel , kvm-devel --=-BS4k9LxQef/kt1d/0J97 Content-Type: text/plain Content-Transfer-Encoding: 7bit >>From 498f162fc9d9fb897c756273c481101a44a220de Mon Sep 17 00:00:00 2001 From: Dor Laor Date: Thu, 13 Mar 2008 00:11:41 +0200 Subject: [PATCH] Fix sci irq set when acpi timer about to wrap. The acpi timer should generate sci irq when enabled and when bit 23 of the timer counter toogles. It fixes time reading by the performance counter api of windows guest. Signed-off-by: Yaniv Kamay Signed-off-by: Dor Laor --- qemu/hw/acpi.c | 81 +++++++++++++++++++++++++++++-------------------------- 1 files changed, 43 insertions(+), 38 deletions(-) diff --git a/qemu/hw/acpi.c b/qemu/hw/acpi.c index e44c8b5..8c47969 100644 --- a/qemu/hw/acpi.c +++ b/qemu/hw/acpi.c @@ -53,12 +53,15 @@ typedef struct PIIX4PMState { 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) @@ -77,47 +80,58 @@ typedef struct PIIX4PMState { 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; - - 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); - } + int sci_level; + + 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) @@ -126,18 +140,9 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) 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; -- 1.5.4.1 --=-BS4k9LxQef/kt1d/0J97 Content-Disposition: attachment; filename=0001-Fix-sci-irq-set-when-acpi-timer-about-to-wrap.patch Content-Type: application/mbox; name=0001-Fix-sci-irq-set-when-acpi-timer-about-to-wrap.patch Content-Transfer-Encoding: 7bit >>From 498f162fc9d9fb897c756273c481101a44a220de Mon Sep 17 00:00:00 2001 From: Dor Laor Date: Thu, 13 Mar 2008 00:11:41 +0200 Subject: [PATCH] Fix sci irq set when acpi timer about to wrap. The acpi timer should generate sci irq when enabled and when bit 23 of the timer counter toogles. It fixes time reading by the performance counter api of windows guest. Signed-off-by: Yaniv Kamay Signed-off-by: Dor Laor --- qemu/hw/acpi.c | 81 +++++++++++++++++++++++++++++-------------------------- 1 files changed, 43 insertions(+), 38 deletions(-) diff --git a/qemu/hw/acpi.c b/qemu/hw/acpi.c index e44c8b5..8c47969 100644 --- a/qemu/hw/acpi.c +++ b/qemu/hw/acpi.c @@ -53,12 +53,15 @@ typedef struct PIIX4PMState { 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) @@ -77,47 +80,58 @@ typedef struct PIIX4PMState { 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; - - 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); - } + int sci_level; + + 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) @@ -126,18 +140,9 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) 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; -- 1.5.4.1 --=-BS4k9LxQef/kt1d/0J97--