diff --git a/xen/arch/arm/vtimer.c b/xen/arch/arm/vtimer.c index 240a850b6e..08411f33a9 100644 --- a/xen/arch/arm/vtimer.c +++ b/xen/arch/arm/vtimer.c @@ -62,7 +62,6 @@ static void virt_timer_expired(void *data) int domain_vtimer_init(struct domain *d, struct xen_arch_domainconfig *config) { - d->arch.phys_timer_base.offset = NOW(); d->arch.virt_timer_base.offset = READ_SYSREG64(CNTPCT_EL0); d->time_offset.seconds = ticks_to_ns(d->arch.virt_timer_base.offset - boot_count); do_div(d->time_offset.seconds, 1000000000); @@ -108,7 +107,6 @@ int vcpu_vtimer_init(struct vcpu *v) init_timer(&t->timer, phys_timer_expired, t, v->processor); t->ctl = 0; - t->cval = NOW(); t->irq = d0 ? timer_get_irq(TIMER_PHYS_NONSECURE_PPI) : GUEST_TIMER_PHYS_NS_PPI; @@ -167,6 +165,7 @@ void virt_timer_restore(struct vcpu *v) static bool vtimer_cntp_ctl(struct cpu_user_regs *regs, uint32_t *r, bool read) { struct vcpu *v = current; + s_time_t expires; if ( !ACCESS_ALLOWED(regs, EL0PTEN) ) return false; @@ -184,8 +183,13 @@ static bool vtimer_cntp_ctl(struct cpu_user_regs *regs, uint32_t *r, bool read) if ( v->arch.phys_timer.ctl & CNTx_CTL_ENABLE ) { - set_timer(&v->arch.phys_timer.timer, - v->arch.phys_timer.cval + v->domain->arch.phys_timer_base.offset); + /* + * If cval is before the point Xen started, expire timer + * immediately. + */ + expires = v->arch.phys_timer.cval > boot_count + ? ticks_to_ns(v->arch.phys_timer.cval - boot_count) : 0; + set_timer(&v->arch.phys_timer.timer, expires); } else stop_timer(&v->arch.phys_timer.timer); @@ -197,26 +201,31 @@ static bool vtimer_cntp_tval(struct cpu_user_regs *regs, uint32_t *r, bool read) { struct vcpu *v = current; - s_time_t now; + uint64_t cntpct; + s_time_t expires; if ( !ACCESS_ALLOWED(regs, EL0PTEN) ) return false; - now = NOW() - v->domain->arch.phys_timer_base.offset; + cntpct = get_cycles(); if ( read ) { - *r = (uint32_t)(ns_to_ticks(v->arch.phys_timer.cval - now) & 0xffffffffull); + *r = (uint32_t)((v->arch.phys_timer.cval - cntpct) & 0xffffffffull); } else { - v->arch.phys_timer.cval = now + ticks_to_ns(*r); + v->arch.phys_timer.cval = cntpct + *r; if ( v->arch.phys_timer.ctl & CNTx_CTL_ENABLE ) { v->arch.phys_timer.ctl &= ~CNTx_CTL_PENDING; - set_timer(&v->arch.phys_timer.timer, - v->arch.phys_timer.cval + - v->domain->arch.phys_timer_base.offset); + /* + * If cval is before the point Xen started, expire timer + * immediately. + */ + expires = v->arch.phys_timer.cval > boot_count + ? ticks_to_ns(v->arch.phys_timer.cval - boot_count) : 0; + set_timer(&v->arch.phys_timer.timer, expires); } } return true; @@ -226,23 +235,28 @@ static bool vtimer_cntp_cval(struct cpu_user_regs *regs, uint64_t *r, bool read) { struct vcpu *v = current; + s_time_t expires; if ( !ACCESS_ALLOWED(regs, EL0PTEN) ) return false; if ( read ) { - *r = ns_to_ticks(v->arch.phys_timer.cval); + *r = v->arch.phys_timer.cval; } else { - v->arch.phys_timer.cval = ticks_to_ns(*r); + v->arch.phys_timer.cval = *r; if ( v->arch.phys_timer.ctl & CNTx_CTL_ENABLE ) { v->arch.phys_timer.ctl &= ~CNTx_CTL_PENDING; - set_timer(&v->arch.phys_timer.timer, - v->arch.phys_timer.cval + - v->domain->arch.phys_timer_base.offset); + /* + * If cval is before the point Xen started, expire timer + * immediately. + */ + expires = v->arch.phys_timer.cval > boot_count + ? ticks_to_ns(v->arch.phys_timer.cval - boot_count) : 0; + set_timer(&v->arch.phys_timer.timer, expires); } } return true; diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index f3f3fb7d7f..adc7fe7210 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -65,9 +65,6 @@ struct arch_domain RELMEM_done, } relmem; - struct { - uint64_t offset; - } phys_timer_base; struct { uint64_t offset; } virt_timer_base;