summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorIsaku Yamahata <yamahata@valinux.co.jp>2011-03-25 19:54:38 +0900
committerAurelien Jarno <aurelien@aurel32.net>2011-04-09 18:39:05 +0200
commita54d41a8b985cc7ff9d4bc52e6ca20a09216b394 (patch)
tree5ee739f336ffaff9ba0d008bef2c0b165528de3d /hw
parent5145b3d1cc4dc77d82086d99b0690a76e1073071 (diff)
downloadqemu-a54d41a8b985cc7ff9d4bc52e6ca20a09216b394.tar.gz
qemu-a54d41a8b985cc7ff9d4bc52e6ca20a09216b394.tar.bz2
qemu-a54d41a8b985cc7ff9d4bc52e6ca20a09216b394.zip
acpi, acpi_piix, vt82c686: factor out PM_TMR logic
factor out PM_TMR logic. Later This will be used by ich9 acpi. Also fixes the same bug in vt82c686.c that was fixed by the following commits. > commit 055479feab63607b8042bb8ebb2e0523f17cbc4e > Author: aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162> > Date: Wed Jan 21 16:31:20 2009 +0000 > > Always return latest pmsts instead of the old one (Xiantao Zhang) > > It may lead to the issue when booting windows guests with acpi=1 > if return the old pmsts. > > Signed-off-by: Xiantao Zhang <xiantao.zhang@intel.com> > Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> Cc: Blue Swirl <blauwirbel@gmail.com> Cc: Huacai Chen <zltjiangshi@gmail.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi.c45
-rw-r--r--hw/acpi.h24
-rw-r--r--hw/acpi_piix4.c45
-rw-r--r--hw/vt82c686.c47
4 files changed, 96 insertions, 65 deletions
diff --git a/hw/acpi.c b/hw/acpi.c
index 8071e7beba..08cb12673b 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -197,3 +197,48 @@ out:
}
return -1;
}
+
+/* ACPI PM_TMR */
+void acpi_pm_tmr_update(ACPIPMTimer *tmr, bool enable)
+{
+ int64_t expire_time;
+
+ /* schedule a timer interruption if needed */
+ if (enable) {
+ expire_time = muldiv64(tmr->overflow_time, get_ticks_per_sec(),
+ PM_TIMER_FREQUENCY);
+ qemu_mod_timer(tmr->timer, expire_time);
+ } else {
+ qemu_del_timer(tmr->timer);
+ }
+}
+
+void acpi_pm_tmr_calc_overflow_time(ACPIPMTimer *tmr)
+{
+ int64_t d = acpi_pm_tmr_get_clock();
+ tmr->overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
+}
+
+uint32_t acpi_pm_tmr_get(ACPIPMTimer *tmr)
+{
+ uint32_t d = acpi_pm_tmr_get_clock();;
+ return d & 0xffffff;
+}
+
+static void acpi_pm_tmr_timer(void *opaque)
+{
+ ACPIPMTimer *tmr = opaque;
+ tmr->update_sci(tmr);
+}
+
+void acpi_pm_tmr_init(ACPIPMTimer *tmr, acpi_update_sci_fn update_sci)
+{
+ tmr->update_sci = update_sci;
+ tmr->timer = qemu_new_timer_ns(vm_clock, acpi_pm_tmr_timer, tmr);
+}
+
+void acpi_pm_tmr_reset(ACPIPMTimer *tmr)
+{
+ tmr->overflow_time = 0;
+ qemu_del_timer(tmr->timer);
+}
diff --git a/hw/acpi.h b/hw/acpi.h
index 5949958067..fc425012b3 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -74,5 +74,29 @@
#define ACPI_BITMASK_ARB_DISABLE 0x0001
/* PM_TMR */
+struct ACPIPMTimer;
+typedef struct ACPIPMTimer ACPIPMTimer;
+
+typedef void (*acpi_update_sci_fn)(ACPIPMTimer *tmr);
+
+struct ACPIPMTimer {
+ QEMUTimer *timer;
+ int64_t overflow_time;
+
+ acpi_update_sci_fn update_sci;
+};
+
+void acpi_pm_tmr_update(ACPIPMTimer *tmr, bool enable);
+void acpi_pm_tmr_calc_overflow_time(ACPIPMTimer *tmr);
+uint32_t acpi_pm_tmr_get(ACPIPMTimer *tmr);
+void acpi_pm_tmr_init(ACPIPMTimer *tmr, acpi_update_sci_fn update_sci);
+void acpi_pm_tmr_reset(ACPIPMTimer *tmr);
+
+#include "qemu-timer.h"
+static inline int64_t acpi_pm_tmr_get_clock(void)
+{
+ return muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY,
+ get_ticks_per_sec());
+}
#endif /* !QEMU_HW_ACPI_H */
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 74044ddd9b..e4ba8fc252 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -60,8 +60,7 @@ typedef struct PIIX4PMState {
APMState apm;
- QEMUTimer *tmr_timer;
- int64_t tmr_overflow_time;
+ ACPIPMTimer tmr;
PMSMBus smb;
uint32_t smb_io_base;
@@ -82,20 +81,10 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s);
#define ACPI_ENABLE 0xf1
#define ACPI_DISABLE 0xf0
-static uint32_t get_pmtmr(PIIX4PMState *s)
-{
- uint32_t d;
- d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
- return d & 0xffffff;
-}
-
static int get_pmsts(PIIX4PMState *s)
{
- int64_t d;
-
- d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY,
- get_ticks_per_sec());
- if (d >= s->tmr_overflow_time)
+ int64_t d = acpi_pm_tmr_get_clock();
+ if (d >= s->tmr.overflow_time)
s->pmsts |= ACPI_BITMASK_TIMER_STATUS;
return s->pmsts;
}
@@ -103,7 +92,6 @@ static int get_pmsts(PIIX4PMState *s)
static void pm_update_sci(PIIX4PMState *s)
{
int sci_level, pmsts;
- int64_t expire_time;
pmsts = get_pmsts(s);
sci_level = (((pmsts & s->pmen) &
@@ -115,19 +103,13 @@ static void pm_update_sci(PIIX4PMState *s)
qemu_set_irq(s->irq, sci_level);
/* schedule a timer interruption if needed */
- if ((s->pmen & ACPI_BITMASK_TIMER_ENABLE) &&
- !(pmsts & ACPI_BITMASK_TIMER_STATUS)) {
- expire_time = muldiv64(s->tmr_overflow_time, get_ticks_per_sec(),
- PM_TIMER_FREQUENCY);
- qemu_mod_timer(s->tmr_timer, expire_time);
- } else {
- qemu_del_timer(s->tmr_timer);
- }
+ acpi_pm_tmr_update(&s->tmr, (s->pmen & ACPI_BITMASK_TIMER_ENABLE) &&
+ !(pmsts & ACPI_BITMASK_TIMER_STATUS));
}
-static void pm_tmr_timer(void *opaque)
+static void pm_tmr_timer(ACPIPMTimer *tmr)
{
- PIIX4PMState *s = opaque;
+ PIIX4PMState *s = container_of(tmr, PIIX4PMState, tmr);
pm_update_sci(s);
}
@@ -144,14 +126,11 @@ static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width,
switch(addr) {
case 0x00:
{
- int64_t d;
int pmsts;
pmsts = get_pmsts(s);
if (pmsts & val & ACPI_BITMASK_TIMER_STATUS) {
/* if TMRSTS is reset, then compute the new overflow time */
- d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY,
- get_ticks_per_sec());
- s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
+ acpi_pm_tmr_calc_overflow_time(&s->tmr);
}
s->pmsts &= ~val;
pm_update_sci(s);
@@ -211,7 +190,7 @@ static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width,
val = s->pmcntrl;
break;
case 0x08:
- val = get_pmtmr(s);
+ val = acpi_pm_tmr_get(&s->tmr);
break;
default:
val = 0;
@@ -316,8 +295,8 @@ static const VMStateDescription vmstate_acpi = {
VMSTATE_UINT16(pmen, PIIX4PMState),
VMSTATE_UINT16(pmcntrl, PIIX4PMState),
VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState),
- VMSTATE_TIMER(tmr_timer, PIIX4PMState),
- VMSTATE_INT64(tmr_overflow_time, PIIX4PMState),
+ VMSTATE_TIMER(tmr.timer, PIIX4PMState),
+ VMSTATE_INT64(tmr.overflow_time, PIIX4PMState),
VMSTATE_STRUCT(gpe, PIIX4PMState, 2, vmstate_gpe, struct gpe_regs),
VMSTATE_STRUCT(pci0_status, PIIX4PMState, 2, vmstate_pci_status,
struct pci_status),
@@ -414,7 +393,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
register_ioport_write(s->smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
register_ioport_read(s->smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
- s->tmr_timer = qemu_new_timer_ns(vm_clock, pm_tmr_timer, s);
+ acpi_pm_tmr_init(&s->tmr, pm_tmr_timer);
qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1);
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 818460d716..6f9c3847cb 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -160,8 +160,7 @@ typedef struct VT686PMState {
uint16_t pmen;
uint16_t pmcntrl;
APMState apm;
- QEMUTimer *tmr_timer;
- int64_t tmr_overflow_time;
+ ACPIPMTimer tmr;
PMSMBus smb;
uint32_t smb_io_base;
} VT686PMState;
@@ -183,45 +182,31 @@ typedef struct VT686MC97State {
#define ACPI_ENABLE 0xf1
#define ACPI_DISABLE 0xf0
-static uint32_t get_pmtmr(VT686PMState *s)
-{
- uint32_t d;
- d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
- return d & 0xffffff;
-}
-
static int get_pmsts(VT686PMState *s)
{
- int64_t d;
- int pmsts;
- pmsts = s->pmsts;
- d = muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
- if (d >= s->tmr_overflow_time)
- s->pmsts |= TMROF_EN;
- return pmsts;
+ int64_t d = acpi_pm_tmr_get_clock();
+ if (d >= s->tmr.overflow_time) {
+ s->pmsts |= ACPI_BITMASK_TIMER_STATUS;
+ }
+ return s->pmsts;
}
static void pm_update_sci(VT686PMState *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->dev.irq[0], sci_level);
/* schedule a timer interruption if needed */
- if ((s->pmen & TMROF_EN) && !(pmsts & TMROF_EN)) {
- expire_time = muldiv64(s->tmr_overflow_time, get_ticks_per_sec(), PM_TIMER_FREQUENCY);
- qemu_mod_timer(s->tmr_timer, expire_time);
- } else {
- qemu_del_timer(s->tmr_timer);
- }
+ acpi_pm_tmr_update(&s->tmr, (s->pmen & ACPI_BITMASK_TIMER_ENABLE) &&
+ !(pmsts & ACPI_BITMASK_TIMER_STATUS));
}
-static void pm_tmr_timer(void *opaque)
+static void pm_tmr_timer(ACPIPMTimer *tmr)
{
- VT686PMState *s = opaque;
+ VT686PMState *s = container_of(tmr, VT686PMState, tmr);
pm_update_sci(s);
}
@@ -233,13 +218,11 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
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_ns(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
- s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
+ acpi_pm_tmr_calc_overflow_time(&s->tmr);
}
s->pmsts &= ~val;
pm_update_sci(s);
@@ -310,7 +293,7 @@ static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
addr &= 0x0f;
switch (addr) {
case 0x08:
- val = get_pmtmr(s);
+ val = acpi_pm_tmr_get(&s->tmr);
break;
default:
val = 0;
@@ -365,8 +348,8 @@ static const VMStateDescription vmstate_acpi = {
VMSTATE_UINT16(pmen, VT686PMState),
VMSTATE_UINT16(pmcntrl, VT686PMState),
VMSTATE_STRUCT(apm, VT686PMState, 0, vmstate_apm, APMState),
- VMSTATE_TIMER(tmr_timer, VT686PMState),
- VMSTATE_INT64(tmr_overflow_time, VT686PMState),
+ VMSTATE_TIMER(tmr.timer, VT686PMState),
+ VMSTATE_INT64(tmr.overflow_time, VT686PMState),
VMSTATE_END_OF_LIST()
}
};
@@ -486,7 +469,7 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
apm_init(&s->apm, NULL, s);
- s->tmr_timer = qemu_new_timer_ns(vm_clock, pm_tmr_timer, s);
+ acpi_pm_tmr_init(&s->tmr, pm_tmr_timer);
pm_smbus_init(&s->dev.qdev, &s->smb);