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: 6858451 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id CC373C05AC for ; Fri, 24 Jul 2015 09:03:53 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B549620608 for ; Fri, 24 Jul 2015 09:03:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8DD5D2060C for ; Fri, 24 Jul 2015 09:03:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754263AbbGXJDl (ORCPT ); Fri, 24 Jul 2015 05:03:41 -0400 Received: from mail-pd0-f179.google.com ([209.85.192.179]:36202 "EHLO mail-pd0-f179.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754177AbbGXJDi (ORCPT ); Fri, 24 Jul 2015 05:03:38 -0400 Received: by pdjr16 with SMTP id r16so10907174pdj.3 for ; Fri, 24 Jul 2015 02:03:37 -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:in-reply-to :references; bh=J2ysj2wzyFd8jLaJ+x0WaR0v7SLk5C3ZrnH5UdcuM7o=; b=lJ7IaE1C5B/fKc0ppx28IFq4O8jc/pXgAcEFthbNxpc9qhQ+mbw84mMi40mJ1W2qRK svsGjdZsJeubH7pVbqiKrR9YADdM+C8ZSZ1Rd7sMkCvOV4KV3PKupVnHEkjarwpavEEf loumwTvK3Oo8TP0DyNqBNze2pZF39nzjqsHY8tq98w1PVscB5w8F697e1OWtv8k5Otja cBFpBVoDEdgSV0iophURJoClMskAljlXUNfAIOMb4t3HLZJSK6mm04EYfXY8jUfIIxBO TKhXk2oyUWg2GDtt7GaGXdN3eKIeKFTK6srq2dVpk7IQrrl1SCJQsR4oL0hoZstdpfI8 qUEg== X-Gm-Message-State: ALoCoQlJN9vy2cCwo3hNcHjexPuZz820A7ZPoVE004Pmt1vUanLvO8zwSs1VUwnpgqc5XKpT/LUi 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: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-8.1 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham 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 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 -------- */ /**