# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
# Date 1170942169 0
# Node ID 6e74932c9a64298ef31af28ad0b53c0e7d2e6781
# Parent 3fbe12560ffe84359e2bc7bce12b0cc34a1e398c
[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@xxxxxxxxxxxxx>
---
xen/arch/x86/hvm/hvm.c | 2 -
xen/arch/x86/hvm/pmtimer.c | 75 +++++++++++++++++++++++-------------------
xen/include/asm-x86/hvm/vpt.h | 14 ++-----
xen/include/public/hvm/save.h | 12 ++++++
4 files changed, 58 insertions(+), 45 deletions(-)
diff -r 3fbe12560ffe -r 6e74932c9a64 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Thu Feb 08 10:44:53 2007 +0000
+++ b/xen/arch/x86/hvm/hvm.c Thu Feb 08 13:42:49 2007 +0000
@@ -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 -r 3fbe12560ffe -r 6e74932c9a64 xen/arch/x86/hvm/pmtimer.c
--- a/xen/arch/x86/hvm/pmtimer.c Thu Feb 08 10:44:53 2007 +0000
+++ b/xen/arch/x86/hvm/pmtimer.c Thu Feb 08 13:42:49 2007 +0000
@@ -1,17 +1,6 @@
#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)
{
@@ -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;
}
+static int pmtimer_save(struct domain *d, hvm_domain_context_t *h)
+{
+ PMTState *s = &d->arch.hvm_domain.pl_time.vpmt;
+ uint32_t x;
+
+ /* 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);
+}
+
+static int pmtimer_load(struct domain *d, hvm_domain_context_t *h)
+{
+ PMTState *s = &d->arch.hvm_domain.pl_time.vpmt;
+
+ /* 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;
+}
+
+HVM_REGISTER_SAVE_RESTORE(PMTIMER, pmtimer_save, pmtimer_load,
+ 1, HVMSR_PER_DOM);
+
+
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->pm.timer = 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);
-
+ /* 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);
}
-void pmtimer_migrate_timers(struct vcpu *v)
-{
- struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt;
-
- if (vpmt->vcpu == v)
- migrate_timer(&vpmt->timer, v->processor);
-}
-
-void pmtimer_deinit(struct domain *d)
-{
- PMTState *s = &d->arch.hvm_domain.pl_time.vpmt;
-
- kill_timer(&s->timer);
-}
diff -r 3fbe12560ffe -r 6e74932c9a64 xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h Thu Feb 08 10:44:53 2007 +0000
+++ b/xen/include/asm-x86/hvm/vpt.h Thu Feb 08 13:42:49 2007 +0000
@@ -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_deinit(struct domain *d);
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 -r 3fbe12560ffe -r 6e74932c9a64 xen/include/public/hvm/save.h
--- a/xen/include/public/hvm/save.h Thu Feb 08 10:44:53 2007 +0000
+++ b/xen/include/public/hvm/save.h Thu Feb 08 13:42:49 2007 +0000
@@ -382,10 +382,20 @@ DECLARE_HVM_SAVE_TYPE(HPET, 12, struct h
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
/*
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|