From: Tim Deegan Date: Thu, 8 Feb 2007 13:42:49 +0000 (+0000) Subject: [HVM] Save/restore: save pmtimer count register X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~15347^2~8 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=8abe0e51d15e6038599fa0d631e78ab41d5aef1b;p=xen.git [HVM] Save/restore: save pmtimer count register Also remove the repeating timer from pmtimer.c because it doesn't do anything. Signed-off-by: Tim Deegan --- diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 96c827d235..9147737846 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -106,7 +106,6 @@ void hvm_migrate_timers(struct vcpu *v) pit_migrate_timers(v); rtc_migrate_timers(v); hpet_migrate_timers(v); - pmtimer_migrate_timers(v); if ( vcpu_vlapic(v)->pt.enabled ) migrate_timer(&vcpu_vlapic(v)->pt.timer, v->processor); } @@ -170,7 +169,6 @@ void hvm_domain_destroy(struct domain *d) { pit_deinit(d); rtc_deinit(d); - pmtimer_deinit(d); hpet_deinit(d); if ( d->arch.hvm_domain.shared_page_va ) diff --git a/xen/arch/x86/hvm/pmtimer.c b/xen/arch/x86/hvm/pmtimer.c index 28be242f84..a396d27df4 100644 --- a/xen/arch/x86/hvm/pmtimer.c +++ b/xen/arch/x86/hvm/pmtimer.c @@ -2,17 +2,6 @@ #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; @@ -30,42 +19,62 @@ static int handle_pmt_io(ioreq_t *p) /* PM_TMR_BLK is read-only */ return 1; } else if (p->dir == 1) { /* read */ + /* Set the correct value in the timer, accounting for time + * elapsed since the last time we did that. */ curr_gtime = hvm_get_guest_time(s->vcpu); - s->pm1_timer += ((curr_gtime - s->last_gtime) * s->scale) >> 32; - p->data = s->pm1_timer; + s->pm.timer += ((curr_gtime - s->last_gtime) * s->scale) >> 32; + p->data = s->pm.timer; s->last_gtime = curr_gtime; return 1; } return 0; } -void pmtimer_init(struct vcpu *v, int base) +static int pmtimer_save(struct domain *d, hvm_domain_context_t *h) { - 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; + PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; + uint32_t x; - 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(v->domain, base, 4, handle_pmt_io); + /* Update the counter to the guest's current time. We always save + * with the domain paused, so the saved time should be after the + * last_gtime, but just in case, make sure we only go forwards */ + x = ((s->vcpu->arch.hvm_vcpu.guest_time - s->last_gtime) * s->scale) >> 32; + if ( x < 1UL<<31 ) + s->pm.timer += x; + return hvm_save_entry(PMTIMER, 0, h, &s->pm); } -void pmtimer_migrate_timers(struct vcpu *v) +static int pmtimer_load(struct domain *d, hvm_domain_context_t *h) { - struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt; + PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; - if (vpmt->vcpu == v) - migrate_timer(&vpmt->timer, v->processor); + /* Reload the counter */ + if ( hvm_load_entry(PMTIMER, h, &s->pm) ) + return -EINVAL; + + /* Calculate future counter values from now. */ + s->last_gtime = hvm_get_guest_time(s->vcpu); + + return 0; } -void pmtimer_deinit(struct domain *d) +HVM_REGISTER_SAVE_RESTORE(PMTIMER, pmtimer_save, pmtimer_load, + 1, HVMSR_PER_DOM); + + +void pmtimer_init(struct vcpu *v, int base) { - PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; + PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt; + + s->pm.timer = 0; + s->scale = ((uint64_t)FREQUENCE_PMTIMER << 32) / ticks_per_sec(v); + s->vcpu = v; - kill_timer(&s->timer); + /* Not implemented: we should set TMR_STS (bit 0 of PM1a_STS) every + * time the timer's top bit flips, and generate an SCI if TMR_EN + * (bit 0 of PM1a_EN) is set. For now, those registers are in + * qemu-dm, and we just calculate the timer's value on demand. */ + + register_portio_handler(v->domain, base, 4, handle_pmt_io); } + diff --git a/xen/include/asm-x86/hvm/vpt.h b/xen/include/asm-x86/hvm/vpt.h index 78c7b536d4..02bc3fa05c 100644 --- a/xen/include/asm-x86/hvm/vpt.h +++ b/xen/include/asm-x86/hvm/vpt.h @@ -94,14 +94,12 @@ typedef struct RTCState { struct periodic_time pt; } RTCState; -#define FREQUENCE_PMTIMER 3579545 +#define FREQUENCE_PMTIMER 3579545 /* Timer should run at 3.579545 MHz */ typedef struct PMTState { - uint32_t pm1_timer; - uint32_t pm1_status; - uint64_t last_gtime; - struct timer timer; - uint64_t scale; - struct vcpu *vcpu; + struct hvm_hw_pmtimer pm; /* 32bit timer value */ + struct vcpu *vcpu; /* Keeps sync with this vcpu's guest-time */ + uint64_t last_gtime; /* Last (guest) time we updated the timer */ + uint64_t scale; /* Multiplier to get from tsc to timer ticks */ } PMTState; struct pl_time { /* platform time */ @@ -134,8 +132,6 @@ void rtc_migrate_timers(struct vcpu *v); void rtc_deinit(struct domain *d); int is_rtc_periodic_irq(void *opaque); void pmtimer_init(struct vcpu *v, int base); -void pmtimer_migrate_timers(struct vcpu *v); -void pmtimer_deinit(struct domain *d); void hpet_migrate_timers(struct vcpu *v); void hpet_init(struct vcpu *v); diff --git a/xen/include/public/hvm/save.h b/xen/include/public/hvm/save.h index 7ed26495c8..c6a856a558 100644 --- a/xen/include/public/hvm/save.h +++ b/xen/include/public/hvm/save.h @@ -382,10 +382,20 @@ struct hvm_hw_hpet { DECLARE_HVM_SAVE_TYPE(HPET, 12, struct hvm_hw_hpet); +/* + * PM timer + */ + +struct hvm_hw_pmtimer { + uint32_t timer; +}; + +DECLARE_HVM_SAVE_TYPE(PMTIMER, 13, struct hvm_hw_pmtimer); + /* * Largest type-code in use */ -#define HVM_SAVE_CODE_MAX 12 +#define HVM_SAVE_CODE_MAX 13 /*