From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kouya Shimura Subject: [PATCH 2/2] x86/hvm: fix corrupt ACPI PM-Timer during live migration Date: Thu, 21 Mar 2013 16:32:26 +0900 Message-ID: <514AB78A.3010109@jp.fujitsu.com> References: <5110A2DD.1080603@jp.fujitsu.com> <511A42E902000078000BDB5E@nat28.tlf.novell.com> <511C7FB7.90907@jp.fujitsu.com> <511E742A02000078000BEDAE@nat28.tlf.novell.com> <51247E56.4060904@jp.fujitsu.com> <5138C72802000078000C3FB0@nat28.tlf.novell.com> <514A9BC4.40508@jp.fujitsu.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii"; Format="flowed" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <514A9BC4.40508@jp.fujitsu.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: Jan Beulich , xen-devel@lists.xen.org List-Id: xen-devel@lists.xenproject.org The ACPI PM-Timer value is broken when a vm is saved. The function pmtimer_save() calculates the value on its own, but vcpu->arch.hvm_vcpu.guest_time is not valid (usually zero). Another problem is a double counting of the PM-Timer value in failure to save a vm. This patch corrects the value, and also makes the calculation more precise. Signed-off-by: Kouya Shimura --- xen/arch/x86/hvm/pmtimer.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/xen/arch/x86/hvm/pmtimer.c b/xen/arch/x86/hvm/pmtimer.c index 5c25cfb..203a939 100644 --- a/xen/arch/x86/hvm/pmtimer.c +++ b/xen/arch/x86/hvm/pmtimer.c @@ -85,7 +85,7 @@ void hvm_acpi_sleep_button(struct domain *d) /* Set the correct value in the timer, accounting for time elapsed * since the last time we did that. */ -static void pmt_update_time(PMTState *s) +static void pmt_update_time(PMTState *s, bool_t update_sci) { uint64_t curr_gtime, tmp; uint32_t tmr_val = s->pm.tmr_val, msb = tmr_val & TMR_VAL_MSB; @@ -107,7 +107,8 @@ static void pmt_update_time(PMTState *s) if ( (tmr_val & TMR_VAL_MSB) != msb ) { s->pm.pm1a_sts |= TMR_STS; - pmt_update_sci(s); + if ( update_sci ) + pmt_update_sci(s); } } @@ -123,7 +124,7 @@ static void pmt_timer_callback(void *opaque) spin_lock(&s->lock); /* Recalculate the timer and make sure we get an SCI if we need one */ - pmt_update_time(s); + pmt_update_time(s, 1); /* How close are we to the next MSB flip? */ pmt_cycles_until_flip = TMR_VAL_MSB - (s->pm.tmr_val & (TMR_VAL_MSB - 1)); @@ -221,7 +222,7 @@ static int handle_pmt_io( if ( spin_trylock(&s->lock) ) { /* We hold the lock: update timer value and return it. */ - pmt_update_time(s); + pmt_update_time(s, 1); *val = s->pm.tmr_val; spin_unlock(&s->lock); } @@ -244,19 +245,11 @@ static int handle_pmt_io( static int pmtimer_save(struct domain *d, hvm_domain_context_t *h) { PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; - uint32_t x, msb = s->pm.tmr_val & TMR_VAL_MSB; int rc; spin_lock(&s->lock); - /* 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.tmr_val += x; - if ( (s->pm.tmr_val & TMR_VAL_MSB) != msb ) - s->pm.pm1a_sts |= TMR_STS; + pmt_update_time(s, 0); /* No point in setting the SCI here because we'll already have saved the * IRQ and *PIC state; we'll fix it up when we restore the domain */ -- 1.7.9.5