diff options
author | Tim Deegan <Tim.Deegan@xensource.com> | 2007-02-08 13:42:49 +0000 |
---|---|---|
committer | Tim Deegan <Tim.Deegan@xensource.com> | 2007-02-08 13:42:49 +0000 |
commit | 8abe0e51d15e6038599fa0d631e78ab41d5aef1b (patch) | |
tree | 19871ddfe888b03d28f5ba858052da89b35f3685 /xen/arch/x86/hvm/pmtimer.c | |
parent | 49d6f8401bf93c7a5ac411db31d7a84a77df66b4 (diff) | |
download | xen-8abe0e51d15e6038599fa0d631e78ab41d5aef1b.tar.gz xen-8abe0e51d15e6038599fa0d631e78ab41d5aef1b.tar.bz2 xen-8abe0e51d15e6038599fa0d631e78ab41d5aef1b.zip |
[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 <Tim.Deegan@xensource.com>
Diffstat (limited to 'xen/arch/x86/hvm/pmtimer.c')
-rw-r--r-- | xen/arch/x86/hvm/pmtimer.c | 73 |
1 files changed, 41 insertions, 32 deletions
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 <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; @@ -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); } + |