From patchwork Fri Jul 24 09:03:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: PranavkumarSawargaonkar X-Patchwork-Id: 51407 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f72.google.com (mail-la0-f72.google.com [209.85.215.72]) by patches.linaro.org (Postfix) with ESMTPS id F008720323 for ; Fri, 24 Jul 2015 09:03:55 +0000 (UTC) Received: by lagw2 with SMTP id w2sf5359072lag.3 for ; Fri, 24 Jul 2015 02:03:55 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=pQtvQIwscMzMoM2CkErMVEwcxX/BrX3nmX5FdHBNikk=; b=icKljB7I3E7f3t25tg2Dzwc8AK5NHQTEYaj14oxw5WrdIVu7scXCV3n37vPMNZyb/e 6y3cRx8dyqZmXFjyuVlCrpyir6Ov4AOTjhfJouyqxRAx8WtALampaje4JTHnh9R6pwKZ a45Yg4Wtsx5Rn8cD28WhZD0QhOrK3yc55eO4aBOBb9Etgvch3J+ZiMKa3sIGZwQ58zPD jWq1G4JLs2r+hbnPVI/x8sD43j65MECDg1vB6Ko9eMtW9rzhXN4hz1qJAWPkKVpkIXLI VPYdajyBIWHBGyzNYvN5iU3Yo8jrth822G3PMRjQomt0VNporAJtu+B8i4jDWFTEA58z +1jQ== X-Gm-Message-State: ALoCoQkf5BA27qhuR97GSrzS8TjUZAe9HRR87QAk6DAqRxah2uMn1vttOC7twFaIPmA9sVibHrud X-Received: by 10.112.148.101 with SMTP id tr5mr5842360lbb.13.1437728634967; Fri, 24 Jul 2015 02:03:54 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.10.74 with SMTP id g10ls354389lab.92.gmail; Fri, 24 Jul 2015 02:03:54 -0700 (PDT) X-Received: by 10.112.138.199 with SMTP id qs7mr12520599lbb.21.1437728634792; Fri, 24 Jul 2015 02:03:54 -0700 (PDT) Received: from mail-la0-f51.google.com (mail-la0-f51.google.com. [209.85.215.51]) by mx.google.com with ESMTPS id bm5si6965152lbc.30.2015.07.24.02.03.54 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 24 Jul 2015 02:03:54 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.51 as permitted sender) client-ip=209.85.215.51; Received: by laah7 with SMTP id h7so10357821laa.0 for ; Fri, 24 Jul 2015 02:03:54 -0700 (PDT) X-Received: by 10.152.207.76 with SMTP id lu12mr12523587lac.29.1437728634645; Fri, 24 Jul 2015 02:03:54 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.7.198 with SMTP id l6csp1030455lba; Fri, 24 Jul 2015 02:03:53 -0700 (PDT) X-Received: by 10.50.13.10 with SMTP id d10mr4183101igc.20.1437728633002; Fri, 24 Jul 2015 02:03:53 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 78si7457997ioz.62.2015.07.24.02.03.52; Fri, 24 Jul 2015 02:03:52 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754295AbbGXJDs (ORCPT + 26 others); Fri, 24 Jul 2015 05:03:48 -0400 Received: from mail-pd0-f171.google.com ([209.85.192.171]:34513 "EHLO mail-pd0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754246AbbGXJDi (ORCPT ); Fri, 24 Jul 2015 05:03:38 -0400 Received: by pdbbh15 with SMTP id bh15so10814459pdb.1 for ; Fri, 24 Jul 2015 02:03:37 -0700 (PDT) X-Received: by 10.70.136.129 with SMTP id qa1mr28477321pdb.81.1437728617615; Fri, 24 Jul 2015 02:03:37 -0700 (PDT) Received: from pnqlab006.amcc.com ([182.73.239.130]) by smtp.gmail.com with ESMTPSA id wp5sm13346655pab.22.2015.07.24.02.03.32 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 24 Jul 2015 02:03:36 -0700 (PDT) From: Pranavkumar Sawargaonkar To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, alex.williamson@redhat.com, christoffer.dall@linaro.org, marc.zyngier@arm.com, will.deacon@arm.com, bhelgaas@google.com, arnd@arndb.de, rob.herring@linaro.org, eric.auger@linaro.org, patches@apm.com, Pranavkumar Sawargaonkar , Ankit Jindal Subject: [RFC 2/2] drivers: vfio: pci: Add virtual MSI doorbell support. Date: Fri, 24 Jul 2015 14:33:10 +0530 Message-Id: <1437728590-23126-3-git-send-email-pranavkumar@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1437728590-23126-1-git-send-email-pranavkumar@linaro.org> References: <1437728590-23126-1-git-send-email-pranavkumar@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: pranavkumar@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.51 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , In ARM/ARM64 MSI transactions goes through iommu/smmu. This means there has to be an iommu mapping created for MSI addresses. This patch adds a new ioctl "VFIO_DEVICE_PCI_MSI_VIRT_DOORBELL". Userspace can call this ioctl to do following things: 1. Create a virtual doorbell mapping between MSI IOVA term as a "virtual msi doorbell" (known by the userspace) and MSI PA (known by the kernel). 2. Set MSI/MSI-X vetcor with a virtual doorbell address instead of PA. Signed-off-by: Ankit Jindal Signed-off-by: Pranavkumar Sawargaonkar Cc: Alex Williamson Cc: Marc Zyngier Cc: Will Deacon Cc: Christoffer Dall --- drivers/vfio/pci/vfio_pci.c | 32 ++++++++++++++++++ drivers/vfio/pci/vfio_pci_intrs.c | 64 +++++++++++++++++++++++++++++++++++ drivers/vfio/pci/vfio_pci_private.h | 3 ++ include/uapi/linux/vfio.h | 19 +++++++++++ 4 files changed, 118 insertions(+) diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 964ad57..9c92707 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -784,6 +784,38 @@ hot_reset_release: kfree(groups); return ret; + } else if (cmd == VFIO_DEVICE_PCI_MSI_VIRT_DOORBELL) { + struct vfio_pci_msi_virt_doorbell hdr; + u64 *data = NULL; + int ret = 0; + size_t size = sizeof(uint64_t); + + minsz = offsetofend(struct vfio_pci_msi_virt_doorbell, count); + + if (copy_from_user(&hdr, (void __user *)arg, minsz)) + return -EFAULT; + + if (hdr.argsz < minsz) + return -EINVAL; + + if (hdr.argsz - minsz < hdr.count * size) + return -EINVAL; + + data = memdup_user((void __user *)(arg + minsz), + hdr.count * size); + if (IS_ERR(data)) + return PTR_ERR(data); + + mutex_lock(&vdev->igate); + + ret = vfio_pci_msi_virt_doorbell(vdev, hdr.flags, + hdr.start, hdr.count, data); + + mutex_unlock(&vdev->igate); + + kfree(data); + + return ret; } return -ENOTTY; diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c index 1f577b4..22a25b8 100644 --- a/drivers/vfio/pci/vfio_pci_intrs.c +++ b/drivers/vfio/pci/vfio_pci_intrs.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -352,8 +353,10 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev, pci_write_msi_msg(irq, &msg); } + ret = request_irq(irq, vfio_msihandler, 0, vdev->ctx[vector].name, trigger); + if (ret) { kfree(vdev->ctx[vector].name); eventfd_ctx_put(trigger); @@ -673,3 +676,64 @@ int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags, return func(vdev, index, start, count, flags, data); } + +int vfio_pci_msi_virt_doorbell(struct vfio_pci_device *vdev, uint32_t flags, + unsigned start, unsigned count, + void *data) +{ + struct pci_dev *pdev = vdev->pdev; + int irq; + bool msix = flags & VFIO_PCI_IS_MSIX; + struct msi_msg msg; + struct irq_data *d; + unsigned long msi_paddr, msi_iova; + struct vfio_device *device; + int ret; + int i, j; + + for (i = 0, j = start; i < count && !ret; i++, j++) { + + device = vfio_device_get_from_dev(&pdev->dev); + irq = msix ? vdev->msix[j].vector : + pdev->irq + j; + + if (flags & VFIO_PCI_MSI_SET_DOORBELL) { + /* Get the MSI message to extract Physical Address */ + d = irq_get_irq_data(irq); + irq_chip_compose_msi_msg(d, &msg); + msi_paddr = (msg.address_hi << 31) | msg.address_lo; + } else { + /* + * Restore the cached value of the message prior + * to the virtual doorbell setting. + */ + get_cached_msi_msg(irq, &msg); + } + + /* MSI IPA/GPA i.e. virtual doorbell address */ + msi_iova = (unsigned long) ((unsigned long *) data)[i]; + + if (flags & VFIO_PCI_MSI_SET_DOORBELL) { + ret = vfio_device_iommu_map(device, + (msi_iova & PAGE_MASK), + (msi_paddr & PAGE_MASK), + PAGE_SIZE, + IOMMU_READ | IOMMU_WRITE | + IOMMU_CACHE); + + /* Fill MSI GPA/IPA as a new MSI doorbell address. */ + msg.address_hi = msi_iova << 31; + msg.address_lo = msi_iova & 0xFFFFFFFF; + } else if (flags & VFIO_PCI_MSI_CLEAR_DOORBELL) { + vfio_device_iommu_unmap(device, (msi_iova & PAGE_MASK), + PAGE_SIZE); + } else { + return -EINVAL; + } + + pci_write_msi_msg(irq, &msg); + } + + return 0; +} + diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h index ae0e1b4..ec76e45 100644 --- a/drivers/vfio/pci/vfio_pci_private.h +++ b/drivers/vfio/pci/vfio_pci_private.h @@ -73,6 +73,9 @@ extern void vfio_pci_intx_unmask(struct vfio_pci_device *vdev); extern int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags, unsigned index, unsigned start, unsigned count, void *data); +extern int vfio_pci_msi_virt_doorbell(struct vfio_pci_device *vdev, + uint32_t flags, unsigned start, + unsigned count, void *data); extern ssize_t vfio_pci_config_rw(struct vfio_pci_device *vdev, char __user *buf, size_t count, diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h index 9fd7b5d..12384f5 100644 --- a/include/uapi/linux/vfio.h +++ b/include/uapi/linux/vfio.h @@ -379,6 +379,25 @@ struct vfio_pci_hot_reset { #define VFIO_DEVICE_PCI_HOT_RESET _IO(VFIO_TYPE, VFIO_BASE + 13) +/** + * VFIO_DEVICE_PCI_MSI_VIRT_DOORBELL - _IOW(VFIO_TYPE, VFIO_BASE + 14, + * struct vfio_pci_msi_virt_doorbell) + * + * Return: 0 on success, -errno on failure. + */ +struct vfio_pci_msi_virt_doorbell { + __u32 argsz; + __u32 flags; +#define VFIO_PCI_MSI_CLEAR_DOORBELL (1 << 0) /* Remove virtual doorbell */ +#define VFIO_PCI_MSI_SET_DOORBELL (1 << 1) /* Set virtual doorbell */ +#define VFIO_PCI_IS_MSIX (1 << 2) /* Is MSI-X ? */ + __u32 start; + __u32 count; + __u64 data[]; +}; + +#define VFIO_DEVICE_PCI_MSI_VIRT_DOORBELL _IO(VFIO_TYPE, VFIO_BASE + 14) + /* -------- API for Type1 VFIO IOMMU -------- */ /**