diff --git a/tools/firmware/acpi/acpi_fadt.h b/tools/firmware/acpi/acpi_fadt.h index d1ecea5588..f30a1dac98 100644 --- a/tools/firmware/acpi/acpi_fadt.h +++ b/tools/firmware/acpi/acpi_fadt.h @@ -18,6 +18,8 @@ #ifndef _FADT_H_ #define _FADT_H_ +#include + // // 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 diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile index 37623ff5eb..843a9232bf 100644 --- a/xen/arch/x86/hvm/Makefile +++ b/xen/arch/x86/hvm/Makefile @@ -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 diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 47d7ca46c4..f950d05295 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include #include @@ -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) diff --git a/xen/arch/x86/hvm/i8254.c b/xen/arch/x86/hvm/i8254.c index 5f27ee25b2..464ddee8f9 100644 --- a/xen/arch/x86/hvm/i8254.c +++ b/xen/arch/x86/hvm/i8254.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include /* Enable DEBUG_PIT may cause guest calibration inaccuracy */ diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index 8993572e10..a1ce8ddf33 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include 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 +#include +#include + +#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); +} diff --git a/xen/arch/x86/hvm/rtc.c b/xen/arch/x86/hvm/rtc.c index 210168c26b..0f5e11986e 100644 --- a/xen/arch/x86/hvm/rtc.c +++ b/xen/arch/x86/hvm/rtc.c @@ -23,7 +23,7 @@ */ #include -#include +#include #include #include #include diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 92167d74fb..88c0802425 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -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); } diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 476f8beae9..ac1be73556 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -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( diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h index 6561519cb1..0ebec779c1 100644 --- a/xen/include/asm-x86/hvm/domain.h +++ b/xen/include/asm-x86/hvm/domain.h @@ -23,7 +23,7 @@ #define __ASM_X86_HVM_DOMAIN_H__ #include -#include +#include #include #include #include diff --git a/xen/include/asm-x86/hvm/vpit.h b/xen/include/asm-x86/hvm/vpt.h similarity index 89% rename from xen/include/asm-x86/hvm/vpit.h rename to xen/include/asm-x86/hvm/vpt.h index 83b1af2622..ada8936af7 100644 --- a/xen/include/asm-x86/hvm/vpit.h +++ b/xen/include/asm-x86/hvm/vpt.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 #include @@ -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__ */ diff --git a/xen/include/public/hvm/ioreq.h b/xen/include/public/hvm/ioreq.h index 8e92b004b1..992505e1c5 100644 --- a/xen/include/public/hvm/ioreq.h +++ b/xen/include/public/hvm/ioreq.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_ */ /*