From patchwork Mon Mar 12 22:33:02 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 146275 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id D400CB6FBE for ; Tue, 13 Mar 2012 09:33:55 +1100 (EST) Received: from localhost ([::1]:45874 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S7DoP-0006UU-JZ for incoming@patchwork.ozlabs.org; Mon, 12 Mar 2012 18:33:53 -0400 Received: from eggs.gnu.org ([208.118.235.92]:41234) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S7Dnp-0005Gq-6w for qemu-devel@nongnu.org; Mon, 12 Mar 2012 18:33:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S7Dnn-0002Mi-0x for qemu-devel@nongnu.org; Mon, 12 Mar 2012 18:33:16 -0400 Received: from mx1.redhat.com ([209.132.183.28]:35956) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S7Dnm-0002MR-N2 for qemu-devel@nongnu.org; Mon, 12 Mar 2012 18:33:14 -0400 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q2CMX3c6010094 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 12 Mar 2012 18:33:04 -0400 Received: from bling.home (ovpn-113-28.phx2.redhat.com [10.3.113.28]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q2CMX2IS007741; Mon, 12 Mar 2012 18:33:03 -0400 From: Alex Williamson To: david@gibson.dropbear.id.au, aik@ozlabs.ru, dwmw2@infradead.org Date: Mon, 12 Mar 2012 16:33:02 -0600 Message-ID: <20120312223302.30321.91922.stgit@bling.home> In-Reply-To: <20120312220109.30321.83419.stgit@bling.home> References: <20120312220109.30321.83419.stgit@bling.home> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: kvm@vger.kernel.org, iommu@lists.linux-foundation.org, qemu-devel@nongnu.org, alex.williamson@redhat.com, joerg.roedel@amd.com, linux-kernel@vger.kernel.org Subject: [Qemu-devel] [PATCH 2/2] intel-iommu: Basic isolation group provider 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/iommu/intel-iommu.c | 70 +++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 70 insertions(+), 0 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index c9c6053..2e5a709 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -3597,6 +3598,73 @@ static struct notifier_block device_nb = { .notifier_call = device_notifier, }; +static int isolation_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct device *dev = data; + struct pci_dev *pdev = to_pci_dev(dev); + + if (iommu_no_mapping(dev) || + !device_to_iommu(pci_domain_nr(pdev->bus), + pdev->bus->number, pdev->devfn)) + return NOTIFY_DONE; + + + if (action == ISOLATION_NOTIFY_ADD_DEVICE) { + struct device *dma_dev = NULL; + struct pci_dev *bridge = pci_find_upstream_pcie_bridge(pdev); + struct isolation_group *group; + + if (bridge) { + if (pci_is_pcie(bridge)) { + struct pci_dev *dma_pdev; + dma_pdev = pci_get_domain_bus_and_slot( + pci_domain_nr(pdev->bus), + bridge->subordinate->number, 0); + dma_dev = &dma_pdev->dev; + } + + if (!dma_dev) + dma_dev = &bridge->dev; + } else + dma_dev = dev; + + group = to_isolation_group(dma_dev); + + if (!group) { + group = isolation_create_group(); + if (IS_ERR(group)) + return NOTIFY_BAD; + + isolation_group_set_iommu_ops(group, &intel_iommu_ops); + + if (dma_dev != dev) + isolation_group_add_dev(group, dma_dev); + } + + if (isolation_group_add_dev(group, dev)) + return NOTIFY_BAD; + + return NOTIFY_STOP; + + } else if (action == ISOLATION_NOTIFY_DEL_DEVICE) { + struct isolation_group *group = to_isolation_group(dev); + + if (isolation_group_del_dev(dev)) + return NOTIFY_BAD; + + isolation_free_group(group); + + return NOTIFY_STOP; + } + + return NOTIFY_DONE; +} + +static struct notifier_block isolation_nb = { + .notifier_call = isolation_notifier, +}; + int __init intel_iommu_init(void) { int ret = 0; @@ -3663,6 +3731,8 @@ int __init intel_iommu_init(void) bus_register_notifier(&pci_bus_type, &device_nb); + isolation_register_notifier(&pci_bus_type, &isolation_nb); + intel_iommu_enabled = 1; return 0;