From patchwork Tue Feb 4 13:54:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mykyta Poturai X-Patchwork-Id: 13959282 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5FDDEC02198 for ; Tue, 4 Feb 2025 13:54:19 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.881483.1291660 (Exim 4.92) (envelope-from ) id 1tfJNS-0008OZ-Vz; Tue, 04 Feb 2025 13:54:10 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 881483.1291660; Tue, 04 Feb 2025 13:54:10 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tfJNS-0008ON-Sl; Tue, 04 Feb 2025 13:54:10 +0000 Received: by outflank-mailman (input) for mailman id 881483; Tue, 04 Feb 2025 13:54:09 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tfJNR-0007bp-9s for xen-devel@lists.xenproject.org; Tue, 04 Feb 2025 13:54:09 +0000 Received: from EUR03-DBA-obe.outbound.protection.outlook.com (mail-dbaeur03on20630.outbound.protection.outlook.com [2a01:111:f403:260d::630]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 80ba3ec8-e2ff-11ef-99a4-01e77a169b0f; Tue, 04 Feb 2025 14:54:07 +0100 (CET) Received: from PAVPR03MB10102.eurprd03.prod.outlook.com (2603:10a6:102:30d::12) by AS8PR03MB10120.eurprd03.prod.outlook.com (2603:10a6:20b:57f::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8398.24; Tue, 4 Feb 2025 13:54:04 +0000 Received: from PAVPR03MB10102.eurprd03.prod.outlook.com ([fe80::35ac:8893:c31c:b971]) by PAVPR03MB10102.eurprd03.prod.outlook.com ([fe80::35ac:8893:c31c:b971%7]) with mapi id 15.20.8398.021; Tue, 4 Feb 2025 13:54:04 +0000 X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 80ba3ec8-e2ff-11ef-99a4-01e77a169b0f ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=iZzjasSgxhDvYo8iZ2WzC3sNfdM7oeHP7CX0B8zBC8Y4KW9y29zCTT4J0igc1ZmXGsHyDsS8dkBi8aXUuwtOiyh+Pw7/WysAogHDU7UQUK9otBZk8pa75UWKGsPiGZ7lkwAkoiUf7FrM+ASo8eCsOzXIZdnsmQHILa7AHB7cGJeXFCSz4oqHA6FJZCyy9741SgmxIL/P4OQxHVCK4NccTpYnmf0hzMqWSsMwhkU09l0K+Z20aBpRFnZUuNdM+vOkWGcGnWoKnoACm4pc0WVyHuZWzQcYpss6Vofxqml0Nf4vB2z27AnGyP9Rqd8wPoYC72cdKF+1YEHDkyhSiKolaw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=7lOCv8zHloXloczKwDCOTV2sKz+Z1GzU7wAw3bdi1Ok=; b=XwxR1UP1ILs04TuL4C8K+dgkfyPUz6Es/umZ9YsEUu+hPOIqN4Po36DsTIHg97UtpkDj0F1OH2YjPEb87Qi9Nl+ctw9sc1g5uDUycT+C0Pyd6+tS3E6uz4ZI60B643sfs20hLEsOnb+V3Xl1bDqK0HfJ/k34SmP3lHuPSgFKw3inyYf93aNc4N81Lmu/+wpFodovlUj8ZZKMoHir5n3XnIXyP1bbZQy0yAssgG8yNxvEWdrHsQA0TVtkI2lVQB2pNMGC+/M2pKIiSADHqFPJvueWTz61ijeBHk6DciU0yoOuf6dxTO22DgTgPXdmqgKH4QqZRJAZt5wDVGU03lKXdA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=epam.com; dmarc=pass action=none header.from=epam.com; dkim=pass header.d=epam.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=epam.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=7lOCv8zHloXloczKwDCOTV2sKz+Z1GzU7wAw3bdi1Ok=; b=rjT0x1MHCESZTL7s8GfqpHHsWsLR3st7CXVChevNAr4/gh0urE29EZemPaNzXMxmF2w31/Oe/r0xB8qDFxqGMKCcyzcUTBajUIzRy3nFPsVHuqW8n33tmcQeDo0luaK6M1xMWHyUQzdqBfRjJRUtgX7iCf/ulln355I4CJvrKvzVMaWS72DMLgyg1gqlu+OK/r3cZvojPYD4PX6jDOHAoQDr+vMbRcizyIaeu2rwUKSnctp1buYGdU6i0iqTpXbBste+C+/inmD+b3vcNpGnjPONhbMd3Gj5m3KZX6m+ygzzy8mJo5yK2Pv9Luj0QLglIR4etMLAiVXUKPgUi7iz2w== From: Mykyta Poturai To: "xen-devel@lists.xenproject.org" CC: Stewart Hildebrand , Oleksandr Andrushchenko , Julien Grall , Rahul Singh , Stefano Stabellini , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk , Oleksandr Tyshchenko , Mykyta Poturai Subject: [PATCH v7 4/8] xen/arm: smmuv2: Add PCI devices support for SMMUv2 Thread-Topic: [PATCH v7 4/8] xen/arm: smmuv2: Add PCI devices support for SMMUv2 Thread-Index: AQHbdwxAjvatoQuLmUGc7gGfIraVwA== Date: Tue, 4 Feb 2025 13:54:03 +0000 Message-ID: References: In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=epam.com; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: PAVPR03MB10102:EE_|AS8PR03MB10120:EE_ x-ms-office365-filtering-correlation-id: 9d83a466-cb4e-41b4-86a9-08dd452362ee x-ld-processed: b41b72d0-4e9f-4c26-8a69-f949f367c91d,ExtAddr x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0;ARA:13230040|1800799024|376014|366016|38070700018; x-microsoft-antispam-message-info: =?iso-8859-1?q?ovdUm4XUauanYyfEBc+vl6pOuh?= =?iso-8859-1?q?3RHlU3ym16M4JGSAA6+bgfJskjavtcMlthDB7D49cj5bmKA9nVHxsF7VM2dv?= =?iso-8859-1?q?7WZJDtlD2gimOrixUJjTMICHWDpoy+8AuNp7FrlTbw0BxLS+86xn62bZuEHG?= =?iso-8859-1?q?+Q/iYaa7x1zBH6i8ySBGH8HP6WJW7qEI/0+S4KVvR/DIZsgHKTLEh1lMcTGw?= =?iso-8859-1?q?o/q2WTTwLneeZZWmLTqQKAmch08c3rZQhxmBWatsRaKj/tV2iVhvFfJ2KlLG?= =?iso-8859-1?q?jYwJx4iGn6gMfYSVetNjh8J3lJmB0Eapj7f2iIuVmF6WTeZijg9LpmZSjxQv?= =?iso-8859-1?q?qUTqV2oyj1SpwaCtD6rKnp5M5Q0RhaFlq0uxLLD/Dm3oFfOvWk+HHh0oqQ/+?= =?iso-8859-1?q?sgPWHsJrpO16EinSBuheOPyT4jIdl2kuVcbsiuIHr1LBIzl8bNnoPzTujr2R?= =?iso-8859-1?q?PGZe4mu/AavVcasEFxVggM9DKIjWifigQX2oeMgT7XT0b3xvB5v+xIjsMOwL?= =?iso-8859-1?q?jfzl9glb/1GFWy6WHTUPPOTCmnG+VXAs6PCs9XjwbAcm+e/RdhIL8nvdZomX?= =?iso-8859-1?q?LlazWisvAsxmetSmR9qdXF17e9T8ioNaYiJ9O9M4dt2wgBRCajFkk8swYi5U?= =?iso-8859-1?q?49wzR0i3N8ROwvBEwrkXJo9J03O5sSrbTbg5tVk4bS0yydP98QSOprBe0Vbi?= =?iso-8859-1?q?Xx0HMXkVLGL0TaMzepFHZXcbSmDu6+rgXy5VBL3fScoG8ZuhgkS7s2J+l2F5?= =?iso-8859-1?q?nKzO/kQnv7FMux8yGcEfv4xryLiQN3h1m55yA0Z+m6wIGlQoBpkBmia1sJPN?= =?iso-8859-1?q?N9Bv7nUEhiaQMHBKNQTi/7IT/te4ITxrR9HdkgUeKA9oyMNUL4bpQYIoF4Px?= =?iso-8859-1?q?VJmv3yD4Dz6cXyd93aTab2WOSfshB2rolJzx5e5cTXOe5f2LLpgJxujdWxY0?= =?iso-8859-1?q?p+lrqpI9VUBsNTQn+AE442KV27mImBJdExQVEpequKoHpFvbrG09JnqXaPkT?= =?iso-8859-1?q?gxg4P+H+OWo5T7ab+lxx9XglutVFuYvDYgFKVJliXTLCHnvW2TOkD7gc5WkO?= =?iso-8859-1?q?eqDsyD6HeKlpHHlU9FOIGKNgT+8g1NgSiWNtQm1lzi5IrWEreTvO7PTViQMX?= =?iso-8859-1?q?I/DzSxwl8b4q9an3GDw/xDNRuaW+gUFvxwQuaytfqCVRefZEUuvyXXfkqBUX?= =?iso-8859-1?q?GHy2ShldLpQ2Ge0tYGke1n2Um8z3IhIgE69qZMeDWURqLsUPFLJvkfijqxIR?= =?iso-8859-1?q?BLfAxZonFV1P7I239TgbXjylbNMzFvsXbTLS20dbEeo+k185PBE7zhxbPR+0?= =?iso-8859-1?q?+qgtwnBJM8bcnH+gOYzu4indNoixRu8+GuAC+PJlyKKHQ1KHo+lgHNNY4iOY?= =?iso-8859-1?q?8Gl10NAJ9hf8t88nN/hrzajXAM2BfV80TBJkeIWje53AJAY5QgGAYVv0M76q?= =?iso-8859-1?q?pL?= x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PAVPR03MB10102.eurprd03.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(376014)(366016)(38070700018);DIR:OUT;SFP:1101; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?iso-8859-1?q?UTIgingT1mqyiYybcUwVumH?= =?iso-8859-1?q?QTRaPBdraZulgmNxE8ErJwBfjk+w9L+oE/TtUncVn0suin+d4pOsx1rgmagI?= =?iso-8859-1?q?whd0xgpEonmuDhJX9aZ+RfZjGwD5Fvedt5SJ75ekXKsve1L5VgbVFSa+hKpM?= =?iso-8859-1?q?RQHGiMCot6MBCrWeLa4g3Wx9zVqRe8fwAvoDL6QUwE5SK0TrVHwdAGm+yjq4?= =?iso-8859-1?q?BKrZePZ1BLsQxT6PUxweTif5BQk+09VP4pHGoeHLS+LCC5gLKgJQPVWe2T/J?= =?iso-8859-1?q?5MIM+vziqd2mYMIGHeH+lPpFNaT7dWZoKQ7HXJZo3czZ7Ch9DHNR/uOB7ikO?= =?iso-8859-1?q?e7YtCws14WqVpyKqx/A9dzVB+upVNIpj0ug4bMJ4hzTHvBKHyck+na1/H3kI?= =?iso-8859-1?q?ALhaqLaKnvabRzaN5gp9+wu6OvHPIl+wvb16+hUbCUMUzIpABfT4D1rgW++h?= =?iso-8859-1?q?y/QLcqHRMPb4wtIiUJyFw3oyRRn6JqA/lruEF65E5Jn6H0UknVTBiCgWL9q+?= =?iso-8859-1?q?4jv12X6rVgVTanMG/658pDnJ4SgQPHV/9dkAaqxYfyGT7aJ3w0Kn4RyBvFsw?= =?iso-8859-1?q?8C5yuBccP55TteSY+f/gf4vrrbH3Wi0U9JGIMFEtdOD4UCr89NAA2YzvXsv1?= =?iso-8859-1?q?5nh/CB/6vQkjfxERjgS7uLHVusH7cnFuVWz8YfAsLo/3MDbhRtUeOUC2G/GD?= =?iso-8859-1?q?EDao3XyfAoAj8cSIpvYk0yDfEZC54QOiukLhEOrhK6L7f28B2lnc5uMVUlea?= =?iso-8859-1?q?kNJicA1pZfYz55a3bRkHwKH93KZctTUh6nYQaaecF2qdFUt4B+Wdsd0cZTDF?= =?iso-8859-1?q?WP0EcLn+nLGbztST4o1tEUqOit31caL7VKB4inhUsi4wWQURq6jM1WWCNhGO?= =?iso-8859-1?q?1PaBnuw1ADlD9HSRdwUJ+lQhIf/DaB3IJEupTrK0X3ZGzLZ1UIt6+CyLq7Uq?= =?iso-8859-1?q?tj8Gnnn8Y6NYOSW58udfLfPxw1aAoxwtK4u8KMdnzvMFi5VeGwsPCtDjoc09?= =?iso-8859-1?q?w03HZHxu1GBoUpfufhUD893rdVu7/USp8IChX8CtIgMVp6WBCy5roa0Osiz7?= =?iso-8859-1?q?opLj3Kv+WwrnZzGF+CjHt0Ke2hSt08/ycVHv1rbOxiqQWCbWeI/umY2JE/94?= =?iso-8859-1?q?gscvP9yM8zY8CQ7/pkxb0haa/0NTGisUKWavYlLs90RLLfyt9MHbD6amZxYl?= =?iso-8859-1?q?ejEZPeRSpsxVeeL1ICV0y9kkun6YjAvfYxnN2iy70NVj0TExTyPUl4R513iw?= =?iso-8859-1?q?RSvdIaYki9LDjVewuy6j75vIa2kggSnU3LoRzvUBpf6c4XpOCHZYaIgcWQVe?= =?iso-8859-1?q?qF6Y5JTZOSyO71+YVIRHjSBH/7rbbwgWOqLkn+nzpAAQ5setV0F2z6htb9K4?= =?iso-8859-1?q?OVfHbwrhDyK4Egq3Em1OMQmFoFkosO2sRPRRGhM3G5qj43Dm62VKnntkn4dm?= =?iso-8859-1?q?zNsyH8j2laB/q3vmAAvUm9xFVJ7OVknGF9t5PX1kfcFeeN+iSP3ovqHBGf9S?= =?iso-8859-1?q?7NKPrLM1FyfKZF0BDEBE9xWNMwJEjB/msl8d4J8IHlEbYNZSRgv50aUJiDfU?= =?iso-8859-1?q?NLghF4BmH7BqeBL1QInq+kjMETJeTxQ3tpxJsvtZsGjkCxxw2HfaunaCygqV?= =?iso-8859-1?q?LgMO35T+kA2MJyzf7+jeit5XaV7LBtXrIBBINtw=3D=3D?= MIME-Version: 1.0 X-OriginatorOrg: epam.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: PAVPR03MB10102.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 9d83a466-cb4e-41b4-86a9-08dd452362ee X-MS-Exchange-CrossTenant-originalarrivaltime: 04 Feb 2025 13:54:03.6975 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: b41b72d0-4e9f-4c26-8a69-f949f367c91d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: eCb5sUt8Ou8oYBLaJpcQ33TbviOQihttPZ7ULNfKPjfhVZnhQmcoVS8DW7c/FepWsU1HDoBE5I4pqMhDUrpPWA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR03MB10120 From: Oleksandr Andrushchenko Implement support for PCI devices in the SMMU driver. Make arm_smmu_master structure to hold a pointer to the device to allow it to hold PCI devices. Trigger iommu-map parsing when new PCI device is added. Add checks to assign/deassign functions to ensure PCI devices are handled correctly. Implement basic quarantining. All pci devices are automatically assigned to hardware domain if it exists to ensure it can probe them. TODO: Implement scratch page quarantining support. Signed-off-by: Oleksandr Tyshchenko Signed-off-by: Oleksandr Andrushchenko Signed-off-by: Stewart Hildebrand Signed-off-by: Mykyta Poturai --- v6->v7: * use d->pci_lock in arm_smmu_assign_dev() * remove !is_hardware_domain and pdev->domain == d checks in assign to support future dom0less use case when dom0 is using vPCI * remove stale todo in dev_get_dev_node * don't print "" * remove redundant dt_device_is_protected check * remove assign/deassing prints * change assign logic to remove reassign reimplementation * check if pdev->domain exists before assigning to it * explain pdev->devfn check * make reassign check stricter and update comment v5->v6: * check for hardware_domain == NULL (dom0less test case) * locking: assign pdev->domain before list_add() v4->v5: * assign device to pdev->domain (usually dom0) by default in add_device() hook * deassign from hwdom * rebase on top of ("dynamic node programming using overlay dtbo") series * remove TODO in comment about device prints * add TODO regarding locking * fixup after dropping ("xen/arm: Move is_protected flag to struct device") v3->v4: * add new device_is_protected check in add_device hook to match SMMUv3 and IPMMU-VMSA drivers v2->v3: * invoke iommu_add_pci_sideband_ids() from add_device hook v1->v2: * ignore add_device/assign_device/reassign_device calls for phantom functions (i.e. devfn != pdev->devfn) downstream->v1: * wrap unused function in #ifdef 0 * remove the remove_device() stub since it was submitted separately to the list [XEN][PATCH v6 12/19] xen/smmu: Add remove_device callback for smmu_iommu ops https://lists.xenproject.org/archives/html/xen-devel/2023-05/msg00204.html * arm_smmu_(de)assign_dev: return error instead of crashing system * update condition in arm_smmu_reassign_dev * style fixup * add && !is_hardware_domain(d) into condition in arm_smmu_assign_dev() (cherry picked from commit 0c11a7f65f044c26d87d1e27ac6283ef1f9cfb7a from the downstream branch spider-master from https://github.com/xen-troops/xen.git) --- xen/drivers/passthrough/arm/smmu.c | 190 ++++++++++++++++++++++------- 1 file changed, 147 insertions(+), 43 deletions(-) diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c index 03d22bce1e..cfddcbb1ad 100644 --- a/xen/drivers/passthrough/arm/smmu.c +++ b/xen/drivers/passthrough/arm/smmu.c @@ -132,11 +132,21 @@ enum irqreturn { typedef enum irqreturn irqreturn_t; -/* Device logger functions - * TODO: Handle PCI - */ -#define dev_print(dev, lvl, fmt, ...) \ - printk(lvl "smmu: %s: " fmt, dt_node_full_name(dev_to_dt(dev)), ## __VA_ARGS__) +/* Device logger functions */ +#ifndef CONFIG_HAS_PCI +#define dev_print(dev, lvl, fmt, ...) \ + printk(lvl "smmu: %s: " fmt, dev_name(dev), ## __VA_ARGS__) +#else +#define dev_print(dev, lvl, fmt, ...) ({ \ + if ( !dev_is_pci((dev)) ) \ + printk(lvl "smmu: %s: " fmt, dev_name((dev)), ## __VA_ARGS__); \ + else \ + { \ + struct pci_dev *pdev = dev_to_pci((dev)); \ + printk(lvl "smmu: %pp: " fmt, &pdev->sbdf, ## __VA_ARGS__); \ + } \ +}) +#endif #define dev_dbg(dev, fmt, ...) dev_print(dev, XENLOG_DEBUG, fmt, ## __VA_ARGS__) #define dev_notice(dev, fmt, ...) dev_print(dev, XENLOG_INFO, fmt, ## __VA_ARGS__) @@ -188,6 +198,7 @@ static void __iomem *devm_ioremap_resource(struct device *dev, * Xen: PCI functions * TODO: It should be implemented when PCI will be supported */ +#if 0 /* unused */ #define to_pci_dev(dev) (NULL) static inline int pci_for_each_dma_alias(struct pci_dev *pdev, int (*fn) (struct pci_dev *pdev, @@ -197,6 +208,7 @@ static inline int pci_for_each_dma_alias(struct pci_dev *pdev, BUG(); return 0; } +#endif /* Xen: misc */ #define PHYS_MASK_SHIFT PADDR_BITS @@ -631,7 +643,7 @@ struct arm_smmu_master_cfg { for (i = 0; idx = (cfg)->smendx[i], (i) < (num); ++(i)) struct arm_smmu_master { - struct device_node *of_node; + struct device *dev; struct rb_node node; struct arm_smmu_master_cfg cfg; }; @@ -723,7 +735,7 @@ arm_smmu_get_fwspec(struct arm_smmu_master_cfg *cfg) { struct arm_smmu_master *master = container_of(cfg, struct arm_smmu_master, cfg); - return dev_iommu_fwspec_get(&master->of_node->dev); + return dev_iommu_fwspec_get(master->dev); } static void parse_driver_options(struct arm_smmu_device *smmu) @@ -742,21 +754,11 @@ static void parse_driver_options(struct arm_smmu_device *smmu) static struct device_node *dev_get_dev_node(struct device *dev) { -#if 0 /* Xen: TODO: Add support for PCI */ - if (dev_is_pci(dev)) { - struct pci_bus *bus = to_pci_dev(dev)->bus; - - while (!pci_is_root_bus(bus)) - bus = bus->parent; - return bus->bridge->parent->of_node; - } -#endif - return dev->of_node; } static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu, - struct device_node *dev_node) + struct device *dev) { struct rb_node *node = smmu->masters.rb_node; @@ -765,9 +767,9 @@ static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu, master = container_of(node, struct arm_smmu_master, node); - if (dev_node < master->of_node) + if (dev < master->dev) node = node->rb_left; - else if (dev_node > master->of_node) + else if (dev > master->dev) node = node->rb_right; else return master; @@ -802,9 +804,9 @@ static int insert_smmu_master(struct arm_smmu_device *smmu, = container_of(*new, struct arm_smmu_master, node); parent = *new; - if (master->of_node < this->of_node) + if (master->dev < this->dev) new = &((*new)->rb_left); - else if (master->of_node > this->of_node) + else if (master->dev > this->dev) new = &((*new)->rb_right); else return -EEXIST; @@ -836,28 +838,30 @@ static int arm_smmu_dt_add_device_legacy(struct arm_smmu_device *smmu, struct arm_smmu_master *master; struct device_node *dev_node = dev_get_dev_node(dev); - master = find_smmu_master(smmu, dev_node); + master = find_smmu_master(smmu, dev); if (master) { dev_err(dev, - "rejecting multiple registrations for master device %s\n", - dev_node->name); + "rejecting multiple registrations for master device\n"); return -EBUSY; } master = devm_kzalloc(dev, sizeof(*master), GFP_KERNEL); if (!master) return -ENOMEM; - master->of_node = dev_node; + master->dev = dev; - /* Xen: Let Xen know that the device is protected by an SMMU */ - dt_device_set_protected(dev_node); + if ( !dev_is_pci(dev) ) + { + /* Xen: Let Xen know that the device is protected by an SMMU */ + dt_device_set_protected(dev_node); + } for (i = 0; i < fwspec->num_ids; ++i) { if (!(smmu->features & ARM_SMMU_FEAT_STREAM_MATCH) && (fwspec->ids[i] >= smmu->num_mapping_groups)) { dev_err(dev, - "stream ID for master device %s greater than maximum allowed (%d)\n", - dev_node->name, smmu->num_mapping_groups); + "SMMU stream ID %d is greater than maximum allowed (%d)\n", + fwspec->ids[i], smmu->num_mapping_groups); return -ERANGE; } master->cfg.smendx[i] = INVALID_SMENDX; @@ -872,7 +876,7 @@ static int arm_smmu_dt_remove_device_legacy(struct arm_smmu_device *smmu, struct device_node *dev_node = dev_get_dev_node(dev); int ret; - master = find_smmu_master(smmu, dev_node); + master = find_smmu_master(smmu, dev); if (master == NULL) { dev_err(dev, "No registrations found for master device %s\n", @@ -884,8 +888,9 @@ static int arm_smmu_dt_remove_device_legacy(struct arm_smmu_device *smmu, if (ret) return ret; - /* Protected by dt_host_lock and dtdevs_lock as caller holds these locks. */ - dev_node->is_protected = false; + if ( !dev_is_pci(dev) ) + /* Protected by dt_host_lock and dtdevs_lock as caller holds these locks. */ + dev_node->is_protected = false; kfree(master); return 0; @@ -914,6 +919,12 @@ static int register_smmu_master(struct arm_smmu_device *smmu, fwspec); } +/* Forward declaration */ +static int arm_smmu_assign_dev(struct domain *d, u8 devfn, + struct device *dev, u32 flag); +static int arm_smmu_deassign_dev(struct domain *d, uint8_t devfn, + struct device *dev); + /* * The driver which supports generic IOMMU DT bindings must have this * callback implemented. @@ -938,6 +949,23 @@ static int arm_smmu_dt_add_device_generic(u8 devfn, struct device *dev) { struct arm_smmu_device *smmu; struct iommu_fwspec *fwspec; + int ret; + +#ifdef CONFIG_HAS_PCI + if ( dev_is_pci(dev) ) + { + struct pci_dev *pdev = dev_to_pci(dev); + int ret; + + /* Ignore calls for phantom functions */ + if ( devfn != pdev->devfn ) + return 0; + + ret = iommu_add_pci_sideband_ids(pdev); + if ( ret < 0 ) + iommu_fwspec_free(dev); + } +#endif fwspec = dev_iommu_fwspec_get(dev); if (fwspec == NULL) @@ -947,7 +975,25 @@ static int arm_smmu_dt_add_device_generic(u8 devfn, struct device *dev) if (smmu == NULL) return -ENXIO; - return arm_smmu_dt_add_device_legacy(smmu, dev, fwspec); + ret = arm_smmu_dt_add_device_legacy(smmu, dev, fwspec); + if ( ret ) + return ret; + +#ifdef CONFIG_HAS_PCI + if ( dev_is_pci(dev) ) + { + struct pci_dev *pdev = dev_to_pci(dev); + + /* + * During PHYSDEVOP_pci_device_add, Xen does not assign the + * device, so we must do it here. + */ + if ( pdev->domain ) + ret = arm_smmu_assign_dev(pdev->domain, devfn, dev, 0); + } +#endif + + return ret; } static int arm_smmu_dt_xlate_generic(struct device *dev, @@ -970,11 +1016,10 @@ static struct arm_smmu_device *find_smmu_for_device(struct device *dev) { struct arm_smmu_device *smmu; struct arm_smmu_master *master = NULL; - struct device_node *dev_node = dev_get_dev_node(dev); spin_lock(&arm_smmu_devices_lock); list_for_each_entry(smmu, &arm_smmu_devices, list) { - master = find_smmu_master(smmu, dev_node); + master = find_smmu_master(smmu, dev); if (master) break; } @@ -2066,6 +2111,7 @@ static bool arm_smmu_capable(enum iommu_cap cap) } #endif +#if 0 /* Not used */ static int __arm_smmu_get_pci_sid(struct pci_dev *pdev, u16 alias, void *data) { *((u16 *)data) = alias; @@ -2076,6 +2122,7 @@ static void __arm_smmu_release_pci_iommudata(void *data) { kfree(data); } +#endif static int arm_smmu_add_device(struct device *dev) { @@ -2083,12 +2130,13 @@ static int arm_smmu_add_device(struct device *dev) struct arm_smmu_master_cfg *cfg; struct iommu_group *group; void (*releasefn)(void *data) = NULL; - int ret; smmu = find_smmu_for_device(dev); if (!smmu) return -ENODEV; + /* There is no need to distinguish here, thanks to PCI-IOMMU DT bindings */ +#if 0 if (dev_is_pci(dev)) { struct pci_dev *pdev = to_pci_dev(dev); struct iommu_fwspec *fwspec; @@ -2113,10 +2161,12 @@ static int arm_smmu_add_device(struct device *dev) &fwspec->ids[0]); releasefn = __arm_smmu_release_pci_iommudata; cfg->smmu = smmu; - } else { + } else +#endif + { struct arm_smmu_master *master; - master = find_smmu_master(smmu, dev->of_node); + master = find_smmu_master(smmu, dev); if (!master) { return -ENODEV; } @@ -2784,6 +2834,42 @@ static int arm_smmu_assign_dev(struct domain *d, u8 devfn, return -ENOMEM; } +#ifdef CONFIG_HAS_PCI + if ( dev_is_pci(dev) ) + { + struct pci_dev *pdev = dev_to_pci(dev); + + /* Ignore calls for phantom functions */ + if ( devfn != pdev->devfn ) + return 0; + + ASSERT(pcidevs_locked()); + + write_lock(&pdev->domain->pci_lock); + list_del(&pdev->domain_list); + write_unlock(&pdev->domain->pci_lock); + + pdev->domain = d; + + write_lock(&d->pci_lock); + list_add(&pdev->domain_list, &d->pdev_list); + write_unlock(&d->pci_lock); + + /* dom_io is used as a sentinel for quarantined devices */ + if ( d == dom_io ) + { + struct iommu_domain *domain = dev_iommu_domain(dev); + if ( !iommu_quarantine ) + return 0; + + if ( domain && domain->priv ) + arm_smmu_deassign_dev(domain->priv->cfg.domain, devfn, dev); + + return 0; + } + } +#endif + if (!dev_iommu_group(dev)) { ret = arm_smmu_add_device(dev); if (ret) @@ -2833,11 +2919,27 @@ out: return ret; } -static int arm_smmu_deassign_dev(struct domain *d, struct device *dev) +static int arm_smmu_deassign_dev(struct domain *d, uint8_t devfn, + struct device *dev) { struct iommu_domain *domain = dev_iommu_domain(dev); struct arm_smmu_xen_domain *xen_domain; +#ifdef CONFIG_HAS_PCI + if ( dev_is_pci(dev) ) + { + struct pci_dev *pdev = dev_to_pci(dev); + + /* Ignore calls for phantom functions */ + if ( devfn != pdev->devfn ) + return 0; + + /* dom_io is used as a sentinel for quarantined devices */ + if ( d == dom_io ) + return 0; + } +#endif + xen_domain = dom_iommu(d)->arch.priv; if (!domain || domain->priv->cfg.domain != d) { @@ -2864,14 +2966,16 @@ static int arm_smmu_reassign_dev(struct domain *s, struct domain *t, { int ret = 0; - /* Don't allow remapping on other domain than hwdom */ - if ( t && !is_hardware_domain(t) ) + /* Don't allow remapping on other domain than hwdom + * or dom_io for PCI devices + */ + if ( t && !is_hardware_domain(t) && (t != dom_io || !dev_is_pci(dev)) ) return -EPERM; if (t == s) return 0; - ret = arm_smmu_deassign_dev(s, dev); + ret = arm_smmu_deassign_dev(s, devfn, dev); if (ret) return ret;