From 9fdbd92554d13e0354ddc0a4a1ce24edd743100e Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 23 Apr 2008 12:59:43 +0300 Subject: Revert "kvm: qemu: fix sci irq set when acpi timer about to wrap" This reverts commit 6bb0805aeabd5c6ef5408f57c7da5ca6385dd0f5, which kills system_powerdown. Signed-off-by: Avi Kivity --- hw/acpi.c | 81 ++++++++++++++++++++++++++++++--------------------------------- 1 file changed, 38 insertions(+), 43 deletions(-) diff --git a/hw/acpi.c b/hw/acpi.c index a7e5e2627..c4419c402 100644 --- a/hw/acpi.c +++ b/hw/acpi.c @@ -54,15 +54,12 @@ 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) @@ -81,58 +78,47 @@ 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) { - update_pmtmr(s); - return s->pmtmr & TIMER_MASK; + uint32_t d; + d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec); + return d & 0xffffff; } - static int get_pmsts(PIIX4PMState *s) { - /* Just increase the accurancy by double computing the timer value */ - update_pmtmr(s); - - return s->pmsts; + 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; } static void pm_update_sci(PIIX4PMState *s) { - 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); + 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); + } } static void pm_tmr_timer(void *opaque) { PIIX4PMState *s = opaque; - update_pmtmr(s); + pm_update_sci(s); } static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) @@ -141,9 +127,18 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) addr &= 0x3f; switch(addr) { case 0x00: - s->pmsts &= ~val; - update_pmtmr(s); - pm_update_sci(s); + { + 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); + } break; case 0x02: s->pmen = val; -- cgit v1.2.3