All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gleb Natapov <gleb@redhat.com>
To: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>,
	avi@redhat.com, kvm@vger.kernel.org,
	linux-kernel@vger.kernel.org, jan.kiszka@siemens.com
Subject: Re: [PATCH v5 1/4] kvm: Extend irqfd to support level interrupts
Date: Wed, 18 Jul 2012 13:49:06 +0300	[thread overview]
Message-ID: <20120718104906.GE26120@redhat.com> (raw)
In-Reply-To: <20120718104844.GF4700@redhat.com>

On Wed, Jul 18, 2012 at 01:48:44PM +0300, Michael S. Tsirkin wrote:
> On Wed, Jul 18, 2012 at 01:44:29PM +0300, Gleb Natapov wrote:
> > On Wed, Jul 18, 2012 at 01:41:14PM +0300, Michael S. Tsirkin wrote:
> > > On Mon, Jul 16, 2012 at 02:33:47PM -0600, Alex Williamson wrote:
> > > > In order to inject a level interrupt from an external source using an
> > > > irqfd, we need to allocate a new irq_source_id.  This allows us to
> > > > assert and (later) de-assert an interrupt line independently from
> > > > users of KVM_IRQ_LINE and avoid lost interrupts.
> > > > 
> > > > We also add what may appear like a bit of excessive infrastructure
> > > > around an object for storing this irq_source_id.  However, notice
> > > > that we only provide a way to assert the interrupt here.  A follow-on
> > > > interface will make use of the same irq_source_id to allow de-assert.
> > > > 
> > > > Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
> > > > ---
> > > > 
> > > >  Documentation/virtual/kvm/api.txt |    6 ++
> > > >  arch/x86/kvm/x86.c                |    1 
> > > >  include/linux/kvm.h               |    3 +
> > > >  virt/kvm/eventfd.c                |  114 ++++++++++++++++++++++++++++++++++++-
> > > >  4 files changed, 120 insertions(+), 4 deletions(-)
> > > > 
> > > > diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> > > > index 100acde..c7267d5 100644
> > > > --- a/Documentation/virtual/kvm/api.txt
> > > > +++ b/Documentation/virtual/kvm/api.txt
> > > > @@ -1981,6 +1981,12 @@ the guest using the specified gsi pin.  The irqfd is removed using
> > > >  the KVM_IRQFD_FLAG_DEASSIGN flag, specifying both kvm_irqfd.fd
> > > >  and kvm_irqfd.gsi.
> > > >  
> > > > +The KVM_IRQFD_FLAG_LEVEL flag indicates the gsi input is for a level
> > > > +triggered interrupt.  In this case a new irqchip input is allocated
> > > > +which is logically OR'd with other inputs allowing multiple sources
> > > > +to independently assert level interrupts.  The KVM_IRQFD_FLAG_LEVEL
> > > > +is only necessary on setup, teardown is identical to that above.
> > > > +KVM_IRQFD_FLAG_LEVEL support is indicated by KVM_CAP_IRQFD_LEVEL.
> > > >  
> > > >  5. The kvm_run structure
> > > >  ------------------------
> > > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > > > index a01a424..80bed07 100644
> > > > --- a/arch/x86/kvm/x86.c
> > > > +++ b/arch/x86/kvm/x86.c
> > > > @@ -2148,6 +2148,7 @@ int kvm_dev_ioctl_check_extension(long ext)
> > > >  	case KVM_CAP_GET_TSC_KHZ:
> > > >  	case KVM_CAP_PCI_2_3:
> > > >  	case KVM_CAP_KVMCLOCK_CTRL:
> > > > +	case KVM_CAP_IRQFD_LEVEL:
> > > >  		r = 1;
> > > >  		break;
> > > >  	case KVM_CAP_COALESCED_MMIO:
> > > > diff --git a/include/linux/kvm.h b/include/linux/kvm.h
> > > > index 2ce09aa..b2e6e4f 100644
> > > > --- a/include/linux/kvm.h
> > > > +++ b/include/linux/kvm.h
> > > > @@ -618,6 +618,7 @@ struct kvm_ppc_smmu_info {
> > > >  #define KVM_CAP_PPC_GET_SMMU_INFO 78
> > > >  #define KVM_CAP_S390_COW 79
> > > >  #define KVM_CAP_PPC_ALLOC_HTAB 80
> > > > +#define KVM_CAP_IRQFD_LEVEL 81
> > > >  
> > > >  #ifdef KVM_CAP_IRQ_ROUTING
> > > >  
> > > > @@ -683,6 +684,8 @@ struct kvm_xen_hvm_config {
> > > >  #endif
> > > >  
> > > >  #define KVM_IRQFD_FLAG_DEASSIGN (1 << 0)
> > > > +/* Available with KVM_CAP_IRQFD_LEVEL */
> > > > +#define KVM_IRQFD_FLAG_LEVEL (1 << 1)
> > > >  
> > > >  struct kvm_irqfd {
> > > >  	__u32 fd;
> > > > diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
> > > > index 7d7e2aa..ecdbfea 100644
> > > > --- a/virt/kvm/eventfd.c
> > > > +++ b/virt/kvm/eventfd.c
> > > > @@ -36,6 +36,68 @@
> > > >  #include "iodev.h"
> > > >  
> > > >  /*
> > > > + * An irq_source_id can be created from KVM_IRQFD for level interrupt
> > > > + * injections and shared with other interfaces for EOI or de-assert.
> > > > + * Create an object with reference counting to make it easy to use.
> > > > + */
> > > > +struct _irq_source {
> > > > +	int id; /* the IRQ source ID */
> > > > +	bool level_asserted; /* Track assertion state and protect with lock */
> > > > +	spinlock_t lock;     /* to avoid unnecessary re-assert/spurious eoi. */
> > > > +	struct kvm *kvm;
> > > > +	struct kref kref;
> > > > +};
> > > > +
> > > > +static void _irq_source_release(struct kref *kref)
> > > > +{
> > > > +	struct _irq_source *source;
> > > > +
> > > > +	source = container_of(kref, struct _irq_source, kref);
> > > > +
> > > > +	/* This also de-asserts */
> > > > +	kvm_free_irq_source_id(source->kvm, source->id);
> > > > +	kfree(source);
> > > > +}
> > > > +
> > > > +static void _irq_source_put(struct _irq_source *source)
> > > > +{
> > > > +	if (source)
> > > > +		kref_put(&source->kref, _irq_source_release);
> > > > +}
> > > > +
> > > > +static struct _irq_source *__attribute__ ((used)) /* white lie for now */
> > > > +_irq_source_get(struct _irq_source *source)
> > > > +{
> > > > +	if (source)
> > > > +		kref_get(&source->kref);
> > > > +
> > > > +	return source;
> > > > +}
> > > > +
> > > > +static struct _irq_source *_irq_source_alloc(struct kvm *kvm)
> > > > +{
> > > > +	struct _irq_source *source;
> > > > +	int id;
> > > > +
> > > > +	source = kzalloc(sizeof(*source), GFP_KERNEL);
> > > > +	if (!source)
> > > > +		return ERR_PTR(-ENOMEM);
> > > > +
> > > > +	id = kvm_request_irq_source_id(kvm);
> > > > +	if (id < 0) {
> > > > +		kfree(source);
> > > > +		return ERR_PTR(id);
> > > > +	}
> > > > +
> > > > +	kref_init(&source->kref);
> > > > +	spin_lock_init(&source->lock);
> > > > +	source->kvm = kvm;
> > > > +	source->id = id;
> > > > +
> > > > +	return source;
> > > > +}
> > > > +
> > > > +/*
> > > >   * --------------------------------------------------------------------
> > > >   * irqfd: Allows an fd to be used to inject an interrupt to the guest
> > > >   *
> > > > @@ -52,6 +114,8 @@ struct _irqfd {
> > > >  	/* Used for level IRQ fast-path */
> > > >  	int gsi;
> > > >  	struct work_struct inject;
> > > > +	/* IRQ source ID for level triggered irqfds */
> > > > +	struct _irq_source *source;
> > > >  	/* Used for setup/shutdown */
> > > >  	struct eventfd_ctx *eventfd;
> > > >  	struct list_head list;
> > > > @@ -62,7 +126,7 @@ struct _irqfd {
> > > >  static struct workqueue_struct *irqfd_cleanup_wq;
> > > >  
> > > >  static void
> > > > -irqfd_inject(struct work_struct *work)
> > > > +irqfd_inject_edge(struct work_struct *work)
> > > >  {
> > > >  	struct _irqfd *irqfd = container_of(work, struct _irqfd, inject);
> > > >  	struct kvm *kvm = irqfd->kvm;
> > > > @@ -71,6 +135,29 @@ irqfd_inject(struct work_struct *work)
> > > >  	kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi, 0);
> > > >  }
> > > >  
> > > > +static void
> > > > +irqfd_inject_level(struct work_struct *work)
> > > > +{
> > > > +	struct _irqfd *irqfd = container_of(work, struct _irqfd, inject);
> > > > +
> > > > +	/*
> > > > +	 * Inject an interrupt only if not already asserted.
> > > > +	 *
> > > > +	 * We can safely ignore the kvm_set_irq return value here.  If
> > > > +	 * masked, the irr bit is still set and will eventually be serviced.
> > > > +	 * This interface does not guarantee immediate injection.  If
> > > > +	 * coalesced, an eoi will be coming where we can de-assert and
> > > > +	 * re-inject if necessary.  NB, if you need to know if an interrupt
> > > > +	 * was coalesced, this interface is not for you.
> > > > +	 */
> > > > +	spin_lock(&irqfd->source->lock);
> > > > +	if (!irqfd->source->level_asserted) {
> > > > +		kvm_set_irq(irqfd->kvm, irqfd->source->id, irqfd->gsi, 1);
> > > > +		irqfd->source->level_asserted = true;
> > > > +	}
> > > > +	spin_unlock(&irqfd->source->lock);
> > > > +}
> > > > +
> > > 
> > > So as was discussed kvm_set_irq under spinlock is bad for scalability
> > > with multiple VCPUs.  Why do we need a spinlock simply to protect
> > > level_asserted?  Let's use an atomic test and set/test and clear and the
> > > problem goes away.
> > > 
> > That sad reality is that for level interrupt we already scan all vcpus
> > under spinlock.
> 
> Where?
> 
ioapic

--
			Gleb.

  reply	other threads:[~2012-07-18 10:49 UTC|newest]

Thread overview: 96+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-16 20:33 [PATCH v5 0/4] kvm: level irqfd and new eoifd Alex Williamson
2012-07-16 20:33 ` [PATCH v5 1/4] kvm: Extend irqfd to support level interrupts Alex Williamson
2012-07-17 21:26   ` Michael S. Tsirkin
2012-07-17 21:57     ` Alex Williamson
2012-07-17 22:00       ` Michael S. Tsirkin
2012-07-17 22:16         ` Alex Williamson
2012-07-17 22:28           ` Michael S. Tsirkin
2012-07-18 10:41   ` Michael S. Tsirkin
2012-07-18 10:44     ` Gleb Natapov
2012-07-18 10:48       ` Michael S. Tsirkin
2012-07-18 10:49         ` Gleb Natapov [this message]
2012-07-18 10:53           ` Michael S. Tsirkin
2012-07-18 10:55             ` Gleb Natapov
2012-07-18 11:22               ` Michael S. Tsirkin
2012-07-18 11:39                 ` Michael S. Tsirkin
2012-07-18 11:48                   ` Gleb Natapov
2012-07-18 12:07                     ` Michael S. Tsirkin
2012-07-18 14:47                       ` Alex Williamson
2012-07-18 15:38                         ` Michael S. Tsirkin
2012-07-18 15:48                           ` Alex Williamson
2012-07-18 15:58                             ` Michael S. Tsirkin
2012-07-18 18:42                               ` Marcelo Tosatti
2012-07-18 19:00                                 ` Gleb Natapov
2012-07-18 19:07                                 ` Alex Williamson
2012-07-18 19:13                                   ` Alex Williamson
2012-07-18 19:16                                     ` Michael S. Tsirkin
2012-07-18 20:28                                     ` Alex Williamson
2012-07-18 21:23                                       ` Marcelo Tosatti
2012-07-18 21:30                                         ` Michael S. Tsirkin
2012-07-16 20:33 ` [PATCH v5 2/4] kvm: KVM_EOIFD, an eventfd for EOIs Alex Williamson
2012-07-17 10:21   ` Michael S. Tsirkin
2012-07-17 13:59     ` Alex Williamson
2012-07-17 14:10       ` Michael S. Tsirkin
2012-07-17 14:29         ` Alex Williamson
2012-07-17 14:42           ` Michael S. Tsirkin
2012-07-17 14:57             ` Alex Williamson
2012-07-17 15:13               ` Michael S. Tsirkin
2012-07-17 15:41                 ` Alex Williamson
2012-07-17 15:53                   ` Michael S. Tsirkin
2012-07-17 16:06                     ` Alex Williamson
2012-07-17 16:19                       ` Michael S. Tsirkin
2012-07-17 16:52                         ` Alex Williamson
2012-07-17 18:58                           ` Michael S. Tsirkin
2012-07-17 20:03                             ` Alex Williamson
2012-07-17 21:23                               ` Michael S. Tsirkin
2012-07-17 22:09                                 ` Alex Williamson
2012-07-17 22:24                                   ` Michael S. Tsirkin
2012-07-18  2:44                                     ` Alex Williamson
2012-07-18 10:31                                       ` Michael S. Tsirkin
2012-07-16 20:34 ` [PATCH v5 3/4] kvm: Create kvm_clear_irq() Alex Williamson
2012-07-17  0:51   ` Michael S. Tsirkin
2012-07-17  2:42     ` Alex Williamson
2012-07-17  0:55   ` Michael S. Tsirkin
2012-07-17 10:14   ` Michael S. Tsirkin
2012-07-17 13:56     ` Alex Williamson
2012-07-17 14:08       ` Michael S. Tsirkin
2012-07-17 14:21         ` Alex Williamson
2012-07-17 14:53           ` Michael S. Tsirkin
2012-07-17 15:20             ` Alex Williamson
2012-07-17 15:36               ` Michael S. Tsirkin
2012-07-17 15:51                 ` Alex Williamson
2012-07-17 15:57                   ` Michael S. Tsirkin
2012-07-17 16:01                     ` Gleb Natapov
2012-07-17 16:08                     ` Alex Williamson
2012-07-17 16:14                       ` Michael S. Tsirkin
2012-07-17 16:17                         ` Alex Williamson
2012-07-17 16:21                           ` Michael S. Tsirkin
2012-07-17 16:45                             ` Alex Williamson
2012-07-17 18:55                               ` Michael S. Tsirkin
2012-07-17 19:51                                 ` Alex Williamson
2012-07-17 21:05                                   ` Michael S. Tsirkin
2012-07-17 22:01                                     ` Alex Williamson
2012-07-17 22:05                                       ` Michael S. Tsirkin
2012-07-17 22:22                                         ` Alex Williamson
2012-07-17 22:31                                           ` Michael S. Tsirkin
2012-07-18  6:27                         ` Gleb Natapov
2012-07-18 10:20                           ` Michael S. Tsirkin
2012-07-18 10:27                             ` Gleb Natapov
2012-07-18 10:33                               ` Michael S. Tsirkin
2012-07-18 10:36                                 ` Gleb Natapov
2012-07-18 10:51                                   ` Michael S. Tsirkin
2012-07-18 10:53                                     ` Gleb Natapov
2012-07-18 11:08                                       ` Michael S. Tsirkin
2012-07-18 11:50                                         ` Gleb Natapov
2012-07-18 21:55                           ` Michael S. Tsirkin
2012-07-17 16:36                       ` Michael S. Tsirkin
2012-07-17 17:09                         ` Gleb Natapov
2012-07-17 10:18   ` Michael S. Tsirkin
2012-07-16 20:34 ` [PATCH v5 4/4] kvm: Convert eoifd to use kvm_clear_irq Alex Williamson
2012-07-18 10:43 ` [PATCH v5 0/4] kvm: level irqfd and new eoifd Michael S. Tsirkin
2012-07-19 16:59 ` Michael S. Tsirkin
2012-07-19 17:29   ` Alex Williamson
2012-07-19 17:45     ` Michael S. Tsirkin
2012-07-19 18:48       ` Alex Williamson
2012-07-20 10:07         ` Michael S. Tsirkin
2012-07-22 15:09           ` Gleb Natapov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120718104906.GE26120@redhat.com \
    --to=gleb@redhat.com \
    --cc=alex.williamson@redhat.com \
    --cc=avi@redhat.com \
    --cc=jan.kiszka@siemens.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mst@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.