From patchwork Mon Aug 4 12:08:22 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Auger X-Patchwork-Id: 4669941 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 47E34C0338 for ; Mon, 4 Aug 2014 12:12:23 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D6AA920127 for ; Mon, 4 Aug 2014 12:12:21 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3D798200E6 for ; Mon, 4 Aug 2014 12:12:20 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XEH5G-0000As-3p; Mon, 04 Aug 2014 12:09:46 +0000 Received: from mail-wi0-f172.google.com ([209.85.212.172]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1XEH5D-0000AO-F2 for linux-arm-kernel@lists.infradead.org; Mon, 04 Aug 2014 12:09:44 +0000 Received: by mail-wi0-f172.google.com with SMTP id n3so4879243wiv.11 for ; Mon, 04 Aug 2014 05:09:17 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=Wp0WYou9qdvI67VMZAaOT+fWWI0t7sKzADGKoIwWc00=; b=EU+j7gaF458tsO4SodOYVXYAlgg76ShOXEq0EhwnUHcRfUo8TxKPA8iAQkJ6Ke8uYM OvPSlEJvLhc5kZI/WphORP0PUrU4vqz8JEZj1kRHrKMwLHs+5jCmDpqXUnNl4M8UPByD x1rwyhYtnWhDVH4RYX18o477N+apbiODRP4EOxpt1fEi3IS8KUT4avUEYU1/hWsExcc4 9i7zh7PA+piq0hQOZHh5sbtCW9wMG9axS/mj30Zk9d3SqSVPbXiiIIbL58dWMn/vIwyW YH95zn9OMLCjf9skR+CRKlHOIAoO92NCWT3qkNCJPgFl8SE7SiBWENRCmV6FS1tossfQ XEjQ== X-Gm-Message-State: ALoCoQm8PM574EqYng6Q/1nevhkHfDP2YoBtS5CpIQdA0ZIaxLK4Y7hPlEMKg1AQtTmtPH16BppR X-Received: by 10.180.187.6 with SMTP id fo6mr28968524wic.58.1407154156533; Mon, 04 Aug 2014 05:09:16 -0700 (PDT) Received: from gnx2579.gnb.st.com (LCaen-156-56-7-90.w80-11.abo.wanadoo.fr. [80.11.198.90]) by mx.google.com with ESMTPSA id cx5sm43136046wjb.8.2014.08.04.05.09.14 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 04 Aug 2014 05:09:15 -0700 (PDT) From: Eric Auger To: eric.auger@st.com, eric.auger@linaro.org, christoffer.dall@linaro.org, marc.zyngier@arm.com, linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org Subject: [RFC PATCH] ARM: KVM: add irqfd support Date: Mon, 4 Aug 2014 14:08:22 +0200 Message-Id: <1407154102-26459-1-git-send-email-eric.auger@linaro.org> X-Mailer: git-send-email 1.9.1 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140804_050943_802899_7EF6D65A X-CRM114-Status: GOOD ( 24.33 ) X-Spam-Score: -0.7 (/) Cc: patches@linaro.org, will.deacon@arm.com, a.rigo@virtualopensystems.com, linux-kernel@vger.kernel.org, paulus@samba.org, a.motakis@virtualopensystems.com X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch enables irqfd on ARM. irqfd framework enables to inject a virtual IRQ into a guest upon an eventfd trigger. User-side uses KVM_IRQFD VM ioctl to provide KVM with a kvm_irqfd struct that associates a VM, an eventfd, an IRQ number (aka. the gsi). When an actor signals the eventfd (typically a VFIO platform driver), the kvm irqfd subsystem injects the provided virtual IRQ into the guest. The gsi must correspond to a shared peripheral interrupt (SPI), ie the GIC interrupt ID is gsi+32. CONFIG_HAVE_KVM_EVENTFD and CONFIG_HAVE_KVM_IRQFD are turned on. No IRQ routing table is used thanks to Paul Mackerras' patch serie: "IRQFD without IRQ routing, enabled for XICS" (https://www.mail-archive.com/kvm@vger.kernel.org/msg104478.html) Signed-off-by: Eric Auger --- This patch would deprecate the previous patch featuring GSI routing (https://patches.linaro.org/32261/) irqchip.c and irq_comm.c are not used at all. This RFC applies on top of Christoffer Dall's serie arm/arm64: KVM: Various VGIC cleanups and improvements https://lists.cs.columbia.edu/pipermail/kvmarm/2014-June/009979.html All pieces can be found on git://git.linaro.org/people/eric.auger/linux.git branch irqfd_integ_v4 This work was tested with Calxeda Midway xgmac main interrupt with qemu-system-arm and QEMU VFIO platform device. --- Documentation/virtual/kvm/api.txt | 5 +++- arch/arm/include/uapi/asm/kvm.h | 3 +++ arch/arm/kvm/Kconfig | 3 ++- arch/arm/kvm/Makefile | 2 +- arch/arm/kvm/irq.h | 25 ++++++++++++++++++ virt/kvm/arm/vgic.c | 54 ++++++++++++++++++++++++++++++++++++--- 6 files changed, 85 insertions(+), 7 deletions(-) create mode 100644 arch/arm/kvm/irq.h diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 0fe3649..04310d9 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -2132,7 +2132,7 @@ into the hash PTE second double word). 4.75 KVM_IRQFD Capability: KVM_CAP_IRQFD -Architectures: x86 s390 +Architectures: x86 s390 arm Type: vm ioctl Parameters: struct kvm_irqfd (in) Returns: 0 on success, -1 on error @@ -2158,6 +2158,9 @@ Note that closing the resamplefd is not sufficient to disable the irqfd. The KVM_IRQFD_FLAG_RESAMPLE is only necessary on assignment and need not be specified with KVM_IRQFD_FLAG_DEASSIGN. +On ARM/arm64 the injected must be a shared peripheral interrupt (SPI). +This means the programmed GIC interrupt ID is gsi+32. + 4.76 KVM_PPC_ALLOCATE_HTAB Capability: KVM_CAP_PPC_ALLOC_HTAB diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index e6ebdd3..3034c66 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -194,6 +194,9 @@ struct kvm_arch_memory_slot { /* Highest supported SPI, from VGIC_NR_IRQS */ #define KVM_ARM_IRQ_GIC_MAX 127 +/* One single KVM irqchip, ie. the VGIC */ +#define KVM_NR_IRQCHIPS 1 + /* PSCI interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n)) diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig index 4be5bb1..7800261 100644 --- a/arch/arm/kvm/Kconfig +++ b/arch/arm/kvm/Kconfig @@ -24,6 +24,7 @@ config KVM select KVM_MMIO select KVM_ARM_HOST depends on ARM_VIRT_EXT && ARM_LPAE && !CPU_BIG_ENDIAN + select HAVE_KVM_EVENTFD ---help--- Support hosting virtualized guest machines. You will also need to select one or more of the processor modules below. @@ -55,7 +56,7 @@ config KVM_ARM_MAX_VCPUS config KVM_ARM_VGIC bool "KVM support for Virtual GIC" depends on KVM_ARM_HOST && OF - select HAVE_KVM_IRQCHIP + select HAVE_KVM_IRQFD default y ---help--- Adds support for a hardware assisted, in-kernel GIC emulation. diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile index 789bca9..2fa2f82 100644 --- a/arch/arm/kvm/Makefile +++ b/arch/arm/kvm/Makefile @@ -15,7 +15,7 @@ AFLAGS_init.o := -Wa,-march=armv7-a$(plus_virt) AFLAGS_interrupts.o := -Wa,-march=armv7-a$(plus_virt) KVM := ../../../virt/kvm -kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o +kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o obj-y += kvm-arm.o init.o interrupts.o obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o diff --git a/arch/arm/kvm/irq.h b/arch/arm/kvm/irq.h new file mode 100644 index 0000000..1275d91 --- /dev/null +++ b/arch/arm/kvm/irq.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2014 Linaro Ltd. + * Authors: Eric Auger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __IRQ_H +#define __IRQ_H + +#include +/* + * Placeholder for irqchip and irq/msi routing declarations + * included in irqchip.c + */ + +#endif diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index 123030b..907e735 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c @@ -1259,7 +1259,10 @@ epilog: static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) { struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; + struct vgic_dist *dist = &vcpu->kvm->arch.vgic; bool level_pending = false; + struct kvm *kvm = vcpu->kvm; + int is_assigned_irq; kvm_debug("MISR = %08x\n", vgic_cpu->vgic_misr); @@ -1273,6 +1276,7 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) for_each_set_bit(lr, (unsigned long *)vgic_cpu->vgic_eisr, vgic_cpu->nr_lr) { irq = vgic_cpu->vgic_lr[lr] & GICH_LR_VIRTUALID; + spin_lock(&dist->lock); BUG_ON(vgic_irq_is_edge(vcpu, irq)); vgic_irq_clear_queued(vcpu, irq); @@ -1285,6 +1289,17 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) * interrupt. */ vgic_dist_irq_clear_soft_pend(vcpu, irq); + spin_unlock(&dist->lock); + + is_assigned_irq = kvm_irq_has_notifier(kvm, 0, + irq - VGIC_NR_PRIVATE_IRQS); + + if (is_assigned_irq) { + kvm_debug("EOI irqchip routed vIRQ %d\n", irq); + kvm_notify_acked_irq(kvm, 0, + irq - VGIC_NR_PRIVATE_IRQS); + } + spin_lock(&dist->lock); /* Any additional pending interrupt? */ if (vgic_dist_irq_get_level(vcpu, irq)) { @@ -1305,6 +1320,7 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) */ set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr); vgic_cpu->vgic_lr[lr] &= ~GICH_LR_ACTIVE_BIT; + spin_unlock(&dist->lock); } } @@ -1344,8 +1360,10 @@ static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu) /* Check if we still have something up our sleeve... */ pending = find_first_zero_bit((unsigned long *)vgic_cpu->vgic_elrsr, vgic_cpu->nr_lr); + spin_lock(&dist->lock); if (level_pending || pending < vgic_cpu->nr_lr) set_bit(vcpu->vcpu_id, &dist->irq_pending_on_cpu); + spin_unlock(&dist->lock); } void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu) @@ -1362,14 +1380,10 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu) void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu) { - struct vgic_dist *dist = &vcpu->kvm->arch.vgic; - if (!irqchip_in_kernel(vcpu->kvm)) return; - spin_lock(&dist->lock); __kvm_vgic_sync_hwstate(vcpu); - spin_unlock(&dist->lock); } int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu) @@ -2146,3 +2160,35 @@ struct kvm_device_ops kvm_arm_vgic_v2_ops = { .get_attr = vgic_get_attr, .has_attr = vgic_has_attr, }; + +int kvm_irq_map_gsi(struct kvm *kvm, + struct kvm_kernel_irq_routing_entry *entries, int gsi) +{ + return gsi; +} + +int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin) +{ + return pin; +} + +int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, + bool line_status) +{ + int r = -EINVAL; + unsigned int spi = irq + VGIC_NR_PRIVATE_IRQS; + + if (spi > KVM_ARM_IRQ_GIC_MAX) + return r; + + kvm_debug("Inject irqchip routed vIRQ %d\n", irq); + r = kvm_vgic_inject_irq(kvm, 0, spi, level); + return r; +} + +/* MSI not implemented yet */ +int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, + struct kvm *kvm, int irq_source_id, int level, bool line_status) +{ + return 0; +}