aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/hvm/pmtimer.c
diff options
context:
space:
mode:
authorTim Deegan <Tim.Deegan@xensource.com>2007-02-08 13:42:49 +0000
committerTim Deegan <Tim.Deegan@xensource.com>2007-02-08 13:42:49 +0000
commit8abe0e51d15e6038599fa0d631e78ab41d5aef1b (patch)
tree19871ddfe888b03d28f5ba858052da89b35f3685 /xen/arch/x86/hvm/pmtimer.c
parent49d6f8401bf93c7a5ac411db31d7a84a77df66b4 (diff)
downloadxen-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.c73
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);
}
+