From patchwork Wed Feb 8 07:58:45 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Xu X-Patchwork-Id: 9561843 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id AA9CD601E5 for ; Wed, 8 Feb 2017 07:59:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9CE841FF21 for ; Wed, 8 Feb 2017 07:59:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 917602835B; Wed, 8 Feb 2017 07:59:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 125A81FF21 for ; Wed, 8 Feb 2017 07:59:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932382AbdBHH7A (ORCPT ); Wed, 8 Feb 2017 02:59:00 -0500 Received: from mx1.redhat.com ([209.132.183.28]:55630 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932294AbdBHH67 (ORCPT ); Wed, 8 Feb 2017 02:58:59 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1651463144 for ; Wed, 8 Feb 2017 07:59:00 +0000 (UTC) Received: from pxdev.xzpeter.org.com (ovpn-8-35.pek2.redhat.com [10.72.8.35]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v187wrce009888; Wed, 8 Feb 2017 02:58:57 -0500 From: Peter Xu To: kvm@vger.kernel.org Cc: Paolo Bonzini , peterx@redhat.com, =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= Subject: [RFC PATCH 1/2] kvm: x86: add new gsi route type EVENTFD Date: Wed, 8 Feb 2017 15:58:45 +0800 Message-Id: <1486540726-15954-2-git-send-email-peterx@redhat.com> In-Reply-To: <1486540726-15954-1-git-send-email-peterx@redhat.com> References: <1486540726-15954-1-git-send-email-peterx@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Wed, 08 Feb 2017 07:59:00 +0000 (UTC) Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP A new GSI routing type KVM_GSI_ROUTING_EVENTFD is introduced. This type of irq routing does not trigger any guest event directly, instead, it triggers a pre-configured eventfd handle, so that a gsi interrupt can be forwarded to somewhere else, like, a userspace program (QEMU). This idea was invoked when I was trying to solve an emulated VT-d issue when guest kernel setup incorrect IRTE. When that happens, instead of raising error immediately, what we should do is to keep the error, and inject this error to vIOMMU when the specific interrupt is triggered. However this is very hard to be achieved since for now vIOMMU is working in userspace, while currently there is no simple way that kernel irq can talk to a userspace program. With this patch, we can easily provide such a way that when guest fault irq is triggered, kernel can notify user program by signaling the corresponding eventfd handle (which should have been configured before hand by the userspace vIOMMU). Then userspace vIOMMU can process the realtime irq error and report to guest properly. Signed-off-by: Peter Xu --- arch/x86/kvm/irq_comm.c | 33 +++++++++++++++++++++++++++++++++ include/linux/kvm_host.h | 7 +++++++ include/uapi/linux/kvm.h | 6 ++++++ virt/kvm/irqchip.c | 6 ++++++ 4 files changed, 52 insertions(+) diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c index 6c01916..d37de0b 100644 --- a/arch/x86/kvm/irq_comm.c +++ b/arch/x86/kvm/irq_comm.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -179,6 +180,16 @@ static int kvm_hv_set_sint(struct kvm_kernel_irq_routing_entry *e, return kvm_hv_synic_set_irq(kvm, e->hv_sint.vcpu, e->hv_sint.sint); } +static int kvm_set_gsi_eventfd(struct kvm_kernel_irq_routing_entry *e, + struct kvm *kvm, int irq_source_id, int level, + bool line_status) +{ + if (!level || eventfd_signal(e->eventfd.ctx, 1) != 1) + return -1; + + return 1; +} + int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm, int irq_source_id, int level, bool line_status) @@ -292,6 +303,7 @@ int kvm_set_routing_entry(struct kvm *kvm, int r = -EINVAL; int delta; unsigned max_pin; + struct eventfd_ctx *eventfd; switch (ue->type) { case KVM_IRQ_ROUTING_IRQCHIP: @@ -332,6 +344,15 @@ int kvm_set_routing_entry(struct kvm *kvm, e->hv_sint.vcpu = ue->u.hv_sint.vcpu; e->hv_sint.sint = ue->u.hv_sint.sint; break; + case KVM_IRQ_ROUTING_EVENTFD: + eventfd = eventfd_ctx_fdget(ue->u.eventfd.fd); + if (IS_ERR(eventfd)) { + r = PTR_ERR(eventfd); + goto out; + } + e->eventfd.ctx = eventfd; + e->set = kvm_set_gsi_eventfd; + break; default: goto out; } @@ -448,3 +469,15 @@ void kvm_arch_irq_routing_update(struct kvm *kvm) { kvm_hv_irq_routing_update(kvm); } + +void free_irq_routing_entry(struct kvm_kernel_irq_routing_entry *e) +{ + switch (e->type) { + case KVM_IRQ_ROUTING_EVENTFD: + if (e->eventfd.ctx) + eventfd_ctx_put(e->eventfd.ctx); + break; + default: + break; + } +} diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 1c5190d..0eee182 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -306,6 +306,10 @@ struct kvm_hv_sint { u32 sint; }; +struct kvm_gsi_eventfd { + struct eventfd_ctx *ctx; +}; + struct kvm_kernel_irq_routing_entry { u32 gsi; u32 type; @@ -326,6 +330,7 @@ struct kvm_kernel_irq_routing_entry { } msi; struct kvm_s390_adapter_int adapter; struct kvm_hv_sint hv_sint; + struct kvm_gsi_eventfd eventfd; }; struct hlist_node link; }; @@ -340,6 +345,8 @@ struct kvm_irq_routing_table { */ struct hlist_head map[0]; }; + +void free_irq_routing_entry(struct kvm_kernel_irq_routing_entry *e); #endif #ifndef KVM_PRIVATE_MEM_SLOTS diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index cac48ed..efe530c 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -902,11 +902,16 @@ struct kvm_irq_routing_hv_sint { __u32 sint; }; +struct kvm_irq_routing_eventfd { + __u32 fd; +}; + /* gsi routing entry types */ #define KVM_IRQ_ROUTING_IRQCHIP 1 #define KVM_IRQ_ROUTING_MSI 2 #define KVM_IRQ_ROUTING_S390_ADAPTER 3 #define KVM_IRQ_ROUTING_HV_SINT 4 +#define KVM_IRQ_ROUTING_EVENTFD 5 struct kvm_irq_routing_entry { __u32 gsi; @@ -918,6 +923,7 @@ struct kvm_irq_routing_entry { struct kvm_irq_routing_msi msi; struct kvm_irq_routing_s390_adapter adapter; struct kvm_irq_routing_hv_sint hv_sint; + struct kvm_irq_routing_eventfd eventfd; __u32 pad[8]; } u; }; diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c index 3bcc999..35612ce 100644 --- a/virt/kvm/irqchip.c +++ b/virt/kvm/irqchip.c @@ -109,6 +109,11 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, return ret; } +void __attribute__((weak)) +free_irq_routing_entry(struct kvm_kernel_irq_routing_entry *e) +{ +} + static void free_irq_routing_table(struct kvm_irq_routing_table *rt) { int i; @@ -121,6 +126,7 @@ static void free_irq_routing_table(struct kvm_irq_routing_table *rt) struct hlist_node *n; hlist_for_each_entry_safe(e, n, &rt->map[i], link) { + free_irq_routing_entry(e); hlist_del(&e->link); kfree(e); }