[HVM] Save/restore: save pmtimer count register
authorTim Deegan <Tim.Deegan@xensource.com>
Thu, 8 Feb 2007 13:42:49 +0000 (13:42 +0000)
committerTim Deegan <Tim.Deegan@xensource.com>
Thu, 8 Feb 2007 13:42:49 +0000 (13:42 +0000)
Also remove the repeating timer from pmtimer.c because it doesn't do anything.
Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/pmtimer.c
xen/include/asm-x86/hvm/vpt.h
xen/include/public/hvm/save.h

index 96c827d2356ecbe744acf04ae0458c46b8350f90..91477378460436f88af0f997c294632a1faf69d3 100644 (file)
@@ -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 )
index 28be242f84022574896fd028572195e540b1be45..a396d27df4fb6d3184e897ba6d819ae864c40591 100644 (file)
@@ -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);
 }
+
index 78c7b536d420671b36dc3c5801fd59982b48ee4d..02bc3fa05c7313a6ea2ffdcace8a420abe08c6f3 100644 (file)
@@ -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);
index 7ed26495c82e69a4050cc85e0d08e0104c74cbbf..c6a856a55866e902c99ff9e5d03b5b67c9883c2b 100644 (file)
@@ -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
 
 
 /*