From patchwork Tue Sep 17 09:18:40 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Mackerras X-Patchwork-Id: 275411 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 208DF2C00DC for ; Tue, 17 Sep 2013 19:21:03 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752265Ab3IQJVB (ORCPT ); Tue, 17 Sep 2013 05:21:01 -0400 Received: from ozlabs.org ([203.10.76.45]:49045 "EHLO ozlabs.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751859Ab3IQJVA (ORCPT ); Tue, 17 Sep 2013 05:21:00 -0400 Received: by ozlabs.org (Postfix, from userid 1003) id 05DD32C00DA; Tue, 17 Sep 2013 19:20:59 +1000 (EST) Date: Tue, 17 Sep 2013 19:18:40 +1000 From: Paul Mackerras To: kvm@vger.kernel.org Cc: kvm-ppc@vger.kernel.org, Alexander Graf Subject: [PATCH 1/2] KVM: Implement default IRQ routing Message-ID: <20130917091840.GA12722@iris.ozlabs.ibm.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org This implements a simple way to express the case of IRQ routing where there is one in-kernel PIC and the system interrupts (GSIs) are routed 1-1 to the corresponding pins of the PIC. This is expressed by having kvm->irq_routing == NULL with a skeleton irq routing entry in the new kvm->default_irq_route field. This provides a convenient way to provide backwards compatibility when adding IRQ routing capability to an existing in-kernel PIC, such as the XICS emulation on powerpc. Signed-off-by: Paul Mackerras --- include/linux/kvm_host.h | 1 + virt/kvm/eventfd.c | 4 ++++ virt/kvm/irqchip.c | 23 ++++++++++++++++++++--- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 749bdb1..609f587 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -394,6 +394,7 @@ struct kvm { * if configured, irqfds.lock. */ struct kvm_irq_routing_table __rcu *irq_routing; + struct kvm_kernel_irq_routing_entry default_irq_route; struct hlist_head mask_notifier_list; struct hlist_head irq_ack_notifier_list; #endif diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c index abe4d60..7010cb3 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c @@ -272,6 +272,10 @@ static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd, { struct kvm_kernel_irq_routing_entry *e; + if (!irq_rt) { + rcu_assign_pointer(irqfd->irq_entry, NULL); + return; + } if (irqfd->gsi >= irq_rt->nr_rt_entries) { rcu_assign_pointer(irqfd->irq_entry, NULL); return; diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c index 20dc9e4..ebc2941 100644 --- a/virt/kvm/irqchip.c +++ b/virt/kvm/irqchip.c @@ -30,13 +30,24 @@ #include #include "irq.h" +static inline int pin_to_gsi(struct kvm *kvm, unsigned irqchip, unsigned pin) +{ + struct kvm_irq_routing_table *rt; + int gsi = pin; + + rt = rcu_dereference(kvm->irq_routing); + if (rt) + gsi = rt->chip[irqchip][pin]; + return gsi; +} + bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin) { struct kvm_irq_ack_notifier *kian; int gsi; rcu_read_lock(); - gsi = rcu_dereference(kvm->irq_routing)->chip[irqchip][pin]; + gsi = pin_to_gsi(kvm, irqchip, pin); if (gsi != -1) hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, link) @@ -59,7 +70,7 @@ void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) trace_kvm_ack_irq(irqchip, pin); rcu_read_lock(); - gsi = rcu_dereference(kvm->irq_routing)->chip[irqchip][pin]; + gsi = pin_to_gsi(kvm, irqchip, pin); if (gsi != -1) hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, link) @@ -126,7 +137,13 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, */ rcu_read_lock(); irq_rt = rcu_dereference(kvm->irq_routing); - if (irq < irq_rt->nr_rt_entries) + if (!irq_rt) { + if (kvm->default_irq_route.set) { + irq_set[i] = kvm->default_irq_route; + irq_set[i].gsi = irq; + irq_set[i++].irqchip.pin = irq; + } + } else if (irq < irq_rt->nr_rt_entries) hlist_for_each_entry(e, &irq_rt->map[irq], link) irq_set[i++] = *e; rcu_read_unlock();