Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752142AbdFSRPM (ORCPT ); Mon, 19 Jun 2017 13:15:12 -0400 Received: from mx1.redhat.com ([209.132.183.28]:37342 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750913AbdFSRPL (ORCPT ); Mon, 19 Jun 2017 13:15:11 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 7605A80463 Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=alex.williamson@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 7605A80463 Subject: [PATCH v2 5/9] vfio: Create interface for vfio bus drivers to register From: Alex Williamson To: kvm@vger.kernel.org Cc: eric.auger@redhat.com, alex.williamson@redhat.com, linux-kernel@vger.kernel.org Date: Mon, 19 Jun 2017 11:15:00 -0600 Message-ID: <20170619171500.14047.55872.stgit@gimli.home> In-Reply-To: <20170619170323.14047.26504.stgit@gimli.home> References: <20170619170323.14047.26504.stgit@gimli.home> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Mon, 19 Jun 2017 17:15:05 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3582 Lines: 120 Generally we don't know about vfio bus drivers until a device is added to the vfio-core with vfio_add_group_dev(), this optional registration with vfio_register_bus_driver() allows vfio-core to track known drivers. Our current use for this information is to know whether a driver is vfio compatible during a bind operation. For devices on buses with driver_override support, we can use this linkage to block non-vfio drivers from binding to devices where the iommu group state would trigger a BUG to avoid host/user integrity issues. Signed-off-by: Alex Williamson Reviewed-by: Eric Auger --- drivers/vfio/vfio.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/vfio.h | 3 +++ 2 files changed, 58 insertions(+) diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 7597a377eb4e..f40d1508d368 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -43,6 +43,8 @@ struct class *class; struct list_head iommu_drivers_list; struct mutex iommu_drivers_lock; + struct list_head bus_drivers_list; + struct mutex bus_drivers_lock; struct list_head group_list; struct idr group_idr; struct mutex group_lock; @@ -51,6 +53,11 @@ wait_queue_head_t release_q; } vfio; +struct vfio_bus_driver { + struct device_driver *drv; + struct list_head vfio_next; +}; + struct vfio_iommu_driver { const struct vfio_iommu_driver_ops *ops; struct list_head vfio_next; @@ -2243,6 +2250,52 @@ int vfio_unregister_notifier(struct device *dev, enum vfio_notify_type type, } EXPORT_SYMBOL(vfio_unregister_notifier); +int vfio_register_bus_driver(struct device_driver *drv) +{ + struct vfio_bus_driver *driver, *tmp; + + driver = kzalloc(sizeof(*driver), GFP_KERNEL); + if (!driver) + return -ENOMEM; + + driver->drv = drv; + + mutex_lock(&vfio.bus_drivers_lock); + + /* Check for duplicates */ + list_for_each_entry(tmp, &vfio.bus_drivers_list, vfio_next) { + if (tmp->drv == drv) { + mutex_unlock(&vfio.bus_drivers_lock); + kfree(driver); + return -EINVAL; + } + } + + list_add(&driver->vfio_next, &vfio.bus_drivers_list); + + mutex_unlock(&vfio.bus_drivers_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(vfio_register_bus_driver); + +void vfio_unregister_bus_driver(struct device_driver *drv) +{ + struct vfio_bus_driver *driver; + + mutex_lock(&vfio.bus_drivers_lock); + list_for_each_entry(driver, &vfio.bus_drivers_list, vfio_next) { + if (driver->drv == drv) { + list_del(&driver->vfio_next); + mutex_unlock(&vfio.bus_drivers_lock); + kfree(driver); + return; + } + } + mutex_unlock(&vfio.bus_drivers_lock); +} +EXPORT_SYMBOL_GPL(vfio_unregister_bus_driver); + /** * Module/class support */ @@ -2266,8 +2319,10 @@ static int __init vfio_init(void) idr_init(&vfio.group_idr); mutex_init(&vfio.group_lock); mutex_init(&vfio.iommu_drivers_lock); + mutex_init(&vfio.bus_drivers_lock); INIT_LIST_HEAD(&vfio.group_list); INIT_LIST_HEAD(&vfio.iommu_drivers_list); + INIT_LIST_HEAD(&vfio.bus_drivers_list); init_waitqueue_head(&vfio.release_q); ret = misc_register(&vfio_dev); diff --git a/include/linux/vfio.h b/include/linux/vfio.h index 9b34d0af5d27..dab0f8105e4a 100644 --- a/include/linux/vfio.h +++ b/include/linux/vfio.h @@ -92,6 +92,9 @@ struct vfio_iommu_driver_ops { extern void vfio_unregister_iommu_driver( const struct vfio_iommu_driver_ops *ops); +extern int vfio_register_bus_driver(struct device_driver *drv); +extern void vfio_unregister_bus_driver(struct device_driver *drv); + /* * External user API */