From patchwork Sun Jul 26 16:22:25 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Michael S. Tsirkin" X-Patchwork-Id: 37428 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n6QGNV7g008915 for ; Sun, 26 Jul 2009 16:23:31 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753790AbZGZQX3 (ORCPT ); Sun, 26 Jul 2009 12:23:29 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753793AbZGZQX3 (ORCPT ); Sun, 26 Jul 2009 12:23:29 -0400 Received: from mx2.redhat.com ([66.187.237.31]:45800 "EHLO mx2.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753775AbZGZQX2 (ORCPT ); Sun, 26 Jul 2009 12:23:28 -0400 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n6QGNOZg018300 for ; Sun, 26 Jul 2009 12:23:24 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n6QGNNgb003221; Sun, 26 Jul 2009 12:23:23 -0400 Received: from redhat.com (vpn-6-213.tlv.redhat.com [10.35.6.213]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n6QGNKEf002614; Sun, 26 Jul 2009 12:23:21 -0400 Date: Sun, 26 Jul 2009 19:22:25 +0300 From: "Michael S. Tsirkin" To: avi@redhat.com, gleb@redhat.com, mtosatti@redhat.com, kvm@vger.kernel.org Subject: [PATCHv0 RFC] kvm: irqfd support for level interrupts Message-ID: <20090726162225.GA21972@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.19 (2009-01-05) X-Scanned-By: MIMEDefang 2.58 on 172.16.27.26 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Here's an untested patch with partial support for level triggered interrupts in irqfd. What this patch has: support for clearing interrupt on ack. What this patch does not have: support signalling eventfd on ack so that userspace can take action and e.g. reenable interrupt. Gleb, Marcelo, I'd like your input on the approach taken wrt locking. Does it look sane? Avi, how's the interface? I intend to also add an eventfd probably in the padding in the irqfd struct. Signed-off-by: Michael S. Tsirkin Acked-by: Gregory Haskins --- -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 230a91a..8bf16af 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -488,6 +488,7 @@ struct kvm_x86_mce { #endif #define KVM_IRQFD_FLAG_DEASSIGN (1 << 0) +#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 99017e8..fcbf5b5 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c @@ -45,12 +45,14 @@ struct _irqfd { struct kvm *kvm; struct eventfd_ctx *eventfd; int gsi; + int is_level; struct list_head list; poll_table pt; wait_queue_head_t *wqh; wait_queue_t wait; struct work_struct inject; struct work_struct shutdown; + struct kvm_irq_ack_notifier kian; }; static struct workqueue_struct *irqfd_cleanup_wq; @@ -63,10 +65,15 @@ irqfd_inject(struct work_struct *work) mutex_lock(&kvm->irq_lock); kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi, 1); - kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi, 0); + if (!irqfd->is_level) + kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi, 0); mutex_unlock(&kvm->irq_lock); } +static void irqfd_irq_acked(struct kvm_irq_ack_notifier *kian) +{ + kvm_set_irq(kian->kvm, KVM_USERSPACE_IRQ_SOURCE_ID, kian->gsi, 0); +} /* * Race-free decouple logic (ordering is critical) */ @@ -87,6 +94,9 @@ irqfd_shutdown(struct work_struct *work) */ flush_work(&irqfd->inject); + if (irqfd->is_level) + kvm_unregister_irq_ack_notifier(&irqfd->kian); + /* * It is now safe to release the object's resources */ @@ -166,7 +176,7 @@ irqfd_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh, } static int -kvm_irqfd_assign(struct kvm *kvm, int fd, int gsi) +kvm_irqfd_assign(struct kvm *kvm, int fd, int gsi, int is_level) { struct _irqfd *irqfd; struct file *file = NULL; @@ -180,6 +190,7 @@ kvm_irqfd_assign(struct kvm *kvm, int fd, int gsi) irqfd->kvm = kvm; irqfd->gsi = gsi; + irqfd->is_level = is_level; INIT_LIST_HEAD(&irqfd->list); INIT_WORK(&irqfd->inject, irqfd_inject); INIT_WORK(&irqfd->shutdown, irqfd_shutdown); @@ -198,6 +209,12 @@ kvm_irqfd_assign(struct kvm *kvm, int fd, int gsi) irqfd->eventfd = eventfd; + if (is_level) { + irqfd->kian.gsi = gsi; + irqfd->kian.irq_acked = irqfd_irq_acked; + kvm_register_irq_ack_notifier(&irqfd->kian); + } + /* * Install our own custom wake-up handling so we are notified via * a callback whenever someone signals the underlying eventfd @@ -281,10 +298,13 @@ kvm_irqfd_deassign(struct kvm *kvm, int fd, int gsi) int kvm_irqfd(struct kvm *kvm, int fd, int gsi, int flags) { + if (flags & ~(KVM_IRQFD_FLAG_DEASSIGN | KVM_IRQFD_FLAG_LEVEL)) + return -EINVAL; + if (flags & KVM_IRQFD_FLAG_DEASSIGN) return kvm_irqfd_deassign(kvm, fd, gsi); - return kvm_irqfd_assign(kvm, fd, gsi); + return kvm_irqfd_assign(kvm, fd, gsi, !!(flags & KVM_IRQFD_FLAG_LEVEL)); } /*