mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
xen/arm: initialize virt_timer and phys_timer with the same values on all vcpus
Introduce a domain wide vtimer initialization function to initialize the phys_timer and the virt_timer offsets. Use the domain phys_timer and virt_timer offsets throughout the vtimer code instead of the per-vcpu offsets. Remove the per-vcpu offsets from struct vtimer altogether. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
1 parent
43e39ffc70
commit
afb2edfc32
4 files changed
+35
-17
No files matched your search
@@ -485,6 +485,9 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags)
|
||||
if ( (rc = domain_vgic_init(d)) != 0 )
|
||||
goto fail;
|
||||
|
||||
if ( (rc = vcpu_domain_init(d)) != 0 )
|
||||
goto fail;
|
||||
|
||||
/* Domain 0 gets a real UART not an emulated one */
|
||||
if ( d->domain_id && (rc = domain_uart0_init(d)) != 0 )
|
||||
goto fail;
|
||||
|
||||
+16
-8
@@ -44,13 +44,20 @@ static void virt_timer_expired(void *data)
|
||||
vgic_vcpu_inject_irq(t->v, 27, 1);
|
||||
}
|
||||
|
||||
int vcpu_domain_init(struct domain *d)
|
||||
{
|
||||
d->arch.phys_timer_base.offset = NOW();
|
||||
d->arch.virt_timer_base.offset = READ_SYSREG64(CNTVCT_EL0) +
|
||||
READ_SYSREG64(CNTVOFF_EL2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vcpu_vtimer_init(struct vcpu *v)
|
||||
{
|
||||
struct vtimer *t = &v->arch.phys_timer;
|
||||
|
||||
init_timer(&t->timer, phys_timer_expired, t, v->processor);
|
||||
t->ctl = 0;
|
||||
t->offset = NOW();
|
||||
t->cval = NOW();
|
||||
t->irq = 30;
|
||||
t->v = v;
|
||||
@@ -58,7 +65,6 @@ int vcpu_vtimer_init(struct vcpu *v)
|
||||
t = &v->arch.virt_timer;
|
||||
init_timer(&t->timer, virt_timer_expired, t, v->processor);
|
||||
t->ctl = 0;
|
||||
t->offset = READ_SYSREG64(CNTVCT_EL0) + READ_SYSREG64(CNTVOFF_EL2);
|
||||
t->cval = 0;
|
||||
t->irq = 27;
|
||||
t->v = v;
|
||||
@@ -84,7 +90,7 @@ int virt_timer_save(struct vcpu *v)
|
||||
!(v->arch.virt_timer.ctl & CNTx_CTL_MASK))
|
||||
{
|
||||
set_timer(&v->arch.virt_timer.timer, ticks_to_ns(v->arch.virt_timer.cval +
|
||||
v->arch.virt_timer.offset - boot_count));
|
||||
v->domain->arch.virt_timer_base.offset - boot_count));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -98,7 +104,7 @@ int virt_timer_restore(struct vcpu *v)
|
||||
migrate_timer(&v->arch.virt_timer.timer, v->processor);
|
||||
migrate_timer(&v->arch.phys_timer.timer, v->processor);
|
||||
|
||||
WRITE_SYSREG64(v->arch.virt_timer.offset, CNTVOFF_EL2);
|
||||
WRITE_SYSREG64(v->domain->arch.virt_timer_base.offset, CNTVOFF_EL2);
|
||||
WRITE_SYSREG64(v->arch.virt_timer.cval, CNTV_CVAL_EL0);
|
||||
WRITE_SYSREG32(v->arch.virt_timer.ctl, CNTV_CTL_EL0);
|
||||
return 0;
|
||||
@@ -128,7 +134,8 @@ static int vtimer_emulate_32(struct cpu_user_regs *regs, union hsr hsr)
|
||||
if ( v->arch.phys_timer.ctl & CNTx_CTL_ENABLE )
|
||||
{
|
||||
set_timer(&v->arch.phys_timer.timer,
|
||||
v->arch.phys_timer.cval + v->arch.phys_timer.offset);
|
||||
v->arch.phys_timer.cval +
|
||||
v->domain->arch.phys_timer_base.offset);
|
||||
}
|
||||
else
|
||||
stop_timer(&v->arch.phys_timer.timer);
|
||||
@@ -137,7 +144,7 @@ static int vtimer_emulate_32(struct cpu_user_regs *regs, union hsr hsr)
|
||||
return 1;
|
||||
|
||||
case HSR_CPREG32(CNTP_TVAL):
|
||||
now = NOW() - v->arch.phys_timer.offset;
|
||||
now = NOW() - v->domain->arch.phys_timer_base.offset;
|
||||
if ( cp32.read )
|
||||
{
|
||||
*r = (uint32_t)(ns_to_ticks(v->arch.phys_timer.cval - now) & 0xffffffffull);
|
||||
@@ -149,7 +156,8 @@ static int vtimer_emulate_32(struct cpu_user_regs *regs, union hsr hsr)
|
||||
{
|
||||
v->arch.phys_timer.ctl &= ~CNTx_CTL_PENDING;
|
||||
set_timer(&v->arch.phys_timer.timer,
|
||||
v->arch.phys_timer.cval + v->arch.phys_timer.offset);
|
||||
v->arch.phys_timer.cval +
|
||||
v->domain->arch.phys_timer_base.offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +182,7 @@ static int vtimer_emulate_64(struct cpu_user_regs *regs, union hsr hsr)
|
||||
case HSR_CPREG64(CNTPCT):
|
||||
if ( cp64.read )
|
||||
{
|
||||
now = NOW() - v->arch.phys_timer.offset;
|
||||
now = NOW() - v->domain->arch.phys_timer_base.offset;
|
||||
ticks = ns_to_ticks(now);
|
||||
*r1 = (uint32_t)(ticks & 0xffffffff);
|
||||
*r2 = (uint32_t)(ticks >> 32);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifndef __ARCH_ARM_VTIMER_H__
|
||||
#define __ARCH_ARM_VTIMER_H__
|
||||
|
||||
extern int vcpu_domain_init(struct domain *d);
|
||||
extern int vcpu_vtimer_init(struct vcpu *v);
|
||||
extern int vtimer_emulate(struct cpu_user_regs *regs, union hsr hsr);
|
||||
extern int virt_timer_save(struct vcpu *v);
|
||||
|
||||
@@ -47,6 +47,14 @@ enum domain_type {
|
||||
#define is_pv64_domain(d) (0)
|
||||
#endif
|
||||
|
||||
struct vtimer {
|
||||
struct vcpu *v;
|
||||
int irq;
|
||||
struct timer timer;
|
||||
uint32_t ctl;
|
||||
uint64_t cval;
|
||||
};
|
||||
|
||||
struct arch_domain
|
||||
{
|
||||
#ifdef CONFIG_ARM_64
|
||||
@@ -61,6 +69,13 @@ struct arch_domain
|
||||
uint32_t vpidr;
|
||||
register_t vmpidr;
|
||||
|
||||
struct {
|
||||
uint64_t offset;
|
||||
} phys_timer_base;
|
||||
struct {
|
||||
uint64_t offset;
|
||||
} virt_timer_base;
|
||||
|
||||
struct {
|
||||
/*
|
||||
* Covers access to other members of this struct _except_ for
|
||||
@@ -91,15 +106,6 @@ struct arch_domain
|
||||
|
||||
} __cacheline_aligned;
|
||||
|
||||
struct vtimer {
|
||||
struct vcpu *v;
|
||||
int irq;
|
||||
struct timer timer;
|
||||
uint32_t ctl;
|
||||
uint64_t offset;
|
||||
uint64_t cval;
|
||||
};
|
||||
|
||||
struct arch_vcpu
|
||||
{
|
||||
struct {
|
||||
|
||||