On Tue, Sep 11, 2012 at 2:50 PM, Marc Zyngier <marc.zyngier@xxxxxxx> wrote: > Recomputing the whole GIC state when injecting a single interrupt > is a tiny bit silly. > > Instead, just computing the new state for this particular IRQ saves > a bit of processing and makes things noticeably faster. > > Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx> > --- > arch/arm/include/asm/kvm_vgic.h | 1 + > arch/arm/kvm/vgic.c | 51 +++++++++++++++++++++++++++++++++-------- > 2 files changed, 42 insertions(+), 10 deletions(-) > > diff --git a/arch/arm/include/asm/kvm_vgic.h b/arch/arm/include/asm/kvm_vgic.h > index 5efc94d..84a3177 100644 > --- a/arch/arm/include/asm/kvm_vgic.h > +++ b/arch/arm/include/asm/kvm_vgic.h > @@ -183,6 +183,7 @@ struct vgic_dist { > u8 irq_sgi_sources[VGIC_MAX_CPUS][16]; > > /* Target CPU for each IRQ */ > + u8 irq_spi_cpu[VGIC_NR_SHARED_IRQS]; > struct vgic_bitmap irq_spi_target[VGIC_MAX_CPUS]; > > /* Bitmap indicating which CPU has something pending */ > diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c > index 6581ad0..fd8865d 100644 > --- a/arch/arm/kvm/vgic.c > +++ b/arch/arm/kvm/vgic.c > @@ -47,6 +47,9 @@ > * registers, stored on each vcpu. We only keep one bit of > * information per interrupt, making sure that only one vcpu can > * accept the interrupt. > + * The same is true when injecting an interrupt, except that we only > + * consider a single interrupt at a time. The irq_spi_cpu array > + * contains the target CPU for each SPI. > * > * The handling of level interrupts adds some extra complexity. We > * need to track when the interrupt has been EOIed, so we can sample > @@ -313,6 +316,7 @@ static void vgic_set_target_reg(struct kvm *kvm, u32 val, int irq) > int shift = i * 8; > target = ffs((val >> shift) & 0xffU); > target = target ? (target - 1) : 0; > + dist->irq_spi_cpu[irq + i] = target; > kvm_for_each_vcpu(c, vcpu, kvm) { > bmap = vgic_bitmap_get_shared_map(&dist->irq_spi_target[c]); > if (c == target) > @@ -866,15 +870,17 @@ static void vgic_kick_vcpus(struct kvm *kvm) > } > } > > -int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num, > - bool level) > +static bool vgic_update_irq_state(struct kvm *kvm, int cpuid, > + unsigned int irq_num, bool level) > { > struct vgic_dist *dist = &kvm->arch.vgic; > + struct kvm_vcpu *vcpu; > int is_edge, state; > + int pend, enabled; > unsigned long flags; > - bool updated_state = false; > > spin_lock_irqsave(&dist->lock, flags); > + > is_edge = vgic_irq_is_edge(dist, irq_num); > state = vgic_bitmap_get_irq_val(&dist->irq_state, cpuid, irq_num); > > @@ -883,16 +889,41 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num, > * - level triggered and we change level > * - edge triggered and we have a rising edge > */ > - if ((!is_edge && (state ^ level)) || > - (is_edge && !state && level)) { > - vgic_bitmap_set_irq_val(&dist->irq_state, cpuid, > - irq_num, level); > - vgic_update_state(kvm); > - updated_state = true; > + if (!((!is_edge && (state ^ level)) || > + (is_edge && !state && level))) { > + spin_unlock_irqrestore(&dist->lock, flags); > + return false; > } this really needs to be more readable, but I'll change it. > + > + vgic_bitmap_set_irq_val(&dist->irq_state, cpuid, irq_num, level); > + > + enabled = vgic_bitmap_get_irq_val(&dist->irq_enabled, cpuid, irq_num); > + pend = level && enabled; > + > + if (irq_num >= 32) { > + cpuid = dist->irq_spi_cpu[irq_num - 32]; > + pend &= vgic_bitmap_get_irq_val(&dist->irq_spi_target[cpuid], > + 0, irq_num); > + } > + > + kvm_debug("Inject IRQ%d level %d CPU%d\n", irq_num, level, cpuid); > + > + vcpu = kvm_get_vcpu(kvm, cpuid); > + if (pend) { > + set_bit(irq_num, vcpu->arch.vgic_cpu.pending); > + set_bit(cpuid, &dist->irq_pending_on_cpu); > + } else > + clear_bit(irq_num, vcpu->arch.vgic_cpu.pending); > + > spin_unlock_irqrestore(&dist->lock, flags); > > - if (updated_state) > + return true; > +} > + > +int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num, > + bool level) > +{ > + if (vgic_update_irq_state(kvm, cpuid, irq_num, level)) > vgic_kick_vcpus(kvm); > > return 0; > -- > 1.7.12 > thanks, applied (with updated logic statement) -Christoffer _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm