mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
[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>
This commit is contained in:
1 parent
94e4fb8a1d
commit
fcf4e106d0
12 files changed
+103
-15
No files matched your search
@@ -18,6 +18,8 @@
|
||||
#ifndef _FADT_H_
|
||||
#define _FADT_H_
|
||||
|
||||
#include <xen/hvm/ioreq.h>
|
||||
|
||||
//
|
||||
// FADT Definitions, see ACPI 2.0 specification for details.
|
||||
//
|
||||
@@ -51,7 +53,9 @@
|
||||
//
|
||||
// Fixed Feature Flags
|
||||
//
|
||||
#define ACPI_FIXED_FEATURE_FLAGS (ACPI_PROC_C1|ACPI_SLP_BUTTON|ACPI_WBINVD|ACPI_PWR_BUTTON|ACPI_FIX_RTC)
|
||||
#define ACPI_FIXED_FEATURE_FLAGS (ACPI_PROC_C1 | ACPI_SLP_BUTTON | \
|
||||
ACPI_WBINVD | ACPI_PWR_BUTTON | \
|
||||
ACPI_FIX_RTC | ACPI_TMR_VAL_EXT)
|
||||
|
||||
//
|
||||
// PM1A Event Register Block Generic Address Information
|
||||
@@ -59,7 +63,6 @@
|
||||
#define ACPI_PM1A_EVT_BLK_ADDRESS_SPACE_ID ACPI_SYSTEM_IO
|
||||
#define ACPI_PM1A_EVT_BLK_BIT_WIDTH 0x20
|
||||
#define ACPI_PM1A_EVT_BLK_BIT_OFFSET 0x00
|
||||
#define ACPI_PM1A_EVT_BLK_ADDRESS 0x000000000000c010
|
||||
|
||||
//
|
||||
// PM1B Event Register Block Generic Address Information
|
||||
@@ -75,7 +78,6 @@
|
||||
#define ACPI_PM1A_CNT_BLK_ADDRESS_SPACE_ID ACPI_SYSTEM_IO
|
||||
#define ACPI_PM1A_CNT_BLK_BIT_WIDTH 0x10
|
||||
#define ACPI_PM1A_CNT_BLK_BIT_OFFSET 0x00
|
||||
#define ACPI_PM1A_CNT_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x04)
|
||||
|
||||
//
|
||||
// PM1B Control Register Block Generic Address Information
|
||||
@@ -100,7 +102,6 @@
|
||||
#define ACPI_PM_TMR_BLK_ADDRESS_SPACE_ID ACPI_SYSTEM_IO
|
||||
#define ACPI_PM_TMR_BLK_BIT_WIDTH 0x20
|
||||
#define ACPI_PM_TMR_BLK_BIT_OFFSET 0x00
|
||||
#define ACPI_PM_TMR_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x08)
|
||||
|
||||
//
|
||||
// General Purpose Event 0 Register Block Generic Address
|
||||
|
||||
@@ -5,6 +5,7 @@ obj-y += hvm.o
|
||||
obj-y += i8254.o
|
||||
obj-y += i8259.o
|
||||
obj-y += rtc.o
|
||||
obj-y += pmtimer.o
|
||||
obj-y += instrlen.o
|
||||
obj-y += intercept.o
|
||||
obj-y += io.o
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
#include <asm/mc146818rtc.h>
|
||||
#include <asm/spinlock.h>
|
||||
#include <asm/hvm/hvm.h>
|
||||
#include <asm/hvm/vpit.h>
|
||||
#include <asm/hvm/vpt.h>
|
||||
#include <asm/hvm/support.h>
|
||||
#include <public/sched.h>
|
||||
#include <public/hvm/ioreq.h>
|
||||
@@ -285,6 +285,7 @@ void hvm_setup_platform(struct domain* d)
|
||||
pt_timer_fn, v, v->processor);
|
||||
pit_init(v, cpu_khz);
|
||||
rtc_init(v, RTC_PORT(0), RTC_IRQ);
|
||||
pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS);
|
||||
}
|
||||
|
||||
void pic_irq_request(void *data, int level)
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include <asm/hvm/hvm.h>
|
||||
#include <asm/hvm/io.h>
|
||||
#include <asm/hvm/support.h>
|
||||
#include <asm/hvm/vpit.h>
|
||||
#include <asm/hvm/vpt.h>
|
||||
#include <asm/current.h>
|
||||
|
||||
/* Enable DEBUG_PIT may cause guest calibration inaccuracy */
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include <asm/shadow.h>
|
||||
#include <asm/hvm/hvm.h>
|
||||
#include <asm/hvm/support.h>
|
||||
#include <asm/hvm/vpit.h>
|
||||
#include <asm/hvm/vpt.h>
|
||||
#include <asm/hvm/vpic.h>
|
||||
#include <asm/hvm/vlapic.h>
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
#include <asm/mc146818rtc.h>
|
||||
#include <asm/hvm/vpit.h>
|
||||
#include <asm/hvm/vpt.h>
|
||||
#include <asm/hvm/io.h>
|
||||
#include <asm/hvm/support.h>
|
||||
#include <asm/current.h>
|
||||
|
||||
@@ -922,6 +922,7 @@ static void svm_relinquish_guest_resources(struct domain *d)
|
||||
|
||||
kill_timer(&d->arch.hvm_domain.pl_time.periodic_tm.timer);
|
||||
rtc_deinit(d);
|
||||
pmtimer_deinit(d);
|
||||
|
||||
if ( d->arch.hvm_domain.shared_page_va )
|
||||
unmap_domain_page_global(
|
||||
@@ -937,6 +938,7 @@ static void svm_migrate_timers(struct vcpu *v)
|
||||
struct periodic_time *pt =
|
||||
&(v->domain->arch.hvm_domain.pl_time.periodic_tm);
|
||||
struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
|
||||
struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt;
|
||||
|
||||
if ( pt->enabled )
|
||||
{
|
||||
@@ -947,6 +949,7 @@ static void svm_migrate_timers(struct vcpu *v)
|
||||
migrate_timer(&VLAPIC(v)->vlapic_timer, v->processor);
|
||||
migrate_timer(&vrtc->second_timer, v->processor);
|
||||
migrate_timer(&vrtc->second_timer2, v->processor);
|
||||
migrate_timer(&vpmt->timer, v->processor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -147,6 +147,7 @@ static void vmx_relinquish_guest_resources(struct domain *d)
|
||||
|
||||
kill_timer(&d->arch.hvm_domain.pl_time.periodic_tm.timer);
|
||||
rtc_deinit(d);
|
||||
pmtimer_deinit(d);
|
||||
|
||||
if ( d->arch.hvm_domain.shared_page_va )
|
||||
unmap_domain_page_global(
|
||||
@@ -489,6 +490,7 @@ void vmx_migrate_timers(struct vcpu *v)
|
||||
{
|
||||
struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
|
||||
struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
|
||||
struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt;
|
||||
|
||||
if ( pt->enabled )
|
||||
{
|
||||
@@ -499,6 +501,7 @@ void vmx_migrate_timers(struct vcpu *v)
|
||||
migrate_timer(&VLAPIC(v)->vlapic_timer, v->processor);
|
||||
migrate_timer(&vrtc->second_timer, v->processor);
|
||||
migrate_timer(&vrtc->second_timer2, v->processor);
|
||||
migrate_timer(&vpmt->timer, v->processor);
|
||||
}
|
||||
|
||||
static void vmx_store_cpu_guest_regs(
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#define __ASM_X86_HVM_DOMAIN_H__
|
||||
|
||||
#include <asm/hvm/vpic.h>
|
||||
#include <asm/hvm/vpit.h>
|
||||
#include <asm/hvm/vpt.h>
|
||||
#include <asm/hvm/vlapic.h>
|
||||
#include <asm/hvm/vioapic.h>
|
||||
#include <public/hvm/params.h>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* vpit.h: Virtual PIT definitions
|
||||
* vpt.h: Virtual Platform Timer definitions
|
||||
*
|
||||
* Copyright (c) 2004, Intel Corporation.
|
||||
*
|
||||
@@ -17,8 +17,8 @@
|
||||
* Place - Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_X86_HVM_VPIT_H__
|
||||
#define __ASM_X86_HVM_VPIT_H__
|
||||
#ifndef __ASM_X86_HVM_VPT_H__
|
||||
#define __ASM_X86_HVM_VPT_H__
|
||||
|
||||
#include <xen/config.h>
|
||||
#include <xen/init.h>
|
||||
@@ -70,7 +70,17 @@ typedef struct RTCState {
|
||||
struct vcpu *vcpu;
|
||||
struct periodic_time *pt;
|
||||
} RTCState;
|
||||
|
||||
|
||||
#define FREQUENCE_PMTIMER 3579545
|
||||
typedef struct PMTState {
|
||||
uint32_t pm1_timer;
|
||||
uint32_t pm1_status;
|
||||
uint64_t last_gtime;
|
||||
struct timer timer;
|
||||
uint64_t scale;
|
||||
struct vcpu *vcpu;
|
||||
} PMTState;
|
||||
|
||||
/*
|
||||
* Abstract layer of periodic time, one short time.
|
||||
*/
|
||||
@@ -95,7 +105,7 @@ struct pl_time { /* platform time */
|
||||
struct periodic_time periodic_tm;
|
||||
struct PITState vpit;
|
||||
struct RTCState vrtc;
|
||||
/* TODO: ACPI time */
|
||||
struct PMTState vpmt;
|
||||
};
|
||||
|
||||
static __inline__ s_time_t get_scheduled(
|
||||
@@ -132,8 +142,10 @@ extern void destroy_periodic_time(struct periodic_time *pt);
|
||||
void pit_init(struct vcpu *v, unsigned long cpu_khz);
|
||||
void rtc_init(struct vcpu *v, int base, int irq);
|
||||
void rtc_deinit(struct domain *d);
|
||||
void pmtimer_init(struct vcpu *v, int base);
|
||||
void pmtimer_deinit(struct domain *d);
|
||||
int is_rtc_periodic_irq(void *opaque);
|
||||
void pt_timer_fn(void *data);
|
||||
void pit_time_fired(struct vcpu *v, void *priv);
|
||||
|
||||
#endif /* __ASM_X86_HVM_VPIT_H__ */
|
||||
#endif /* __ASM_X86_HVM_VPT_H__ */
|
||||
@@ -86,6 +86,10 @@ struct buffered_iopage {
|
||||
}; /* sizeof this structure must be in one page */
|
||||
typedef struct buffered_iopage buffered_iopage_t;
|
||||
|
||||
#define ACPI_PM1A_EVT_BLK_ADDRESS 0x000000000000c010
|
||||
#define ACPI_PM1A_CNT_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x04)
|
||||
#define ACPI_PM_TMR_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x08)
|
||||
|
||||
#endif /* _IOREQ_H_ */
|
||||
|
||||
/*
|
||||
|
||||