From nobody Sun Sep 7 06:47:11 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; arc=fail (BodyHash is different from the expected one); dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1755226638291749.1430900749934; Thu, 14 Aug 2025 19:57:18 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 4142D985; Thu, 14 Aug 2025 22:57:17 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 07A62B31; Thu, 14 Aug 2025 22:54:47 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 948D9984; Thu, 14 Aug 2025 22:54:37 -0400 (EDT) Received: from NAM11-DM6-obe.outbound.protection.outlook.com (mail-dm6nam11on2084.outbound.protection.outlook.com [40.107.223.84]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id B413F97E for ; Thu, 14 Aug 2025 22:54:33 -0400 (EDT) Received: from PH7PR12MB6834.namprd12.prod.outlook.com (2603:10b6:510:1b4::18) by PH7PR12MB5685.namprd12.prod.outlook.com (2603:10b6:510:13c::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9031.15; Fri, 15 Aug 2025 02:54:29 +0000 Received: from PH7PR12MB6834.namprd12.prod.outlook.com ([fe80::f432:162b:b94e:d2cb]) by PH7PR12MB6834.namprd12.prod.outlook.com ([fe80::f432:162b:b94e:d2cb%4]) with mapi id 15.20.9009.017; Fri, 15 Aug 2025 02:54:28 +0000 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=0.2 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, FORGED_SPF_HELO,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_PASS autolearn=no autolearn_force=no version=3.4.4 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=QD1hb6E1Ud7tcFcNwPnHamfiQOMGcwrB3v/JTSVyqUGifSDhl61dp3P65ihHQR/jhtiFmp+y1WbrMsEFerwGVLwkQH21Yxf3UW07fVHyZFIFWXxOblvVcBklaN4UhBibLqMDSPtl6nt2w8YjtbBy2GHvkZnV5Larwa2IRp9hbnC9vG3tQ7BctK7yPvwQxEIADn5xqehnzUJIpLvHZD+NHMRCRSL6i1NXNdZ31GqyjdU8WFehR95/xJr/e0reLZiryTmxI+aOXlzY+i9n8N/Wp16BaBbuR8/8oFhGbLGvcyLAM6dAeeXlN0VHyT2RNq9FfG8jJqxBE/fiBNIi2SZKMA== 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=fOw+lwd5J7DulSoW1djv3N/oSbw84J6eC+7DzUyCeCc=; b=VwIBMBLp4KYHF4IKJQ0MPUs1WH42b0yuyG15MbAhB/EXnwM36mCX82Fl6mgbnyBbZw1yv/ZtTZwD2Lj9bDw19OXX//+LXuQ3s/X69+0/w+vbvxe2lItHpzpLrDSrCmYwz/PFxg4gn1GlnZo8QucfyhJtvJTDdcJEqy3zz4FhP8qlECz8feIQNaggai9wzssNXawKgYeR46AmBx4ZsJ7VmRiR/mpho0Q+8pQgvtvGj1Ve20OWKYqWYGQvUa2u7HAPkdeMwjdD3LnidchXRUkGXzlWS16861cWi3dqrx6MwAINYTcfu8EBAqRjYSnYCF1EQbdhT250BMwz6uxHVpZzcg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=fOw+lwd5J7DulSoW1djv3N/oSbw84J6eC+7DzUyCeCc=; b=Zg1EBW2lwz5ovl3/5EzAfWtI6boyx98j/+4P+mO4n2VNYP4IAr1nuCrB+zInVpYyXHUrMASG7mPguxvG41sFiIDE1sPKtz6/OISNw7qUzL8HDa9NVql2pJc7mdMzdQZRRivFa+OUmTl6ypJZr3sQ+5eZTHzafIAEKORgXxiNLN1CHzdFsAGhLOmtvmchvDYwfZomgGWadp2cbuG5UbSgdgSpGlfKMErF/DdhKu1VrtOVSmsOPG0Hofqv8PKRP1z7hq9kYo3S8eCAfr5u1bMNkSpUAORUaYuolZcElEnmaZTJD4nlRpV6aBRbTX2MWJo3MIMrKJrW+xdfiKAlwEFF1g== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; To: devel@lists.libvirt.org Subject: [RFC PATCH 1/5] qemu: add IOMMU model smmuv3Dev Date: Thu, 14 Aug 2025 19:54:10 -0700 Message-ID: <20250815025415.2805374-2-nathanc@nvidia.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250815025415.2805374-1-nathanc@nvidia.com> References: <20250815025415.2805374-1-nathanc@nvidia.com> X-ClientProxiedBy: BYAPR05CA0098.namprd05.prod.outlook.com (2603:10b6:a03:e0::39) To PH7PR12MB6834.namprd12.prod.outlook.com (2603:10b6:510:1b4::18) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PH7PR12MB6834:EE_|PH7PR12MB5685:EE_ X-MS-Office365-Filtering-Correlation-Id: 95858a45-1ef9-4293-1dd9-08dddba70d6c X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|366016|376014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?gkFEsC4df0NXEwETuFN1N5VOY57KnbCAAKwmx9j+3Lw14/WRLmPOm8Iu9qE1?= =?us-ascii?Q?MxSAvFYpIo7mPC5kMJb/caCuq+RL4HZKyuW/odv6ogQKYI3tf1dweTnPeiFe?= =?us-ascii?Q?kF3L9KmP4Bag5Tr+nTV0OwcR2f7QfMV5YbvkLkiTqwPsTTjESahyvCzD2wp6?= =?us-ascii?Q?aOLNWA0CQVoU78AHgvT03loNSvPmu4o6d/GrJygAORycWoQdq0as35M3qXhY?= =?us-ascii?Q?NxoHbQmCzIpu84lACHposjjUXAhPeJLfq36iQg2O/NJ3HeR2JSlIctK7jbKM?= =?us-ascii?Q?qcm517UJbA5py/RTYN2BV/6cimDyyO5DqHmrFvp94O8c+1fZOuQns/oKmzdP?= =?us-ascii?Q?mqfU/M0KDkAsT3RVGuHjkKb3Lrdkop+SMCIBHe9vsnmjn7pXixI6qspdMoP0?= =?us-ascii?Q?ub1m9wSawZNEYmy2n0xcNLfc0x21UaVF+JlpCt7RjQjBEX33bWU/Hrc7Fx0N?= =?us-ascii?Q?CceHQB3uiyxbs7xr3AZ5FO19nl7zo9RenyJqjeQcTA7bL1VIb80wLP7NC1nY?= =?us-ascii?Q?jCIvBFV1g2zBJGz/x0h0U0N6CUcepLk0yM7lJ4DmrhuXFJZF5CS1FVMEYr/e?= =?us-ascii?Q?zixmXPDCHqLrSEKzD7NjhKVE35a2XujchIYtVIUCDQYcvsClwKcSFT5hDKH3?= =?us-ascii?Q?US0Fr/F9KpE60ifF7/yDc0Iw3Ld5awQ4fZIK1agT7uC28qIiGCqi5zAEV3KL?= =?us-ascii?Q?oUgBXWy7AlMGVXhCpNYWvinHfOcLYU3O1E9u11QQVo2FbZvumr0YeH+09qsm?= =?us-ascii?Q?Mv56UkCpcej3X9RUv2Mmg6mOf/IMiGdAuz+3lyi/L9gVCa45OyQ5G7XIANRQ?= =?us-ascii?Q?IPa1tIT6q7K4NK3PuKerA/55sOV0In7rCMUfy6Cg6arH4LEMWOVM9PsWfAcL?= =?us-ascii?Q?w9N0dxbNbarajn0KEtkvcFN/jyKkQi5f1FPcHoQebqsgi68Woymx0AB7V8pg?= =?us-ascii?Q?z5O+ZnPjrvJ+kMlFSZOOFk2wrcZHZE0loU15ATkDxaKf+R2ZHqoLARByZ6ow?= =?us-ascii?Q?sPCSW6ICBgQ5CBMjguOR6A8pxFFwjEk3Y9+tVFr1JCQA7iH7RnMMCNoWvijl?= =?us-ascii?Q?INUT79GdEUD3DccLIdt9uOoN4d99lvEpAuOQ/qTsA0JtCUhPFDFvHxG/jEoa?= =?us-ascii?Q?H+1IKZ21or0rJFp0O0Zn2LdbwV7su1LgLwpN7ByzDAnby5Z3v0SEb24OQy8s?= =?us-ascii?Q?3fDFsyxw8NPjxlJtq5ifD9NEEmI7eBrVBsXR7TJUR9oc/Wbk4UwOfpv3hOXU?= =?us-ascii?Q?RBGHAHeveW264RC5hXz4DfTUfQ5SDNP7A8hAiMM5oIGIMMdgZYKvqikQ+Fdp?= =?us-ascii?Q?ABI48SY/55TfcGyz7rTvFkaTEMV/8VVJLJFMsffdWIlHWPpem9kwClqX5u1e?= =?us-ascii?Q?HyDnyHtyVJ/CBonAb9jrGzHmlp9OL0yAqIy6F6tAxMqaHb6Iy7Ovtwuc80r1?= =?us-ascii?Q?BaEcIFE538U=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PH7PR12MB6834.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(366016)(376014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?vIsUL+0JXYyMLcQcBGUTU9fr8m/SYnVSFvhduOo/e4EBlf1joa9+GXCl5oc2?= =?us-ascii?Q?tYq9wNoP9IHBZ4wY0Nz+Ma0mqWZVHZnHNQlNSsMqY/5RPwi4wMxo1e0JVLEz?= =?us-ascii?Q?xFhKwmRK6sgHSMFYrgBiVyWmtfsd3IwPczT8JzhmeT31qD6I2di8ovI77hDh?= =?us-ascii?Q?TydxvEAr169NryD9URMgrhQBzBL6S+4zB7WGzmFj61nipNJbnvUseIq8V/E4?= =?us-ascii?Q?g2F7JwKwCLoA+DgRz5nlbO7AfJrFs64eYClJXah2taUmTF+9+A0pSlZ76hej?= =?us-ascii?Q?p0vFk2HXbqUdv6RbEPRD+WH1/FaaOexrHfSnXRqXXkexjq7BcBdXwuWzysyD?= =?us-ascii?Q?yM57Tzmv3fOrOAYxtiaYqc5jTTHqhV5elu7i0gBkSJDjoHgZkkWn5ZrAaCka?= =?us-ascii?Q?41IQlc1oED+yaIgl3fBuK7q/UpCB9+dnr5thdXmiNevuBo1MvtOwzzelNNmq?= =?us-ascii?Q?muKGsV7aTyDh83yf+dW19H4WhScotTYzkjjJGtff7RiEiP+4omW9hn2STcjI?= =?us-ascii?Q?zkcZ44MCUav8qmk6OChBZ8TUkB+KBuneth9mfYZc3aEsh/Tmc4HPm7onbQs8?= =?us-ascii?Q?PCscFsOsIb5I2e6TERcXDk5KUjbC9/saQYTqo6bhsNcqU1A0SwIOYvFfzBDB?= =?us-ascii?Q?wT8tTgvAthpOXcDOSJG6ewcqSApT//5cYl/lC4VrT/zQ73fZgFB7BTClUiZn?= =?us-ascii?Q?EpN9WsMYf2IpBW/RZvESiU3UR6c3C/98awZX/8NRSk51vBqptPDgQ3Y1RkaO?= =?us-ascii?Q?oHZYmR4L2pMTA4v/PU0Ig9PNfES1THH57PWTQkVVz7XvCzV38RlX95ePW57K?= =?us-ascii?Q?olQdUGkAcKiFMnrvMfe4S0aqV4Zv548JDxJC8fHlzmBzlcjRzuJ7a2V1g7P8?= =?us-ascii?Q?sS8llphakYSXvcsjwg7r4c1UQi5hLdJP8sfuJB7NiM7D2L4YK3hvoAl2n5SK?= =?us-ascii?Q?b/4Cw9Ex7FMN59QM6VN+fWKy/iq9AkSdbeXyVfP/ttFs6a8ZHrDBcBUKfBi5?= =?us-ascii?Q?4otozrNAnoSVetIItsErG84FkvQwPqtjgi1cwNrsNi5ixBoqn/JUUiVerADH?= =?us-ascii?Q?eQVUd4nT5NC35utmxU13Lsn2+BxIVbpL/bR0pc7PyjB6Lqs4KqWwFhDO5xVH?= =?us-ascii?Q?kct/55g0LxcjyUapxs7LuiRMjdrZWBOLPFKNiQKSvtHeFPOYndjFXB0nmYnu?= =?us-ascii?Q?XkJM7OrcEiQziJgstgZG6TkFXHRhj+LNm/U4/VqTOrVpWfM+CKAHq/ZVdH1s?= =?us-ascii?Q?7EfAOqb8lkhHUZX8f2hDVCTRCp9N5gQFaNsAYfksOnp6eHh/IeLPJuIWXq0g?= =?us-ascii?Q?XSPCr6IfKPDkk5KtS+6vCg74w/Iam1dTFVMy6gl3/k4OtM4GUBVmq5vwSh4I?= =?us-ascii?Q?yyPM8OYlF5/+0GroQVSIWD1WoJZpJ0AxYgGn2Nb9O3mRv3DPxbODwIKnmZPr?= =?us-ascii?Q?M7rnmW4UEYOMieoVlFQMCPJPsr4Xea6AqAgDkOBUiRr9I4sKOsvAH28Uso2o?= =?us-ascii?Q?UoN1bmZd2up881Ysw8OXzLzYr2jGJhUVf1zEUqHASG4BSobzhIKywyJwyh7t?= =?us-ascii?Q?q2wf4+9Sr3pNUOhZjmcuf2SEKuCeIxYabJYMYqNg?= X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 95858a45-1ef9-4293-1dd9-08dddba70d6c X-MS-Exchange-CrossTenant-AuthSource: PH7PR12MB6834.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Aug 2025 02:54:28.8849 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: sjk/z6hZXSSGJ4VuKh2z2IOx5AbfKKZShqv/PkloUKtoPYpgwjT650fJvIrHciiLohJAk+BqOvL4CIT7gGrXhQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB5685 Content-Transfer-Encoding: quoted-printable Message-ID-Hash: IVNTVDBUJ42KWIFE5RTFFHP5QTB4NLDC X-Message-ID-Hash: IVNTVDBUJ42KWIFE5RTFFHP5QTB4NLDC X-MailFrom: nathanc@nvidia.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header CC: shameerali.kolothum.thodi@huawei.com, nicolinc@nvidia.com, nathanc@nvidia.com X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: From: Nathan Chen via Devel Reply-To: Nathan Chen X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1755226640460116600 Content-Type: text/plain; charset="utf-8" Introduce support for "smmuv3Dev" IOMMU model and "parentIdx" and "accel" IOMMU device attributes. The former indicates the index of the controller that a smmuv3Dev IOMMU device is attached to, while the latter indicates whether hardware accelerated SMMUv3 support is to be enabled. Signed-off-by: Nathan Chen --- docs/formatdomain.rst | 13 +++++- src/conf/domain_conf.c | 35 +++++++++++++++ src/conf/domain_conf.h | 3 ++ src/conf/domain_validate.c | 26 +++++++++-- src/conf/schemas/domaincommon.rng | 11 +++++ src/qemu/qemu_command.c | 73 +++++++++++++++++++++++++++++-- src/qemu/qemu_domain_address.c | 2 + src/qemu/qemu_validate.c | 16 +++++++ 8 files changed, 170 insertions(+), 9 deletions(-) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 976746e292..2558df18ef 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -9090,8 +9090,17 @@ Example: ``model`` Supported values are ``intel`` (for Q35 guests) ``smmuv3`` (:since:`since 5.5.0`, for ARM virt guests), ``virtio`` - (:since:`since 8.3.0`, for Q35 and ARM virt guests) and - ``amd`` (:since:`since 11.5.0`). + (:since:`since 8.3.0`, for Q35 and ARM virt guests), + ``amd`` (:since:`since 11.5.0`), and ``smmuv3Dev`` (for + ARM virt guests). + +``parentIdx`` + The ``parentIdx`` attribute notes the index of the controller that a + smmuv3Dev IOMMU device is attached to. + +``accel`` + The ``accel`` attribute with possible values ``on`` and ``off`` can be = used + to enable hardware acceleration support for smmuv3Dev IOMMU devices. =20 ``driver`` The ``driver`` subelement can be used to configure additional options, = some diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 59958c2f08..dc222887d4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1353,6 +1353,7 @@ VIR_ENUM_IMPL(virDomainIOMMUModel, "smmuv3", "virtio", "amd", + "smmuv3Dev", ); =20 VIR_ENUM_IMPL(virDomainVsockModel, @@ -2813,6 +2814,8 @@ virDomainIOMMUDefNew(void) =20 iommu =3D g_new0(virDomainIOMMUDef, 1); =20 + iommu->parent_idx =3D -1; + return g_steal_pointer(&iommu); } =20 @@ -14362,6 +14365,14 @@ virDomainIOMMUDefParseXML(virDomainXMLOption *xmlo= pt, VIR_XML_PROP_REQUIRED, &iommu->model) < 0) return NULL; =20 + if (virXMLPropInt(node, "parentIdx", 10, VIR_XML_PROP_NONE, + &iommu->parent_idx, -1) < 0) + return NULL; + + if (virXMLPropTristateSwitch(node, "accel", VIR_XML_PROP_NONE, + &iommu->accel) < 0) + return NULL; + if ((driver =3D virXPathNode("./driver", ctxt))) { if (virXMLPropTristateSwitch(driver, "intremap", VIR_XML_PROP_NONE, &iommu->intremap) < 0) @@ -22021,6 +22032,18 @@ virDomainIOMMUDefCheckABIStability(virDomainIOMMUD= ef *src, dst->aw_bits, src->aw_bits); return false; } + if (src->parent_idx !=3D dst->parent_idx) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target domain IOMMU device parent_idx value '%1$= d' does not match source '%2$d'"), + dst->parent_idx, src->parent_idx); + return false; + } + if (src->accel !=3D dst->accel) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target domain IOMMU device accel value '%1$d' do= es not match source '%2$d'"), + dst->accel, src->accel); + return false; + } if (src->dma_translation !=3D dst->dma_translation) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target domain IOMMU device dma translation '%1$s= ' does not match source '%2$s'"), @@ -28342,6 +28365,18 @@ virDomainIOMMUDefFormat(virBuffer *buf, virBufferAsprintf(&attrBuf, " model=3D'%s'", virDomainIOMMUModelTypeToString(iommu->model)); =20 + if (iommu->parent_idx >=3D 0 && iommu->model =3D=3D VIR_DOMAIN_IOMMU_M= ODEL_SMMUV3_DEV) { + virBufferAsprintf(&attrBuf, " parentIdx=3D'%d'", + iommu->parent_idx); + } + + if (iommu->model =3D=3D VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV) { + if (iommu->accel !=3D VIR_TRISTATE_SWITCH_ABSENT) { + virBufferAsprintf(&attrBuf, " accel=3D'%s'", + virTristateSwitchTypeToString(iommu->accel)); + } + } + virXMLFormatElement(buf, "iommu", &attrBuf, &childBuf); } =20 diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 596d138973..f87c5bbe93 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -3036,6 +3036,7 @@ typedef enum { VIR_DOMAIN_IOMMU_MODEL_SMMUV3, VIR_DOMAIN_IOMMU_MODEL_VIRTIO, VIR_DOMAIN_IOMMU_MODEL_AMD, + VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV, =20 VIR_DOMAIN_IOMMU_MODEL_LAST } virDomainIOMMUModel; @@ -3047,10 +3048,12 @@ struct _virDomainIOMMUDef { virTristateSwitch eim; virTristateSwitch iotlb; unsigned int aw_bits; + int parent_idx; virDomainDeviceInfo info; virTristateSwitch dma_translation; virTristateSwitch xtsup; virTristateSwitch pt; + virTristateSwitch accel; }; =20 typedef enum { diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index 40edecef83..f1b1b8cc55 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -3085,7 +3085,8 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *io= mmu) iommu->eim !=3D VIR_TRISTATE_SWITCH_ABSENT || iommu->iotlb !=3D VIR_TRISTATE_SWITCH_ABSENT || iommu->aw_bits !=3D 0 || - iommu->dma_translation !=3D VIR_TRISTATE_SWITCH_ABSENT) { + iommu->dma_translation !=3D VIR_TRISTATE_SWITCH_ABSENT || + iommu->accel !=3D VIR_TRISTATE_SWITCH_ABSENT) { virReportError(VIR_ERR_XML_ERROR, _("iommu model '%1$s' doesn't support additiona= l attributes"), virDomainIOMMUModelTypeToString(iommu->model)); @@ -3097,7 +3098,8 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *io= mmu) if (iommu->caching_mode !=3D VIR_TRISTATE_SWITCH_ABSENT || iommu->eim !=3D VIR_TRISTATE_SWITCH_ABSENT || iommu->aw_bits !=3D 0 || - iommu->dma_translation !=3D VIR_TRISTATE_SWITCH_ABSENT) { + iommu->dma_translation !=3D VIR_TRISTATE_SWITCH_ABSENT || + iommu->accel !=3D VIR_TRISTATE_SWITCH_ABSENT) { virReportError(VIR_ERR_XML_ERROR, _("iommu model '%1$s' doesn't support some addi= tional attributes"), virDomainIOMMUModelTypeToString(iommu->model)); @@ -3107,7 +3109,24 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *i= ommu) =20 case VIR_DOMAIN_IOMMU_MODEL_INTEL: if (iommu->pt !=3D VIR_TRISTATE_SWITCH_ABSENT || - iommu->xtsup !=3D VIR_TRISTATE_SWITCH_ABSENT) { + iommu->xtsup !=3D VIR_TRISTATE_SWITCH_ABSENT || + iommu->accel !=3D VIR_TRISTATE_SWITCH_ABSENT) { + virReportError(VIR_ERR_XML_ERROR, + _("iommu model '%1$s' doesn't support some addi= tional attributes"), + virDomainIOMMUModelTypeToString(iommu->model)); + return -1; + } + break; + + case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV: + if (iommu->intremap !=3D VIR_TRISTATE_SWITCH_ABSENT || + iommu->caching_mode !=3D VIR_TRISTATE_SWITCH_ABSENT || + iommu->eim !=3D VIR_TRISTATE_SWITCH_ABSENT || + iommu->iotlb !=3D VIR_TRISTATE_SWITCH_ABSENT || + iommu->aw_bits !=3D 0 || + iommu->dma_translation !=3D VIR_TRISTATE_SWITCH_ABSENT || + iommu->xtsup !=3D VIR_TRISTATE_SWITCH_ABSENT || + iommu->pt !=3D VIR_TRISTATE_SWITCH_ABSENT) { virReportError(VIR_ERR_XML_ERROR, _("iommu model '%1$s' doesn't support some addi= tional attributes"), virDomainIOMMUModelTypeToString(iommu->model)); @@ -3132,6 +3151,7 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *io= mmu) =20 case VIR_DOMAIN_IOMMU_MODEL_VIRTIO: case VIR_DOMAIN_IOMMU_MODEL_AMD: + case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV: case VIR_DOMAIN_IOMMU_MODEL_LAST: break; } diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincom= mon.rng index a714c3fcc5..0e57d2a9b9 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -6246,8 +6246,19 @@ smmuv3 virtio amd + smmuv3Dev + + + + + + + + + + diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 457dee7029..8a124a495b 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6250,6 +6250,63 @@ qemuBuildBootCommandLine(virCommand *cmd, } =20 =20 +static virJSONValue * +qemuBuildPCISmmuv3DevDevProps(const virDomainDef *def, + const virDomainIOMMUDef *iommu) +{ + g_autoptr(virJSONValue) props =3D NULL; + g_autofree char *bus =3D NULL; + size_t i; + bool contIsPHB =3D false; + + for (i =3D 0; i < def->ncontrollers; i++) { + virDomainControllerDef *cont =3D def->controllers[i]; + if (cont->idx =3D=3D iommu->parent_idx) { + if (cont->type =3D=3D VIR_DOMAIN_CONTROLLER_TYPE_PCI) { + const char *alias =3D cont->info.alias; + contIsPHB =3D virDomainControllerIsPSeriesPHB(cont); + + if (!alias) + return NULL; + + if (virDomainDeviceAliasIsUserAlias(alias)) { + if (cont->model =3D=3D VIR_DOMAIN_CONTROLLER_MODEL_PCI= _ROOT && + iommu->parent_idx <=3D 0) { + if (qemuDomainSupportsPCIMultibus(def)) + bus =3D g_strdup("pci.0"); + else + bus =3D g_strdup("pci"); + } else if (cont->model =3D=3D VIR_DOMAIN_CONTROLLER_MO= DEL_PCIE_ROOT) { + bus =3D g_strdup("pcie.0"); + } + } else { + bus =3D g_strdup(alias); + } + break; + } + } + } + + if (!bus) + return NULL; + + if (contIsPHB && iommu->parent_idx > 0) { + char *temp_bus =3D g_strdup_printf("%s.0", bus); + g_free(bus); + bus =3D temp_bus; + } + + if (virJSONValueObjectAdd(&props, + "s:driver", "arm-smmuv3", + "s:primary-bus", bus, + "b:accel", (iommu->accel =3D=3D VIR_TRISTATE= _SWITCH_ON), + NULL) < 0) + return NULL; + + return g_steal_pointer(&props); +} + + static int qemuBuildIOMMUCommandLine(virCommand *cmd, const virDomainDef *def, @@ -6298,7 +6355,6 @@ qemuBuildIOMMUCommandLine(virCommand *cmd, return 0; =20 case VIR_DOMAIN_IOMMU_MODEL_SMMUV3: - /* There is no -device for SMMUv3, so nothing to be done here */ return 0; =20 case VIR_DOMAIN_IOMMU_MODEL_AMD: @@ -6329,6 +6385,14 @@ qemuBuildIOMMUCommandLine(virCommand *cmd, =20 return 0; =20 + case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV: + if (!(props =3D qemuBuildPCISmmuv3DevDevProps(def, iommu))) + return -1; + if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCaps) = < 0) + return -1; + + return 0; + case VIR_DOMAIN_IOMMU_MODEL_LAST: default: virReportEnumRangeError(virDomainIOMMUModel, iommu->model); @@ -7162,6 +7226,7 @@ qemuBuildMachineCommandLine(virCommand *cmd, case VIR_DOMAIN_IOMMU_MODEL_INTEL: case VIR_DOMAIN_IOMMU_MODEL_VIRTIO: case VIR_DOMAIN_IOMMU_MODEL_AMD: + case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV: /* These IOMMUs are formatted in qemuBuildIOMMUCommandLine */ break; =20 @@ -10807,15 +10872,15 @@ qemuBuildCommandLine(virDomainObj *vm, if (qemuBuildBootCommandLine(cmd, def) < 0) return NULL; =20 - if (qemuBuildIOMMUCommandLine(cmd, def, qemuCaps) < 0) - return NULL; - if (qemuBuildGlobalControllerCommandLine(cmd, def) < 0) return NULL; =20 if (qemuBuildControllersCommandLine(cmd, def, qemuCaps) < 0) return NULL; =20 + if (qemuBuildIOMMUCommandLine(cmd, def, qemuCaps) < 0) + return NULL; + if (qemuBuildMemoryDeviceCommandLine(cmd, cfg, def, priv) < 0) return NULL; =20 diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 96a9ca9b14..06bf4fab32 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -952,6 +952,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDevic= eDef *dev, =20 case VIR_DOMAIN_IOMMU_MODEL_INTEL: case VIR_DOMAIN_IOMMU_MODEL_SMMUV3: + case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV: case VIR_DOMAIN_IOMMU_MODEL_LAST: /* These are not PCI devices */ return 0; @@ -2378,6 +2379,7 @@ qemuDomainAssignDevicePCISlots(virDomainDef *def, =20 case VIR_DOMAIN_IOMMU_MODEL_INTEL: case VIR_DOMAIN_IOMMU_MODEL_SMMUV3: + case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV: case VIR_DOMAIN_IOMMU_MODEL_LAST: /* These are not PCI devices */ break; diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index adba3e4a89..163d7758b8 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -5406,6 +5406,22 @@ qemuValidateDomainDeviceDefIOMMU(const virDomainIOMM= UDef *iommu, } break; =20 + case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV: + if (!qemuDomainIsARMVirt(def)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("IOMMU device: '%1$s' is only supported with = ARM Virt machines"), + virDomainIOMMUModelTypeToString(iommu->model)); + return -1; + } + // TODO: Check for pluggable device SMMUv3 qemu capability + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_VIRT_IOMMU)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("IOMMU device: '%1$s' is not supported with t= his QEMU binary"), + virDomainIOMMUModelTypeToString(iommu->model)); + return -1; + } + break; + case VIR_DOMAIN_IOMMU_MODEL_LAST: default: virReportEnumRangeError(virDomainIOMMUModel, iommu->model); --=20 2.43.0 From nobody Sun Sep 7 06:47:11 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; arc=fail (BodyHash is different from the expected one); dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1755226827589139.1381014792147; Thu, 14 Aug 2025 20:00:27 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 9A6B3A29; Thu, 14 Aug 2025 23:00:26 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id EDA39A54; Thu, 14 Aug 2025 22:55:19 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 82F31BC1; Thu, 14 Aug 2025 22:55:15 -0400 (EDT) Received: from NAM11-CO1-obe.outbound.protection.outlook.com (mail-co1nam11on2051.outbound.protection.outlook.com [40.107.220.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id CE51D9E6 for ; Thu, 14 Aug 2025 22:54:41 -0400 (EDT) Received: from PH7PR12MB6834.namprd12.prod.outlook.com (2603:10b6:510:1b4::18) by PH7PR12MB5685.namprd12.prod.outlook.com (2603:10b6:510:13c::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9031.15; Fri, 15 Aug 2025 02:54:34 +0000 Received: from PH7PR12MB6834.namprd12.prod.outlook.com ([fe80::f432:162b:b94e:d2cb]) by PH7PR12MB6834.namprd12.prod.outlook.com ([fe80::f432:162b:b94e:d2cb%4]) with mapi id 15.20.9009.017; Fri, 15 Aug 2025 02:54:34 +0000 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=0.2 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, FORGED_SPF_HELO,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_PASS autolearn=no autolearn_force=no version=3.4.4 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=vrYnaBFrZWH8Cox+ZKB8+h4usloEn0Wrlb/UpWxAqsSS368rXOsgVkvNTddaOXpS5y0HtkDmZaK05IcL0vE3v9bdNKIOK19j4bdlXwjjkzl3fAvvv3FVqpTz3wkVG/97LcLibYly4e/HWLXWVuG1T1J5HDZ7H90wHunqwXICsPZUDzADuqciGfwwvVWcr7h7DHVeRCPddx+HR+pZUx3km+raGfyVhvClmEpzBHFhaM0yet28bfXcVBoW/bc3d2MDE5GkP3gXsTI1h30cwqhABCS+vWH/IbaiZlehXP25sur0IME/wxCIfHz+rP+shgYTSKI43TT+3MPMO2uDOxH5YA== 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=F4fRbl9X9fCWgyhJmLjTBGiC7+c8VVV4VKAWAVXjkMw=; b=CBachJiTrhrmbhqRf1ZfkWz3ooyFELIcZ+oTFI0QoRiFT7d+Mdgfd2YJgVZ770gyoasPWS1yOiKMX6r67qrssO1BIo+7daLvDwDBHpl5qkYD0MiFXa1MFI0RIkITqZgESuE/ZwQ6BFCL/HHEgm2KPBgxyrna7I6ynf7ya+qoqYHCe4Ve4UuzEX/xcN3DtZ+f/cegFyYYLH5Ud4gYPs3+smU9RSSpXHB3HsM8NX5QK+VGLSHuGmy4yjU4NPTt0PpCLtJSwznGV871mOKAZQKsGK3jfZluFZReQt2SeWzNAsyGWGRPPD5xvTbiZZ4EUOCW1N9scvDoG1kEy8ZIILSoZg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=F4fRbl9X9fCWgyhJmLjTBGiC7+c8VVV4VKAWAVXjkMw=; b=cR5jFNnIzhOdvywgcM1EhxfhA7lc/huHEZQRE/VU6SUgMHT5CTO4FurB6gAHdK+33oakufbE2VV2iZoVJ4xHNlTxObNEKIP9oXtPqSGFKg9K+tyRutJjSijSgqesgsBSE8+CpO2d7kegT2XZachw+zQntrnvCI9/4RqQbVwLw6zbDaxxHq7bP5YPC13NDe9qGjod4g+MJGgQ8fhQLjb2T50wF+HGDgWfSie2ef2MYdVRB4zqBZFvUB/jYD7LYtRJRopUKUAw9BcFlrFfiRxaEKv7i91cO0fvch4VfRbGpUoKlohgChyG/4uO8CF/AwlQhA9fdnOPby/YurNZKB9i6w== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; To: devel@lists.libvirt.org Subject: [RFC PATCH 2/5] conf: Support multiple smmuv3Dev IOMMU devices Date: Thu, 14 Aug 2025 19:54:11 -0700 Message-ID: <20250815025415.2805374-3-nathanc@nvidia.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250815025415.2805374-1-nathanc@nvidia.com> References: <20250815025415.2805374-1-nathanc@nvidia.com> X-ClientProxiedBy: SJ0PR05CA0094.namprd05.prod.outlook.com (2603:10b6:a03:334::9) To PH7PR12MB6834.namprd12.prod.outlook.com (2603:10b6:510:1b4::18) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PH7PR12MB6834:EE_|PH7PR12MB5685:EE_ X-MS-Office365-Filtering-Correlation-Id: e177aeaf-3825-45f8-86b5-08dddba710a4 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|366016|376014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?nxnZEyclijH0KYf3MZEtJ2Kh/uG5wTvJaF2sGQChcbH5Kq3etApz1QPan09p?= =?us-ascii?Q?9cdMwGRQBq9gWIyaB2iGtHsvSxmDHiAWewfVWZ/+nsOo2XhmqEOhGWlIaeW+?= =?us-ascii?Q?KGAbyXns76PkoSoNQHmRDNt6LRgVrscsNvga3lPR0bXAYCS5WjvKvKiCfSGS?= =?us-ascii?Q?lcSvM8uGM3vLN3JH2IKJuHI9jav2GPIa0e+Mz8ZhR3d/HTZKc4pu6yI+qOKp?= =?us-ascii?Q?WwT/gO3ql4iDaKvGyTibj2sqe+IEeA9g8RH/vLchvo6jOjUz3kkl4c1zzucQ?= =?us-ascii?Q?dN/BjxSDcJzs9VhMxaGvS5Otr3JqIo8IhM35gq/KEY+7N6O396pIjjXxlQ4P?= =?us-ascii?Q?+avDI6RU0NUkevxfFm+MwXsyT/kxTo7ua96tQor7EGM4LQZZBI9l7DwR0ULt?= =?us-ascii?Q?nSfbM0yYnPQ1+KajcXP9lhPxIAjvZB7UQpsTNVHbBIN/mOYRFDgXZEhdZelh?= =?us-ascii?Q?HLs/E/hl3876LRAULMiV8yXgW/on5UZAhjB5x1Y24p+vJxrmu+YRa08D0sGT?= =?us-ascii?Q?hFTWgJZpjWSFg8HSSuMJTTg6CfHEA+ZqulE8J/ToQ7gmzWSb9IncbBNFkWFr?= =?us-ascii?Q?8mYV/TANvb46PkMkDPwX7DmeioXthEhCBFBN1Ck/miUNEv/Ifwr1iZfnRYBc?= =?us-ascii?Q?q36c0RsCFL7cDBX60FYSJ5Km7opSX+BBjTgC5U969JDfS0py4awerm/ss2LL?= =?us-ascii?Q?GF+vL7juLLnlaGVGJMO+w89nBG60s+XyVf+u2GEW4OyCNMINEkdgf/o4CLy5?= =?us-ascii?Q?9YmzGuM7sZ0ghPNK+oi9h6pfEvWRycdyBvqhdPbVM7SPmqaqb9IEHOw0vHJA?= =?us-ascii?Q?b+Hckqn0MI2mVnnEO8dbQlLb6dNkeh6WWqKoJEZ7BRbqmOHuWekPKJx5L9OH?= =?us-ascii?Q?SHI5voOVeAAccl3z3HXSd65WqR4mmJ5JcIP90mbUNF/mpl8+s1ud/pm++SPC?= =?us-ascii?Q?D5xl0fuRpoo/V6jjZFceDrKtUsiYVrRHrLQ+bj+yXJPxVmp1074v599OufIm?= =?us-ascii?Q?V1VKelXYbebZaY+gCIYcF7n0p6MFu1Syj0y9PU8rBujfVTp10K2rRwq+fTWn?= =?us-ascii?Q?0eJTRu7xN7ZFk2I2MhZXQaMeXUnCz6JyNZ4MHoKlq3tfs7Bj2iuz8bNKpvbq?= =?us-ascii?Q?z/Mp3ZTceAChbsDFFbc69qlGidpezsHVxiIuB2RTjDDnICU1YufyWhIlHkEe?= =?us-ascii?Q?bvv0pPBGm0crlAaF/GWLt8+QdkiBW0MgBnuAUQEeJOxT4IKNJFun76I87lV6?= =?us-ascii?Q?5OSTuS1Egvb8uaKtaI0448miJIcqPDjEM8HPYAOGPPgQN96Mz7kK6371VAKq?= =?us-ascii?Q?k6eb85KqowbPri3pzP59MKWk21Gh9iOTaZbanESiEM/V15sdUjWaJ/h2nQET?= =?us-ascii?Q?gvU4dp0mFxOF/gyqbfM9nyIh08fT2UBam4Ayj1NMFMjuNki1NPMZrPYz94BZ?= =?us-ascii?Q?VCfbdpIZuEc=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PH7PR12MB6834.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(366016)(376014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?kOwzp1e3TvM1fpffSUh2IYZuquxFASZZA/2/bDixGdOLQjZeM6/DEzrttaWF?= =?us-ascii?Q?qjssCci+hQrtoT296V+Zx4Tq/Aho+ZLIRBh4G28WIaNzHz0SsR3n/1gFZSZq?= =?us-ascii?Q?hrCDOklLXbTcjfdAfbcyVM5cgXdhLTmZYUgTBuDxvmJeiUYJtP3y9QVLOqlQ?= =?us-ascii?Q?xjaYmTnkiZzbTeYI6LJMvO9zJrMoCc0Q6uv/w9OyCYNSBwKhMELGATCdAJcK?= =?us-ascii?Q?6WxvNpB6KHBVKuhNOZfPPFnx8pHRTESX8claUGBUxfbAzG/WkG72aBVHbxu9?= =?us-ascii?Q?EjKecAa1MiwvaQYaj94sdhkWNAblfj6DXQFJTGbTXzDdwOdrsnNi1pN6pbiV?= =?us-ascii?Q?pRJwU2KYJy4+TkeHyT04fpS1ZOENic/0JSwbKrYwmiZUEqXgG3jDnPjbk45C?= =?us-ascii?Q?vFVCm1XGXcb1J8NSIHgmXyi2huFpE4CLBikbQWKhkfw+9em0SaXj0EI20sAf?= =?us-ascii?Q?OyUGPsrTKh5Ub99haH1qvKVjv9aDA/+Rjg4yI6DbfP+NXvp5s3ML5wKRFJx3?= =?us-ascii?Q?Hc3/drzjeaXSQ9UWDQsInwR9i4WenMvXdpXw+JjAMprV3u9yNXVqslaxfCSO?= =?us-ascii?Q?HneRVC7RtpQAhA73K1r3VyswAE98wGq/e2R4WSUCkquUxVZ7qIcZ+XGATccP?= =?us-ascii?Q?ifM2cFFokPGU4HU/AsHyAqgguOzEvmsUOBtzl7a9wgXojS8txBw4NW4Z7IP1?= =?us-ascii?Q?b3AJ3gwPfdFUYW8+oCO/9Hewv/X8+gied5n3lVd3plkK84bZT2+zDNBGXDCC?= =?us-ascii?Q?fkCaUmpbihf47mrIUWIhNUTySzRPcFbzgv9xXuUxa3JKFmteh9dAEjtOj6ky?= =?us-ascii?Q?jcl6EeC1cQ96NPBXNI/xF76W71LRi5Wp1E0M6O5tGH/1arB6lAEbPNITWrAa?= =?us-ascii?Q?LEXCwkTPM6c2VHvm6Hs0lpNXhDrIdCvuRbWyB3S55ILs576hLyapRBGFo1A+?= =?us-ascii?Q?BtHeYhGckcnDOqGLJzpLUOKCYTnZh1rphwxklyfoj0BVNAQ2NhQC7MlplAl5?= =?us-ascii?Q?k2ghclfx8lOiyMiJZ3ekOIygSRwf6RwROiav6iORRkB9bTwuyZqDXO2BKIfK?= =?us-ascii?Q?fbno06+iaPTbrVQh17sya+KjKup56YnUuRxEpZGvPJG6DA0mwsqMHAmSDdKN?= =?us-ascii?Q?qNBhoi0DssnLEIxOG3FDPKOvRDlLLaBswwJddyYdZXRTNOCbDrDC5V1DYHBS?= =?us-ascii?Q?zKTxYiYLNPXzFfvtg8r9hKuru8UDtZ8iUyZvNMCiaEKnvz2OasxlpNjqAsV3?= =?us-ascii?Q?y7mB3fZQGaKYLAds0sL7AkOxzG6nJHf3GejPz+NxUlZO9UMqRpTPu8/hoJSS?= =?us-ascii?Q?U93OGpvO10TJhMZSpbKu/zhD6jOClkfGLbuYia5rKAqn4z+ybNOsD5aqfMJx?= =?us-ascii?Q?VId6WrHuEmf0F0giIsC4ayXMr+0+m0/4mZKvQiQvlIFC1RiDQ/eqwtWRqzVm?= =?us-ascii?Q?Mf6nFok7KbqXJHY4M6Ehz8+Sva8i1xruZRcpXfFsBDhc7bxnnqZZY5Jv+jfH?= =?us-ascii?Q?3qNT2eNJL2qeLFAqwnfd+/4IJznW82CvxY72VJOwYPLOPl2cPBvIdpPIWJCo?= =?us-ascii?Q?ACzhHTJyHjps+9KNNXKSIn1O5YO8nD8o3CgZ09lj?= X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: e177aeaf-3825-45f8-86b5-08dddba710a4 X-MS-Exchange-CrossTenant-AuthSource: PH7PR12MB6834.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Aug 2025 02:54:34.3187 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: SsIm6pJRDphYW42RIMCfntBdsiN1UgRTCPYAbE8cgFUpwZWGB+2tkOcXuPPZGCFEz9yJOv2giqAHvaWFUXNPWA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB5685 Content-Transfer-Encoding: quoted-printable Message-ID-Hash: OG345PDSSMZO3EJKV2U5QG7UYGPAJO2U X-Message-ID-Hash: OG345PDSSMZO3EJKV2U5QG7UYGPAJO2U X-MailFrom: nathanc@nvidia.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header CC: shameerali.kolothum.thodi@huawei.com, nicolinc@nvidia.com, nathanc@nvidia.com X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: From: Nathan Chen via Devel Reply-To: Nathan Chen X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1755226829983116600 Content-Type: text/plain; charset="utf-8" Add support for parsing multiple IOMMU devices from the VM definition when "smmuv3Dev" is the IOMMU model. Signed-off-by: Nathan Chen --- src/conf/domain_conf.c | 153 ++++++++++++++++++++++++++---- src/conf/domain_conf.h | 9 +- src/conf/domain_validate.c | 32 ++++--- src/conf/schemas/domaincommon.rng | 4 +- src/libvirt_private.syms | 2 + src/qemu/qemu_alias.c | 15 ++- src/qemu/qemu_command.c | 146 ++++++++++++++-------------- src/qemu/qemu_domain_address.c | 35 +++---- src/qemu/qemu_driver.c | 8 +- src/qemu/qemu_postparse.c | 11 ++- src/qemu/qemu_validate.c | 2 +- 11 files changed, 284 insertions(+), 133 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index dc222887d4..5ea4d6424b 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4132,7 +4132,8 @@ void virDomainDefFree(virDomainDef *def) virDomainCryptoDefFree(def->cryptos[i]); g_free(def->cryptos); =20 - virDomainIOMMUDefFree(def->iommu); + for (i =3D 0; i < def->niommus; i++) + virDomainIOMMUDefFree(def->iommu[i]); =20 virDomainPstoreDefFree(def->pstore); =20 @@ -5004,9 +5005,9 @@ virDomainDeviceInfoIterateFlags(virDomainDef *def, } =20 device.type =3D VIR_DOMAIN_DEVICE_IOMMU; - if (def->iommu) { - device.data.iommu =3D def->iommu; - if ((rc =3D cb(def, &device, &def->iommu->info, opaque)) !=3D 0) + for (i =3D 0; i < def->niommus; i++) { + device.data.iommu =3D def->iommu[i]; + if ((rc =3D cb(def, &device, &def->iommu[i]->info, opaque)) !=3D 0) return rc; } =20 @@ -16446,6 +16447,112 @@ virDomainInputDefFind(const virDomainDef *def, } =20 =20 +bool +virDomainIOMMUDefEquals(const virDomainIOMMUDef *a, + const virDomainIOMMUDef *b) +{ + if (a->model !=3D b->model || + a->intremap !=3D b->intremap || + a->caching_mode !=3D b->caching_mode || + a->eim !=3D b->eim || + a->iotlb !=3D b->iotlb || + a->aw_bits !=3D b->aw_bits || + a->parent_idx !=3D b->parent_idx || + a->accel !=3D b->accel || + a->dma_translation !=3D b->dma_translation) + return false; + + switch (a->info.type) { + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: + if (a->info.addr.pci.domain !=3D b->info.addr.pci.domain || + a->info.addr.pci.bus !=3D b->info.addr.pci.bus || + a->info.addr.pci.slot !=3D b->info.addr.pci.slot || + a->info.addr.pci.function !=3D b->info.addr.pci.function) { + return false; + } + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE: + if (a->info.addr.drive.controller !=3D b->info.addr.drive.controll= er || + a->info.addr.drive.bus !=3D b->info.addr.drive.bus || + a->info.addr.drive.unit !=3D b->info.addr.drive.unit) { + return false; + } + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL: + if (a->info.addr.vioserial.controller !=3D b->info.addr.vioserial.= controller || + a->info.addr.vioserial.bus !=3D b->info.addr.vioserial.bus || + a->info.addr.vioserial.port !=3D b->info.addr.vioserial.port) { + return false; + } + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID: + if (a->info.addr.ccid.controller !=3D b->info.addr.ccid.controller= || + a->info.addr.ccid.slot !=3D b->info.addr.ccid.slot) { + return false; + } + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA: + if (a->info.addr.isa.iobase !=3D b->info.addr.isa.iobase || + a->info.addr.isa.irq !=3D b->info.addr.isa.irq) { + return false; + } + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM: + if (a->info.addr.dimm.slot !=3D b->info.addr.dimm.slot) { + return false; + } + + if (a->info.addr.dimm.base !=3D b->info.addr.dimm.base) { + return false; + } + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW: + if (a->info.addr.ccw.cssid !=3D b->info.addr.ccw.cssid || + a->info.addr.ccw.ssid !=3D b->info.addr.ccw.ssid || + a->info.addr.ccw.devno !=3D b->info.addr.ccw.devno) { + return false; + } + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB: + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO: + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390: + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO: + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE: + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED: + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST: + break; + } + + if (a->info.acpiIndex !=3D b->info.acpiIndex) { + return false; + } + + return true; +} + + +ssize_t +virDomainIOMMUDefFind(const virDomainDef *def, + const virDomainIOMMUDef *iommu) +{ + size_t i; + + for (i =3D 0; i < def->niommus; i++) { + if (virDomainIOMMUDefEquals(iommu, def->iommu[i])) + return i; + } + + return -1; +} + + bool virDomainVsockDefEquals(const virDomainVsockDef *a, const virDomainVsockDef *b) @@ -20098,19 +20205,28 @@ virDomainDefParseXML(xmlXPathContextPtr ctxt, } VIR_FREE(nodes); =20 + /* analysis of iommu devices */ if ((n =3D virXPathNodeSet("./devices/iommu", ctxt, &nodes)) < 0) return NULL; =20 - if (n > 1) { + if (n > 1 && !virXPathBoolean("./devices/iommu/@model =3D 'smmuv3Dev'"= , ctxt)) { virReportError(VIR_ERR_XML_ERROR, "%s", - _("only a single IOMMU device is supported")); + _("multiple IOMMU devices are only supported with m= odel smmuv3Dev")); return NULL; } =20 - if (n > 0) { - if (!(def->iommu =3D virDomainIOMMUDefParseXML(xmlopt, nodes[0], - ctxt, flags))) + if (n > 0) + def->iommu =3D g_new0(virDomainIOMMUDef *, n); + + for (i =3D 0; i < n; i++) { + virDomainIOMMUDef *iommu; + + iommu =3D virDomainIOMMUDefParseXML(xmlopt, nodes[i], ctxt, flags); + + if (!iommu) return NULL; + + def->iommu[def->niommus++] =3D iommu; } VIR_FREE(nodes); =20 @@ -22558,15 +22674,17 @@ virDomainDefCheckABIStabilityFlags(virDomainDef *= src, goto error; } =20 - if (!!src->iommu !=3D !!dst->iommu) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Target domain IOMMU device count does not match = source")); + if (src->niommus !=3D dst->niommus) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target domain IOMMU device count %1$zu does not = match source %2$zu"), + dst->niommus, src->niommus); goto error; } =20 - if (src->iommu && - !virDomainIOMMUDefCheckABIStability(src->iommu, dst->iommu)) - goto error; + for (i =3D 0; i < src->niommus; i++) { + if (!virDomainIOMMUDefCheckABIStability(src->iommu[i], dst->iommu[= i])) + goto error; + } =20 if (!!src->vsock !=3D !!dst->vsock) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -29402,8 +29520,9 @@ virDomainDefFormatInternalSetRootName(virDomainDef = *def, for (n =3D 0; n < def->ncryptos; n++) { virDomainCryptoDefFormat(buf, def->cryptos[n], flags); } - if (def->iommu) - virDomainIOMMUDefFormat(buf, def->iommu); + + for (n =3D 0; n < def->niommus; n++) + virDomainIOMMUDefFormat(buf, def->iommu[n]); =20 if (def->vsock) virDomainVsockDefFormat(buf, def->vsock); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index f87c5bbe93..edb18632f3 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -3294,6 +3294,9 @@ struct _virDomainDef { size_t nwatchdogs; virDomainWatchdogDef **watchdogs; =20 + size_t niommus; + virDomainIOMMUDef **iommu; + /* At maximum 2 TPMs on the domain if a TPM Proxy is present. */ size_t ntpms; virDomainTPMDef **tpms; @@ -3303,7 +3306,6 @@ struct _virDomainDef { virDomainNVRAMDef *nvram; virCPUDef *cpu; virDomainRedirFilterDef *redirfilter; - virDomainIOMMUDef *iommu; virDomainVsockDef *vsock; virDomainPstoreDef *pstore; =20 @@ -4308,6 +4310,11 @@ virDomainShmemDef *virDomainShmemDefRemove(virDomain= Def *def, size_t idx) ssize_t virDomainInputDefFind(const virDomainDef *def, const virDomainInputDef *input) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT; +bool virDomainIOMMUDefEquals(const virDomainIOMMUDef *a, + const virDomainIOMMUDef *b); +ssize_t virDomainIOMMUDefFind(const virDomainDef *def, + const virDomainIOMMUDef *iommu) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT; bool virDomainVsockDefEquals(const virDomainVsockDef *a, const virDomainVsockDef *b) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT; diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index f1b1b8cc55..b2f94b921f 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -1840,21 +1840,31 @@ virDomainDefCputuneValidate(const virDomainDef *def) static int virDomainDefIOMMUValidate(const virDomainDef *def) { + size_t i; + if (!def->iommu) return 0; =20 - if (def->iommu->intremap =3D=3D VIR_TRISTATE_SWITCH_ON && - def->features[VIR_DOMAIN_FEATURE_IOAPIC] !=3D VIR_DOMAIN_IOAPIC_QE= MU) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("IOMMU interrupt remapping requires split I/O API= C (ioapic driver=3D'qemu')")); - return -1; - } + for (i =3D 0; i < def->niommus; i++) { + virDomainIOMMUDef *iommu =3D def->iommu[i]; + if (def->niommus > 1 && iommu->model !=3D VIR_DOMAIN_IOMMU_MODEL_S= MMUV3_DEV) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("IOMMU model smmuv3Dev must be specified for = multiple IOMMU definitions")); + } =20 - if (def->iommu->eim =3D=3D VIR_TRISTATE_SWITCH_ON && - def->iommu->intremap !=3D VIR_TRISTATE_SWITCH_ON) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("IOMMU eim requires interrupt remapping to be ena= bled")); - return -1; + if (iommu->intremap =3D=3D VIR_TRISTATE_SWITCH_ON && + def->features[VIR_DOMAIN_FEATURE_IOAPIC] !=3D VIR_DOMAIN_IOAPI= C_QEMU) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("IOMMU interrupt remapping requires split I/O= APIC (ioapic driver=3D'qemu')")); + return -1; + } + + if (iommu->eim =3D=3D VIR_TRISTATE_SWITCH_ON && + iommu->intremap !=3D VIR_TRISTATE_SWITCH_ON) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("IOMMU eim requires interrupt remapping to be= enabled")); + return -1; + } } =20 return 0; diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincom= mon.rng index 0e57d2a9b9..fd19f115f7 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -6944,9 +6944,9 @@ - + - + diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b846011f0f..924cfa1db7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -491,6 +491,8 @@ virDomainInputSourceGrabToggleTypeToString; virDomainInputSourceGrabTypeFromString; virDomainInputSourceGrabTypeToString; virDomainInputTypeToString; +virDomainIOMMUDefEquals; +virDomainIOMMUDefFind; virDomainIOMMUDefFree; virDomainIOMMUDefNew; virDomainIOMMUModelTypeFromString; diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index a27c688d79..5f2b11b9a6 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -647,10 +647,14 @@ qemuAssignDeviceVsockAlias(virDomainVsockDef *vsock) =20 =20 static void -qemuAssignDeviceIOMMUAlias(virDomainIOMMUDef *iommu) +qemuAssignDeviceIOMMUAlias(virDomainDef *def, + virDomainIOMMUDef **iommu) { - if (!iommu->info.alias) - iommu->info.alias =3D g_strdup("iommu0"); + size_t i; + for (i =3D 0; i < def->niommus; i++) { + if (!iommu[i]->info.alias) + iommu[i]->info.alias =3D g_strdup_printf("iommu%zu", i); + } } =20 =20 @@ -766,8 +770,9 @@ qemuAssignDeviceAliases(virDomainDef *def) if (def->vsock) { qemuAssignDeviceVsockAlias(def->vsock); } - if (def->iommu) - qemuAssignDeviceIOMMUAlias(def->iommu); + if (def->iommu && def->niommus > 0) { + qemuAssignDeviceIOMMUAlias(def, def->iommu); + } for (i =3D 0; i < def->ncryptos; i++) { qemuAssignDeviceCryptoAlias(def, def->cryptos[i]); } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8a124a495b..cecd0661ca 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6252,10 +6252,12 @@ qemuBuildBootCommandLine(virCommand *cmd, =20 static virJSONValue * qemuBuildPCISmmuv3DevDevProps(const virDomainDef *def, - const virDomainIOMMUDef *iommu) + const virDomainIOMMUDef *iommu, + size_t id) { g_autoptr(virJSONValue) props =3D NULL; g_autofree char *bus =3D NULL; + g_autofree char *smmuv3_id =3D NULL; size_t i; bool contIsPHB =3D false; =20 @@ -6296,9 +6298,12 @@ qemuBuildPCISmmuv3DevDevProps(const virDomainDef *de= f, bus =3D temp_bus; } =20 + smmuv3_id =3D g_strdup_printf("smmuv3.%zu", id); + if (virJSONValueObjectAdd(&props, "s:driver", "arm-smmuv3", "s:primary-bus", bus, + "s:id", smmuv3_id, "b:accel", (iommu->accel =3D=3D VIR_TRISTATE= _SWITCH_ON), NULL) < 0) return NULL; @@ -6312,91 +6317,92 @@ qemuBuildIOMMUCommandLine(virCommand *cmd, const virDomainDef *def, virQEMUCaps *qemuCaps) { + size_t i; g_autoptr(virJSONValue) props =3D NULL; g_autoptr(virJSONValue) wrapperProps =3D NULL; - const virDomainIOMMUDef *iommu =3D def->iommu; - - if (!iommu) + if (!def->iommu || def->niommus <=3D 0) return 0; =20 - switch (iommu->model) { - case VIR_DOMAIN_IOMMU_MODEL_INTEL: - if (virJSONValueObjectAdd(&props, - "s:driver", "intel-iommu", - "s:id", iommu->info.alias, - "S:intremap", qemuOnOffAuto(iommu->intre= map), - "T:caching-mode", iommu->caching_mode, - "S:eim", qemuOnOffAuto(iommu->eim), - "T:device-iotlb", iommu->iotlb, - "z:aw-bits", iommu->aw_bits, - "T:dma-translation", iommu->dma_translat= ion, - NULL) < 0) - return -1; + for (i =3D 0; i < def->niommus; i++) { + virDomainIOMMUDef *iommu =3D def->iommu[i]; + switch (iommu->model) { + case VIR_DOMAIN_IOMMU_MODEL_INTEL: + if (virJSONValueObjectAdd(&props, + "s:driver", "intel-iommu", + "s:id", iommu->info.alias, + "S:intremap", qemuOnOffAuto(iommu->i= ntremap), + "T:caching-mode", iommu->caching_mod= e, + "S:eim", qemuOnOffAuto(iommu->eim), + "T:device-iotlb", iommu->iotlb, + "z:aw-bits", iommu->aw_bits, + "T:dma-translation", iommu->dma_tran= slation, + NULL) < 0) + return -1; =20 - if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCaps) = < 0) - return -1; + if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCa= ps) < 0) + return -1; =20 - return 0; + return 0; + case VIR_DOMAIN_IOMMU_MODEL_VIRTIO: + if (virJSONValueObjectAdd(&props, + "s:driver", "virtio-iommu", + "s:id", iommu->info.alias, + NULL) < 0) { + return -1; + } =20 - case VIR_DOMAIN_IOMMU_MODEL_VIRTIO: - if (virJSONValueObjectAdd(&props, - "s:driver", "virtio-iommu", - "s:id", iommu->info.alias, - NULL) < 0) { - return -1; - } + if (qemuBuildDeviceAddressProps(props, def, &iommu->info) < 0) + return -1; =20 - if (qemuBuildDeviceAddressProps(props, def, &iommu->info) < 0) - return -1; + if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCa= ps) < 0) + return -1; =20 - if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCaps) = < 0) - return -1; + return 0; + case VIR_DOMAIN_IOMMU_MODEL_SMMUV3: + /* There is no -device for SMMUv3, so nothing to be done here = */ + return 0; =20 - return 0; + case VIR_DOMAIN_IOMMU_MODEL_AMD: + if (virJSONValueObjectAdd(&wrapperProps, + "s:driver", "AMDVI-PCI", + "s:id", iommu->info.alias, + NULL) < 0) + return -1; =20 - case VIR_DOMAIN_IOMMU_MODEL_SMMUV3: - return 0; + if (qemuBuildDeviceAddressProps(wrapperProps, def, &iommu->inf= o) < 0) + return -1; =20 - case VIR_DOMAIN_IOMMU_MODEL_AMD: - if (virJSONValueObjectAdd(&wrapperProps, - "s:driver", "AMDVI-PCI", - "s:id", iommu->info.alias, - NULL) < 0) - return -1; + if (qemuBuildDeviceCommandlineFromJSON(cmd, wrapperProps, def,= qemuCaps) < 0) + return -1; =20 - if (qemuBuildDeviceAddressProps(wrapperProps, def, &iommu->info) <= 0) - return -1; + if (virJSONValueObjectAdd(&props, + "s:driver", "amd-iommu", + "s:pci-id", iommu->info.alias, + "S:intremap", qemuOnOffAuto(iommu->i= ntremap), + "T:pt", iommu->pt, + "T:xtsup", iommu->xtsup, + "T:device-iotlb", iommu->iotlb, + NULL) < 0) + return -1; =20 - if (qemuBuildDeviceCommandlineFromJSON(cmd, wrapperProps, def, qem= uCaps) < 0) - return -1; + if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCa= ps) < 0) + return -1; =20 - if (virJSONValueObjectAdd(&props, - "s:driver", "amd-iommu", - "s:pci-id", iommu->info.alias, - "S:intremap", qemuOnOffAuto(iommu->intre= map), - "T:pt", iommu->pt, - "T:xtsup", iommu->xtsup, - "T:device-iotlb", iommu->iotlb, - NULL) < 0) - return -1; + return 0; =20 - if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCaps) = < 0) - return -1; + case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV: + if (!(props =3D qemuBuildPCISmmuv3DevDevProps(def, iommu, i))) + return -1; + if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCa= ps) < 0) + return -1; + break; =20 - return 0; =20 - case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV: - if (!(props =3D qemuBuildPCISmmuv3DevDevProps(def, iommu))) - return -1; - if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCaps) = < 0) + case VIR_DOMAIN_IOMMU_MODEL_LAST: + default: + virReportEnumRangeError(virDomainIOMMUModel, iommu->model); return -1; - - return 0; - - case VIR_DOMAIN_IOMMU_MODEL_LAST: - default: - virReportEnumRangeError(virDomainIOMMUModel, iommu->model); - return -1; + } } =20 return 0; @@ -7217,8 +7223,8 @@ qemuBuildMachineCommandLine(virCommand *cmd, if (qemuAppendDomainFeaturesMachineParam(&buf, def, qemuCaps) < 0) return -1; =20 - if (def->iommu) { - switch (def->iommu->model) { + if (def->iommu && def->niommus =3D=3D 1) { + switch (def->iommu[0]->model) { case VIR_DOMAIN_IOMMU_MODEL_SMMUV3: virBufferAddLit(&buf, ",iommu=3Dsmmuv3"); break; @@ -7232,7 +7238,7 @@ qemuBuildMachineCommandLine(virCommand *cmd, =20 case VIR_DOMAIN_IOMMU_MODEL_LAST: default: - virReportEnumRangeError(virDomainIOMMUModel, def->iommu->model= ); + virReportEnumRangeError(virDomainIOMMUModel, def->iommu[0]->mo= del); return -1; } } diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 06bf4fab32..2ddc629304 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -2365,24 +2365,25 @@ qemuDomainAssignDevicePCISlots(virDomainDef *def, /* Nada - none are PCI based (yet) */ } =20 - if (def->iommu) { - virDomainIOMMUDef *iommu =3D def->iommu; - - switch (iommu->model) { - case VIR_DOMAIN_IOMMU_MODEL_VIRTIO: - case VIR_DOMAIN_IOMMU_MODEL_AMD: - if (virDeviceInfoPCIAddressIsWanted(&iommu->info) && - qemuDomainPCIAddressReserveNextAddr(addrs, &iommu->info) <= 0) { - return -1; - } - break; + if (def->iommu && def->niommus > 0) { + for (i =3D 0; i < def->niommus; i++) { + virDomainIOMMUDef *iommu =3D def->iommu[i]; + switch (iommu->model) { + case VIR_DOMAIN_IOMMU_MODEL_VIRTIO: + case VIR_DOMAIN_IOMMU_MODEL_AMD: + if (virDeviceInfoPCIAddressIsWanted(&iommu->info) && + qemuDomainPCIAddressReserveNextAddr(addrs, &iommu->inf= o) < 0) { + return -1; + } + break; =20 - case VIR_DOMAIN_IOMMU_MODEL_INTEL: - case VIR_DOMAIN_IOMMU_MODEL_SMMUV3: - case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV: - case VIR_DOMAIN_IOMMU_MODEL_LAST: - /* These are not PCI devices */ - break; + case VIR_DOMAIN_IOMMU_MODEL_INTEL: + case VIR_DOMAIN_IOMMU_MODEL_SMMUV3: + case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV: + case VIR_DOMAIN_IOMMU_MODEL_LAST: + /* These are not PCI devices */ + break; + } } } =20 diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ac72ea5cb0..3d65f78c9e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6894,12 +6894,12 @@ qemuDomainAttachDeviceConfig(virDomainDef *vmdef, break; =20 case VIR_DOMAIN_DEVICE_IOMMU: - if (vmdef->iommu) { + if (vmdef->iommu && vmdef->niommus > 0) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain already has an iommu device")); return -1; } - vmdef->iommu =3D g_steal_pointer(&dev->data.iommu); + VIR_APPEND_ELEMENT(vmdef->iommu, vmdef->niommus, dev->data.iommu); break; =20 case VIR_DOMAIN_DEVICE_VIDEO: @@ -7113,12 +7113,12 @@ qemuDomainDetachDeviceConfig(virDomainDef *vmdef, break; =20 case VIR_DOMAIN_DEVICE_IOMMU: - if (!vmdef->iommu) { + if ((idx =3D virDomainIOMMUDefFind(vmdef, dev->data.iommu)) < 0) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("matching iommu device not found")); return -1; } - g_clear_pointer(&vmdef->iommu, virDomainIOMMUDefFree); + VIR_DELETE_ELEMENT(vmdef->iommu, idx, vmdef->niommus); break; =20 case VIR_DOMAIN_DEVICE_VIDEO: diff --git a/src/qemu/qemu_postparse.c b/src/qemu/qemu_postparse.c index 9c2427970d..e2744a4a61 100644 --- a/src/qemu/qemu_postparse.c +++ b/src/qemu/qemu_postparse.c @@ -1503,7 +1503,7 @@ qemuDomainDefAddDefaultDevices(virQEMUDriver *driver, } } =20 - if (addIOMMU && !def->iommu && + if (addIOMMU && !def->iommu && def->niommus =3D=3D 0 && virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_INTEL_IOMMU) && virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_INTREMAP) && virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_EIM)) { @@ -1515,7 +1515,8 @@ qemuDomainDefAddDefaultDevices(virQEMUDriver *driver, iommu->intremap =3D VIR_TRISTATE_SWITCH_ON; iommu->eim =3D VIR_TRISTATE_SWITCH_ON; =20 - def->iommu =3D g_steal_pointer(&iommu); + def->iommu =3D g_new0(virDomainIOMMUDef *, 1); + def->iommu[def->niommus++] =3D g_steal_pointer(&iommu); } =20 if (qemuDomainDefAddDefaultAudioBackend(driver, def) < 0) @@ -1591,9 +1592,9 @@ qemuDomainDefEnableDefaultFeatures(virDomainDef *def, * domain already has IOMMU without inremap. This will be fixed in * qemuDomainIOMMUDefPostParse() but there domain definition can't be * modified so change it now. */ - if (def->iommu && - (def->iommu->intremap =3D=3D VIR_TRISTATE_SWITCH_ON || - qemuDomainNeedsIOMMUWithEIM(def)) && + if (def->iommu && def->niommus =3D=3D 1 && + (def->iommu[0]->intremap =3D=3D VIR_TRISTATE_SWITCH_ON || + qemuDomainNeedsIOMMUWithEIM(def)) && def->features[VIR_DOMAIN_FEATURE_IOAPIC] =3D=3D VIR_DOMAIN_IOAPIC_= NONE) { def->features[VIR_DOMAIN_FEATURE_IOAPIC] =3D VIR_DOMAIN_IOAPIC_QEM= U; } diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 163d7758b8..1b5b1deb5d 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -851,7 +851,7 @@ qemuValidateDomainVCpuTopology(const virDomainDef *def,= virQEMUCaps *qemuCaps) QEMU_MAX_VCPUS_WITHOUT_EIM); return -1; } - if (!def->iommu || def->iommu->eim !=3D VIR_TRISTATE_SWITCH_ON) { + if (!def->iommu || def->iommu[0]->eim !=3D VIR_TRISTATE_SWITCH_ON)= { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("more than %1$d vCPUs require extended interr= upt mode enabled on the iommu device"), QEMU_MAX_VCPUS_WITHOUT_EIM); --=20 2.43.0 From nobody Sun Sep 7 06:47:11 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; arc=fail (BodyHash is different from the expected one); dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 175522668676266.88223955078865; Thu, 14 Aug 2025 19:58:06 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 212CFB34; Thu, 14 Aug 2025 22:58:06 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 10586B9F; Thu, 14 Aug 2025 22:54:57 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 98124984; Thu, 14 Aug 2025 22:54:52 -0400 (EDT) Received: from NAM11-CO1-obe.outbound.protection.outlook.com (mail-co1nam11on2051.outbound.protection.outlook.com [40.107.220.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 7CD35984 for ; Thu, 14 Aug 2025 22:54:41 -0400 (EDT) Received: from PH7PR12MB6834.namprd12.prod.outlook.com (2603:10b6:510:1b4::18) by PH7PR12MB5685.namprd12.prod.outlook.com (2603:10b6:510:13c::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9031.15; Fri, 15 Aug 2025 02:54:37 +0000 Received: from PH7PR12MB6834.namprd12.prod.outlook.com ([fe80::f432:162b:b94e:d2cb]) by PH7PR12MB6834.namprd12.prod.outlook.com ([fe80::f432:162b:b94e:d2cb%4]) with mapi id 15.20.9009.017; Fri, 15 Aug 2025 02:54:37 +0000 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=0.2 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, FORGED_SPF_HELO,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_PASS autolearn=no autolearn_force=no version=3.4.4 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=fyI9/RufgFWTGUXw/Y0XlsPE0pAIQ2VK9F58TaigNMZkFMElS0b8FP+yTT7/3bi+7pRQZqjqF8vYUdIeZVruiUNqQknJot7Xxbu0l+h8bFPoXeE4OvG2Da3SM3tKq7ZvA4ykWDfT7Bl3jHGc87zqt9k40Hr6iHRY+UgnRBnn34LEzwuQScB8DIskIACbA0x0CNMDtIYJKYnSGT9AIQr2j2MXIPM/ynWMihn8sjUB+wX8P9SuRMcYzdo6h32K8Ha+HouAq8RSl34FtGsZGMxcpZfHjpSo6jXfiS1bn7INRoVpMre0GYO1/glOrrtVD5UQMLSBIXXPIlmOsccMSnNGog== 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=Zrd4xH9f0340gfroFPXTka19pqdjCccyzTYTh7CTetM=; b=sRnAbcA8cER0jwptZvte4swwwKhSGMOMHgzEuRMEBkfRhskK61LCAAqXmSrbeZMrgHLnv38qtfOyHDiXWhUi4/GLFWNp7cf1MF1S9TvSjjrrqqG7GLbygPsuOOImuVgfhFZ+PLpuVBSCUzovuUbnsC8dmDKSAJY5VV/GxYAkWhI+wgW+5ram92gvMNJ81P8aFT917Ai0trhacjOi6g1pGPe4XX26Gl5QY3XJ3GCD6a721CwQzbX34m761jaQJlWQKiMByfXYFk4OwjxdqlE2gi0Z4s4VAwHmD1ITM180HHm7WJtEo7FvcvJEYxv7bwz86/Tl8YwiCYP9v5vUOx3qrQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Zrd4xH9f0340gfroFPXTka19pqdjCccyzTYTh7CTetM=; b=uZl+wKKK7i4Tl1Gi7iq1g7qgNnWLYqOFSo5h/Nduf5FalOlBB+OgSADsoSNCyfmrsJ34StoOhyvqZTyCE5f3fND/0sVpEsXx/VDeaeWePQiuTrppOM+KcVslQgMlO8rwHynug+295Dj6mSOsm25pnaWUJSm2TBPkecuUzPs6RdBDxxeupsjnhkhznp1lXY+lw3QWhR1AsqLlnmjOK7GT66Sfjb9wwjVsSJZMv1SueQ+yktZi7Yl/SxP8Ozsx65/bQWnlYRs3TlsTcy1KyWpniVpQ76aEfzH5d9VKlFXOJinxA1vcbeEHD8ZHOOxi9SKaEdHGsR9/rlJhOsikbQQPcg== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; To: devel@lists.libvirt.org Subject: [RFC PATCH 3/5] qemu: Implement support for associating iommufd to hostdev Date: Thu, 14 Aug 2025 19:54:12 -0700 Message-ID: <20250815025415.2805374-4-nathanc@nvidia.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250815025415.2805374-1-nathanc@nvidia.com> References: <20250815025415.2805374-1-nathanc@nvidia.com> X-ClientProxiedBy: BYAPR05CA0082.namprd05.prod.outlook.com (2603:10b6:a03:e0::23) To PH7PR12MB6834.namprd12.prod.outlook.com (2603:10b6:510:1b4::18) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PH7PR12MB6834:EE_|PH7PR12MB5685:EE_ X-MS-Office365-Filtering-Correlation-Id: 7f3b227d-ca54-44d6-5ae6-08dddba7126e X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|366016|376014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?PlotTl7JJRmBraJ5IkRo1nbx8O4IEpEZ95oW/tx76B6yTl+252SRwnysZS3w?= =?us-ascii?Q?ix+PWfc96gy5FiBzvV71u3zCpqnFwmzemoXEdimn4EsqJRmBmawqYwKFE2aX?= =?us-ascii?Q?pGUE7wsXLabwrHHcTgUFWR9FU1Bsfo7tiaHBz0WgScON3EKz9Wr8zjDBf8hD?= =?us-ascii?Q?rGfJvwQr3DXWUJez81ez0YFbWr4dcICUlCY9v/j8pbT8uF8GPdWeHiH+VPj4?= =?us-ascii?Q?3/feOtq5inQaTgBnRd3uJTCPu4RXta9Fk84CV/VCUEzq4/faBL7UDnPpLBPF?= =?us-ascii?Q?Uz6AgsiCcBXEzicC1Fcda1R0X3gr5/oTYB31xcSzie8Mzth/63PNJ6MmH+Pj?= =?us-ascii?Q?JWAmfSAicHURwdPe2l7fS/qwhcCeZWxO7lcpL/AmFCM1p+RIfkyZGcu6EiZL?= =?us-ascii?Q?oYRdNNDUW40hcCqe9FbjXLpspc1BQvmG8OHKsdIuEzCbYLbeguuus8B2eDTI?= =?us-ascii?Q?jtokl811e+u9LcBf9BOZFgSfUDkbSd0iJU9pJ3ozubTGkU/So1juIpp0waP+?= =?us-ascii?Q?6Nhrs8SVKuZJqnkXXRE3stUFJuKjkvxkD/HKshXKvUjjxjmCeM+Z/yI7f6Jy?= =?us-ascii?Q?Om7l5f2HUx9pvcjYAAFZyzvmtzmgS+JNc7H5bmpMgcGUaKwAkfccbl0ZX9oo?= =?us-ascii?Q?pvcO5F+phGsr7nQfvOLVC9cydFI7bwqkAw+wbgvz09nC9OHu8FdoGAMkSbxq?= =?us-ascii?Q?eONVyUryc6ZfWo6DRak7q2fmz0oGxEUz/aGVJVQKFliVXpzHJxwJ/4gCRxxj?= =?us-ascii?Q?+yLacLprlk1hhMGIUILIsoCzQ8TaGqjSta9BUFwyL8v/z3DkKN3BSRxjyW+8?= =?us-ascii?Q?WqL9faPMBnXgHE7kpYI0WzdMwkRqmAb91MJCvIkIK795VP4wIzswS3oH2ltT?= =?us-ascii?Q?OuuBL+Xtk1M8WCBPasbm33IPgHbXiFsB+vLwB0RAe1n/7sEfh9eCXeJ/thJl?= =?us-ascii?Q?bhHURPXOKjSf6dFHgeS1UzrDtHJq3YZh/5gnGg1pJb5ZW4zGtGRW0SsBqBHS?= =?us-ascii?Q?pJk6UDFpwpBNPTQfqAYoFEyNU944UKRNOoKvT1kPyUlsHkmIyZDHEuLihfG9?= =?us-ascii?Q?OX/JLzEgT11Hn99YMvWhsBb2IkArTXEA/x8c2H+exyn6tVSScEsvcrrPx22D?= =?us-ascii?Q?mGhVlRm1uJKfph02E+FFeU9NtzlWL5npPXW3+ob6AelH8i8Gh0LnzvbvOnqH?= =?us-ascii?Q?GmeozcMnzHnFnR+2cafSiHH00VPBJJigvvXPsgI1RhwoGIw18uCrV59RvKxB?= =?us-ascii?Q?b3ykSmYrW+Fi6y4SDqzgPXhx5CzTj5cbkaCGAXaHfRKBdIFPzWEPZi2Rft8P?= =?us-ascii?Q?f5724ovbmQSBZjgvXyXucBy/KxBZ6p8Q3FW0VG2iX9jcw3wdOnOzwaYvXiv1?= =?us-ascii?Q?dTaKzXLqLdAE44nuhZ2xEs/o5rzYZWoXO+7srt8Vany5nnyZZQ=3D=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PH7PR12MB6834.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(366016)(376014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?qcPFVIUaUg59dn0W48goZKDkWlKEyp4urWg+Fua5OyzjehsKJAeoFBqzYk0s?= =?us-ascii?Q?rMuzeyDRNC0+YhoBvpBg5yqZ7Wycg/cpy5ITbwCfbGRT4Omcc3VRLZh51Glo?= =?us-ascii?Q?F6dpJK3nYfU0zHKVQYey+9U0lEVXEt2ZTrWgpSlYRkSWqMK2WkODalUxJZUN?= =?us-ascii?Q?/LXBU7u/hTXZorLUeNlVJQj64HRrL7Wuotp2EXuPlJcrYDS4hGkL8iOIuxGB?= =?us-ascii?Q?8GLzTLM2m9Nt7JEkCoLvqsuZ6YnxNffQx3V8+oV4BA1L/I7KhwLe5SKPU0DB?= =?us-ascii?Q?zphVVxJNN1QpyY8cAMScUJtQEtHD3Zty4KxRZkdFd+aKpe9HrtpivncRTpb4?= =?us-ascii?Q?YDpCcBp3C+pdli1z25aBkm6srHBmlVBLidsCMzMmvXftFC5shG9kOMZvbRsq?= =?us-ascii?Q?JUuK8xBDYtFzr5obOGxL83VvKSRweITU3BwvPpbhDe5MXAJfqwvlGghzfGBz?= =?us-ascii?Q?y2kX16d9YuVoXU/AjZgg6MbiVL4wn6fCJ4d2HXys3jFoyFFwKJzjpfVbTjCf?= =?us-ascii?Q?TdbHUC00cVYj0yfksjXWXn/fskhNZu8DPLjy4aFd5Rl+Gg/AS638tOpIDZKG?= =?us-ascii?Q?DMQt9QQ3vhqcCF4eY9F5pd5YJLkk/U9YYJbH8Ls6DJLEkvgXt5LDNll8C0zA?= =?us-ascii?Q?6sw0KWlnwkQuUeiTi0lL0SibFCFYlwz9u5gQUjJ/nkTu4nVRYZnHiZyaJwxf?= =?us-ascii?Q?1ewY5DobvPNfmSCfRrd4OKugBiO+BgCa1fsT/xLdGVt7gav8+YBPjdlGllAm?= =?us-ascii?Q?sjF+84Ok5cOuyKhUISxz6mgAoDNMZPzOJirMGmI6AW1PWEbW3XkvHyOtVhW6?= =?us-ascii?Q?uIE2apj6mkZ3qyGtrJeKRo1YIX3EXt0WqToRiJY0PJlhxw2d3MKGmguJrySV?= =?us-ascii?Q?QQWVL4OhXxrJvJVwpl0hSZp1Lb7utioflhAppL7AQ6ONUF2mJRS5jAw7yLWk?= =?us-ascii?Q?a7zupw5UrpZTwKZIiP/4T4kruU5k7qB1Ynbs98sJ7+kieC4O9aCvaGCqt/Un?= =?us-ascii?Q?djcC0VOnLyy4BPg8L8CbVdRuq1J0ev0VQ788zjnmFIYt8RuxzsgMcMqsx+6t?= =?us-ascii?Q?V9Fs8tmoeBxPGlMTGlBOnFsPBQaa1rvhq4+oWRSR+2AEkA558eQlZ7pCzIwv?= =?us-ascii?Q?amqnm58jjEjwaaFZhBjMEKDDweA3JDV1FqO9k+KnDBIfIklHeBxewhTteox7?= =?us-ascii?Q?tB9d6ZhVXNnnNDJkw2kSnb1vt4Lab6OCoqVlxGwg8wSouJyepJzKKE9RGh70?= =?us-ascii?Q?I4IGA0STWizGBYqHw87tQx1KyFm/YOHrdM5cYXEUtDgLZEaqNYwN15p0K3sL?= =?us-ascii?Q?ufloBWJYJElW5876jmmiefHdtXx0aG3GEqoqOMwFOJlNdSk1/cyWDeQKI8Ox?= =?us-ascii?Q?Rj7ypkN3+tdiWM6L67fAyA4Hnb/CUyZhV+dvmb68r4nndREMPc4CKB/iAAqz?= =?us-ascii?Q?tZ3YpPomp3a6JEyKWQQjXw5qYGl4zv7UpGQhM9ARFYMSpkxQ20uJsFNsFZLY?= =?us-ascii?Q?66IC02UVEWws8emejwtvZGZxz/bVt1GDVI+c7WR1ctSnwKeAZsO+KUO7Ez8H?= =?us-ascii?Q?pqrxfaKsDYf+CoOHbklu7HrDl4tujvMJEm2pAd46?= X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 7f3b227d-ca54-44d6-5ae6-08dddba7126e X-MS-Exchange-CrossTenant-AuthSource: PH7PR12MB6834.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Aug 2025 02:54:37.2883 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: /g3vKtwZnYSmJYOY2nGMjxI96lHMEVf/GxIHPew8doGQrhniQjfnvkaM/1ScPYYAMoK972Jom2C+orbFehs7Vg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB5685 Content-Transfer-Encoding: quoted-printable Message-ID-Hash: ZHJJSSLNIZBYZ42Z75354BDF62QVYFGE X-Message-ID-Hash: ZHJJSSLNIZBYZ42Z75354BDF62QVYFGE X-MailFrom: nathanc@nvidia.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header CC: shameerali.kolothum.thodi@huawei.com, nicolinc@nvidia.com, nathanc@nvidia.com X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: From: Nathan Chen via Devel Reply-To: Nathan Chen X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1755226689135124100 Content-Type: text/plain; charset="utf-8" Implement iommufdId attribute for hostdev devices that can be used to specify associated iommufd object when launching a qemu VM. Signed-off-by: Nathan Chen --- docs/formatdomain.rst | 9 +++++++++ src/conf/domain_conf.c | 20 ++++++++++++++++++++ src/conf/domain_conf.h | 1 + src/conf/schemas/domaincommon.rng | 9 +++++++++ src/qemu/qemu_command.c | 14 ++++++++++++++ 5 files changed, 53 insertions(+) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 2558df18ef..e2b9be16c9 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -4581,6 +4581,7 @@ or: + iommufd0 ... @@ -4829,6 +4830,14 @@ or: device; if PCI ROM loading is disabled through this attribute, attempts= to tweak the loading process further using the ``bar`` or ``file`` attribu= tes will be rejected. :since:`Since 4.3.0 (QEMU and KVM only)`. +``iommufdId`` + The ``iommufdId`` element is used to specify using the iommufd interfac= e to + propagate DMA mappings to the kernel, instead of legacy VFIO. When the + element is present, an iommufd object with its ID specified by ``iommuf= dId`` + will be created by the resulting qemu command. Libvirt will open the + /dev/iommu and VFIO device cdev, passing the associated file descriptor + numbers to the qemu command. + ``address`` The ``address`` element for USB devices has a ``bus`` and ``device`` attribute to specify the USB bus and device number the device appears a= t on diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 5ea4d6424b..38d8f2998a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -13581,6 +13581,15 @@ virDomainVideoDefParseXML(virDomainXMLOption *xmlo= pt, return g_steal_pointer(&def); } =20 +static void +virDomainHostdevDefIommufdParseXML(xmlXPathContextPtr ctxt, + char** iommufdId) +{ + g_autofree char *iommufdIdtmp =3D virXPathString("string(./iommufdId)"= , ctxt); + if (iommufdIdtmp) + *iommufdId =3D g_steal_pointer(&iommufdIdtmp); +} + static virDomainHostdevDef * virDomainHostdevDefParseXML(virDomainXMLOption *xmlopt, xmlNodePtr node, @@ -13655,6 +13664,8 @@ virDomainHostdevDefParseXML(virDomainXMLOption *xml= opt, if (virDomainNetTeamingInfoParseXML(ctxt, &def->teaming) < 0) goto error; =20 + virDomainHostdevDefIommufdParseXML(ctxt, &def->iommufdId); + return def; =20 error: @@ -21195,6 +21206,11 @@ virDomainHostdevDefCheckABIStability(virDomainHost= devDef *src, } } =20 + if (src->iommufdId && dst->iommufdId) { + if (STRNEQ(src->iommufdId, dst->iommufdId)) + return false; + } + if (!virDomainDeviceInfoCheckABIStability(src->info, dst->info)) return false; =20 @@ -27554,6 +27570,10 @@ virDomainHostdevDefFormat(virBuffer *buf, if (def->shareable) virBufferAddLit(buf, "\n"); =20 + if (def->iommufdId) { + virBufferAsprintf(buf, "%s\n", def->iommufd= Id); + } + virDomainDeviceInfoFormat(buf, def->info, flags | VIR_DOMAIN_DEF_FORMA= T_ALLOW_BOOT | VIR_DOMAIN_DEF_FORMA= T_ALLOW_ROM); =20 diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index edb18632f3..367e7686f1 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -375,6 +375,7 @@ struct _virDomainHostdevDef { virDomainHostdevCaps caps; } source; virDomainNetTeamingInfo *teaming; + char *iommufdId; virDomainDeviceInfo *info; /* Guest address */ }; =20 diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincom= mon.rng index fd19f115f7..662f12c4f1 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -6507,6 +6507,9 @@ + + + @@ -7761,6 +7764,12 @@ =20 + + + + + + diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index cecd0661ca..6b3e2ffd0d 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4846,6 +4846,7 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def, "S:failover_pair_id", failover_pair_id, "S:display", qemuOnOffAuto(pcisrc->display), "B:ramfb", ramfb, + "S:iommufd", dev->iommufdId, NULL) < 0) return NULL; =20 @@ -5225,6 +5226,8 @@ qemuBuildHostdevCommandLine(virCommand *cmd, virQEMUCaps *qemuCaps) { size_t i; + g_autoptr(virJSONValue) props =3D NULL; + int iommufd =3D 0; =20 for (i =3D 0; i < def->nhostdevs; i++) { virDomainHostdevDef *hostdev =3D def->hostdevs[i]; @@ -5234,6 +5237,17 @@ qemuBuildHostdevCommandLine(virCommand *cmd, g_autofree char *vhostfdName =3D NULL; int vhostfd =3D -1; =20 + if (hostdev->iommufdId && iommufd =3D=3D 0) { + iommufd =3D 1; + if (qemuMonitorCreateObjectProps(&props, "iommufd", + hostdev->iommufdId, + NULL) < 0) + return -1; + + if (qemuBuildObjectCommandlineFromJSON(cmd, props) < 0) + return -1; + } + if (hostdev->mode !=3D VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) continue; =20 --=20 2.43.0 From nobody Sun Sep 7 06:47:11 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; arc=fail (BodyHash is different from the expected one); dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1755226929052944.7037008852008; Thu, 14 Aug 2025 20:02:09 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 5F92EADC; Thu, 14 Aug 2025 23:02:08 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 5409CC18; Thu, 14 Aug 2025 22:55:42 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 64ADD999; Thu, 14 Aug 2025 22:55:39 -0400 (EDT) Received: from NAM11-CO1-obe.outbound.protection.outlook.com (mail-co1nam11on2086.outbound.protection.outlook.com [40.107.220.86]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 65247B15 for ; Thu, 14 Aug 2025 22:54:43 -0400 (EDT) Received: from PH7PR12MB6834.namprd12.prod.outlook.com (2603:10b6:510:1b4::18) by PH7PR12MB5685.namprd12.prod.outlook.com (2603:10b6:510:13c::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9031.15; Fri, 15 Aug 2025 02:54:38 +0000 Received: from PH7PR12MB6834.namprd12.prod.outlook.com ([fe80::f432:162b:b94e:d2cb]) by PH7PR12MB6834.namprd12.prod.outlook.com ([fe80::f432:162b:b94e:d2cb%4]) with mapi id 15.20.9009.017; Fri, 15 Aug 2025 02:54:38 +0000 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=0.2 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, FORGED_SPF_HELO,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_PASS autolearn=no autolearn_force=no version=3.4.4 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=B/0qDh8wxEz8yjOgE5KwQZ99CCAiiQTvLSmshhnZIigBdEKCGq5ju2rAOmUR23u2ypUAOPN5UHtQVWD3J/QGoY5HpZcSdT2y2N6M4AfN0jdEk42sl7Ppua+SY3fKjO67XoUxGy7LNXMjLAiMaiL6988fPLVng4Pyc/ntJwdj1IaQATAUu28RY+MY9IBo8Zwn6UpMQs4IS/Xq+JSvuCTwvSVnBw2EgLuwyx/leoXSsJuLxJAoCfwVeZlJLASlYRPaQG5YHUWVFPa2P8irnFG0vs7L1HaD8qNRyCzPXvGjMVv8w/Tln6ZRkL+ZEGi+YH1BQEZPgPJM9XH5Vcj7PEPj3g== 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=/zSrQU8H1NPnxidodqAjH8kilpudJOfTro+bjakd4mE=; b=ol3BHVpAE3e7HuzC6e3ta2iTIG62Icg7Z4DUBf8tcNPx/FjF/29BkiYsWhHqWg+OQHesGSZ33lB1+5KojXJvvu+r7lAFPlb9o+FskasNqyfnje5xfLpPmTHauhtWMngLqIbuYLn9eQNcM95x/nDQxLhMXw5vUe5SWMK8+bsoNQfJRfD+vRVg4RbNNXwz9jpAcJ/mXtIkmcToB0cPOzf/EIjEyhOhQ21TqC6hsKbmLRPM+MThVmRNQhWZuSVbgSfHcLYgtLZysrE9sDinQKvRzRfgzdDR5uoc/NEWD1NPJA1xEOLwQv4hp+tLqThkif0k2xgIQ76hXk7NhLBh/y9zRQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=/zSrQU8H1NPnxidodqAjH8kilpudJOfTro+bjakd4mE=; b=gavtZZd68WfWb6lMcZsW5ggL7JhbBIS/FCNZEM+SHJ0f8Zpe0jj0jmGYAJzDtFBGCzqXbfMcYImyehPXAOwocrs6VJxJYqRNQ+TpV1i3urEnFSPlGsYwDf4QIr3SWbDZjYICHilhCeKpXCBwspBfuV7wBLYg3zqSDyQu+EsCuWno+iN6boc3BnwmSiaJZOP/a4ib7mDQnsLFOA147IkjucEoXblYj2AL1eeCuKtzLIn+aRBVgGB+fmN8zLP9CJQsTDwfSV4UoMual8+hGBEiF77Ev4ckGkdOqRySrsbrIOm+eqv4R8llBUARQr/yBHHUaQjGMNQfoGrngI6D5zhZfw== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; To: devel@lists.libvirt.org Subject: [RFC PATCH 4/5] qemu: open iommufd FDs from libvirt backend Date: Thu, 14 Aug 2025 19:54:13 -0700 Message-ID: <20250815025415.2805374-5-nathanc@nvidia.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250815025415.2805374-1-nathanc@nvidia.com> References: <20250815025415.2805374-1-nathanc@nvidia.com> X-ClientProxiedBy: BYAPR05CA0082.namprd05.prod.outlook.com (2603:10b6:a03:e0::23) To PH7PR12MB6834.namprd12.prod.outlook.com (2603:10b6:510:1b4::18) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PH7PR12MB6834:EE_|PH7PR12MB5685:EE_ X-MS-Office365-Filtering-Correlation-Id: 7f9b891c-fa11-44f8-d9f7-08dddba7135f X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|366016|376014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?NTsHrAXB/jv1v+UBRMnyi0MTVrGSo9v4d8BITkdfaPbtUxcxHzv8C5H81R7T?= =?us-ascii?Q?kr6tp2YHqT0pYAxuVDCT6IlDObZb+MJR0b007VuHd0angRynxX/Xpk4H7WAS?= =?us-ascii?Q?P75v5cvJKsJ2kcfBdIvLEK2xyV4uGTOSkJ8TpvYrFyUtEF7w4SE9gQ1kpY9c?= =?us-ascii?Q?skmqOE02O9zA6BbQoSGWCnr8Vww298NyvgJOk9R8pApJT5FM/7A5W3FGVGIM?= =?us-ascii?Q?hPOsWUEcZvx9wWaUzxN92cMEPULXJAbbEsJ2apojByokmtpGVNCUBGGEx4kk?= =?us-ascii?Q?wJrieMURNTzg/TBiSIR75a6tRp9CeNcY6sItueC8zbRXD0PttBhOa/2q46am?= =?us-ascii?Q?AF5RNQehaIfHgNX3A0lKO/LSCHIu8muBe/sMO26M44eOHIHWDuSZhVCthhQI?= =?us-ascii?Q?vZ3dbHWEaBmJl4n1W1KDbFZbaEtELG1NpotfKHAcRJeaqe0/YKEz68mDP34v?= =?us-ascii?Q?yGAQZt3/Sn6zVStu9MtqrCbtfRcdmK4lSoRnIU3XagXhb0ekuDtX6r6Iol8j?= =?us-ascii?Q?pdSPYUVf0uXwG1xHYS7ToqMPrQEzVgGEonyndUIG6mqHRpKBbPnIXK7L6enw?= =?us-ascii?Q?hGhzzcFL20fEn5D6x37Ca7N64DsRzEc7Pz5sA1o/OV2QJXysXfKRgGDQ4OfA?= =?us-ascii?Q?pniKyqRKqC6faRc5Mlt5zmiKBdixpyzKf0G8eX4KQCsN9P4Xu7cbsE33IHzN?= =?us-ascii?Q?QsQm6QEyiv/qb+ptuWI4GqPChGrRB10AaXFiY0jw0bwPC21PgzUKK5w0zVIu?= =?us-ascii?Q?9qSL9cYksJZlCmmZ+YxYjoaQmnkIkTsYI4K+CtYTiE7wbB/flFilLfMLEG/9?= =?us-ascii?Q?DE7OP230SY3xAySphCDFURolko6fCrHsVrdV8E9yjNZ3tT7nqDc7gu0uKvPC?= =?us-ascii?Q?9ZHoPSV2Zjv3txg9iIokIRIneNPEpXVfTZvzLvxMuYmqun3zEwa2g8qcWTY8?= =?us-ascii?Q?VSDJub3Qlgz73LpBrTDNEiXZ2EK2hvXseQcUCF2S5EDc2oZKwLbVRy2HbOM9?= =?us-ascii?Q?OlSls8AF+xCSshMVvO63igAm8vXO/9PDEnOAvai9OpzSu76Lgi4+evL9xWzX?= =?us-ascii?Q?Em95oY/eDPMUQB6/PSYOM7fzZxhYIdaKQBlsp8FefrO7U+6IIhoyxfjSkas+?= =?us-ascii?Q?vdLdzxipF5w+nTN/vjoLXIeOJJ1L/512j56uMllsNvTsBTQD1/VZhLwkjFOh?= =?us-ascii?Q?4fN1yluxDgGHhkL27skIPwZwZzwwBkEz8+Bil1HbcG6TNPTo22OYymcZojSI?= =?us-ascii?Q?kcjKLP5y+UPCP4zRddgC1nhGpjEcae0eF4JBNmoou4nVVJMrJasWv/EdUReL?= =?us-ascii?Q?jUcU+ykS8rZAonyL7hk/wen0YAS5urlrAR6PVZscMLAbKmZuhk3GGnR37off?= =?us-ascii?Q?+6GbWwCljzafEKIY5OCXfF1WIk0c/91J0IeZcK4U+2KYhOEWKoIBWGBcaK40?= =?us-ascii?Q?zrUFZCcZHjg=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PH7PR12MB6834.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(366016)(376014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?GhCVnJJkVKDwMq2b10jlDTpuFrVqOFvsxfp06kehFIFnu1buMo4nG0tlyHbn?= =?us-ascii?Q?82BgtsAa1CwyCMKE9YyM8YIfW85+ERBBpkIToOhqo3k8uLXtL0Fi+mNOggJj?= =?us-ascii?Q?NDel+MqzzvKM/TTb0crmI6LAhEK5CNDvfanoW9oxyZ18iWDpv3MZp5On1yg+?= =?us-ascii?Q?XsVfDIvMkRFvJtwiJiLwFv1VRh6joVr4LX9bEP3DBtrB7lYil9/vYwl+TeX8?= =?us-ascii?Q?wFr6zEMWMV/b0VsHuuZ5XAxC0/E8O0mHCTSmSgCBjPKHaQhRrpuuN6QXX1Xm?= =?us-ascii?Q?gB1z6dq4GzbzSQ1texu4rgnjRAWLrWEkrn4sF/zxBo3eAh9W7O5cvagY9z6C?= =?us-ascii?Q?+8lvexnukjwtoibGWdDpsptq9Jv7jLmrct3CilV5Zdd9dZfxGT19LFeA976F?= =?us-ascii?Q?ggmQ7VGMxGiYfLSWZaf/aLhsIjRngOaCKDo9U7t+wCkOB8b+aORDpIuPtzeo?= =?us-ascii?Q?AIUQwFXOzl+bWLoIrWGcY7aepnJEMCuPJhH2qS9Sz12q3zjNWdjn6BtIWolc?= =?us-ascii?Q?CuBPK4eWjLtAkTfxwnjyBIx8/6aOfd5V5betcZ0jps1OBUifXBNyjgTfOJu6?= =?us-ascii?Q?xG42JwfElmNObFi2QlpxJ2OsTzX8qHGnIwA930V7MIyiLURBsvKxcgmy7E9k?= =?us-ascii?Q?QPyVzDeQBhq6Ra4ZD41yv6qdDHS1RFKE6mZ2JodQW1tyxgEPGHSbR+P9RtSb?= =?us-ascii?Q?kU5sEfnq6nrhzCFWhieM3tqtX21iNXn2EX3iv0K2YLt5DRylHntbvChvjwos?= =?us-ascii?Q?GSRcYdMWTlZqMNjkzUTScOTv/bxjanhR8HtNWO0YFBIceZYpIB4qB443kb58?= =?us-ascii?Q?JiQ+ugo5XUfb7j/GuRdj0+7l6jyoa1J4+OyGi2rRt90tP0vCJuZ0Khar41FE?= =?us-ascii?Q?2DxxnIs/sDvQgxVBkLCBkZYK7pqa3zNTCiH7QVAC6HM/VmCMuNN9EeWSl1/L?= =?us-ascii?Q?ApHxIu7O9Haz8qQwzf5RIOHn/26VJFsIff1gdL53AFi//GBtJOpWmEGSaBwZ?= =?us-ascii?Q?j3C0QI5z4wtQGUXYVDjosUQc0LYZfkXxSvixPMUuqRAf7P8xo5yHWw6qIXlS?= =?us-ascii?Q?sEQskHQwwSOU3deVoLj8NWQbCUVOGKMIgDJlfuB5yzrKfsn97lyVJWoMWR6f?= =?us-ascii?Q?4tr6364Ut2e8GGHfcnXpcaPS51jR73LnDFBbdjKtE+IlM05LLWtSPZLw65nl?= =?us-ascii?Q?1WG3GteCKKfHvPyL57fc3h/lTJfVKw4Tng+Sm99BE4jMK5QRFKAtD/xqni8W?= =?us-ascii?Q?4t+ZqDTgLr+qWCRuv4/IQda1rRfzixaCTYnVTwUvSf+GZ2eG/sQgEsOnvgtS?= =?us-ascii?Q?Z0IbCv/ymRR/MwpvpumHLF5geoCkXCfZrRYIbe2M/FGyeP76XUIYI4d5bZtZ?= =?us-ascii?Q?Ejtg1Grbj0z2DM4tkX63eN/6YlE7584dA0M8mn5X5WDNwJlOzpq1a7ZIam58?= =?us-ascii?Q?gMxO4wviRuSKGj9juVFmL9bJi/ZPQvswJOx2avIH4B162H0s49iE3RAWmqVg?= =?us-ascii?Q?X1ZPtYLcbEkxwQUCCjZrUV2lBeBcO7MaEdazlLvtQW/0YW8MofwHut49peAh?= =?us-ascii?Q?wK6Do5BOKnGDqUyd7iz3QsHua4XZmrs6y+hoJykd?= X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 7f9b891c-fa11-44f8-d9f7-08dddba7135f X-MS-Exchange-CrossTenant-AuthSource: PH7PR12MB6834.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Aug 2025 02:54:38.8907 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: M5YPEDGp7rR5/asfAxmVJEuQmispwHjI3USt2dPJK61uYe+ReXspGS+2zx9jgyObJ8xXdanP2H/FxWUdPi5Buw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB5685 Content-Transfer-Encoding: quoted-printable Message-ID-Hash: ZIHD53WZBIZ6AEUYO5MKGL6U3QBK62ZN X-Message-ID-Hash: ZIHD53WZBIZ6AEUYO5MKGL6U3QBK62ZN X-MailFrom: nathanc@nvidia.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header CC: shameerali.kolothum.thodi@huawei.com, nicolinc@nvidia.com, nathanc@nvidia.com X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: From: Nathan Chen via Devel Reply-To: Nathan Chen X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1755226932028124100 Content-Type: text/plain; charset="utf-8" Open iommufd FDs from libvirt backend without exposing these FDs to XML users, i.e. one per domain for /dev/iommu and one per iommufd hostdev for /dev/vfio/devices/vfioX, and pass the FD to qemu command line. Signed-off-by: Nathan Chen --- src/qemu/qemu_command.c | 44 +++++++- src/qemu/qemu_command.h | 3 +- src/qemu/qemu_domain.c | 8 ++ src/qemu/qemu_domain.h | 7 ++ src/qemu/qemu_hotplug.c | 2 +- src/qemu/qemu_process.c | 232 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 290 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 6b3e2ffd0d..359dbb2621 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4797,7 +4797,8 @@ qemuBuildVideoCommandLine(virCommand *cmd, =20 virJSONValue * qemuBuildPCIHostdevDevProps(const virDomainDef *def, - virDomainHostdevDef *dev) + virDomainHostdevDef *dev, + virDomainObj *vm) { g_autoptr(virJSONValue) props =3D NULL; virDomainHostdevSubsysPCI *pcisrc =3D &dev->source.subsys.u.pci; @@ -4807,6 +4808,13 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def, const char *driver =3D NULL; /* 'ramfb' property must be omitted unless it's to be enabled */ bool ramfb =3D pcisrc->ramfb =3D=3D VIR_TRISTATE_SWITCH_ON; + bool useIommufd =3D false; + qemuDomainObjPrivate *priv =3D vm ? vm->privateData : NULL; + + if (pcisrc->driver.name =3D=3D VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO= && + dev->iommufdId) { + useIommufd =3D true; + } =20 /* caller has to assign proper passthrough driver name */ switch (pcisrc->driver.name) { @@ -4850,6 +4858,18 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def, NULL) < 0) return NULL; =20 + if (useIommufd && priv) { + g_autofree char *vfioFdName =3D g_strdup_printf("vfio-%04x:%02x:%0= 2x.%d", + pcisrc->addr.domain,= pcisrc->addr.bus, + pcisrc->addr.slot, p= cisrc->addr.function); + + int vfiofd =3D GPOINTER_TO_INT(g_hash_table_lookup(priv->vfioDevic= eFds, vfioFdName)); + if (virJSONValueObjectAdd(&props, + "S:fd", g_strdup_printf("%d", vfiofd), + NULL) < 0) + return NULL; + } + if (qemuBuildDeviceAddressProps(props, def, dev->info) < 0) return NULL; =20 @@ -5223,11 +5243,13 @@ qemuBuildHostdevSCSICommandLine(virCommand *cmd, static int qemuBuildHostdevCommandLine(virCommand *cmd, const virDomainDef *def, - virQEMUCaps *qemuCaps) + virQEMUCaps *qemuCaps, + virDomainObj *vm) { size_t i; g_autoptr(virJSONValue) props =3D NULL; int iommufd =3D 0; + qemuDomainObjPrivate *priv =3D vm->privateData; =20 for (i =3D 0; i < def->nhostdevs; i++) { virDomainHostdevDef *hostdev =3D def->hostdevs[i]; @@ -5239,8 +5261,11 @@ qemuBuildHostdevCommandLine(virCommand *cmd, =20 if (hostdev->iommufdId && iommufd =3D=3D 0) { iommufd =3D 1; + virCommandPassFD(cmd, priv->iommufd, VIR_COMMAND_PASS_FD_CLOSE= _PARENT); + if (qemuMonitorCreateObjectProps(&props, "iommufd", hostdev->iommufdId, + "S:fd", g_strdup_printf("%d",= priv->iommufd), NULL) < 0) return -1; =20 @@ -5270,7 +5295,18 @@ qemuBuildHostdevCommandLine(virCommand *cmd, if (qemuCommandAddExtDevice(cmd, hostdev->info, def, qemuCaps)= < 0) return -1; =20 - if (!(devprops =3D qemuBuildPCIHostdevDevProps(def, hostdev))) + if (hostdev->iommufdId) { + virDomainHostdevSubsysPCI *pcisrc =3D &hostdev->source.sub= sys.u.pci; + g_autofree char *vfioFdName =3D g_strdup_printf("vfio-%04x= :%02x:%02x.%d", + pcisrc->addr= .domain, pcisrc->addr.bus, + pcisrc->addr= .slot, pcisrc->addr.function); + + int vfiofd =3D GPOINTER_TO_INT(g_hash_table_lookup(priv->v= fioDeviceFds, vfioFdName)); + + virCommandPassFD(cmd, vfiofd, VIR_COMMAND_PASS_FD_CLOSE_PA= RENT); + } + + if (!(devprops =3D qemuBuildPCIHostdevDevProps(def, hostdev, v= m))) return -1; =20 if (qemuBuildDeviceCommandlineFromJSON(cmd, devprops, def, qem= uCaps) < 0) @@ -10960,7 +10996,7 @@ qemuBuildCommandLine(virDomainObj *vm, if (qemuBuildRedirdevCommandLine(cmd, def, qemuCaps) < 0) return NULL; =20 - if (qemuBuildHostdevCommandLine(cmd, def, qemuCaps) < 0) + if (qemuBuildHostdevCommandLine(cmd, def, qemuCaps, vm) < 0) return NULL; =20 if (migrateURI) diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index ad068f1f16..380aac261f 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -180,7 +180,8 @@ qemuBuildThreadContextProps(virJSONValue **tcProps, /* Current, best practice */ virJSONValue * qemuBuildPCIHostdevDevProps(const virDomainDef *def, - virDomainHostdevDef *dev); + virDomainHostdevDef *dev, + virDomainObj *vm); =20 virJSONValue * qemuBuildRNGDevProps(const virDomainDef *def, diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index a2c7c88a7e..2086dbb575 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1954,6 +1954,11 @@ qemuDomainObjPrivateFree(void *data) =20 virChrdevFree(priv->devs); =20 + if (priv->iommufd >=3D 0) { + virEventRemoveHandle(priv->iommufd); + priv->iommufd =3D -1; + } + if (priv->pidMonitored >=3D 0) { virEventRemoveHandle(priv->pidMonitored); priv->pidMonitored =3D -1; @@ -1975,6 +1980,7 @@ qemuDomainObjPrivateFree(void *data) =20 g_clear_pointer(&priv->blockjobs, g_hash_table_unref); g_clear_pointer(&priv->fds, g_hash_table_unref); + g_clear_pointer(&priv->vfioDeviceFds, g_hash_table_unref); =20 /* This should never be non-NULL if we get here, but just in case... */ if (priv->eventThread) { @@ -2003,7 +2009,9 @@ qemuDomainObjPrivateAlloc(void *opaque) =20 priv->blockjobs =3D virHashNew(virObjectUnref); priv->fds =3D virHashNew(g_object_unref); + priv->vfioDeviceFds =3D g_hash_table_new(g_str_hash, g_str_equal); =20 + priv->iommufd =3D -1; priv->pidMonitored =3D -1; =20 /* agent commands block by default, user can choose different behavior= */ diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 1afd932764..6460323554 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -266,6 +266,10 @@ struct _qemuDomainObjPrivate { /* named file descriptor groups associated with the VM */ GHashTable *fds; =20 + int iommufd; + + GHashTable *vfioDeviceFds; + char *memoryBackingDir; }; =20 @@ -1172,3 +1176,6 @@ qemuDomainCheckCPU(virArch arch, bool qemuDomainMachineSupportsFloppy(const char *machine, virQEMUCaps *qemuCaps); + +int qemuProcessOpenVfioFds(virDomainObj *vm); +void qemuProcessCloseVfioFds(virDomainObj *vm); diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index e9568af125..e0e693e251 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1633,7 +1633,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriver *driver, goto error; } =20 - if (!(devprops =3D qemuBuildPCIHostdevDevProps(vm->def, hostdev))) + if (!(devprops =3D qemuBuildPCIHostdevDevProps(vm->def, hostdev, vm))) goto error; =20 qemuDomainObjEnterMonitor(vm); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index a81c02c9d5..1bc779c6aa 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -25,6 +25,7 @@ #include #include #include +#include #if WITH_SYS_SYSCALL_H # include #endif @@ -8025,6 +8026,9 @@ qemuProcessLaunch(virConnectPtr conn, if (qemuExtDevicesStart(driver, vm, incomingMigrationExtDevices) < 0) goto cleanup; =20 + if (qemuProcessOpenVfioFds(vm) < 0) + goto cleanup; + if (!(cmd =3D qemuBuildCommandLine(vm, incoming ? "defer" : NULL, vmop, @@ -10206,3 +10210,231 @@ qemuProcessHandleNbdkitExit(qemuNbdkitProcess *nb= dkit, qemuProcessEventSubmit(vm, QEMU_PROCESS_EVENT_NBDKIT_EXITED, 0, 0, nbd= kit); virObjectUnlock(vm); } + +/** + * qemuProcessOpenIommuFd: + * @vm: domain object + * @iommuFd: returned file descriptor + * + * Opens /dev/iommu file descriptor for the VM. + * + * Returns: 0 on success, -1 on failure + */ +static int +qemuProcessOpenIommuFd(virDomainObj *vm, int *iommuFd) +{ + int fd =3D -1; + + VIR_DEBUG("Opening IOMMU FD for domain %s", vm->def->name); + + if ((fd =3D open("/dev/iommu", O_RDWR | O_CLOEXEC)) < 0) { + if (errno =3D=3D ENOENT) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("IOMMU FD support requires /dev/iommu device"= )); + } else { + virReportSystemError(errno, "%s", + _("cannot open /dev/iommu")); + } + return -1; + } + + *iommuFd =3D fd; + VIR_DEBUG("Opened IOMMU FD %d for domain %s", fd, vm->def->name); + return 0; +} + +/** + * qemuProcessGetVfioDevicePath: + * @hostdev: host device definition + * @vfioPath: returned VFIO device path + * + * Constructs the VFIO device path for a PCI hostdev. + * + * Returns: 0 on success, -1 on failure + */ +static int +qemuProcessGetVfioDevicePath(virDomainHostdevDef *hostdev, + char **vfioPath) +{ + virPCIDeviceAddress *addr; + g_autofree char *sysfsPath =3D NULL; + DIR *dir =3D NULL; + struct dirent *entry =3D NULL; + int ret =3D -1; + + if (hostdev->mode !=3D VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || + hostdev->source.subsys.type !=3D VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PC= I) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("VFIO FD only supported for PCI hostdevs")); + return -1; + } + + addr =3D &hostdev->source.subsys.u.pci.addr; + + /* Build sysfs path: /sys/bus/pci/devices/DDDD:BB:DD.F/vfio-dev/ */ + sysfsPath =3D g_strdup_printf("/sys/bus/pci/devices/" + "%04x:%02x:%02x.%d/vfio-dev/", + addr->domain, addr->bus, + addr->slot, addr->function); + + if (virDirOpen(&dir, sysfsPath) < 0) { + virReportSystemError(errno, + _("cannot open VFIO sysfs directory %1$s"), + sysfsPath); + return -1; + } + + /* Find the vfio device name in the directory */ + while (virDirRead(dir, &entry, sysfsPath) > 0) { + if (STRPREFIX(entry->d_name, "vfio")) { + *vfioPath =3D g_strdup_printf("/dev/vfio/devices/%s", entry->d= _name); + ret =3D 0; + break; + } + } + + if (ret < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot find VFIO device for PCI device %1$04x:%2= $02x:%3$02x.%4$d"), + addr->domain, addr->bus, addr->slot, addr->function= ); + } + + virDirClose(dir); + return ret; +} + +/** + * qemuProcessOpenVfioDeviceFd: + * @hostdev: host device definition + * @vfioFd: returned file descriptor + * + * Opens the VFIO device file descriptor for a hostdev. + * + * Returns: 0 on success, -1 on failure + */ +static int +qemuProcessOpenVfioDeviceFd(virDomainHostdevDef *hostdev, + int *vfioFd) +{ + g_autofree char *vfioPath =3D NULL; + int fd =3D -1; + + if (qemuProcessGetVfioDevicePath(hostdev, &vfioPath) < 0) + return -1; + + VIR_DEBUG("Opening VFIO device %s", vfioPath); + + if ((fd =3D open(vfioPath, O_RDWR | O_CLOEXEC)) < 0) { + if (errno =3D=3D ENOENT) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("VFIO device %1$s not found - ensure device i= s bound to vfio-pci driver"), + vfioPath); + } else { + virReportSystemError(errno, + _("cannot open VFIO device %1$s"), vfioPa= th); + } + return -1; + } + + *vfioFd =3D fd; + VIR_DEBUG("Opened VFIO device FD %d for %s", *vfioFd, vfioPath); + return 0; +} + +/** + * qemuProcessOpenVfioFds: + * @vm: domain object + * + * Opens all necessary VFIO file descriptors for the domain. + * + * Returns: 0 on success, -1 on failure + */ +int +qemuProcessOpenVfioFds(virDomainObj *vm) +{ + qemuDomainObjPrivate *priv =3D vm->privateData; + bool needsIommuFd =3D false; + size_t i; + + /* Check if we have any hostdevs that need VFIO FDs */ + for (i =3D 0; i < vm->def->nhostdevs; i++) { + virDomainHostdevDef *hostdev =3D vm->def->hostdevs[i]; + int vfioFd =3D -1; + g_autofree char *fdname =3D NULL; + + if (hostdev->mode =3D=3D VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && + hostdev->source.subsys.type =3D=3D VIR_DOMAIN_HOSTDEV_SUBSYS_T= YPE_PCI) { + + /* Check if this hostdev uses VFIO with IOMMU FD */ + if (hostdev->source.subsys.u.pci.driver.name =3D=3D VIR_DEVICE= _HOSTDEV_PCI_DRIVER_NAME_VFIO && + hostdev->iommufdId) { + + needsIommuFd =3D true; + + /* Open VFIO device FD */ + if (qemuProcessOpenVfioDeviceFd(hostdev, &vfioFd) < 0) + goto error; + + /* Store the FD */ + fdname =3D g_strdup_printf("vfio-%04x:%02x:%02x.%d", + hostdev->source.subsys.u.pci.addr= .domain, + hostdev->source.subsys.u.pci.addr= .bus, + hostdev->source.subsys.u.pci.addr= .slot, + hostdev->source.subsys.u.pci.addr= .function); + + g_hash_table_insert(priv->vfioDeviceFds, g_steal_pointer(&= fdname), GINT_TO_POINTER(vfioFd)); + + VIR_DEBUG("Stored VFIO FD for device %s", fdname); + } + } + } + + /* Open IOMMU FD if needed */ + if (needsIommuFd) { + int iommuFd =3D -1; + + if (qemuProcessOpenIommuFd(vm, &iommuFd) < 0) + goto error; + + priv->iommufd =3D iommuFd; + + VIR_DEBUG("Stored IOMMU FD"); + } + + return 0; + + error: + qemuProcessCloseVfioFds(vm); + return -1; +} + +/** + * qemuProcessCloseVfioFds: + * @vm: domain object + * + * Closes all VFIO file descriptors for the domain. + */ +void +qemuProcessCloseVfioFds(virDomainObj *vm) +{ + qemuDomainObjPrivate *priv =3D vm->privateData; + GHashTableIter iter; + gpointer key, value; + + /* Close all VFIO device FDs */ + if (priv->vfioDeviceFds) { + g_hash_table_iter_init(&iter, priv->vfioDeviceFds); + while (g_hash_table_iter_next(&iter, &key, &value)) { + int fd =3D GPOINTER_TO_INT(value); + VIR_DEBUG("Closing VFIO device FD %d for %s", fd, (char*)key); + VIR_FORCE_CLOSE(fd); + } + g_hash_table_remove_all(priv->vfioDeviceFds); + } + + /* Close IOMMU FD */ + if (priv->iommufd >=3D 0) { + VIR_DEBUG("Closing IOMMU FD %d", priv->iommufd); + VIR_FORCE_CLOSE(priv->iommufd); + } +} --=20 2.43.0 From nobody Sun Sep 7 06:47:11 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; arc=fail (BodyHash is different from the expected one); dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1755227005179129.03097699979367; Thu, 14 Aug 2025 20:03:25 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id A4FF1980; Thu, 14 Aug 2025 23:03:24 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id D8ADCC5F; Thu, 14 Aug 2025 22:55:46 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id E73A1B92; Thu, 14 Aug 2025 22:55:42 -0400 (EDT) Received: from NAM11-BN8-obe.outbound.protection.outlook.com (mail-bn8nam11on2064.outbound.protection.outlook.com [40.107.236.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 776CAB26 for ; Thu, 14 Aug 2025 22:54:46 -0400 (EDT) Received: from PH7PR12MB6834.namprd12.prod.outlook.com (2603:10b6:510:1b4::18) by PH7PR12MB5685.namprd12.prod.outlook.com (2603:10b6:510:13c::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9031.15; Fri, 15 Aug 2025 02:54:42 +0000 Received: from PH7PR12MB6834.namprd12.prod.outlook.com ([fe80::f432:162b:b94e:d2cb]) by PH7PR12MB6834.namprd12.prod.outlook.com ([fe80::f432:162b:b94e:d2cb%4]) with mapi id 15.20.9009.017; Fri, 15 Aug 2025 02:54:42 +0000 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=0.2 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, FORGED_SPF_HELO,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_PASS autolearn=no autolearn_force=no version=3.4.4 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=sTCdQ1te0rI6c031e86pLZHS27mtQjelly43Hgzs4yBrbG/LXFn2t207LomJVZRYmMEiNfe0rjsNV0i+Jw6T4ZVECiSux996Hzyxo5QuqocVe8VLrl6IlWfrh+31/afjEOT8LKIxiHUJcAMLeuGN2T8zf28RqoB4H4EZjZCooKjeR9xrZnRAtV0EpapjwuVQCwbFghE2NE6NphkmWbazUCJCMF8xi9rjiVD+MF21ISjv3YdBwBQ2KPB7kKDSiB9/sZQiiRaoezK7mBach+aI/naY5Ce4spc3lQGtixh/Z3VByVzRVXcyq8buyrV08joC7eioFuwwbwh11AAPaDkY4g== 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=OjABdEgSYDbdWboCInNRjGjHX4sOnmDNCN311GwFpA4=; b=vvJk3jdDaFFPh3IF2Jna1uw7F/STfmoV30cZ8ShsMHXZcas2gGvAJDANFLkBarcy1/NbblYiDc7Rj01iqZ8WAEj9qyGNhmOZpkaoqDHxVZTzWLf8Pli5z4VEjZR/g5IHfWunwtvFLm+yoFG7I3yuTjYsQiE2c3RG6NrbvjbqfUUlrfllmCqV5L/dDk4PR53OdfN8wGE+lbl8aUTd8J+Zn0zC0kBHPBlVIdYyz7wIbV9aFpcpxkbrAH2R/eRtsUgDp5YyrP/ShyItxsBt0ul5U96kzZgli1lcFOySef0QNcnPKgQWvH6hxqj1XqUSRgAs3dqTV+JzCXYV4IOWxb7xLg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=OjABdEgSYDbdWboCInNRjGjHX4sOnmDNCN311GwFpA4=; b=duwoITeVHKOiBiYfnrGL16saWkWMIcXEZAj2mj+7MxiZnhjXqB6hLKXyioqB/7gwity27RTDxSDKkccYUAzUnSDpKL1EF+gEJomqyzTRyK7erVLpjMToe3dskOk3jmnn6/9baDgrnpPFLlG3TutKtHNtb1HuD8PtmjBW3MtOFnJhH/7RuDk4tGTp7RaLpb6q1J+1AiyBszKwVWBN0WwLoPYBOLhLzDR8Bq33gceUmK/FgPu4J5HPyi+1SA4OvDD4u32L9TqzPimp7Al/PqKUouK6hlvR/EgbeiaouLfeY9kZoT8aisZhUgFIdmIqad5F65doQbKE4vOysRE4lDta9Q== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; To: devel@lists.libvirt.org Subject: [RFC PATCH 5/5] qemu: Update Cgroup, namespace, and seclabel for qemu to access iommufd paths Date: Thu, 14 Aug 2025 19:54:14 -0700 Message-ID: <20250815025415.2805374-6-nathanc@nvidia.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250815025415.2805374-1-nathanc@nvidia.com> References: <20250815025415.2805374-1-nathanc@nvidia.com> X-ClientProxiedBy: BYAPR05CA0087.namprd05.prod.outlook.com (2603:10b6:a03:e0::28) To PH7PR12MB6834.namprd12.prod.outlook.com (2603:10b6:510:1b4::18) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PH7PR12MB6834:EE_|PH7PR12MB5685:EE_ X-MS-Office365-Filtering-Correlation-Id: 7c1c5fc0-36b9-4c0b-f28c-08dddba7154e X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|366016|376014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?u4D2T40bQG2m715MSzahniOkxAh07mUpSy1DUDwnvL6CGJRmg5vMA0JgdiZu?= =?us-ascii?Q?DO25rn7qwPFkdxM/aqC37B3wPL1apNQLyEGQojOhSFNdCEy81ReutvEf+8GN?= =?us-ascii?Q?ZDz/D4KeJSlXY2IgkEeavnhzFDXxVWuOTK26nfL54pLVu/FBGdGhl/BA0INI?= =?us-ascii?Q?zJc8z+KCcno/U1ARF332+Exx+LMFaE1a8mIkqAMsERl/ZtwOku1oEw9RNF3z?= =?us-ascii?Q?Y+/ezNUGIs8VYxypEOzOfYVOggF5bAWYAxTuc5bHAGCptg+EQgUKScTxnnPP?= =?us-ascii?Q?5bncwhJmM7cdZEMdF836K0F9XmI0xjcoZpY0psleHpwAiMPCacqd/XEoB9FV?= =?us-ascii?Q?aJVhuokltPNjBdgadB+wfD50tx8AXrDf2ZauXp+zXzrSbKgb+U022QGz2ch4?= =?us-ascii?Q?/tWCq1f5aApFccucMwgeqq+5e2ZK+qJfS+RVmVQRfIevZNK6F/b16I92ECnL?= =?us-ascii?Q?IL9Pqv+NOR50HoQUPo5TrOY5+BPeQ6nVc/g/dtQCiUdBhi9ZJt1Te4KMGq02?= =?us-ascii?Q?+ShQ8OqhHH+rQQhJ1U3P8GApCV1q/mOOOeQ4e3oELHJP65Qa3d7vcyfuws14?= =?us-ascii?Q?/Pf+bf9mKe8Go3uTO5GcrZvocSVkci3rkviJdR5H+hbFtrHeGyUkIltvZGDe?= =?us-ascii?Q?FWxImGDsz4oUoU6GRFn+iwLQu+MOihBshifj0BKJKHhPeut2VgJvhQ736xq6?= =?us-ascii?Q?lJE+G6SNujI5SRWbgf9fD9X/RqMge6DFa9C3bHz8v4CNi3dJYrCOUwfS5F4Q?= =?us-ascii?Q?QqJ6nBed/OvFmNppj3Huf5QpA1hJMZrLL/0IrroBm4WP6FQTwkf93mhIN3pS?= =?us-ascii?Q?oYNVuErpwGyTz71fGsrwxj+7zUAD9V3xDEbgP2uNjM6SBn7sxlOxcTubrk1r?= =?us-ascii?Q?swkljNIpSS5CLtDD9osqOUiXy+NkDUIV0lxGuDANIab8hYrmkKdKWDGL6mCc?= =?us-ascii?Q?LdHNI/cxWnWy/loTAcov0R+VWbqLvYFmhhQVORKcH95Q0HDxvL64Zw6gvhYP?= =?us-ascii?Q?CtosTFxEW2wLEg9tRMC4dqNEenhvkgrTy/AEnOrhuSm65qWV8J18HWou+V36?= =?us-ascii?Q?SX5uPlGIHDCmKTx97HLDZIyUBzNOd2lfUrxkq7/+QU/cc4VM2G/132j01W4r?= =?us-ascii?Q?IoWEo1Mv+DNQsGVYIdQcgO3T8ihnWx8/DVdFQmvuKIMoTS1sSdVd0/F3yCNr?= =?us-ascii?Q?ivo9CJtFRPIN4UgUxSf5ffpC2/8T7mLxEJWBHXcGJEcRcseuTVePdhtILmUH?= =?us-ascii?Q?CHIP444MVWM9uGAQMymZiNBYV4MNY7g+OpZBdKJQH8403CHvSembh2zTsGDl?= =?us-ascii?Q?sT/BfOwd3rsYZjlqWCAAM/Ci2HbSKWeuIje4AV7aMbBOla8QMVKpyAmGajbB?= =?us-ascii?Q?RcZOWAMqYJSBV7oBrwK9FYOTohnskl0wk3Dd92S4tMl7rX16kQ=3D=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PH7PR12MB6834.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(366016)(376014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?QZqTIJR6v8p+v7R8tfDQy4sbTb1wsqpTwkl8Nco62AKgtxBUtVuTcxxpOkue?= =?us-ascii?Q?LHYS1LlyOhznWMtGEO1WYBgKLtm4rCwIMmY/yFiILu/mU4ixs2fRdPtEX0Pz?= =?us-ascii?Q?9pJnUfWIyvDHRPEc/DHSphNcwm4A2dNbpTzcmG+bPjaUzWoBj2vIbgPM2yAu?= =?us-ascii?Q?ziRqpQjs8j+VZCUTVdBxJEkC+Hu1G7/g1mOv36GRda2V8wPATWL3velpCPJC?= =?us-ascii?Q?Ka37iKCdNL1btN5CKYgX66kUOqTisysrpCHhZoVMG0b64UrdB3WJ2lVVpI2F?= =?us-ascii?Q?M+YK3FApjquYd6JuiPrHMM25kG5NcBZfct6Co9U8pf9M+sKjfkmbo3qacaGX?= =?us-ascii?Q?vi5pqPS0SXtNRQU7MM1V5ZI3NgjoO+6dsjyJIz+6PdRyIbIHfdtKa4yvcLOX?= =?us-ascii?Q?ZUTNJQxz+SPBeNN9PMtAoN6ptzP66pOW6rxOsGrlbZHnmSd5QsaBY48RYG8b?= =?us-ascii?Q?yBNEazvm+2a0UTjM2M8R8SfxhVvuh+pqjrZPZs9P+cHNRryYAIEOr+A5++1T?= =?us-ascii?Q?3vjXVjjp3DbpnNzMJeqaixYIyRLwi8fE+rrOf0P6CSK6qYEyYjDcyTS2FISp?= =?us-ascii?Q?yiYZvE1Tke27WXbzJs9r0iyzWKXKg38LjEL6teMYKTy/SyZHc5A8h3rx9uR+?= =?us-ascii?Q?ccthBVIOOAS0ePAluHR7dskHUGaOUWQfmqCsheA22+vUYjS4qgNw5+aD4vbK?= =?us-ascii?Q?QVQptDMWhP0D06pQg52tmDATU6ioLIuFiDPEFKIvX+kBuCbdOr51eeyJCf4h?= =?us-ascii?Q?ynVASKZ5P/fVi7m8F3UeloWtLIBvFW2/t3ZqLMFVmZeXwpWwIdrVimLqiSFc?= =?us-ascii?Q?LNlM6S5Bf54AloQMIExzt7X5oY08q80kQkUdXEDlqPrOCeOlJqcoqpf/Rc9J?= =?us-ascii?Q?0BeGux0Y1JCioDTy/uOPWDePoy+medlMIoPgGhNpLktONutwgOAt4n7o/M6N?= =?us-ascii?Q?289yo3+aeIrLqjnPmEEUYtvsyr+3YqC+3aVAAwVR1eufbjaoWY2RqQy9xoZH?= =?us-ascii?Q?8u+tUFaPShh9T44F1NAwqwD/JRnhpoejUE/Az/hLTIKZEHq2JVRJdPOmTmt0?= =?us-ascii?Q?61/IId+/qrJ1oKczBoZjtqbMFlhhSrCCyEb4M26jz73G9BXz9HQEp7hleus8?= =?us-ascii?Q?YEu9rcqEj2QXJ+kD7g5ItvDbbh+iRXa7AjGX0W/lRcTp/pLh0ixlyHUA5sgS?= =?us-ascii?Q?mQBlS3xFoc6fdaGV/54+HA/deg1bI0wJqjl+ux12WejJlrzYfPo7jm31Icay?= =?us-ascii?Q?Q/hvKGumY9x9B1nui1f9EWqABmTXkrNanrunEKiRUYDzce3jnvlqX0imZpGT?= =?us-ascii?Q?hCfpalQn6e5ocmxSbZ7VaOFeW5WJAgZJx8PgKXwfMRPIJF3yu8v2FurWzHGC?= =?us-ascii?Q?3JubzfVFnOea5GlQIBM1vMOMfJwW/9yltXyFz1oks/RPvJZRORE1iX31raXC?= =?us-ascii?Q?UbJPeikmgPGCwHlFegP/ynDbriC5G5LCszRvYpGj3rll6wZkolsKlUyo0Y8O?= =?us-ascii?Q?WKUyLFHQ7Wt1fb2IVtJ0psgwrGzQ9RXGXMc2M+EP7yuLfyyn2cNf3ORZRcB3?= =?us-ascii?Q?cN/HK83eSj+q52QW51sYDjFWme5NeTlBlxeD5/EV?= X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 7c1c5fc0-36b9-4c0b-f28c-08dddba7154e X-MS-Exchange-CrossTenant-AuthSource: PH7PR12MB6834.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Aug 2025 02:54:42.1146 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: IEfMKfN1oanX/6LqL/3kdGlb2tinuRdVzoadwG72WEsyW8nl0/Dn+IwzWMAl4+Rr+szhoOLF4HPl7lqAUIe4LQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB5685 Content-Transfer-Encoding: quoted-printable Message-ID-Hash: O4AVJXJTT254ZXAMUHPYUZLT2BANRSV5 X-Message-ID-Hash: O4AVJXJTT254ZXAMUHPYUZLT2BANRSV5 X-MailFrom: nathanc@nvidia.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header CC: shameerali.kolothum.thodi@huawei.com, nicolinc@nvidia.com, nathanc@nvidia.com X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: From: Nathan Chen via Devel Reply-To: Nathan Chen X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1755227011022124100 Content-Type: text/plain; charset="utf-8" Allow access to /dev/iommu and /dev/vfio/devices/vfio* when launching a qemu VM with iommufd feature enabled. Signed-off-by: Nathan Chen --- src/qemu/qemu_cgroup.c | 61 ++++++++++++++++++++++++++++ src/qemu/qemu_cgroup.h | 1 + src/qemu/qemu_namespace.c | 44 +++++++++++++++++++++ src/security/security_apparmor.c | 11 ++++++ src/security/security_dac.c | 23 +++++++++++ src/security/security_selinux.c | 24 +++++++++++ src/util/virpci.c | 68 ++++++++++++++++++++++++++++++++ src/util/virpci.h | 1 + 8 files changed, 233 insertions(+) diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index f10976c2b0..73d0cb3a7a 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -462,6 +462,54 @@ qemuTeardownInputCgroup(virDomainObj *vm, } =20 =20 +int +qemuSetupIommufdCgroup(virDomainObj *vm) +{ + qemuDomainObjPrivate *priv =3D vm->privateData; + g_autoptr(DIR) dir =3D NULL; + struct dirent *dent; + g_autofree char *path =3D NULL; + int iommufd =3D 0; + size_t i; + + for (i =3D 0; i < vm->def->nhostdevs; i++) { + if (vm->def->hostdevs[i]->iommufdId) { + iommufd =3D 1; + break; + } + } + + if (iommufd =3D=3D 1) { + if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DE= VICES)) + return 0; + if (virDirOpen(&dir, "/dev/vfio/devices") < 0) { + if (errno =3D=3D ENOENT) + return 0; + return -1; + } + while (virDirRead(dir, &dent, "/dev/vfio/devices") > 0) { + if (STRPREFIX(dent->d_name, "vfio")) { + path =3D g_strdup_printf("/dev/vfio/devices/%s", dent->d_n= ame); + } + if (path && + qemuCgroupAllowDevicePath(vm, path, + VIR_CGROUP_DEVICE_RW, false) < 0= ) { + return -1; + } + path =3D NULL; + } + if (virFileExists("/dev/iommu")) + path =3D g_strdup("/dev/iommu"); + if (path && + qemuCgroupAllowDevicePath(vm, path, + VIR_CGROUP_DEVICE_RW, false) < 0) { + return -1; + } + } + return 0; +} + + /** * qemuSetupHostdevCgroup: * vm: domain object @@ -760,6 +808,7 @@ qemuSetupDevicesCgroup(virDomainObj *vm) g_autoptr(virQEMUDriverConfig) cfg =3D virQEMUDriverGetConfig(priv->dr= iver); const char *const *deviceACL =3D (const char *const *) cfg->cgroupDevi= ceACL; int rv =3D -1; + int iommufd =3D 0; size_t i; =20 if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICE= S)) @@ -830,6 +879,18 @@ qemuSetupDevicesCgroup(virDomainObj *vm) return -1; } =20 + for (i =3D 0; i < vm->def->nhostdevs; i++) { + if (vm->def->hostdevs[i]->iommufdId) { + iommufd =3D 1; + break; + } + } + + if (iommufd =3D=3D 1) { + if (qemuSetupIommufdCgroup(vm) < 0) + return -1; + } + for (i =3D 0; i < vm->def->nmems; i++) { if (qemuSetupMemoryDevicesCgroup(vm, vm->def->mems[i]) < 0) return -1; diff --git a/src/qemu/qemu_cgroup.h b/src/qemu/qemu_cgroup.h index 3668034cde..bea677ba3c 100644 --- a/src/qemu/qemu_cgroup.h +++ b/src/qemu/qemu_cgroup.h @@ -42,6 +42,7 @@ int qemuSetupHostdevCgroup(virDomainObj *vm, int qemuTeardownHostdevCgroup(virDomainObj *vm, virDomainHostdevDef *dev) G_GNUC_WARN_UNUSED_RESULT; +int qemuSetupIommufdCgroup(virDomainObj *vm); int qemuSetupMemoryDevicesCgroup(virDomainObj *vm, virDomainMemoryDef *mem); int qemuTeardownMemoryDevicesCgroup(virDomainObj *vm, diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c index f72da83929..965a304f7f 100644 --- a/src/qemu/qemu_namespace.c +++ b/src/qemu/qemu_namespace.c @@ -677,6 +677,47 @@ qemuDomainSetupLaunchSecurity(virDomainObj *vm, } =20 =20 +static int +qemuDomainSetupIommufd(virDomainObj *vm, + GSList **paths) +{ + g_autoptr(DIR) dir =3D NULL; + struct dirent *dent; + g_autofree char *path =3D NULL; + int iommufd =3D 0; + size_t i; + + for (i =3D 0; i < vm->def->nhostdevs; i++) { + if (vm->def->hostdevs[i]->iommufdId) { + iommufd =3D 1; + break; + } + } + + /* Check if iommufd is enabled */ + if (iommufd =3D=3D 1) { + if (virDirOpen(&dir, "/dev/vfio/devices") < 0) { + if (errno =3D=3D ENOENT) + return 0; + return -1; + } + while (virDirRead(dir, &dent, "/dev/vfio/devices") > 0) { + if (STRPREFIX(dent->d_name, "vfio")) { + path =3D g_strdup_printf("/dev/vfio/devices/%s", dent->d_n= ame); + *paths =3D g_slist_prepend(*paths, g_steal_pointer(&path)); + } + } + path =3D NULL; + if (virFileExists("/dev/iommu")) + path =3D g_strdup("/dev/iommu"); + if (path) + *paths =3D g_slist_prepend(*paths, g_steal_pointer(&path)); + } + + return 0; +} + + static int qemuNamespaceMknodPaths(virDomainObj *vm, GSList *paths, @@ -700,6 +741,9 @@ qemuDomainBuildNamespace(virQEMUDriverConfig *cfg, if (qemuDomainSetupAllDisks(vm, &paths) < 0) return -1; =20 + if (qemuDomainSetupIommufd(vm, &paths) < 0) + return -1; + if (qemuDomainSetupAllHostdevs(vm, &paths) < 0) return -1; =20 diff --git a/src/security/security_apparmor.c b/src/security/security_appar= mor.c index 68ac39611f..73dc750c94 100644 --- a/src/security/security_apparmor.c +++ b/src/security/security_apparmor.c @@ -856,6 +856,17 @@ AppArmorSetSecurityHostdevLabel(virSecurityManager *mg= r, } ret =3D AppArmorSetSecurityPCILabel(pci, vfioGroupDev, ptr); VIR_FREE(vfioGroupDev); + + if (dev->iommufdId) { + g_autofree char *vfiofdDev =3D virPCIDeviceGetIOMMUFDDev(p= ci); + if (vfiofdDev) { + int ret2 =3D AppArmorSetSecurityPCILabel(pci, vfiofdDe= v, ptr); + if (ret2 < 0) + ret =3D ret2; + } else { + return -1; + } + } } else { ret =3D virPCIDeviceFileIterate(pci, AppArmorSetSecurityPCILab= el, ptr); } diff --git a/src/security/security_dac.c b/src/security/security_dac.c index 2f788b872a..327e36466d 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1290,6 +1290,18 @@ virSecurityDACSetHostdevLabel(virSecurityManager *mg= r, ret =3D virSecurityDACSetHostdevLabelHelper(vfioGroupDev, false, &cbdata); + if (dev->iommufdId) { + g_autofree char *vfiofdDev =3D virPCIDeviceGetIOMMUFDDev(p= ci); + if (vfiofdDev) { + int ret2 =3D virSecurityDACSetHostdevLabelHelper(vfiof= dDev, + false, + &cbdata= ); + if (ret2 < 0) + ret =3D ret2; + } else { + return -1; + } + } } else { ret =3D virPCIDeviceFileIterate(pci, virSecurityDACSetPCILabel, @@ -1450,6 +1462,17 @@ virSecurityDACRestoreHostdevLabel(virSecurityManager= *mgr, =20 ret =3D virSecurityDACRestoreFileLabelInternal(mgr, NULL, vfioGroupDev, fal= se); + if (dev->iommufdId) { + g_autofree char *vfiofdDev =3D virPCIDeviceGetIOMMUFDDev(p= ci); + if (vfiofdDev) { + int ret2 =3D virSecurityDACRestoreFileLabelInternal(mg= r, NULL, + vfio= fdDev, false); + if (ret2 < 0) + ret =3D ret2; + } else { + return -1; + } + } } else { ret =3D virPCIDeviceFileIterate(pci, virSecurityDACRestorePCIL= abel, mgr); } diff --git a/src/security/security_selinux.c b/src/security/security_selinu= x.c index fa5d1568eb..60dcadd839 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -2248,6 +2248,19 @@ virSecuritySELinuxSetHostdevSubsysLabel(virSecurityM= anager *mgr, ret =3D virSecuritySELinuxSetHostdevLabelHelper(vfioGroupDev, false, &data); + if (dev->iommufdId) { + g_autofree char *vfiofdDev =3D virPCIDeviceGetIOMMUFDDev(p= ci); + if (vfiofdDev) { + int ret2 =3D virSecuritySELinuxSetHostdevLabelHelper(v= fiofdDev, + fal= se, + &da= ta); + if (ret2 < 0) + ret =3D ret2; + } else { + return -1; + } + } + } else { ret =3D virPCIDeviceFileIterate(pci, virSecuritySELinuxSetPCIL= abel, &data); } @@ -2481,6 +2494,17 @@ virSecuritySELinuxRestoreHostdevSubsysLabel(virSecur= ityManager *mgr, return -1; =20 ret =3D virSecuritySELinuxRestoreFileLabel(mgr, vfioGroupDev, = false); + + if (dev->iommufdId) { + g_autofree char *vfiofdDev =3D virPCIDeviceGetIOMMUFDDev(p= ci); + if (vfiofdDev) { + int ret2 =3D virSecuritySELinuxRestoreFileLabel(mgr, v= fiofdDev, false); + if (ret2 < 0) + ret =3D ret2; + } else { + return -1; + } + } } else { ret =3D virPCIDeviceFileIterate(pci, virSecuritySELinuxRestore= PCILabel, mgr); } diff --git a/src/util/virpci.c b/src/util/virpci.c index 90617e69c6..6e6e5e47c0 100644 --- a/src/util/virpci.c +++ b/src/util/virpci.c @@ -2478,6 +2478,74 @@ virPCIDeviceGetIOMMUGroupDev(virPCIDevice *dev) return g_strdup_printf("/dev/vfio/%s", groupFile); } =20 +/* virPCIDeviceGetIOMMUFDDev - return the name of the device used + * to control this PCI device's group (e.g. "/dev/vfio/devices/vfio15") + */ +char * +virPCIDeviceGetIOMMUFDDev(virPCIDevice *dev) +{ + g_autofree char *path =3D NULL; + const char *pci_addr =3D NULL; + g_autoptr(DIR) dir =3D NULL; + struct dirent *entry; + char *vfiodev =3D NULL; + + /* Get PCI device address */ + pci_addr =3D virPCIDeviceGetName(dev); + if (!pci_addr) + return NULL; + + /* First try: look in PCI device's vfio-dev subdirectory */ + path =3D g_strdup_printf("/sys/bus/pci/devices/%s/vfio-dev", pci_addr); + + if (virDirOpen(&dir, path) =3D=3D 1) { + while (virDirRead(dir, &entry, path) > 0) { + if (!g_str_has_prefix(entry->d_name, "vfio")) + continue; + + vfiodev =3D g_strdup_printf("/dev/vfio/devices/%s", entry->d_n= ame); + break; + } + /* g_autoptr will automatically close dir when it goes out of scop= e */ + dir =3D NULL; + } + + /* Second try: scan /sys/class/vfio-dev for matching device */ + if (!vfiodev) { + g_free(path); + path =3D g_strdup("/sys/class/vfio-dev"); + + if (virDirOpen(&dir, path) =3D=3D 1) { + while (virDirRead(dir, &entry, path) > 0) { + g_autofree char *dev_link =3D NULL; + g_autofree char *target =3D NULL; + + if (!g_str_has_prefix(entry->d_name, "vfio")) + continue; + + dev_link =3D g_strdup_printf("/sys/class/vfio-dev/%s/devic= e", entry->d_name); + + if (virFileResolveLink(dev_link, &target) < 0) + continue; + + if (strstr(target, pci_addr)) { + vfiodev =3D g_strdup_printf("/dev/vfio/devices/%s", en= try->d_name); + break; + } + } + /* g_autoptr will automatically close dir */ + } + } + + /* Verify the device path exists and is accessible */ + if (vfiodev && !virFileExists(vfiodev)) { + VIR_FREE(vfiodev); + return NULL; + } + + return vfiodev; +} + static int virPCIDeviceDownstreamLacksACS(virPCIDevice *dev) { diff --git a/src/util/virpci.h b/src/util/virpci.h index fc538566e1..996ffab2f9 100644 --- a/src/util/virpci.h +++ b/src/util/virpci.h @@ -203,6 +203,7 @@ int virPCIDeviceAddressGetIOMMUGroupNum(virPCIDeviceAdd= ress *addr); char *virPCIDeviceAddressGetIOMMUGroupDev(const virPCIDeviceAddress *devAd= dr); bool virPCIDeviceExists(const virPCIDeviceAddress *addr); char *virPCIDeviceGetIOMMUGroupDev(virPCIDevice *dev); +char *virPCIDeviceGetIOMMUFDDev(virPCIDevice *dev); =20 int virPCIDeviceIsAssignable(virPCIDevice *dev, int strict_acs_check); --=20 2.43.0