From patchwork Tue Aug 16 08:14:16 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jike Song X-Patchwork-Id: 9282877 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 F044260839 for ; Tue, 16 Aug 2016 08:17:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DDAA528DE5 for ; Tue, 16 Aug 2016 08:17:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D193D28E03; Tue, 16 Aug 2016 08:17:20 +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=unavailable version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7BB7328DE5 for ; Tue, 16 Aug 2016 08:17:19 +0000 (UTC) Received: from localhost ([::1]:40680 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bZZYk-0002Tv-J4 for patchwork-qemu-devel@patchwork.kernel.org; Tue, 16 Aug 2016 04:17:18 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44285) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bZZY9-0002Qb-J6 for qemu-devel@nongnu.org; Tue, 16 Aug 2016 04:16:44 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bZZY4-0005Hl-0G for qemu-devel@nongnu.org; Tue, 16 Aug 2016 04:16:40 -0400 Received: from mga02.intel.com ([134.134.136.20]:26029) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bZZY3-0005HC-LV for qemu-devel@nongnu.org; Tue, 16 Aug 2016 04:16:35 -0400 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga101.jf.intel.com with ESMTP; 16 Aug 2016 01:16:33 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="5.28,529,1464678000"; d="scan'208"; a="1026170566" Received: from kvmgt1.bj.intel.com ([10.238.154.158]) by fmsmga001.fm.intel.com with ESMTP; 16 Aug 2016 01:16:25 -0700 From: Jike Song To: alex.williamson@redhat.com, kwankhede@nvidia.com, cjia@nvidia.com Date: Tue, 16 Aug 2016 16:14:16 +0800 Message-Id: <1471335257-6226-5-git-send-email-jike.song@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1471335257-6226-1-git-send-email-jike.song@intel.com> References: <1471335257-6226-1-git-send-email-jike.song@intel.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.20 Subject: [Qemu-devel] [RFC v6-based v1 4/5] vfio_mpci: remove PCI-specific logic X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kevin.tian@intel.com, guangrong.xiao@linux.intel.com, kvm@vger.kernel.org, qemu-devel@nongnu.org, zhenyuw@linux.intel.com, jike.song@intel.com, kraxel@redhat.com, pbonzini@redhat.com, bjsdjshi@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP As a generic mdev driver, 'vfio_mpci' should be BUS-agnostic and as thin as possible, passing through all device operations directly to underlying physical driver(a.k.a the device-model). Signed-off-by: Jike Song --- drivers/vfio/mdev/mdev_core.c | 107 -------- drivers/vfio/mdev/vfio_mpci.c | 469 ++++-------------------------------- drivers/vfio/pci/vfio_pci_private.h | 6 + include/linux/mdev.h | 62 +---- include/linux/vfio.h | 7 - 5 files changed, 69 insertions(+), 582 deletions(-) diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c index 934dac9..f824856 100644 --- a/drivers/vfio/mdev/mdev_core.c +++ b/drivers/vfio/mdev/mdev_core.c @@ -272,113 +272,6 @@ int mdev_device_destroy(struct device *dev, uuid_le uuid, uint32_t instance) return __mdev_device_destroy(&mdev->dev, (void *)false); } -int mdev_device_invalidate_mapping(struct mdev_device *mdev, - unsigned long addr, unsigned long size) -{ - int ret = -EINVAL; - struct mdev_phys_mapping *phys_mappings; - struct addr_desc *addr_desc; - - if (!mdev || !mdev->phys_mappings.mapping) - return ret; - - phys_mappings = &mdev->phys_mappings; - - mutex_lock(&phys_mappings->addr_desc_list_lock); - - list_for_each_entry(addr_desc, &phys_mappings->addr_desc_list, next) { - - if ((addr > addr_desc->start) && - (addr + size < addr_desc->start + addr_desc->size)) { - unmap_mapping_range(phys_mappings->mapping, - addr, size, 0); - ret = 0; - goto unlock_exit; - } - } - -unlock_exit: - mutex_unlock(&phys_mappings->addr_desc_list_lock); - return ret; -} -EXPORT_SYMBOL(mdev_device_invalidate_mapping); - -/* Sanity check for the physical mapping list for mediated device */ - -int mdev_add_phys_mapping(struct mdev_device *mdev, - struct address_space *mapping, - unsigned long addr, unsigned long size) -{ - struct mdev_phys_mapping *phys_mappings; - struct addr_desc *addr_desc, *new_addr_desc; - int ret = 0; - - if (!mdev) - return -EINVAL; - - phys_mappings = &mdev->phys_mappings; - if (phys_mappings->mapping && (mapping != phys_mappings->mapping)) - return -EINVAL; - - if (!phys_mappings->mapping) { - phys_mappings->mapping = mapping; - mutex_init(&phys_mappings->addr_desc_list_lock); - INIT_LIST_HEAD(&phys_mappings->addr_desc_list); - } - - mutex_lock(&phys_mappings->addr_desc_list_lock); - - list_for_each_entry(addr_desc, &phys_mappings->addr_desc_list, next) { - if ((addr + size < addr_desc->start) || - (addr_desc->start + addr_desc->size) < addr) - continue; - else { - /* should be no overlap */ - ret = -EINVAL; - goto mapping_exit; - } - } - - /* add the new entry to the list */ - new_addr_desc = kzalloc(sizeof(*new_addr_desc), GFP_KERNEL); - - if (!new_addr_desc) { - ret = -ENOMEM; - goto mapping_exit; - } - - new_addr_desc->start = addr; - new_addr_desc->size = size; - list_add(&new_addr_desc->next, &phys_mappings->addr_desc_list); - -mapping_exit: - mutex_unlock(&phys_mappings->addr_desc_list_lock); - return ret; -} -EXPORT_SYMBOL(mdev_add_phys_mapping); - -void mdev_del_phys_mapping(struct mdev_device *mdev, unsigned long addr) -{ - struct mdev_phys_mapping *phys_mappings; - struct addr_desc *addr_desc; - - if (!mdev) - return; - - phys_mappings = &mdev->phys_mappings; - - mutex_lock(&phys_mappings->addr_desc_list_lock); - list_for_each_entry(addr_desc, &phys_mappings->addr_desc_list, next) { - if (addr_desc->start == addr) { - list_del(&addr_desc->next); - kfree(addr_desc); - break; - } - } - mutex_unlock(&phys_mappings->addr_desc_list_lock); -} -EXPORT_SYMBOL(mdev_del_phys_mapping); - void mdev_device_supported_config(struct device *dev, char *str) { struct parent_device *parent = dev_to_parent_dev(dev); diff --git a/drivers/vfio/mdev/vfio_mpci.c b/drivers/vfio/mdev/vfio_mpci.c index 502aeb7..ca47676 100644 --- a/drivers/vfio/mdev/vfio_mpci.c +++ b/drivers/vfio/mdev/vfio_mpci.c @@ -1,5 +1,5 @@ /* - * VFIO based Mediated PCI device driver + * VFIO Bus driver for Mediated device * * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. * Author: Neo Jia @@ -24,453 +24,88 @@ #define DRIVER_VERSION "0.1" #define DRIVER_AUTHOR "NVIDIA Corporation" -#define DRIVER_DESC "VFIO based Mediated PCI device driver" +#define DRIVER_DESC "VFIO Bus driver for Mediated device" struct vfio_mdev { struct iommu_group *group; struct mdev_device *mdev; - int refcnt; - struct vfio_region_info vfio_region_info[VFIO_PCI_NUM_REGIONS]; - struct mutex vfio_mdev_lock; }; -static int vfio_mpci_open(void *device_data) +static int vfio_mdev_open(void *device_data) { - int ret = 0; - struct vfio_mdev *vmdev = device_data; - struct mdev_device *mdev = vmdev->mdev; - struct parent_device *parent = dev_to_parent_dev(mdev->dev.parent); - if (!try_module_get(THIS_MODULE)) return -ENODEV; - mutex_lock(&vmdev->vfio_mdev_lock); - if (!vmdev->refcnt && parent->ops->get_region_info) { - int index; - - for (index = VFIO_PCI_BAR0_REGION_INDEX; - index < VFIO_PCI_NUM_REGIONS; index++) { - ret = parent->ops->get_region_info(vmdev->mdev, index, - &vmdev->vfio_region_info[index]); - if (ret) - goto open_error; - } - } - - vmdev->refcnt++; - -open_error: - mutex_unlock(&vmdev->vfio_mdev_lock); - if (ret) - module_put(THIS_MODULE); - - return ret; -} - -static void vfio_mpci_close(void *device_data) -{ - struct vfio_mdev *vmdev = device_data; - - mutex_lock(&vmdev->vfio_mdev_lock); - vmdev->refcnt--; - if (!vmdev->refcnt) { - memset(&vmdev->vfio_region_info, 0, - sizeof(vmdev->vfio_region_info)); - } - mutex_unlock(&vmdev->vfio_mdev_lock); - module_put(THIS_MODULE); -} - -static u8 mpci_find_pci_capability(struct mdev_device *mdev, u8 capability) -{ - loff_t pos = VFIO_PCI_INDEX_TO_OFFSET(VFIO_PCI_CONFIG_REGION_INDEX); - struct parent_device *parent = dev_to_parent_dev(mdev->dev.parent); - u16 status; - u8 cap_ptr, cap_id = 0xff; - - parent->ops->read(mdev, (char *)&status, sizeof(status), - pos + PCI_STATUS); - if (!(status & PCI_STATUS_CAP_LIST)) - return 0; - - parent->ops->read(mdev, &cap_ptr, sizeof(cap_ptr), - pos + PCI_CAPABILITY_LIST); - - do { - cap_ptr &= 0xfc; - parent->ops->read(mdev, &cap_id, sizeof(cap_id), - pos + cap_ptr + PCI_CAP_LIST_ID); - if (cap_id == capability) - return cap_ptr; - parent->ops->read(mdev, &cap_ptr, sizeof(cap_ptr), - pos + cap_ptr + PCI_CAP_LIST_NEXT); - } while (cap_ptr && cap_id != 0xff); - return 0; } -static int mpci_get_irq_count(struct vfio_mdev *vmdev, int irq_type) +static void vfio_mdev_close(void *device_data) { - loff_t pos = VFIO_PCI_INDEX_TO_OFFSET(VFIO_PCI_CONFIG_REGION_INDEX); - struct mdev_device *mdev = vmdev->mdev; - struct parent_device *parent = dev_to_parent_dev(mdev->dev.parent); - - if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) { - u8 pin; - - parent->ops->read(mdev, &pin, sizeof(pin), - pos + PCI_INTERRUPT_PIN); - if (IS_ENABLED(CONFIG_VFIO_PCI_INTX) && pin) - return 1; - - } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) { - u8 cap_ptr; - u16 flags; - - cap_ptr = mpci_find_pci_capability(mdev, PCI_CAP_ID_MSI); - if (cap_ptr) { - parent->ops->read(mdev, (char *)&flags, sizeof(flags), - pos + cap_ptr + PCI_MSI_FLAGS); - return 1 << ((flags & PCI_MSI_FLAGS_QMASK) >> 1); - } - } else if (irq_type == VFIO_PCI_MSIX_IRQ_INDEX) { - u8 cap_ptr; - u16 flags; - - cap_ptr = mpci_find_pci_capability(mdev, PCI_CAP_ID_MSIX); - if (cap_ptr) { - parent->ops->read(mdev, (char *)&flags, sizeof(flags), - pos + cap_ptr + PCI_MSIX_FLAGS); - - return (flags & PCI_MSIX_FLAGS_QSIZE) + 1; - } - } else if (irq_type == VFIO_PCI_ERR_IRQ_INDEX) { - u8 cap_ptr; - - cap_ptr = mpci_find_pci_capability(mdev, PCI_CAP_ID_EXP); - if (cap_ptr) - return 1; - } else if (irq_type == VFIO_PCI_REQ_IRQ_INDEX) { - return 1; - } - - return 0; + module_put(THIS_MODULE); } -static long vfio_mpci_unlocked_ioctl(void *device_data, +static long vfio_mdev_unlocked_ioctl(void *device_data, unsigned int cmd, unsigned long arg) { - int ret = 0; struct vfio_mdev *vmdev = device_data; struct mdev_device *mdev = vmdev->mdev; struct parent_device *parent = dev_to_parent_dev(mdev->dev.parent); - unsigned long minsz; - - switch (cmd) { - case VFIO_DEVICE_GET_INFO: - { - struct vfio_device_info info; - - minsz = offsetofend(struct vfio_device_info, num_irqs); - - if (copy_from_user(&info, (void __user *)arg, minsz)) - return -EFAULT; - - if (info.argsz < minsz) - return -EINVAL; - - info.flags = VFIO_DEVICE_FLAGS_PCI; - - if (parent->ops->reset) - info.flags |= VFIO_DEVICE_FLAGS_RESET; - - info.num_regions = VFIO_PCI_NUM_REGIONS; - info.num_irqs = VFIO_PCI_NUM_IRQS; - - return copy_to_user((void __user *)arg, &info, minsz); - } - case VFIO_DEVICE_GET_REGION_INFO: - { - struct vfio_region_info info; - - minsz = offsetofend(struct vfio_region_info, offset); - - if (copy_from_user(&info, (void __user *)arg, minsz)) - return -EFAULT; - - if (info.argsz < minsz) - return -EINVAL; - - switch (info.index) { - case VFIO_PCI_CONFIG_REGION_INDEX: - case VFIO_PCI_BAR0_REGION_INDEX ... VFIO_PCI_BAR5_REGION_INDEX: - info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); - info.size = vmdev->vfio_region_info[info.index].size; - if (!info.size) { - info.flags = 0; - break; - } - - info.flags = vmdev->vfio_region_info[info.index].flags; - break; - case VFIO_PCI_VGA_REGION_INDEX: - case VFIO_PCI_ROM_REGION_INDEX: - default: - return -EINVAL; - } - - return copy_to_user((void __user *)arg, &info, minsz); - } - case VFIO_DEVICE_GET_IRQ_INFO: - { - struct vfio_irq_info info; - - minsz = offsetofend(struct vfio_irq_info, count); - - if (copy_from_user(&info, (void __user *)arg, minsz)) - return -EFAULT; - - if (info.argsz < minsz || info.index >= VFIO_PCI_NUM_IRQS) - return -EINVAL; - - switch (info.index) { - case VFIO_PCI_INTX_IRQ_INDEX ... VFIO_PCI_MSI_IRQ_INDEX: - case VFIO_PCI_REQ_IRQ_INDEX: - break; - /* pass thru to return error */ - case VFIO_PCI_MSIX_IRQ_INDEX: - default: - return -EINVAL; - } - - info.flags = VFIO_IRQ_INFO_EVENTFD; - info.count = mpci_get_irq_count(vmdev, info.index); - - if (info.count == -1) - return -EINVAL; - - if (info.index == VFIO_PCI_INTX_IRQ_INDEX) - info.flags |= (VFIO_IRQ_INFO_MASKABLE | - VFIO_IRQ_INFO_AUTOMASKED); - else - info.flags |= VFIO_IRQ_INFO_NORESIZE; - - return copy_to_user((void __user *)arg, &info, minsz); - } - case VFIO_DEVICE_SET_IRQS: - { - struct vfio_irq_set hdr; - u8 *data = NULL, *ptr = NULL; - - minsz = offsetofend(struct vfio_irq_set, count); - - if (copy_from_user(&hdr, (void __user *)arg, minsz)) - return -EFAULT; - - if (hdr.argsz < minsz || hdr.index >= VFIO_PCI_NUM_IRQS || - hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK | - VFIO_IRQ_SET_ACTION_TYPE_MASK)) - return -EINVAL; - - if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) { - size_t size; - int max = mpci_get_irq_count(vmdev, hdr.index); - - if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL) - size = sizeof(uint8_t); - else if (hdr.flags & VFIO_IRQ_SET_DATA_EVENTFD) - size = sizeof(int32_t); - else - return -EINVAL; - - if (hdr.argsz - minsz < hdr.count * size || - hdr.start >= max || hdr.start + hdr.count > max) - return -EINVAL; - - ptr = data = memdup_user((void __user *)(arg + minsz), - hdr.count * size); - if (IS_ERR(data)) - return PTR_ERR(data); - } - - if (parent->ops->set_irqs) - ret = parent->ops->set_irqs(mdev, hdr.flags, hdr.index, - hdr.start, hdr.count, data); - - kfree(ptr); - return ret; - } - case VFIO_DEVICE_RESET: - { - if (parent->ops->reset) - return parent->ops->reset(vmdev->mdev); - - return -EINVAL; - } - } - return -ENOTTY; + + if (parent && parent->ops && parent->ops->ioctl) + return parent->ops->ioctl(mdev, cmd, arg); + + return -ENODEV; } -static ssize_t vfio_mpci_read(void *device_data, char __user *buf, +static ssize_t vfio_mdev_read(void *device_data, char __user *buf, size_t count, loff_t *ppos) { struct vfio_mdev *vmdev = device_data; struct mdev_device *mdev = vmdev->mdev; struct parent_device *parent = dev_to_parent_dev(mdev->dev.parent); - int ret = 0; - - if (!count) - return 0; - if (parent->ops->read) { - char *ret_data, *ptr; + if (parent && parent->ops && parent->ops->read) + return parent->ops->read(mdev, buf, count, ppos); - ptr = ret_data = kzalloc(count, GFP_KERNEL); - - if (!ret_data) - return -ENOMEM; - - ret = parent->ops->read(mdev, ret_data, count, *ppos); - - if (ret > 0) { - if (copy_to_user(buf, ret_data, ret)) - ret = -EFAULT; - else - *ppos += ret; - } - kfree(ptr); - } - - return ret; + return -ENODEV; } -static ssize_t vfio_mpci_write(void *device_data, const char __user *buf, +static ssize_t vfio_mdev_write(void *device_data, const char __user *buf, size_t count, loff_t *ppos) { struct vfio_mdev *vmdev = device_data; struct mdev_device *mdev = vmdev->mdev; struct parent_device *parent = dev_to_parent_dev(mdev->dev.parent); - int ret = 0; - - if (!count) - return 0; - - if (parent->ops->write) { - char *usr_data, *ptr; - - ptr = usr_data = memdup_user(buf, count); - if (IS_ERR(usr_data)) - return PTR_ERR(usr_data); - - ret = parent->ops->write(mdev, usr_data, count, *ppos); - - if (ret > 0) - *ppos += ret; - - kfree(ptr); - } - - return ret; -} - -static int mdev_dev_mmio_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - int ret; - struct vfio_mdev *vmdev = vma->vm_private_data; - struct mdev_device *mdev; - struct parent_device *parent; - u64 virtaddr = (u64)vmf->virtual_address; - unsigned long req_size, pgoff = 0; - pgprot_t pg_prot; - unsigned int index; - - if (!vmdev && !vmdev->mdev) - return -EINVAL; - - mdev = vmdev->mdev; - parent = dev_to_parent_dev(mdev->dev.parent); - - pg_prot = vma->vm_page_prot; - - if (parent->ops->validate_map_request) { - u64 offset; - loff_t pos; - - offset = virtaddr - vma->vm_start; - req_size = vma->vm_end - virtaddr; - pos = (vma->vm_pgoff << PAGE_SHIFT) + offset; - - ret = parent->ops->validate_map_request(mdev, pos, &virtaddr, - &pgoff, &req_size, &pg_prot); - if (ret) - return ret; - - /* - * Verify pgoff and req_size are valid and virtaddr is within - * vma range - */ - if (!pgoff || !req_size || (virtaddr < vma->vm_start) || - ((virtaddr + req_size) >= vma->vm_end)) - return -EINVAL; - } else { - struct pci_dev *pdev; - - virtaddr = vma->vm_start; - req_size = vma->vm_end - vma->vm_start; - - pdev = to_pci_dev(parent->dev.parent); - index = VFIO_PCI_OFFSET_TO_INDEX(vma->vm_pgoff << PAGE_SHIFT); - pgoff = pci_resource_start(pdev, index) >> PAGE_SHIFT; - } - - ret = remap_pfn_range(vma, virtaddr, pgoff, req_size, pg_prot); - - return ret | VM_FAULT_NOPAGE; -} -void mdev_dev_mmio_close(struct vm_area_struct *vma) -{ - struct vfio_mdev *vmdev = vma->vm_private_data; - struct mdev_device *mdev = vmdev->mdev; + if (parent && parent->ops && parent->ops->write) + return parent->ops->write(mdev, buf, count, ppos); - mdev_del_phys_mapping(mdev, vma->vm_pgoff << PAGE_SHIFT); + return -ENODEV; } -static const struct vm_operations_struct mdev_dev_mmio_ops = { - .fault = mdev_dev_mmio_fault, - .close = mdev_dev_mmio_close, -}; - -static int vfio_mpci_mmap(void *device_data, struct vm_area_struct *vma) +static int vfio_mdev_mmap(void *device_data, struct vm_area_struct *vma) { - unsigned int index; struct vfio_mdev *vmdev = device_data; struct mdev_device *mdev = vmdev->mdev; + struct parent_device *parent = dev_to_parent_dev(mdev->dev.parent); - index = vma->vm_pgoff >> (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT); - - if (index >= VFIO_PCI_ROM_REGION_INDEX) - return -EINVAL; - - vma->vm_private_data = vmdev; - vma->vm_ops = &mdev_dev_mmio_ops; + if (parent && parent->ops && parent->ops->mmap) + return parent->ops->mmap(mdev, vma); - return mdev_add_phys_mapping(mdev, vma->vm_file->f_mapping, - vma->vm_pgoff << PAGE_SHIFT, - vma->vm_end - vma->vm_start); + return -ENODEV; } -static const struct vfio_device_ops vfio_mpci_dev_ops = { - .name = "vfio-mpci", - .open = vfio_mpci_open, - .release = vfio_mpci_close, - .ioctl = vfio_mpci_unlocked_ioctl, - .read = vfio_mpci_read, - .write = vfio_mpci_write, - .mmap = vfio_mpci_mmap, +static const struct vfio_device_ops vfio_mdev_dev_ops = { + .name = "vfio-mdev", + .open = vfio_mdev_open, + .release = vfio_mdev_close, + .ioctl = vfio_mdev_unlocked_ioctl, + .read = vfio_mdev_read, + .write = vfio_mdev_write, + .mmap = vfio_mdev_mmap, }; -int vfio_mpci_probe(struct device *dev) +static int vfio_mdev_probe(struct device *dev) { struct vfio_mdev *vmdev; struct mdev_device *mdev = to_mdev_device(dev); @@ -482,16 +117,15 @@ int vfio_mpci_probe(struct device *dev) vmdev->mdev = mdev; vmdev->group = mdev->group; - mutex_init(&vmdev->vfio_mdev_lock); - ret = vfio_add_group_dev(dev, &vfio_mpci_dev_ops, vmdev); + ret = vfio_add_group_dev(dev, &vfio_mdev_dev_ops, vmdev); if (ret) kfree(vmdev); return ret; } -void vfio_mpci_remove(struct device *dev) +static void vfio_mdev_remove(struct device *dev) { struct vfio_mdev *vmdev; @@ -499,33 +133,34 @@ void vfio_mpci_remove(struct device *dev) kfree(vmdev); } -int vfio_mpci_match(struct device *dev) +/* + * Having one single driver to match all available mdev devices is enough, + * for every possible type. + */ +static int vfio_mdev_match(struct device *dev) { - if (dev_is_pci(dev->parent)) - return 1; - - return 0; + return 1; } -struct mdev_driver vfio_mpci_driver = { - .name = "vfio_mpci", - .probe = vfio_mpci_probe, - .remove = vfio_mpci_remove, - .match = vfio_mpci_match, +static struct mdev_driver vfio_mdev_driver = { + .name = "vfio_mdev", + .probe = vfio_mdev_probe, + .remove = vfio_mdev_remove, + .match = vfio_mdev_match, }; -static int __init vfio_mpci_init(void) +static int __init vfio_mdev_init(void) { - return mdev_register_driver(&vfio_mpci_driver, THIS_MODULE); + return mdev_register_driver(&vfio_mdev_driver, THIS_MODULE); } -static void __exit vfio_mpci_exit(void) +static void __exit vfio_mdev_exit(void) { - mdev_unregister_driver(&vfio_mpci_driver); + mdev_unregister_driver(&vfio_mdev_driver); } -module_init(vfio_mpci_init) -module_exit(vfio_mpci_exit) +module_init(vfio_mdev_init) +module_exit(vfio_mdev_exit) MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h index 4b69e09..2128de8 100644 --- a/drivers/vfio/pci/vfio_pci_private.h +++ b/drivers/vfio/pci/vfio_pci_private.h @@ -19,6 +19,12 @@ #ifndef VFIO_PCI_PRIVATE_H #define VFIO_PCI_PRIVATE_H +#define VFIO_PCI_OFFSET_SHIFT 40 + +#define VFIO_PCI_OFFSET_TO_INDEX(off) (off >> VFIO_PCI_OFFSET_SHIFT) +#define VFIO_PCI_INDEX_TO_OFFSET(index) ((u64)(index) << VFIO_PCI_OFFSET_SHIFT) +#define VFIO_PCI_OFFSET_MASK (((u64)(1) << VFIO_PCI_OFFSET_SHIFT) - 1) + /* Special capability IDs predefined access */ #define PCI_CAP_ID_INVALID 0xFF /* default raw access */ #define PCI_CAP_ID_INVALID_VIRT 0xFE /* default virt access */ diff --git a/include/linux/mdev.h b/include/linux/mdev.h index c06967d..f99c9e2 100644 --- a/include/linux/mdev.h +++ b/include/linux/mdev.h @@ -15,33 +15,17 @@ #include -struct parent_device; /* * Mediated device */ - -struct addr_desc { - unsigned long start; - unsigned long size; - struct list_head next; -}; - -struct mdev_phys_mapping { - struct address_space *mapping; - struct list_head addr_desc_list; - struct mutex addr_desc_list_lock; -}; - +struct parent_device; struct mdev_device { struct device dev; struct iommu_group *group; uuid_le uuid; uint32_t instance; void *driver_data; - - /* internal only */ - struct mdev_phys_mapping phys_mappings; }; @@ -96,19 +80,7 @@ struct mdev_device { * @count: number of bytes to be written * @pos: address. * Retuns number on bytes written on success or error. - * @set_irqs: Called to send about interrupts configuration - * information that VMM sets. - * @mdev: mediated device structure - * @flags, index, start, count and *data : same as that of - * struct vfio_irq_set of VFIO_DEVICE_SET_IRQS API. - * @get_region_info: Called to get VFIO region size and flags of mediated - * device. - * @mdev: mediated device structure - * @region_index: VFIO region index - * @region_info: output, returns size and flags of - * requested region. - * Returns integer: success (0) or error (< 0) - * @validate_map_request: Validate remap pfn request + * @mmap: Memory Map * @mdev: mediated device structure * @pos: address * @virtaddr: target user address to start at. Vendor @@ -133,21 +105,18 @@ struct parent_ops { int (*supported_config)(struct device *dev, char *config); int (*create)(struct mdev_device *mdev, char *mdev_params); int (*destroy)(struct mdev_device *mdev); + int (*reset)(struct mdev_device *mdev); int (*start)(struct mdev_device *mdev); int (*stop)(struct mdev_device *mdev); - ssize_t (*read)(struct mdev_device *mdev, char *buf, size_t count, - loff_t pos); - ssize_t (*write)(struct mdev_device *mdev, char *buf, size_t count, - loff_t pos); - int (*set_irqs)(struct mdev_device *mdev, uint32_t flags, - unsigned int index, unsigned int start, - unsigned int count, void *data); - int (*get_region_info)(struct mdev_device *mdev, int region_index, - struct vfio_region_info *region_info); - int (*validate_map_request)(struct mdev_device *mdev, loff_t pos, - u64 *virtaddr, unsigned long *pfn, - unsigned long *size, pgprot_t *prot); + + ssize_t (*read)(struct mdev_device *mdev, char __user *buf, size_t count, + loff_t *pos); + ssize_t (*write)(struct mdev_device *mdev, const char __user *buf, + size_t count, loff_t *pos); + int (*mmap)(struct mdev_device *mdev, struct vm_area_struct *vma); + long (*ioctl)(struct mdev_device *mdev, unsigned int cmd, + unsigned long arg); }; /* @@ -209,13 +178,4 @@ extern void mdev_unregister_driver(struct mdev_driver *drv); extern struct mdev_device *mdev_get_device_by_group(struct iommu_group *group); -extern int mdev_device_invalidate_mapping(struct mdev_device *mdev, - unsigned long addr, unsigned long size); - -extern int mdev_add_phys_mapping(struct mdev_device *mdev, - struct address_space *mapping, - unsigned long addr, unsigned long size); - - -extern void mdev_del_phys_mapping(struct mdev_device *mdev, unsigned long addr); #endif /* MDEV_H */ diff --git a/include/linux/vfio.h b/include/linux/vfio.h index abae882..f2f0daf 100644 --- a/include/linux/vfio.h +++ b/include/linux/vfio.h @@ -19,13 +19,6 @@ #include #include -#define VFIO_PCI_OFFSET_SHIFT 40 - -#define VFIO_PCI_OFFSET_TO_INDEX(off) (off >> VFIO_PCI_OFFSET_SHIFT) -#define VFIO_PCI_INDEX_TO_OFFSET(index) ((u64)(index) << VFIO_PCI_OFFSET_SHIFT) -#define VFIO_PCI_OFFSET_MASK (((u64)(1) << VFIO_PCI_OFFSET_SHIFT) - 1) - - /** * struct vfio_device_ops - VFIO bus driver device callbacks *