diff options
author | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2006-10-25 11:50:54 +0100 |
---|---|---|
committer | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2006-10-25 11:50:54 +0100 |
commit | fcf4e106d0be62c04c62393632bb8b5a52c2dc8a (patch) | |
tree | 1cd785807ff527ac52f0aad588e46439d09318f2 /xen/arch/x86/hvm/pmtimer.c | |
parent | 94e4fb8a1d430fec021c1981f9fd25df6d0246a1 (diff) | |
download | xen-fcf4e106d0be62c04c62393632bb8b5a52c2dc8a.tar.gz xen-fcf4e106d0be62c04c62393632bb8b5a52c2dc8a.tar.bz2 xen-fcf4e106d0be62c04c62393632bb8b5a52c2dc8a.zip |
[HVM] Move ACPI timer to HV, which is the last platform timer in Qemu.
We found Vista polls ACPI timer very frequently (about 15 times
averagely) when handling timer (RTC @ 64HZ) interrupt routine. Though
the exact reason is known, it should be related to system time
adjustment. When it's in Qemu, the overhead is big. After moving,
Vista's idle overhead decreases dramatically from ~10% to 0.9%.=20
Another benefit is that Vista can only pass Performance rating with
this patch. The root cause is that ACPI timer in Qemu isn't
synchronous with other platform timer in HV, which results in Vista
complains "can't measure TSC frequency".
This patch changes vpit.h to vpt.h, for it not only has pit structure
in it, but other platform timer's structure. Another change is moving
ACPI timer and related address from acpi.h to ioreq.h, which can be shared
by HV and ACPI firmware.
Signed-off-by: Xiaowei Yang <xiaowei.yang@intel.com>
Diffstat (limited to 'xen/arch/x86/hvm/pmtimer.c')
-rw-r--r-- | xen/arch/x86/hvm/pmtimer.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/xen/arch/x86/hvm/pmtimer.c b/xen/arch/x86/hvm/pmtimer.c new file mode 100644 index 0000000000..e0c93536ea --- /dev/null +++ b/xen/arch/x86/hvm/pmtimer.c @@ -0,0 +1,63 @@ +#include <asm/hvm/vpt.h> +#include <asm/hvm/io.h> +#include <asm/hvm/support.h> + +#define TMR_STS (1 << 0) +static void pmt_update_status(void *opaque) +{ + PMTState *s = opaque; + s->pm1_status |= TMR_STS; + + /* TODO: When TMR_EN == 1, generate a SCI event */ + + set_timer(&s->timer, NOW() + (1000000000ULL << 31) / FREQUENCE_PMTIMER); +} + +static int handle_pmt_io(ioreq_t *p) +{ + struct vcpu *v = current; + PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt; + uint64_t curr_gtime; + + if (p->size != 4 || + p->pdata_valid || + p->type != IOREQ_TYPE_PIO){ + printk("HVM_PMT: wrong PM timer IO\n"); + return 1; + } + + if (p->dir == 0) { /* write */ + /* PM_TMR_BLK is read-only */ + return 1; + } else if (p->dir == 1) { /* read */ + curr_gtime = hvm_get_guest_time(s->vcpu); + s->pm1_timer += ((curr_gtime - s->last_gtime) * s->scale) >> 32; + p->u.data = s->pm1_timer; + s->last_gtime = curr_gtime; + return 1; + } + return 0; +} + +void pmtimer_init(struct vcpu *v, int base) +{ + PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt; + + s->pm1_timer = 0; + s->pm1_status = 0; + s->scale = ((uint64_t)FREQUENCE_PMTIMER << 32) / ticks_per_sec(v); + s->vcpu = v; + + init_timer(&s->timer, pmt_update_status, s, v->processor); + /* ACPI supports a 32-bit power management timer */ + set_timer(&s->timer, NOW() + (1000000000ULL << 31) / FREQUENCE_PMTIMER); + + register_portio_handler(base, 4, handle_pmt_io); +} + +void pmtimer_deinit(struct domain *d) +{ + PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; + + kill_timer(&s->timer); +} |