[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 7/8] xen: arm: context switch vtimer PPI state.
On Tue, 10 Nov 2015, Ian Campbell wrote: > ... instead of artificially masking the timer interrupt in the timer > state and relying on the guest to unmask (which it isn't required to > do per the h/w spec, although Linux does). > > By using the newly added hwppi save/restore functionality we make use > of the GICD I[SC]ACTIVER registers to save and restore the active > state of the interrupt, which prevents the nested invocations which > the current masking works around. > > Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx> > --- > v2: Rebased, in particular over Julien's passthrough stuff which > reworked a bunch of IRQ related stuff. > Also largely rewritten since precursor patches now lay very > different groundwork. > --- > xen/arch/arm/time.c | 26 ++------------------------ > xen/arch/arm/vtimer.c | 41 +++++++++++++++++++++++++++++++++++++---- > xen/include/asm-arm/domain.h | 1 + > 3 files changed, 40 insertions(+), 28 deletions(-) > > diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c > index 5ded30c..2a1cdba 100644 > --- a/xen/arch/arm/time.c > +++ b/xen/arch/arm/time.c > @@ -181,28 +181,6 @@ static void timer_interrupt(int irq, void *dev_id, > struct cpu_user_regs *regs) > } > } > > -static void vtimer_interrupt(int irq, void *dev_id, struct cpu_user_regs > *regs) > -{ > - /* > - * Edge-triggered interrupts can be used for the virtual timer. Even > - * if the timer output signal is masked in the context switch, the > - * GIC will keep track that of any interrupts raised while IRQS are > - * disabled. As soon as IRQs are re-enabled, the virtual interrupt > - * will be injected to Xen. > - * > - * If an IDLE vCPU was scheduled next then we should ignore the > - * interrupt. > - */ > - if ( unlikely(is_idle_vcpu(current)) ) > - return; > - > - perfc_incr(virt_timer_irqs); > - > - current->arch.virt_timer.ctl = READ_SYSREG32(CNTV_CTL_EL0); > - WRITE_SYSREG32(current->arch.virt_timer.ctl | CNTx_CTL_MASK, > CNTV_CTL_EL0); > - vgic_vcpu_inject_irq(current, current->arch.virt_timer.irq); > -} > - > /* > * Arch timer interrupt really ought to be level triggered, since the > * design of the timer/comparator mechanism is based around that > @@ -242,8 +220,8 @@ void __cpuinit init_timer_interrupt(void) > > request_irq(timer_irq[TIMER_HYP_PPI], 0, timer_interrupt, > "hyptimer", NULL); > - request_irq(timer_irq[TIMER_VIRT_PPI], 0, vtimer_interrupt, > - "virtimer", NULL); > + route_hwppi_to_current_vcpu(timer_irq[TIMER_VIRT_PPI], "virtimer"); > + > request_irq(timer_irq[TIMER_PHYS_NONSECURE_PPI], 0, timer_interrupt, > "phytimer", NULL); > > diff --git a/xen/arch/arm/vtimer.c b/xen/arch/arm/vtimer.c > index 1418092..82e2b88 100644 > --- a/xen/arch/arm/vtimer.c > +++ b/xen/arch/arm/vtimer.c > @@ -55,9 +55,19 @@ static void phys_timer_expired(void *data) > static void virt_timer_expired(void *data) > { > struct vtimer *t = data; > - t->ctl |= CNTx_CTL_MASK; > - vgic_vcpu_inject_irq(t->v, t->irq); > - perfc_incr(vtimer_virt_inject); > + t->ctl |= CNTx_CTL_PENDING; > + if ( !(t->ctl & CNTx_CTL_MASK) ) > + { > + /* > + * An edge triggered interrupt should now be pending. Since > + * this timer can never expire while the domain is scheduled > + * we know that the gic_restore_hwppi in virt_timer_restore > + * will cause the real hwppi to occur and be routed. > + */ > + gic_hwppi_set_pending(&t->ppi_state); I wonder if calling gic_hwppi_set_pending is actually redundant: virt_timer_restore will write the expired time to cval, causing a new interrupt to be immediately sent as soon as it's enabled, right? > + vcpu_unblock(t->v); > + perfc_incr(vtimer_virt_inject); > + } > } > > int domain_vtimer_init(struct domain *d, struct xen_arch_domainconfig > *config) > @@ -96,9 +106,12 @@ int domain_vtimer_init(struct domain *d, struct > xen_arch_domainconfig *config) > > int vcpu_vtimer_init(struct vcpu *v) > { > + struct pending_irq *p; > struct vtimer *t = &v->arch.phys_timer; > bool_t d0 = is_hardware_domain(v->domain); > > + const unsigned host_vtimer_irq_ppi = timer_get_irq(TIMER_VIRT_PPI); > + > /* > * Hardware domain uses the hardware interrupts, guests get the virtual > * platform. > @@ -116,10 +129,16 @@ int vcpu_vtimer_init(struct vcpu *v) > init_timer(&t->timer, virt_timer_expired, t, v->processor); > t->ctl = 0; > t->irq = d0 > - ? timer_get_irq(TIMER_VIRT_PPI) > + ? host_vtimer_irq_ppi > : GUEST_TIMER_VIRT_PPI; > t->v = v; > > + p = irq_to_pending(v, t->irq); > + p->irq = t->irq; > + > + gic_hwppi_state_init(&v->arch.virt_timer.ppi_state, > + host_vtimer_irq_ppi); > + > v->arch.vtimer_initialized = 1; > > return 0; > @@ -147,6 +166,15 @@ int virt_timer_save(struct vcpu *v) > set_timer(&v->arch.virt_timer.timer, > ticks_to_ns(v->arch.virt_timer.cval + > v->domain->arch.virt_timer_base.offset - boot_count)); > } > + > + /* > + * Since the vtimer irq is a PPI we don't need to worry about > + * racing against it becoming active while we are saving the > + * state, since that requires the guest to be reading the IAR. > + */ > + gic_save_and_mask_hwppi(v, v->arch.virt_timer.irq, > + &v->arch.virt_timer.ppi_state); > + > return 0; > } > > @@ -161,6 +189,11 @@ int virt_timer_restore(struct vcpu *v) > 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); > + > + gic_restore_hwppi(v, > + v->arch.virt_timer.irq, > + &v->arch.virt_timer.ppi_state); > + > return 0; > } > > diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h > index 550e28b..aff21dd 100644 > --- a/xen/include/asm-arm/domain.h > +++ b/xen/include/asm-arm/domain.h > @@ -51,6 +51,7 @@ struct vtimer { > struct timer timer; > uint32_t ctl; > uint64_t cval; > + struct hwppi_state ppi_state; > }; > > struct arch_domain > -- > 2.1.4 > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |