Re: [PATCH v8 06/17] KVM: arm/arm64: VGIC: add refcounting for IRQs
On 08/07/16 14:09, Marc Zyngier wrote: > On 08/07/16 13:54, André Przywara wrote: >> On 08/07/16 11:50, Marc Zyngier wrote: >>> On 08/07/16 11:28, Andre Przywara wrote: Hi, On 07/07/16 16:00, Marc Zyngier wrote: > On 05/07/16 12:22, Andre Przywara wrote: >> @@ -236,6 +254,7 @@ retry: >> goto retry; >> } >> >> +kref_get(>refcount); > > Could you use vgic_get_irq() instead? I know it is slightly overkill, > but I can already tell that we'll need to add some tracing in both the > put and get helpers in order to do some debugging. Having straight > kref_get/put is going to make this tracing difficult, so let's not go > there. I'd rather not. 1) Putting the IRQ on the ap_list is the "other user" of the refcounting, I don't want to mix that unnecessarily with the vgic_get_irq() (as in: get the struct by the number) use case. That may actually help tracing, since we can have separate tracepoints to distinguish them. >>> >>> And yet you end-up doing a vgic_put_irq() in the fold operation. Which >>> is wrong, by the way, as the interrupt is still in in ap_list. This >>> should be moved to the prune operation. >>> 2) This would violate the locking order, since we hold the irq_lock here and possibly take the lpi_list_lock in vgic_get_irq(). I don't think we can or should drop the irq_lock and re-take it just for this. >>> >>> That's a much more convincing argument. And when you take the above into >>> account, you realize that your locking is not correct. You shouldn't be >>> dropping the refcount in fold, but in prune, meaning that you're holding >>> the ap_lock and the irq_lock, same as when you inserted the interrupt in >>> the list. >>> >>> This is outlining an essential principle: if your locking/refcounting is >>> not symmetric, it is likely that you're doing something wrong, and that >>> should bother you really badly. >> >> Can you point me to the exact location where it's not symmetric? >> I just looked at it again and can't find the issue. >> I "put" it in v[23]_fold because we did a vgic_get_irq a few lines >> before to translate the LR's intid into our struct vgic_irq pointer. > > Right. I misread that one, apologies. > >> The vgic_get_irq() call isn't in this patch, because we used it already >> before and this patch is just adding the respective puts. >> The only asymmetry I could find is the expected one when it comes to and >> goes from the ap_list. > > So I assume this is the pendent of the kref_get call? Yes. > > @@ -386,6 +412,7 @@ retry: > list_del(>ap_list); > irq->vcpu = NULL; > spin_unlock(>irq_lock); > + vgic_put_irq(vcpu->kvm, irq); > continue; > > If that's the case, please add a comment, because this is really hard to > find out which vgic_put_irq() balances with a kref_get() and not a > vgic_get_irq(). Yes, that's what I thought as well just _after_ having hit the Send button ... I think much of the confusion stems from the fact that we used vgic_get_irq() before, only that it wasn't a "get" in the refcounting get-put sense. Cheers, Andre. ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Re: [PATCH v8 06/17] KVM: arm/arm64: VGIC: add refcounting for IRQs
On 08/07/16 13:54, André Przywara wrote: > On 08/07/16 11:50, Marc Zyngier wrote: >> On 08/07/16 11:28, Andre Przywara wrote: >>> Hi, >>> >>> On 07/07/16 16:00, Marc Zyngier wrote: On 05/07/16 12:22, Andre Przywara wrote: > In the moment our struct vgic_irq's are statically allocated at guest > creation time. So getting a pointer to an IRQ structure is trivial and > safe. LPIs are more dynamic, they can be mapped and unmapped at any time > during the guest's _runtime_. > In preparation for supporting LPIs we introduce reference counting for > those structures using the kernel's kref infrastructure. > Since private IRQs and SPIs are statically allocated, the refcount never > drops to 0 at the moment, but we increase it when an IRQ gets onto a VCPU > list and decrease it when it gets removed. > This introduces vgic_put_irq(), which wraps kref_put and hides the > release function from the callers. > > Signed-off-by: Andre Przywara> --- > include/kvm/arm_vgic.h | 1 + > virt/kvm/arm/vgic/vgic-init.c| 2 ++ > virt/kvm/arm/vgic/vgic-mmio-v2.c | 8 +++ > virt/kvm/arm/vgic/vgic-mmio-v3.c | 20 +++-- > virt/kvm/arm/vgic/vgic-mmio.c| 25 - > virt/kvm/arm/vgic/vgic-v2.c | 1 + > virt/kvm/arm/vgic/vgic-v3.c | 1 + > virt/kvm/arm/vgic/vgic.c | 48 > +++- > virt/kvm/arm/vgic/vgic.h | 1 + > 9 files changed, 89 insertions(+), 18 deletions(-) > > diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h > index 5142e2a..450b4da 100644 > --- a/include/kvm/arm_vgic.h > +++ b/include/kvm/arm_vgic.h > @@ -96,6 +96,7 @@ struct vgic_irq { > bool active;/* not used for LPIs */ > bool enabled; > bool hw;/* Tied to HW IRQ */ > + struct kref refcount; /* Used for LPIs */ > u32 hwintid;/* HW INTID number */ > union { > u8 targets; /* GICv2 target VCPUs mask */ > diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c > index 90cae48..ac3c1a5 100644 > --- a/virt/kvm/arm/vgic/vgic-init.c > +++ b/virt/kvm/arm/vgic/vgic-init.c > @@ -177,6 +177,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, > unsigned int nr_spis) > spin_lock_init(>irq_lock); > irq->vcpu = NULL; > irq->target_vcpu = vcpu0; > + kref_init(>refcount); > if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) > irq->targets = 0; > else > @@ -211,6 +212,7 @@ static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) > irq->vcpu = NULL; > irq->target_vcpu = vcpu; > irq->targets = 1U << vcpu->vcpu_id; > + kref_init(>refcount); > if (vgic_irq_is_sgi(i)) { > /* SGIs */ > irq->enabled = 1; > diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c > b/virt/kvm/arm/vgic/vgic-mmio-v2.c > index a213936..4152348 100644 > --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c > +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c > @@ -102,6 +102,7 @@ static void vgic_mmio_write_sgir(struct kvm_vcpu > *source_vcpu, > irq->source |= 1U << source_vcpu->vcpu_id; > > vgic_queue_irq_unlock(source_vcpu->kvm, irq); > + vgic_put_irq(source_vcpu->kvm, irq); > } > } > > @@ -116,6 +117,8 @@ static unsigned long vgic_mmio_read_target(struct > kvm_vcpu *vcpu, > struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); > > val |= (u64)irq->targets << (i * 8); > + > + vgic_put_irq(vcpu->kvm, irq); > } > > return val; > @@ -143,6 +146,7 @@ static void vgic_mmio_write_target(struct kvm_vcpu > *vcpu, > irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target); > > spin_unlock(>irq_lock); > + vgic_put_irq(vcpu->kvm, irq); > } > } > > @@ -157,6 +161,8 @@ static unsigned long vgic_mmio_read_sgipend(struct > kvm_vcpu *vcpu, > struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); > > val |= (u64)irq->source << (i * 8); > + > + vgic_put_irq(vcpu->kvm, irq); > } > return val; > } > @@ -178,6 +184,7 @@ static void vgic_mmio_write_sgipendc(struct kvm_vcpu > *vcpu, > irq->pending = false; > > spin_unlock(>irq_lock); > + vgic_put_irq(vcpu->kvm, irq); > } > } > > @@ -201,6 +208,7 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu > *vcpu, > } else { >
Re: [PATCH v8 06/17] KVM: arm/arm64: VGIC: add refcounting for IRQs
On 08/07/16 11:50, Marc Zyngier wrote: > On 08/07/16 11:28, Andre Przywara wrote: >> Hi, >> >> On 07/07/16 16:00, Marc Zyngier wrote: >>> On 05/07/16 12:22, Andre Przywara wrote: In the moment our struct vgic_irq's are statically allocated at guest creation time. So getting a pointer to an IRQ structure is trivial and safe. LPIs are more dynamic, they can be mapped and unmapped at any time during the guest's _runtime_. In preparation for supporting LPIs we introduce reference counting for those structures using the kernel's kref infrastructure. Since private IRQs and SPIs are statically allocated, the refcount never drops to 0 at the moment, but we increase it when an IRQ gets onto a VCPU list and decrease it when it gets removed. This introduces vgic_put_irq(), which wraps kref_put and hides the release function from the callers. Signed-off-by: Andre Przywara--- include/kvm/arm_vgic.h | 1 + virt/kvm/arm/vgic/vgic-init.c| 2 ++ virt/kvm/arm/vgic/vgic-mmio-v2.c | 8 +++ virt/kvm/arm/vgic/vgic-mmio-v3.c | 20 +++-- virt/kvm/arm/vgic/vgic-mmio.c| 25 - virt/kvm/arm/vgic/vgic-v2.c | 1 + virt/kvm/arm/vgic/vgic-v3.c | 1 + virt/kvm/arm/vgic/vgic.c | 48 +++- virt/kvm/arm/vgic/vgic.h | 1 + 9 files changed, 89 insertions(+), 18 deletions(-) diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 5142e2a..450b4da 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -96,6 +96,7 @@ struct vgic_irq { bool active;/* not used for LPIs */ bool enabled; bool hw;/* Tied to HW IRQ */ + struct kref refcount; /* Used for LPIs */ u32 hwintid;/* HW INTID number */ union { u8 targets; /* GICv2 target VCPUs mask */ diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c index 90cae48..ac3c1a5 100644 --- a/virt/kvm/arm/vgic/vgic-init.c +++ b/virt/kvm/arm/vgic/vgic-init.c @@ -177,6 +177,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis) spin_lock_init(>irq_lock); irq->vcpu = NULL; irq->target_vcpu = vcpu0; + kref_init(>refcount); if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) irq->targets = 0; else @@ -211,6 +212,7 @@ static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) irq->vcpu = NULL; irq->target_vcpu = vcpu; irq->targets = 1U << vcpu->vcpu_id; + kref_init(>refcount); if (vgic_irq_is_sgi(i)) { /* SGIs */ irq->enabled = 1; diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c index a213936..4152348 100644 --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c @@ -102,6 +102,7 @@ static void vgic_mmio_write_sgir(struct kvm_vcpu *source_vcpu, irq->source |= 1U << source_vcpu->vcpu_id; vgic_queue_irq_unlock(source_vcpu->kvm, irq); + vgic_put_irq(source_vcpu->kvm, irq); } } @@ -116,6 +117,8 @@ static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu, struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); val |= (u64)irq->targets << (i * 8); + + vgic_put_irq(vcpu->kvm, irq); } return val; @@ -143,6 +146,7 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu, irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target); spin_unlock(>irq_lock); + vgic_put_irq(vcpu->kvm, irq); } } @@ -157,6 +161,8 @@ static unsigned long vgic_mmio_read_sgipend(struct kvm_vcpu *vcpu, struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); val |= (u64)irq->source << (i * 8); + + vgic_put_irq(vcpu->kvm, irq); } return val; } @@ -178,6 +184,7 @@ static void vgic_mmio_write_sgipendc(struct kvm_vcpu *vcpu, irq->pending = false; spin_unlock(>irq_lock); + vgic_put_irq(vcpu->kvm, irq); } } @@ -201,6 +208,7 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu, } else { spin_unlock(>irq_lock); } + vgic_put_irq(vcpu->kvm, irq); }
Re: [PATCH v8 06/17] KVM: arm/arm64: VGIC: add refcounting for IRQs
On 08/07/16 11:28, Andre Przywara wrote: > Hi, > > On 07/07/16 16:00, Marc Zyngier wrote: >> On 05/07/16 12:22, Andre Przywara wrote: >>> In the moment our struct vgic_irq's are statically allocated at guest >>> creation time. So getting a pointer to an IRQ structure is trivial and >>> safe. LPIs are more dynamic, they can be mapped and unmapped at any time >>> during the guest's _runtime_. >>> In preparation for supporting LPIs we introduce reference counting for >>> those structures using the kernel's kref infrastructure. >>> Since private IRQs and SPIs are statically allocated, the refcount never >>> drops to 0 at the moment, but we increase it when an IRQ gets onto a VCPU >>> list and decrease it when it gets removed. >>> This introduces vgic_put_irq(), which wraps kref_put and hides the >>> release function from the callers. >>> >>> Signed-off-by: Andre Przywara>>> --- >>> include/kvm/arm_vgic.h | 1 + >>> virt/kvm/arm/vgic/vgic-init.c| 2 ++ >>> virt/kvm/arm/vgic/vgic-mmio-v2.c | 8 +++ >>> virt/kvm/arm/vgic/vgic-mmio-v3.c | 20 +++-- >>> virt/kvm/arm/vgic/vgic-mmio.c| 25 - >>> virt/kvm/arm/vgic/vgic-v2.c | 1 + >>> virt/kvm/arm/vgic/vgic-v3.c | 1 + >>> virt/kvm/arm/vgic/vgic.c | 48 >>> +++- >>> virt/kvm/arm/vgic/vgic.h | 1 + >>> 9 files changed, 89 insertions(+), 18 deletions(-) >>> >>> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h >>> index 5142e2a..450b4da 100644 >>> --- a/include/kvm/arm_vgic.h >>> +++ b/include/kvm/arm_vgic.h >>> @@ -96,6 +96,7 @@ struct vgic_irq { >>> bool active;/* not used for LPIs */ >>> bool enabled; >>> bool hw;/* Tied to HW IRQ */ >>> + struct kref refcount; /* Used for LPIs */ >>> u32 hwintid;/* HW INTID number */ >>> union { >>> u8 targets; /* GICv2 target VCPUs mask */ >>> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c >>> index 90cae48..ac3c1a5 100644 >>> --- a/virt/kvm/arm/vgic/vgic-init.c >>> +++ b/virt/kvm/arm/vgic/vgic-init.c >>> @@ -177,6 +177,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned >>> int nr_spis) >>> spin_lock_init(>irq_lock); >>> irq->vcpu = NULL; >>> irq->target_vcpu = vcpu0; >>> + kref_init(>refcount); >>> if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) >>> irq->targets = 0; >>> else >>> @@ -211,6 +212,7 @@ static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) >>> irq->vcpu = NULL; >>> irq->target_vcpu = vcpu; >>> irq->targets = 1U << vcpu->vcpu_id; >>> + kref_init(>refcount); >>> if (vgic_irq_is_sgi(i)) { >>> /* SGIs */ >>> irq->enabled = 1; >>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c >>> b/virt/kvm/arm/vgic/vgic-mmio-v2.c >>> index a213936..4152348 100644 >>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c >>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c >>> @@ -102,6 +102,7 @@ static void vgic_mmio_write_sgir(struct kvm_vcpu >>> *source_vcpu, >>> irq->source |= 1U << source_vcpu->vcpu_id; >>> >>> vgic_queue_irq_unlock(source_vcpu->kvm, irq); >>> + vgic_put_irq(source_vcpu->kvm, irq); >>> } >>> } >>> >>> @@ -116,6 +117,8 @@ static unsigned long vgic_mmio_read_target(struct >>> kvm_vcpu *vcpu, >>> struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); >>> >>> val |= (u64)irq->targets << (i * 8); >>> + >>> + vgic_put_irq(vcpu->kvm, irq); >>> } >>> >>> return val; >>> @@ -143,6 +146,7 @@ static void vgic_mmio_write_target(struct kvm_vcpu >>> *vcpu, >>> irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target); >>> >>> spin_unlock(>irq_lock); >>> + vgic_put_irq(vcpu->kvm, irq); >>> } >>> } >>> >>> @@ -157,6 +161,8 @@ static unsigned long vgic_mmio_read_sgipend(struct >>> kvm_vcpu *vcpu, >>> struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); >>> >>> val |= (u64)irq->source << (i * 8); >>> + >>> + vgic_put_irq(vcpu->kvm, irq); >>> } >>> return val; >>> } >>> @@ -178,6 +184,7 @@ static void vgic_mmio_write_sgipendc(struct kvm_vcpu >>> *vcpu, >>> irq->pending = false; >>> >>> spin_unlock(>irq_lock); >>> + vgic_put_irq(vcpu->kvm, irq); >>> } >>> } >>> >>> @@ -201,6 +208,7 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu >>> *vcpu, >>> } else { >>> spin_unlock(>irq_lock); >>> } >>> + vgic_put_irq(vcpu->kvm, irq); >>> } >>> } >>> >>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c >>> b/virt/kvm/arm/vgic/vgic-mmio-v3.c >>> index
Re: [PATCH v8 06/17] KVM: arm/arm64: VGIC: add refcounting for IRQs
Hi, On 07/07/16 16:00, Marc Zyngier wrote: > On 05/07/16 12:22, Andre Przywara wrote: >> In the moment our struct vgic_irq's are statically allocated at guest >> creation time. So getting a pointer to an IRQ structure is trivial and >> safe. LPIs are more dynamic, they can be mapped and unmapped at any time >> during the guest's _runtime_. >> In preparation for supporting LPIs we introduce reference counting for >> those structures using the kernel's kref infrastructure. >> Since private IRQs and SPIs are statically allocated, the refcount never >> drops to 0 at the moment, but we increase it when an IRQ gets onto a VCPU >> list and decrease it when it gets removed. >> This introduces vgic_put_irq(), which wraps kref_put and hides the >> release function from the callers. >> >> Signed-off-by: Andre Przywara>> --- >> include/kvm/arm_vgic.h | 1 + >> virt/kvm/arm/vgic/vgic-init.c| 2 ++ >> virt/kvm/arm/vgic/vgic-mmio-v2.c | 8 +++ >> virt/kvm/arm/vgic/vgic-mmio-v3.c | 20 +++-- >> virt/kvm/arm/vgic/vgic-mmio.c| 25 - >> virt/kvm/arm/vgic/vgic-v2.c | 1 + >> virt/kvm/arm/vgic/vgic-v3.c | 1 + >> virt/kvm/arm/vgic/vgic.c | 48 >> +++- >> virt/kvm/arm/vgic/vgic.h | 1 + >> 9 files changed, 89 insertions(+), 18 deletions(-) >> >> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h >> index 5142e2a..450b4da 100644 >> --- a/include/kvm/arm_vgic.h >> +++ b/include/kvm/arm_vgic.h >> @@ -96,6 +96,7 @@ struct vgic_irq { >> bool active;/* not used for LPIs */ >> bool enabled; >> bool hw;/* Tied to HW IRQ */ >> +struct kref refcount; /* Used for LPIs */ >> u32 hwintid;/* HW INTID number */ >> union { >> u8 targets; /* GICv2 target VCPUs mask */ >> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c >> index 90cae48..ac3c1a5 100644 >> --- a/virt/kvm/arm/vgic/vgic-init.c >> +++ b/virt/kvm/arm/vgic/vgic-init.c >> @@ -177,6 +177,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned >> int nr_spis) >> spin_lock_init(>irq_lock); >> irq->vcpu = NULL; >> irq->target_vcpu = vcpu0; >> +kref_init(>refcount); >> if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) >> irq->targets = 0; >> else >> @@ -211,6 +212,7 @@ static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) >> irq->vcpu = NULL; >> irq->target_vcpu = vcpu; >> irq->targets = 1U << vcpu->vcpu_id; >> +kref_init(>refcount); >> if (vgic_irq_is_sgi(i)) { >> /* SGIs */ >> irq->enabled = 1; >> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c >> b/virt/kvm/arm/vgic/vgic-mmio-v2.c >> index a213936..4152348 100644 >> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c >> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c >> @@ -102,6 +102,7 @@ static void vgic_mmio_write_sgir(struct kvm_vcpu >> *source_vcpu, >> irq->source |= 1U << source_vcpu->vcpu_id; >> >> vgic_queue_irq_unlock(source_vcpu->kvm, irq); >> +vgic_put_irq(source_vcpu->kvm, irq); >> } >> } >> >> @@ -116,6 +117,8 @@ static unsigned long vgic_mmio_read_target(struct >> kvm_vcpu *vcpu, >> struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); >> >> val |= (u64)irq->targets << (i * 8); >> + >> +vgic_put_irq(vcpu->kvm, irq); >> } >> >> return val; >> @@ -143,6 +146,7 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu, >> irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target); >> >> spin_unlock(>irq_lock); >> +vgic_put_irq(vcpu->kvm, irq); >> } >> } >> >> @@ -157,6 +161,8 @@ static unsigned long vgic_mmio_read_sgipend(struct >> kvm_vcpu *vcpu, >> struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); >> >> val |= (u64)irq->source << (i * 8); >> + >> +vgic_put_irq(vcpu->kvm, irq); >> } >> return val; >> } >> @@ -178,6 +184,7 @@ static void vgic_mmio_write_sgipendc(struct kvm_vcpu >> *vcpu, >> irq->pending = false; >> >> spin_unlock(>irq_lock); >> +vgic_put_irq(vcpu->kvm, irq); >> } >> } >> >> @@ -201,6 +208,7 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu >> *vcpu, >> } else { >> spin_unlock(>irq_lock); >> } >> +vgic_put_irq(vcpu->kvm, irq); >> } >> } >> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c >> b/virt/kvm/arm/vgic/vgic-mmio-v3.c >> index fc7b6c9..bfcafbd 100644 >> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c >> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c >> @@ -80,15 +80,17 @@
Re: [PATCH v8 06/17] KVM: arm/arm64: VGIC: add refcounting for IRQs
On 05/07/16 12:22, Andre Przywara wrote: > In the moment our struct vgic_irq's are statically allocated at guest > creation time. So getting a pointer to an IRQ structure is trivial and > safe. LPIs are more dynamic, they can be mapped and unmapped at any time > during the guest's _runtime_. > In preparation for supporting LPIs we introduce reference counting for > those structures using the kernel's kref infrastructure. > Since private IRQs and SPIs are statically allocated, the refcount never > drops to 0 at the moment, but we increase it when an IRQ gets onto a VCPU > list and decrease it when it gets removed. > This introduces vgic_put_irq(), which wraps kref_put and hides the > release function from the callers. > > Signed-off-by: Andre Przywara> --- > include/kvm/arm_vgic.h | 1 + > virt/kvm/arm/vgic/vgic-init.c| 2 ++ > virt/kvm/arm/vgic/vgic-mmio-v2.c | 8 +++ > virt/kvm/arm/vgic/vgic-mmio-v3.c | 20 +++-- > virt/kvm/arm/vgic/vgic-mmio.c| 25 - > virt/kvm/arm/vgic/vgic-v2.c | 1 + > virt/kvm/arm/vgic/vgic-v3.c | 1 + > virt/kvm/arm/vgic/vgic.c | 48 > +++- > virt/kvm/arm/vgic/vgic.h | 1 + > 9 files changed, 89 insertions(+), 18 deletions(-) > > diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h > index 5142e2a..450b4da 100644 > --- a/include/kvm/arm_vgic.h > +++ b/include/kvm/arm_vgic.h > @@ -96,6 +96,7 @@ struct vgic_irq { > bool active;/* not used for LPIs */ > bool enabled; > bool hw;/* Tied to HW IRQ */ > + struct kref refcount; /* Used for LPIs */ > u32 hwintid;/* HW INTID number */ > union { > u8 targets; /* GICv2 target VCPUs mask */ > diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c > index 90cae48..ac3c1a5 100644 > --- a/virt/kvm/arm/vgic/vgic-init.c > +++ b/virt/kvm/arm/vgic/vgic-init.c > @@ -177,6 +177,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned > int nr_spis) > spin_lock_init(>irq_lock); > irq->vcpu = NULL; > irq->target_vcpu = vcpu0; > + kref_init(>refcount); > if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) > irq->targets = 0; > else > @@ -211,6 +212,7 @@ static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) > irq->vcpu = NULL; > irq->target_vcpu = vcpu; > irq->targets = 1U << vcpu->vcpu_id; > + kref_init(>refcount); > if (vgic_irq_is_sgi(i)) { > /* SGIs */ > irq->enabled = 1; > diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c > b/virt/kvm/arm/vgic/vgic-mmio-v2.c > index a213936..4152348 100644 > --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c > +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c > @@ -102,6 +102,7 @@ static void vgic_mmio_write_sgir(struct kvm_vcpu > *source_vcpu, > irq->source |= 1U << source_vcpu->vcpu_id; > > vgic_queue_irq_unlock(source_vcpu->kvm, irq); > + vgic_put_irq(source_vcpu->kvm, irq); > } > } > > @@ -116,6 +117,8 @@ static unsigned long vgic_mmio_read_target(struct > kvm_vcpu *vcpu, > struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); > > val |= (u64)irq->targets << (i * 8); > + > + vgic_put_irq(vcpu->kvm, irq); > } > > return val; > @@ -143,6 +146,7 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu, > irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target); > > spin_unlock(>irq_lock); > + vgic_put_irq(vcpu->kvm, irq); > } > } > > @@ -157,6 +161,8 @@ static unsigned long vgic_mmio_read_sgipend(struct > kvm_vcpu *vcpu, > struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); > > val |= (u64)irq->source << (i * 8); > + > + vgic_put_irq(vcpu->kvm, irq); > } > return val; > } > @@ -178,6 +184,7 @@ static void vgic_mmio_write_sgipendc(struct kvm_vcpu > *vcpu, > irq->pending = false; > > spin_unlock(>irq_lock); > + vgic_put_irq(vcpu->kvm, irq); > } > } > > @@ -201,6 +208,7 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu > *vcpu, > } else { > spin_unlock(>irq_lock); > } > + vgic_put_irq(vcpu->kvm, irq); > } > } > > diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c > b/virt/kvm/arm/vgic/vgic-mmio-v3.c > index fc7b6c9..bfcafbd 100644 > --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c > +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c > @@ -80,15 +80,17 @@ static unsigned long vgic_mmio_read_irouter(struct > kvm_vcpu *vcpu, > { > int intid = VGIC_ADDR_TO_INTID(addr,
Re: [PATCH v8 06/17] KVM: arm/arm64: VGIC: add refcounting for IRQs
On Tue, Jul 05, 2016 at 12:22:58PM +0100, Andre Przywara wrote: > In the moment our struct vgic_irq's are statically allocated at guest > creation time. So getting a pointer to an IRQ structure is trivial and > safe. LPIs are more dynamic, they can be mapped and unmapped at any time > during the guest's _runtime_. > In preparation for supporting LPIs we introduce reference counting for > those structures using the kernel's kref infrastructure. > Since private IRQs and SPIs are statically allocated, the refcount never > drops to 0 at the moment, but we increase it when an IRQ gets onto a VCPU > list and decrease it when it gets removed. > This introduces vgic_put_irq(), which wraps kref_put and hides the > release function from the callers. > > Signed-off-by: Andre Przywara> --- > include/kvm/arm_vgic.h | 1 + > virt/kvm/arm/vgic/vgic-init.c| 2 ++ > virt/kvm/arm/vgic/vgic-mmio-v2.c | 8 +++ > virt/kvm/arm/vgic/vgic-mmio-v3.c | 20 +++-- > virt/kvm/arm/vgic/vgic-mmio.c| 25 - > virt/kvm/arm/vgic/vgic-v2.c | 1 + > virt/kvm/arm/vgic/vgic-v3.c | 1 + > virt/kvm/arm/vgic/vgic.c | 48 > +++- > virt/kvm/arm/vgic/vgic.h | 1 + > 9 files changed, 89 insertions(+), 18 deletions(-) > > diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h > index 5142e2a..450b4da 100644 > --- a/include/kvm/arm_vgic.h > +++ b/include/kvm/arm_vgic.h > @@ -96,6 +96,7 @@ struct vgic_irq { > bool active;/* not used for LPIs */ > bool enabled; > bool hw;/* Tied to HW IRQ */ > + struct kref refcount; /* Used for LPIs */ > u32 hwintid;/* HW INTID number */ > union { > u8 targets; /* GICv2 target VCPUs mask */ > diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c > index 90cae48..ac3c1a5 100644 > --- a/virt/kvm/arm/vgic/vgic-init.c > +++ b/virt/kvm/arm/vgic/vgic-init.c > @@ -177,6 +177,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned > int nr_spis) > spin_lock_init(>irq_lock); > irq->vcpu = NULL; > irq->target_vcpu = vcpu0; > + kref_init(>refcount); > if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) > irq->targets = 0; > else > @@ -211,6 +212,7 @@ static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) > irq->vcpu = NULL; > irq->target_vcpu = vcpu; > irq->targets = 1U << vcpu->vcpu_id; > + kref_init(>refcount); > if (vgic_irq_is_sgi(i)) { > /* SGIs */ > irq->enabled = 1; > diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c > b/virt/kvm/arm/vgic/vgic-mmio-v2.c > index a213936..4152348 100644 > --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c > +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c > @@ -102,6 +102,7 @@ static void vgic_mmio_write_sgir(struct kvm_vcpu > *source_vcpu, > irq->source |= 1U << source_vcpu->vcpu_id; > > vgic_queue_irq_unlock(source_vcpu->kvm, irq); > + vgic_put_irq(source_vcpu->kvm, irq); > } > } > > @@ -116,6 +117,8 @@ static unsigned long vgic_mmio_read_target(struct > kvm_vcpu *vcpu, > struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); > > val |= (u64)irq->targets << (i * 8); > + > + vgic_put_irq(vcpu->kvm, irq); > } > > return val; > @@ -143,6 +146,7 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu, > irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target); > > spin_unlock(>irq_lock); > + vgic_put_irq(vcpu->kvm, irq); > } > } > > @@ -157,6 +161,8 @@ static unsigned long vgic_mmio_read_sgipend(struct > kvm_vcpu *vcpu, > struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); > > val |= (u64)irq->source << (i * 8); > + > + vgic_put_irq(vcpu->kvm, irq); > } > return val; > } > @@ -178,6 +184,7 @@ static void vgic_mmio_write_sgipendc(struct kvm_vcpu > *vcpu, > irq->pending = false; > > spin_unlock(>irq_lock); > + vgic_put_irq(vcpu->kvm, irq); > } > } > > @@ -201,6 +208,7 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu > *vcpu, > } else { > spin_unlock(>irq_lock); > } > + vgic_put_irq(vcpu->kvm, irq); > } > } > > diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c > b/virt/kvm/arm/vgic/vgic-mmio-v3.c > index fc7b6c9..bfcafbd 100644 > --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c > +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c > @@ -80,15 +80,17 @@ static unsigned long vgic_mmio_read_irouter(struct > kvm_vcpu *vcpu, > { > int intid =
[PATCH v8 06/17] KVM: arm/arm64: VGIC: add refcounting for IRQs
In the moment our struct vgic_irq's are statically allocated at guest creation time. So getting a pointer to an IRQ structure is trivial and safe. LPIs are more dynamic, they can be mapped and unmapped at any time during the guest's _runtime_. In preparation for supporting LPIs we introduce reference counting for those structures using the kernel's kref infrastructure. Since private IRQs and SPIs are statically allocated, the refcount never drops to 0 at the moment, but we increase it when an IRQ gets onto a VCPU list and decrease it when it gets removed. This introduces vgic_put_irq(), which wraps kref_put and hides the release function from the callers. Signed-off-by: Andre Przywara--- include/kvm/arm_vgic.h | 1 + virt/kvm/arm/vgic/vgic-init.c| 2 ++ virt/kvm/arm/vgic/vgic-mmio-v2.c | 8 +++ virt/kvm/arm/vgic/vgic-mmio-v3.c | 20 +++-- virt/kvm/arm/vgic/vgic-mmio.c| 25 - virt/kvm/arm/vgic/vgic-v2.c | 1 + virt/kvm/arm/vgic/vgic-v3.c | 1 + virt/kvm/arm/vgic/vgic.c | 48 +++- virt/kvm/arm/vgic/vgic.h | 1 + 9 files changed, 89 insertions(+), 18 deletions(-) diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 5142e2a..450b4da 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -96,6 +96,7 @@ struct vgic_irq { bool active;/* not used for LPIs */ bool enabled; bool hw;/* Tied to HW IRQ */ + struct kref refcount; /* Used for LPIs */ u32 hwintid;/* HW INTID number */ union { u8 targets; /* GICv2 target VCPUs mask */ diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c index 90cae48..ac3c1a5 100644 --- a/virt/kvm/arm/vgic/vgic-init.c +++ b/virt/kvm/arm/vgic/vgic-init.c @@ -177,6 +177,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis) spin_lock_init(>irq_lock); irq->vcpu = NULL; irq->target_vcpu = vcpu0; + kref_init(>refcount); if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) irq->targets = 0; else @@ -211,6 +212,7 @@ static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) irq->vcpu = NULL; irq->target_vcpu = vcpu; irq->targets = 1U << vcpu->vcpu_id; + kref_init(>refcount); if (vgic_irq_is_sgi(i)) { /* SGIs */ irq->enabled = 1; diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c index a213936..4152348 100644 --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c @@ -102,6 +102,7 @@ static void vgic_mmio_write_sgir(struct kvm_vcpu *source_vcpu, irq->source |= 1U << source_vcpu->vcpu_id; vgic_queue_irq_unlock(source_vcpu->kvm, irq); + vgic_put_irq(source_vcpu->kvm, irq); } } @@ -116,6 +117,8 @@ static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu, struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); val |= (u64)irq->targets << (i * 8); + + vgic_put_irq(vcpu->kvm, irq); } return val; @@ -143,6 +146,7 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu, irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target); spin_unlock(>irq_lock); + vgic_put_irq(vcpu->kvm, irq); } } @@ -157,6 +161,8 @@ static unsigned long vgic_mmio_read_sgipend(struct kvm_vcpu *vcpu, struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); val |= (u64)irq->source << (i * 8); + + vgic_put_irq(vcpu->kvm, irq); } return val; } @@ -178,6 +184,7 @@ static void vgic_mmio_write_sgipendc(struct kvm_vcpu *vcpu, irq->pending = false; spin_unlock(>irq_lock); + vgic_put_irq(vcpu->kvm, irq); } } @@ -201,6 +208,7 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu, } else { spin_unlock(>irq_lock); } + vgic_put_irq(vcpu->kvm, irq); } } diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c index fc7b6c9..bfcafbd 100644 --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c @@ -80,15 +80,17 @@ static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu *vcpu, { int intid = VGIC_ADDR_TO_INTID(addr, 64); struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid); + unsigned long ret = 0; if (!irq) return 0; /* The upper word is RAZ for us. */ -