Message ID | 1466034731-9291-1-git-send-email-tim.gardner@canonical.com |
---|---|
State | New |
Headers | show |
ACK clean cherry-pick, nothing newer that seems to need application. --chris On Thu, Jun 16, 2016 at 02:52:11AM +0300, Tim Gardner wrote: > From: Paul Mackerras <paulus@ozlabs.org> > > BugLink: http://bugs.launchpad.net/bugs/1592809 > > Commit c9a5eccac1ab ("kvm/eventfd: add arch-specific set_irq", > 2015-10-16) added the possibility for architecture-specific code > to handle the generation of virtual interrupts in atomic context > where possible, without having to schedule a work function. > > Since we can easily generate virtual interrupts on XICS without > having to do anything worse than take a spinlock, we define a > kvm_arch_set_irq_inatomic() for XICS. We also remove kvm_set_msi() > since it is not used any more. > > The one slightly tricky thing is that with the new interface, we > don't get told whether the interrupt is an MSI (or other edge > sensitive interrupt) vs. level-sensitive. The difference as far > as interrupt generation is concerned is that for LSIs we have to > set the asserted flag so it will continue to fire until it is > explicitly cleared. > > In fact the XICS code gets told which interrupts are LSIs by userspace > when it configures the interrupt via the KVM_DEV_XICS_GRP_SOURCES > attribute group on the XICS device. To store this information, we add > a new "lsi" field to struct ics_irq_state. With that we can also do a > better job of returning accurate values when reading the attribute > group. > > Signed-off-by: Paul Mackerras <paulus@samba.org> > (cherry picked from commit b1a4286b8f3393857a205ec89607683161b75f90) > Signed-off-by: Tim Gardner <tim.gardner@canonical.com> > --- > arch/powerpc/kvm/book3s_xics.c | 25 +++++++++++++++---------- > arch/powerpc/kvm/book3s_xics.h | 1 + > 2 files changed, 16 insertions(+), 10 deletions(-) > > diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c > index 905e94a..df75fc8 100644 > --- a/arch/powerpc/kvm/book3s_xics.c > +++ b/arch/powerpc/kvm/book3s_xics.c > @@ -92,7 +92,7 @@ static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level) > * we are the only setter, thus concurrent access is undefined > * to begin with. > */ > - if (level == 1 || level == KVM_INTERRUPT_SET_LEVEL) > + if ((level == 1 && state->lsi) || level == KVM_INTERRUPT_SET_LEVEL) > state->asserted = 1; > else if (level == 0 || level == KVM_INTERRUPT_UNSET) { > state->asserted = 0; > @@ -1174,9 +1174,11 @@ static int xics_get_source(struct kvmppc_xics *xics, long irq, u64 addr) > prio = irqp->saved_priority; > } > val |= prio << KVM_XICS_PRIORITY_SHIFT; > - if (irqp->asserted) > - val |= KVM_XICS_LEVEL_SENSITIVE | KVM_XICS_PENDING; > - else if (irqp->masked_pending || irqp->resend) > + if (irqp->lsi) { > + val |= KVM_XICS_LEVEL_SENSITIVE; > + if (irqp->asserted) > + val |= KVM_XICS_PENDING; > + } else if (irqp->masked_pending || irqp->resend) > val |= KVM_XICS_PENDING; > ret = 0; > } > @@ -1228,9 +1230,13 @@ static int xics_set_source(struct kvmppc_xics *xics, long irq, u64 addr) > irqp->priority = prio; > irqp->resend = 0; > irqp->masked_pending = 0; > + irqp->lsi = 0; > irqp->asserted = 0; > - if ((val & KVM_XICS_PENDING) && (val & KVM_XICS_LEVEL_SENSITIVE)) > - irqp->asserted = 1; > + if (val & KVM_XICS_LEVEL_SENSITIVE) { > + irqp->lsi = 1; > + if (val & KVM_XICS_PENDING) > + irqp->asserted = 1; > + } > irqp->exists = 1; > arch_spin_unlock(&ics->lock); > local_irq_restore(flags); > @@ -1249,11 +1255,10 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, > return ics_deliver_irq(xics, irq, level); > } > > -int kvm_set_msi(struct kvm_kernel_irq_routing_entry *irq_entry, struct kvm *kvm, > - int irq_source_id, int level, bool line_status) > +int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *irq_entry, > + struct kvm *kvm, int irq_source_id, > + int level, bool line_status) > { > - if (!level) > - return -1; > return kvm_set_irq(kvm, irq_source_id, irq_entry->gsi, > level, line_status); > } > diff --git a/arch/powerpc/kvm/book3s_xics.h b/arch/powerpc/kvm/book3s_xics.h > index 56ea44f..a46b954 100644 > --- a/arch/powerpc/kvm/book3s_xics.h > +++ b/arch/powerpc/kvm/book3s_xics.h > @@ -39,6 +39,7 @@ struct ics_irq_state { > u8 saved_priority; > u8 resend; > u8 masked_pending; > + u8 lsi; /* level-sensitive interrupt */ > u8 asserted; /* Only for LSI */ > u8 exists; > }; > -- > 2.7.4 > > > -- > kernel-team mailing list > kernel-team@lists.ubuntu.com > https://lists.ubuntu.com/mailman/listinfo/kernel-team
Applied to X. -Kamal
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c index 905e94a..df75fc8 100644 --- a/arch/powerpc/kvm/book3s_xics.c +++ b/arch/powerpc/kvm/book3s_xics.c @@ -92,7 +92,7 @@ static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level) * we are the only setter, thus concurrent access is undefined * to begin with. */ - if (level == 1 || level == KVM_INTERRUPT_SET_LEVEL) + if ((level == 1 && state->lsi) || level == KVM_INTERRUPT_SET_LEVEL) state->asserted = 1; else if (level == 0 || level == KVM_INTERRUPT_UNSET) { state->asserted = 0; @@ -1174,9 +1174,11 @@ static int xics_get_source(struct kvmppc_xics *xics, long irq, u64 addr) prio = irqp->saved_priority; } val |= prio << KVM_XICS_PRIORITY_SHIFT; - if (irqp->asserted) - val |= KVM_XICS_LEVEL_SENSITIVE | KVM_XICS_PENDING; - else if (irqp->masked_pending || irqp->resend) + if (irqp->lsi) { + val |= KVM_XICS_LEVEL_SENSITIVE; + if (irqp->asserted) + val |= KVM_XICS_PENDING; + } else if (irqp->masked_pending || irqp->resend) val |= KVM_XICS_PENDING; ret = 0; } @@ -1228,9 +1230,13 @@ static int xics_set_source(struct kvmppc_xics *xics, long irq, u64 addr) irqp->priority = prio; irqp->resend = 0; irqp->masked_pending = 0; + irqp->lsi = 0; irqp->asserted = 0; - if ((val & KVM_XICS_PENDING) && (val & KVM_XICS_LEVEL_SENSITIVE)) - irqp->asserted = 1; + if (val & KVM_XICS_LEVEL_SENSITIVE) { + irqp->lsi = 1; + if (val & KVM_XICS_PENDING) + irqp->asserted = 1; + } irqp->exists = 1; arch_spin_unlock(&ics->lock); local_irq_restore(flags); @@ -1249,11 +1255,10 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, return ics_deliver_irq(xics, irq, level); } -int kvm_set_msi(struct kvm_kernel_irq_routing_entry *irq_entry, struct kvm *kvm, - int irq_source_id, int level, bool line_status) +int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *irq_entry, + struct kvm *kvm, int irq_source_id, + int level, bool line_status) { - if (!level) - return -1; return kvm_set_irq(kvm, irq_source_id, irq_entry->gsi, level, line_status); } diff --git a/arch/powerpc/kvm/book3s_xics.h b/arch/powerpc/kvm/book3s_xics.h index 56ea44f..a46b954 100644 --- a/arch/powerpc/kvm/book3s_xics.h +++ b/arch/powerpc/kvm/book3s_xics.h @@ -39,6 +39,7 @@ struct ics_irq_state { u8 saved_priority; u8 resend; u8 masked_pending; + u8 lsi; /* level-sensitive interrupt */ u8 asserted; /* Only for LSI */ u8 exists; };