From patchwork Thu Sep 1 19:50:50 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 112972 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 28C50B6F8E for ; Fri, 2 Sep 2011 05:52:21 +1000 (EST) Received: from localhost ([::1]:57830 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QzDJ8-0007ww-FM for incoming@patchwork.ozlabs.org; Thu, 01 Sep 2011 15:52:14 -0400 Received: from eggs.gnu.org ([140.186.70.92]:50366) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QzDIu-0007ac-H1 for qemu-devel@nongnu.org; Thu, 01 Sep 2011 15:52:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QzDIn-0002QC-EA for qemu-devel@nongnu.org; Thu, 01 Sep 2011 15:52:00 -0400 Received: from mx1.redhat.com ([209.132.183.28]:24363) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QzDIm-0002NV-Tv for qemu-devel@nongnu.org; Thu, 01 Sep 2011 15:51:53 -0400 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p81JoqXu014293 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 1 Sep 2011 15:50:52 -0400 Received: from s20.home (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p81Joobi026798; Thu, 1 Sep 2011 15:50:50 -0400 From: Alex Williamson To: chrisw@sous-sol.org, aik@au1.ibm.com, pmac@au1.ibm.com, dwg@au1.ibm.com, joerg.roedel@amd.com, agraf@suse.de, benve@cisco.com, aafabbri@cisco.com, B08248@freescale.com, B07421@freescale.com, avi@redhat.com, kvm@vger.kernel.org, qemu-devel@nongnu.org, iommu@lists.linux-foundation.org, linux-pci@vger.kernel.org Date: Thu, 01 Sep 2011 13:50:50 -0600 Message-ID: <20110901195050.2391.12028.stgit@s20.home> In-Reply-To: <20110901194915.2391.97400.stgit@s20.home> References: <20110901194915.2391.97400.stgit@s20.home> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: alex.williamson@redhat.com Subject: [Qemu-devel] [RFC PATCH 4/5] VFIO: Add PCI device support X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Alex Williamson --- drivers/vfio/Kconfig | 7 ++ drivers/vfio/Makefile | 1 drivers/vfio/vfio_main.c | 10 +++ drivers/vfio/vfio_pci.c | 124 +++++++++++++++++++++++++++++++++++++++++++ drivers/vfio/vfio_private.h | 5 ++ 5 files changed, 147 insertions(+), 0 deletions(-) create mode 100644 drivers/vfio/vfio_pci.c diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig index a150521..b17bdbd 100644 --- a/drivers/vfio/Kconfig +++ b/drivers/vfio/Kconfig @@ -3,3 +3,10 @@ menuconfig VFIO depends on IOMMU_API help If you don't know what to do here, say N. + +menuconfig VFIO_PCI + bool "VFIO support for PCI devices" + depends on VFIO && PCI + default y if X86 + help + If you don't know what to do here, say N. diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile index 5eaa074..90ee753 100644 --- a/drivers/vfio/Makefile +++ b/drivers/vfio/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_VFIO) := vfio.o vfio-y := vfio_main.o vfio_iommu.o vfio_device.o +vfio-$(CONFIG_VFIO_PCI) += vfio_pci.o diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c index 7f05692..c6e80f7 100644 --- a/drivers/vfio/vfio_main.c +++ b/drivers/vfio/vfio_main.c @@ -834,6 +834,12 @@ static int __init vfio_init(void) if (ret) goto err_cdev; +#ifdef CONFIG_VFIO_PCI + ret = vfio_pci_init(&vfio); + if (ret) + pr_debug(DRIVER_DESC "PCI init failed %d\n", ret); +#endif + pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); return 0; @@ -864,6 +870,10 @@ static void __exit vfio_cleanup(void) } } +#ifdef CONFIG_VFIO_PCI + vfio_pci_cleanup(&vfio); +#endif + idr_destroy(&vfio.idr); cdev_del(&vfio.cdev); unregister_chrdev_region(vfio.devt, MINORMASK); diff --git a/drivers/vfio/vfio_pci.c b/drivers/vfio/vfio_pci.c new file mode 100644 index 0000000..88325d0 --- /dev/null +++ b/drivers/vfio/vfio_pci.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. All rights reserved. + * Author: Alex Williamson + * + * 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. + * + * Derived from original vfio: + * Copyright 2010 Cisco Systems, Inc. All rights reserved. + * Author: Tom Lyon, pugs@cisco.com + */ + +#include +#include +#include +#include +#include + +#include "vfio_private.h" + +struct vfio_pci_device { + struct vfio_device vdev; + struct pci_dev *pdev; +}; + +static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + return 0; +} + +static void vfio_pci_remove(struct pci_dev *pdev) +{ +} + +static struct pci_driver vfio_pci_driver = { + .name = "vfio", + .id_table = NULL, /* only dynamic id's */ + .probe = vfio_pci_probe, + .remove = vfio_pci_remove, +}; + +static struct vfio_device *vfio_pci_new(struct device *dev) +{ + struct vfio_pci_device *pvdev; + + pvdev = kzalloc(sizeof(*pvdev), GFP_KERNEL); + if (!pvdev) + return ERR_PTR(-ENOMEM); + + printk("%s: alloc pvdev @%p\n", __FUNCTION__, pvdev); + pvdev->pdev = container_of(dev, struct pci_dev, dev); + + // PCI stuff... + + return &pvdev->vdev; +} + +static void vfio_pci_free(struct vfio_device *vdev) +{ + struct vfio_pci_device *pvdev; + + pvdev = container_of(vdev, struct vfio_pci_device, vdev); + + // PCI stuff... + + printk("%s: freeing pvdev @%p\n", __FUNCTION__, pvdev); + kfree(pvdev); +} + +static const struct vfio_device_ops vfio_pci_ops = { + .new = vfio_pci_new, + .free = vfio_pci_free, +}; + +static int vfio_pci_device_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct device *dev = data; + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); + + if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL) + return 0; + + if (action == BUS_NOTIFY_ADD_DEVICE) + return vfio_group_add_dev(dev, (void *)&vfio_pci_ops); + else if (action == BUS_NOTIFY_DEL_DEVICE) + vfio_group_del_dev(dev); + return 0; +} + +static int vfio_pci_add_dev(struct device *dev, void *unused) +{ + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); + + if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL) + return 0; + + return vfio_group_add_dev(dev, (void *)&vfio_pci_ops); +} + +static struct notifier_block vfio_pci_device_nb = { + .notifier_call = vfio_pci_device_notifier, +}; + +void __exit vfio_pci_cleanup(struct vfio *vfio) +{ + bus_unregister_notifier(&pci_bus_type, &vfio_pci_device_nb); + pci_unregister_driver(&vfio_pci_driver); +} + +int __init vfio_pci_init(struct vfio *vfio) +{ + int ret; + + ret = pci_register_driver(&vfio_pci_driver); + if (ret) + return ret; + + bus_register_notifier(&pci_bus_type, &vfio_pci_device_nb); + bus_for_each_dev(&pci_bus_type, NULL, NULL, vfio_pci_add_dev); + + return 0; +} diff --git a/drivers/vfio/vfio_private.h b/drivers/vfio/vfio_private.h index 2cc300c..85c88ea 100644 --- a/drivers/vfio/vfio_private.h +++ b/drivers/vfio/vfio_private.h @@ -79,4 +79,9 @@ struct vfio_group { extern int vfio_group_add_dev(struct device *dev, void *data); extern void vfio_group_del_dev(struct device *dev); +#ifdef CONFIG_VFIO_PCI +extern int vfio_pci_init(struct vfio *vfio); +extern void vfio_pci_cleanup(struct vfio *vfio); +#endif + #endif /* VFIO_PRIVATE_H */