Message ID | 20190606165455.162478-3-marc.zyngier@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: arm/arm64: vgic: ITS translation cache | expand |
Hi Marc, On 6/6/19 6:54 PM, Marc Zyngier wrote: > Our LPI translation cache needs to be able to drop the refcount > on an LPI whilst already holding the lpi_list_lock. > > Let's add a new primitive for this. > > Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Thanks Eric > --- > virt/kvm/arm/vgic/vgic.c | 26 +++++++++++++++++--------- > virt/kvm/arm/vgic/vgic.h | 1 + > 2 files changed, 18 insertions(+), 9 deletions(-) > > diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c > index 191deccf60bf..376a297e2169 100644 > --- a/virt/kvm/arm/vgic/vgic.c > +++ b/virt/kvm/arm/vgic/vgic.c > @@ -130,6 +130,22 @@ static void vgic_irq_release(struct kref *ref) > { > } > > +/* > + * Drop the refcount on the LPI. Must be called with lpi_list_lock held. > + */ > +void __vgic_put_lpi_locked(struct kvm *kvm, struct vgic_irq *irq) > +{ > + struct vgic_dist *dist = &kvm->arch.vgic; > + > + if (!kref_put(&irq->refcount, vgic_irq_release)) > + return; > + > + list_del(&irq->lpi_list); > + dist->lpi_list_count--; > + > + kfree(irq); > +} > + > void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq) > { > struct vgic_dist *dist = &kvm->arch.vgic; > @@ -139,16 +155,8 @@ void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq) > return; > > raw_spin_lock_irqsave(&dist->lpi_list_lock, flags); > - if (!kref_put(&irq->refcount, vgic_irq_release)) { > - raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags); > - return; > - }; > - > - list_del(&irq->lpi_list); > - dist->lpi_list_count--; > + __vgic_put_lpi_locked(kvm, irq); > raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags); > - > - kfree(irq); > } > > void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu) > diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h > index a58e1b263dca..80cd40575bc9 100644 > --- a/virt/kvm/arm/vgic/vgic.h > +++ b/virt/kvm/arm/vgic/vgic.h > @@ -172,6 +172,7 @@ vgic_get_mmio_region(struct kvm_vcpu *vcpu, struct vgic_io_device *iodev, > gpa_t addr, int len); > struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu, > u32 intid); > +void __vgic_put_lpi_locked(struct kvm *kvm, struct vgic_irq *irq); > void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq); > bool vgic_get_phys_line_level(struct vgic_irq *irq); > void vgic_irq_set_phys_pending(struct vgic_irq *irq, bool pending); >
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c index 191deccf60bf..376a297e2169 100644 --- a/virt/kvm/arm/vgic/vgic.c +++ b/virt/kvm/arm/vgic/vgic.c @@ -130,6 +130,22 @@ static void vgic_irq_release(struct kref *ref) { } +/* + * Drop the refcount on the LPI. Must be called with lpi_list_lock held. + */ +void __vgic_put_lpi_locked(struct kvm *kvm, struct vgic_irq *irq) +{ + struct vgic_dist *dist = &kvm->arch.vgic; + + if (!kref_put(&irq->refcount, vgic_irq_release)) + return; + + list_del(&irq->lpi_list); + dist->lpi_list_count--; + + kfree(irq); +} + void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq) { struct vgic_dist *dist = &kvm->arch.vgic; @@ -139,16 +155,8 @@ void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq) return; raw_spin_lock_irqsave(&dist->lpi_list_lock, flags); - if (!kref_put(&irq->refcount, vgic_irq_release)) { - raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags); - return; - }; - - list_del(&irq->lpi_list); - dist->lpi_list_count--; + __vgic_put_lpi_locked(kvm, irq); raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags); - - kfree(irq); } void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu) diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h index a58e1b263dca..80cd40575bc9 100644 --- a/virt/kvm/arm/vgic/vgic.h +++ b/virt/kvm/arm/vgic/vgic.h @@ -172,6 +172,7 @@ vgic_get_mmio_region(struct kvm_vcpu *vcpu, struct vgic_io_device *iodev, gpa_t addr, int len); struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu, u32 intid); +void __vgic_put_lpi_locked(struct kvm *kvm, struct vgic_irq *irq); void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq); bool vgic_get_phys_line_level(struct vgic_irq *irq); void vgic_irq_set_phys_pending(struct vgic_irq *irq, bool pending);
Our LPI translation cache needs to be able to drop the refcount on an LPI whilst already holding the lpi_list_lock. Let's add a new primitive for this. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> --- virt/kvm/arm/vgic/vgic.c | 26 +++++++++++++++++--------- virt/kvm/arm/vgic/vgic.h | 1 + 2 files changed, 18 insertions(+), 9 deletions(-)