Message ID | 1403541463-23734-4-git-send-email-stefano.stabellini@eu.citrix.com |
---|---|
State | New |
Headers | show |
Hi Stefano, On 06/23/2014 05:37 PM, Stefano Stabellini wrote: > -static void gic_irq_set_affinity(struct irq_desc *desc, const cpumask_t *mask) > +static void gic_irq_set_affinity(struct irq_desc *desc, const cpumask_t *cpu_mask) > { > - BUG(); > + volatile unsigned char *bytereg; > + unsigned int mask; > + > + if ( desc == NULL || cpumask_empty(cpu_mask) ) > + return; I think this check is pointless. Every irq_callback relies on the desc is not NULL. Hence, you already check it in irq_set_affinity. For the cpu_mask, we are in trouble is someone is calling with an empty mask. I would replace it by an ASSERT. The check here is pointless here. Every irq_callback rely on the desc is not NULL. Why this > /* XXX different for level vs edge */ > diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c > index b2f922c..5a504ad 100644 > --- a/xen/arch/arm/vgic.c > +++ b/xen/arch/arm/vgic.c > @@ -438,6 +438,32 @@ static void vgic_migrate_irq(struct vcpu *old, struct vcpu *new, unsigned int ir > spin_unlock_irqrestore(&old->arch.vgic.lock, flags); > } > > +static inline void irq_set_affinity(struct irq_desc *desc, > + const cpumask_t *cpu_mask) > +{ > + if ( desc != NULL ) > + desc->handler->set_affinity(desc, cpu_mask); > +} This function belongs to the IRQ module. It might be useful for other part in the future. I would move this function in irq.c or in asm-arm/irq.h if you want to keep it as inline function. Regards,
On Tue, 24 Jun 2014, Julien Grall wrote: > Hi Stefano, > > On 06/23/2014 05:37 PM, Stefano Stabellini wrote: > > -static void gic_irq_set_affinity(struct irq_desc *desc, const cpumask_t *mask) > > +static void gic_irq_set_affinity(struct irq_desc *desc, const cpumask_t *cpu_mask) > > { > > - BUG(); > > + volatile unsigned char *bytereg; > > + unsigned int mask; > > + > > + if ( desc == NULL || cpumask_empty(cpu_mask) ) > > + return; > > I think this check is pointless. Every irq_callback relies on the desc > is not NULL. Hence, you already check it in irq_set_affinity. > > For the cpu_mask, we are in trouble is someone is calling with an empty > mask. I would replace it by an ASSERT. OK > The check here is pointless here. Every irq_callback rely on the desc is > not NULL. Why this > > > /* XXX different for level vs edge */ > > diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c > > index b2f922c..5a504ad 100644 > > --- a/xen/arch/arm/vgic.c > > +++ b/xen/arch/arm/vgic.c > > @@ -438,6 +438,32 @@ static void vgic_migrate_irq(struct vcpu *old, struct vcpu *new, unsigned int ir > > spin_unlock_irqrestore(&old->arch.vgic.lock, flags); > > } > > > > +static inline void irq_set_affinity(struct irq_desc *desc, > > + const cpumask_t *cpu_mask) > > +{ > > + if ( desc != NULL ) > > + desc->handler->set_affinity(desc, cpu_mask); > > +} > > This function belongs to the IRQ module. It might be useful for other > part in the future. > > I would move this function in irq.c or in asm-arm/irq.h if you want to > keep it as inline function. OK
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 54610ce..1965f86 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -192,9 +192,23 @@ static void gic_guest_irq_end(struct irq_desc *desc) /* Deactivation happens in maintenance interrupt / via GICV */ } -static void gic_irq_set_affinity(struct irq_desc *desc, const cpumask_t *mask) +static void gic_irq_set_affinity(struct irq_desc *desc, const cpumask_t *cpu_mask) { - BUG(); + volatile unsigned char *bytereg; + unsigned int mask; + + if ( desc == NULL || cpumask_empty(cpu_mask) ) + return; + + spin_lock(&gic.lock); + + mask = gic_cpu_mask(cpu_mask); + + /* Set target CPU mask (RAZ/WI on uniprocessor) */ + bytereg = (unsigned char *) (GICD + GICD_ITARGETSR); + bytereg[desc->irq] = mask; + + spin_unlock(&gic.lock); } /* XXX different for level vs edge */ diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index b2f922c..5a504ad 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -438,6 +438,32 @@ static void vgic_migrate_irq(struct vcpu *old, struct vcpu *new, unsigned int ir spin_unlock_irqrestore(&old->arch.vgic.lock, flags); } +static inline void irq_set_affinity(struct irq_desc *desc, + const cpumask_t *cpu_mask) +{ + if ( desc != NULL ) + desc->handler->set_affinity(desc, cpu_mask); +} + +void arch_move_irqs(struct vcpu *v) +{ + const cpumask_t *cpu_mask = cpumask_of(v->processor); + struct domain *d = v->domain; + struct pending_irq *p; + struct vcpu *v_target; + int i; + + for ( i = 32; i < d->arch.vgic.nr_lines; i++ ) + { + v_target = vgic_get_target_vcpu(v, i); + if ( v_target == v ) + { + p = irq_to_pending(v, i); + irq_set_affinity(p->desc, cpu_mask); + } + } +} + static void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n) { const unsigned long mask = r; @@ -493,6 +519,7 @@ static void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n) } if ( p->desc != NULL ) { + irq_set_affinity(p->desc, cpumask_of(v_target->processor)); spin_lock_irqsave(&p->desc->lock, flags); p->desc->handler->enable(p->desc); spin_unlock_irqrestore(&p->desc->lock, flags); @@ -681,6 +708,7 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info) unsigned int irq, target, old_target; unsigned long old_target_mask; struct vcpu *v_target, *v_old; + struct pending_irq *p; target = i % 8; old_target_mask = byte_read(rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR)], 0, i/8); @@ -692,6 +720,8 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info) v_target = v->domain->vcpu[target]; v_old = v->domain->vcpu[old_target]; vgic_migrate_irq(v_old, v_target, irq); + p = irq_to_pending(v_target, irq); + irq_set_affinity(p->desc, cpumask_of(v_target->processor)); } i += 8 - target; } diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h index ba9ba9b..dcc2f1c 100644 --- a/xen/include/asm-arm/gic.h +++ b/xen/include/asm-arm/gic.h @@ -228,6 +228,7 @@ int gic_irq_xlate(const u32 *intspec, unsigned int intsize, void gic_clear_lrs(struct vcpu *v); struct vcpu *vgic_get_target_vcpu(struct vcpu *v, unsigned int irq); +void arch_move_irqs(struct vcpu *v); #endif /* __ASSEMBLY__ */ #endif diff --git a/xen/include/asm-x86/irq.h b/xen/include/asm-x86/irq.h index 9066d38..d3c55f3 100644 --- a/xen/include/asm-x86/irq.h +++ b/xen/include/asm-x86/irq.h @@ -197,4 +197,6 @@ void cleanup_domain_irq_mapping(struct domain *); bool_t cpu_has_pending_apic_eoi(void); +static inline void arch_move_irqs(struct vcpu *v) { } + #endif /* _ASM_HW_IRQ_H */