From patchwork Thu May 30 12:25:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: CLEMENT MATHIEU--DRIF X-Patchwork-Id: 1941694 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=eviden.com header.i=@eviden.com header.a=rsa-sha256 header.s=mail header.b=V8nypa8D; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Vqlqd1QLFz20Pc for ; Thu, 30 May 2024 22:26:53 +1000 (AEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sCeqT-0007A4-NL; Thu, 30 May 2024 08:25:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sCeqS-000790-8E for qemu-devel@nongnu.org; Thu, 30 May 2024 08:25:24 -0400 Received: from smarthost3.eviden.com ([80.78.11.84]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sCeqM-00060c-6L for qemu-devel@nongnu.org; Thu, 30 May 2024 08:25:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=eviden.com; i=@eviden.com; q=dns/txt; s=mail; t=1717071918; x=1748607918; h=from:to:cc:subject:date:message-id:references: in-reply-to:content-id:content-transfer-encoding: mime-version; bh=CnU3SpW1Pg/uaqz3Nb+Z7ZxPd3dpDERhJY1nEyqHUdg=; b=V8nypa8DLdl+nUOWhNs5uzYU0IjELAhT/L5RkjWb6JtsLXEK+LYNnw5e NMJfEU85WDT5450QHQ1yGCcU49YIprwf6DozVf/RtGidZKlBzO14aYnsv IePN/vJ+ZGm52fVUMzdxCRh0PxNqYoRe+4afIptw2ndX0mJAIL4gboBsz YbcLoc4O0QXtp+Z3tOqILg1cPRLY/ySUXklMXWoiwWrfqGreI2A/8gYcJ oApJu9y9LpFUF3qJk80LLJSnAm5VlGC/Fm2GK6WYMipnhmly4MQE6HAWl D2xL9of1lz7IkGobA/XYsgN9GYkLpIZU7/jGVzhlPBN56gNvMunO6N0h6 w==; X-IronPort-AV: E=Sophos;i="6.08,201,1712613600"; d="scan'208";a="13581120" X-MGA-submission: MDHEHRsmBaEq/NMQWL2y7WEHsttL+uVL2ecyUtNn0v5geSW7PdqRxFZO6/FlEW8UMnlJCdYy6lIfBsb/v3m8yu7wPnDxx7Q9KJ0TsxALpvCRsy9x25n+SQDUu4D2+uYpebm+cAhAX+BUaNlIhqlNDKeWUXroymd6SRSdvhAZndC3Mw== Received: from mail-he1eur01lp2051.outbound.protection.outlook.com (HELO EUR01-HE1-obe.outbound.protection.outlook.com) ([104.47.0.51]) by smarthost3.eviden.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 May 2024 14:25:07 +0200 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ev+uBjl88jPHGzJhZJqhuvgACC1Q4pRZAtcynRmXNR5hmcngbh2eALLkRCA0skm5YR+4G8fdY3StUtto7WhhtIGJy5eF7rXBgjF6eUtjBnyazuYOJLI9BiV8tRSuB1hq/PdmqVAiXr8KBI68SHqPEZAlIEvaMDyqyuJQ2DnyZ2rabKE8cMwNapppb4kxION6r+olg/7xluTqSQkqTiD8PpqhY7BcPFjAMRWfORup7NnMqpYdwSuuqYgguRDxzxtDZlYE1ABwsbohpc7Skv8l7qwQVHDZahuDH0Du9cNpvldfOvrQ8c8ggU+xy+pPGW/ecldARIBJaj8xu9Lw4NfPWw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; 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=CnU3SpW1Pg/uaqz3Nb+Z7ZxPd3dpDERhJY1nEyqHUdg=; b=XWJSfjv7mcjgG7bxkg/lgCikXdZyXYTZO0r7nqH82wUSBJPQPGWla/WpMXqQ4gyHmR2Bb2Kdr0I7iSDVabarmee/iMkB9+XrdfZ+xX7NPmTAV7MoIttvtAjOqMhmnrSRpRWaX7fZxqKGGAazDPcuufaFlcBPPtJGeb+AHnuWQWsqccw042raYzPrlnAcD46+HhpJ0WitDyxyVmGV24toac7XNZGcIL4Yz+rR8U7ME6XJdjuzIPWvIF6eUIQAcfqQZT6ArYs+7B65/Te23YNqU4lIqsUxSMsk/iFBR+l14CRU8SvqlwR3sYRgYiyI9Y+k3P4YnA5F/EKHWshj0+7AeA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=eviden.com; dmarc=pass action=none header.from=eviden.com; dkim=pass header.d=eviden.com; arc=none Received: from AM8PR07MB7602.eurprd07.prod.outlook.com (2603:10a6:20b:24b::7) by AS8PR07MB8069.eurprd07.prod.outlook.com (2603:10a6:20b:358::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7633.21; Thu, 30 May 2024 12:25:05 +0000 Received: from AM8PR07MB7602.eurprd07.prod.outlook.com ([fe80::fbd7:ca71:b636:6f9d]) by AM8PR07MB7602.eurprd07.prod.outlook.com ([fe80::fbd7:ca71:b636:6f9d%5]) with mapi id 15.20.7633.018; Thu, 30 May 2024 12:25:05 +0000 From: CLEMENT MATHIEU--DRIF To: "qemu-devel@nongnu.org" CC: "jasowang@redhat.com" , "zhenzhong.duan@intel.com" , "kevin.tian@intel.com" , "yi.l.liu@intel.com" , "joao.m.martins@oracle.com" , "peterx@redhat.com" , CLEMENT MATHIEU--DRIF Subject: [PATCH v1 8/8] intel_iommu: add PRI operations support Thread-Topic: [PATCH v1 8/8] intel_iommu: add PRI operations support Thread-Index: AQHasoxnvtS4ZcFnKU+EJPIjk9nm7Q== Date: Thu, 30 May 2024 12:25:05 +0000 Message-ID: <20240530122439.42888-9-clement.mathieu--drif@eviden.com> References: <20240530122439.42888-1-clement.mathieu--drif@eviden.com> In-Reply-To: <20240530122439.42888-1-clement.mathieu--drif@eviden.com> Accept-Language: en-GB, fr-FR, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=eviden.com; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: AM8PR07MB7602:EE_|AS8PR07MB8069:EE_ x-ms-office365-filtering-correlation-id: f11a3497-5307-4362-440e-08dc80a389a2 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; ARA:13230031|376005|1800799015|366007|38070700009; x-microsoft-antispam-message-info: =?utf-8?q?QlygnngDMMfIokMLgenuIo2yiRpqia3?= =?utf-8?q?0osaRtgroNrbBaZCVGsSRvkaQoucsOeROzSRvuAXo5tZY5itQbUc+usKo6qpyZ+mZ?= =?utf-8?q?wC7MCLzwxRE3fyFTXLHL4mbiJ36geb4kcLyZsbCyB5zAqGnPyltZgmckwHCL5pOg2?= =?utf-8?q?j42Robs6jra/NzJi4D5i1Uq6QHr5qdturyufwxyFx6pvZu16XnP0Z4LJ8KyJl8Ngb?= =?utf-8?q?3SLM0893u/tDA+l/hc53WoR1GebfE04jcXI7ESPblW3Zzh2ZGJjdICy0KmUh+yoM7?= =?utf-8?q?8phuQFpujaSXlFG8gDICEkpLVdXtperhWJJlhB53sJuHS2rj75iYl0d3L8lYwiuTp?= =?utf-8?q?0Si5Aiud9SdyFVutqcDO95Di4XH95ZeuLEI3RXMos9RBI9W7dPhz96jDjHerKSNCJ?= =?utf-8?q?svaX5Uo2gpAj+1BSlpYTny4UWKWXsJLeLmXCy8qaWdIqc7lYcfcEN7HjIsaOF3zb0?= =?utf-8?q?w5QusQ9BKZPGzF1CGUoUGDNG2wGjTbSlwtpiMRPJjRUf6x2VE3sOAD8sZFOKVLA84?= =?utf-8?q?Qx9/4p1nGBCUUWxJDHGI215W5ovaBDXu9jA83WdTazKPWJ7tJ89+IWLcLm9wan0Qf?= =?utf-8?q?JcmnSMyBdpU0nnnMmQ19MXm5rT+O4CI9cq3Oh+IhmOoWsc3cCiKg0usvP9oWFmXqr?= =?utf-8?q?aHMvrBWKcZ7weHidAKYNKgJX/0zOasRyImifRE0y08CHdh5EatDUf6L16xz2QEFl9?= =?utf-8?q?wfAiIOXXa9NfJA/seReai3F/7ntCJhVVbLPe7YmlPLW7u49wC3Aq5oEar2xuAD3a+?= =?utf-8?q?vYyUt0QUgy1nBOKCTS/kOH7fdVr+7ffhpObREwEivg/6TuqB9lWGahbmpcKpKDfAw?= =?utf-8?q?81907SKoVGADWgUEVsHgT9qCVfkBaiiIyoaJP9BUMHlNDq4zXP4s7geHZBx84+vJW?= =?utf-8?q?aI+9Bw23g8HiY/8ll3j6l5R7+LZRG46YYqtuxaJgjS1pfIMtZomy1wja4MkAfNkT6?= =?utf-8?q?zfiIj8ZU0/mGfFoQ2ac6XW6OMR//GsFmHoeoynSFuTPNVQn60bScb85/423a2knS5?= =?utf-8?q?SNNGSeg+H+H4zJl1C4JKwt11MEHYrDSZBG+Epni39WtNJTDekgNCAweFfRTd1fFZk?= =?utf-8?q?fKe7G7rMUWZkWKqkhTCgyVrOGpAlkSwGMrUVILgnvr0P59uTu3YGXJqSw2i+cmmRe?= =?utf-8?q?4PM/v/BJIzaUmvF08kg+xAcix7BtF/R93B4a1NnCwCCj1e0FYvzIJG9kkNSr4OuFR?= =?utf-8?q?UQlYrFrNRvxpp4M8090Fd7KttnB873nwnEnokRPmswX0f0EtuHB6IQqpTh9GdHooS?= =?utf-8?q?XfXd29/VzZYMsn2+2vvvwoQrl6GQwFhb8og=3D=3D?= x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:AM8PR07MB7602.eurprd07.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230031)(376005)(1800799015)(366007)(38070700009); DIR:OUT; SFP:1101; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?utf-8?q?5HQKJvJzVPxeF+EEE5nlLuuQP1Of?= =?utf-8?q?rnzEdF7dI3UvoffCnX6B4SbXzocZBz33OBqa/ksgokoVrVH3mGuBMgXFMC5fhtn0D?= =?utf-8?q?Fgu9L+gAnJWXSOwiU0hlChpiR4K1utZ/AcF4FA9DfpA+n5uXh6cTsJcg9AoA0zlnn?= =?utf-8?q?wXxKP8ECKfmOG7ngLP0b96uwFCYKWtmJFZ3fi6jXDGiR5imOdQU3CUMick1ij+Amx?= =?utf-8?q?B3ZtO0VY9Ps7E4q+gc4r5bKDWyT/w7UTWkfcghKLTgwK7GvyMYal8C/FNgBoEYvXD?= =?utf-8?q?cb8jgTK7EFrXrlV/rfHCjWYzQmmGEjV7+DhbKvk7LgQWMxjsJJJeMKuIPhXNxAes1?= =?utf-8?q?8fMDrfL4g+S6zlgr2glYBwi5P7jPHBxf4IiGX4nK6aHIqJdNLg83Anq1Yw0yB6qdY?= =?utf-8?q?SU2AkOEDVhAEvA/OjVo5Tps6135nHU/7mScabi+7Gy2z3lP0q+mabiJ+bhWiNU6ez?= =?utf-8?q?65wy+gSteivIETUQ1cy3y1f5Fx5SsgcqGntTk2Ji1BqwtiBmjklIrNaZGNKTauk4D?= =?utf-8?q?gI2aYKVI7TyPKsPuOeKkeJcq05HlFn2x1NcMMOFI9nOgbEgUdrzxR+0MFcb4LU9fU?= =?utf-8?q?bgt2A+r0cL8TjARw/dUGNBQybJAE4h24JG4keJmupu4Y+kPuzv3fQtXi56aAM9/n/?= =?utf-8?q?gCsFSvoH2VMc3bwdw9hIDCjG9fsRQa2gYFeGuhOoa/TtDEsuYAxDV0DMEee+++s1w?= =?utf-8?q?wyIQmlzyQL8VGt/8nDNdAod2XyjqzcWaknv2oTfF7vGjLBczIkyDGu4MrhJlvBAb+?= =?utf-8?q?F7Dl/fd4rVLy11gJ8HP3F0/Iysgwzsxynodxch4BHnp2tuXARPSUrESmNHn/toy+v?= =?utf-8?q?+jMWCHoLZJGDRJEVYCcPSydK+ftAiqotZvoA4ThtvpDCZORZLY/LuiPUhCvMz31tJ?= =?utf-8?q?Qvz/rSrr7bqgnE+sr4tBzTTz14lLkJwKFAUEFxYk3JH6PiPJv/fVjPPCqjgZjYhhO?= =?utf-8?q?iM5XUwl+LxcwzQIa8cjUAq9i2j+WP1RMsefRmRHpK9YBklTRK5F+88QIZqy4q8bw+?= =?utf-8?q?n10piBQTbczq8IUVlkTFNuaAshhoO1M0jbYTMoVAlddNMaVoF7LDRRe8eznONErQ8?= =?utf-8?q?eV52PsglAXL+Qg+JMfv+DzYwHCFdOw+CjA5qre4CK6IfRhT5wgUd5JdQ84i8HLmvd?= =?utf-8?q?XqtzanlbqTqup6YpD6NtXPjrZYBagNZAkok2TboZLUS0aKBxzFlK0YCwE7wKCQYwV?= =?utf-8?q?7xBW+NKlGMOfveCV1i39AxePpymRMQ2PpJYFYQXRSXe+2ruytiMX8V86lyJliorso?= =?utf-8?q?JKlg0NUkn0V2nCgfXnldYfV3bIb4+JBqhPMLe5gGmExpKFu4fVQ4FTzPTJMEiu8Kx?= =?utf-8?q?/slTsFcOl2mGO5vMt4mS3RjChFJ5t/wqds4jQjJjLxcorCi4NbI3a4SabKR5YXFjl?= =?utf-8?q?pn494d81VY7iOYwbzOBdXl146xt4zI9zEzRXrtK024HF+MsJpaZMWd0NwBoXlRvG1?= =?utf-8?q?qsCUa+0/wAMkmEsMr/25nfZOFYmHqDSoA1EFrATzXGEofABloNcZ9Bp4kuBEYCrpO?= =?utf-8?q?vDH/vzegSsGxUsTtXC5L6MQwKhoTyCPV4dAY3F+C/NV8PydlDuoHEuc=3D?= Content-ID: MIME-Version: 1.0 X-OriginatorOrg: eviden.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: AM8PR07MB7602.eurprd07.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: f11a3497-5307-4362-440e-08dc80a389a2 X-MS-Exchange-CrossTenant-originalarrivaltime: 30 May 2024 12:25:05.5130 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 7d1c7785-2d8a-437d-b842-1ed5d8fbe00a X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: qONImZXfcqXBG1QfKsI0wRX5jAdTdqoBArvgPYW6Kwv7ylL1O9rUQMbb3q9HByMwmjZVtWUOGHujUSh3mq9IYzIK3rlTDFL8XB6G2JVwTRH/AHMwyE0to5CFE3xVZxy+ X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR07MB8069 Received-SPF: pass client-ip=80.78.11.84; envelope-from=clement.mathieu--drif@eviden.com; helo=smarthost3.eviden.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Implement the iommu_pri_request_page IOMMU operation and the behavior when receiving a page group response descriptor Signed-off-by: Clément Mathieu--Drif --- hw/i386/intel_iommu.c | 235 +++++++++++++++++++++++++++++++++ hw/i386/intel_iommu_internal.h | 2 + 2 files changed, 237 insertions(+) diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 899655928d..dcc92aae58 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -51,6 +51,8 @@ ((ce)->val[1] & VTD_SM_CONTEXT_ENTRY_RID2PASID_MASK) #define VTD_CE_GET_PASID_DIR_TABLE(ce) \ ((ce)->val[0] & VTD_PASID_DIR_BASE_ADDR_MASK) +#define VTD_CE_GET_PRE(ce) \ + ((ce)->val[0] & VTD_SM_CONTEXT_ENTRY_PRE) /* pe operations */ #define VTD_PE_GET_TYPE(pe) ((pe)->val[0] & VTD_SM_PASID_ENTRY_PGTT) @@ -1922,6 +1924,7 @@ static const bool vtd_qualified_faults[] = { [VTD_FR_PASID_ENTRY_P] = true, [VTD_FR_PASID_TABLE_ENTRY_INV] = true, [VTD_FR_SM_INTERRUPT_ADDR] = true, + [VTD_FR_SM_PRE_ABS] = true, [VTD_FR_FS_NON_CANONICAL] = true, [VTD_FR_FS_BIT_UPDATE_FAILED] = true, [VTD_FR_MAX] = false, @@ -4379,6 +4382,45 @@ static bool vtd_process_device_piotlb_desc(IntelIOMMUState *s, return true; } +static bool vtd_process_page_group_response_desc(IntelIOMMUState *s, + VTDInvDesc *inv_desc) +{ + VTDAddressSpace *vtd_dev_as; + + if ((inv_desc->lo & VTD_INV_DESC_PGRESP_RSVD_LO) || + (inv_desc->hi & VTD_INV_DESC_PGRESP_RSVD_HI)) { + error_report_once("%s: invalid page group response desc: hi=%"PRIx64 + ", lo=%"PRIx64" (reserved nonzero)", __func__, + inv_desc->hi, inv_desc->lo); + return false; + } + + bool pasid_present = VTD_INV_DESC_PGRESP_PP(inv_desc->lo); + uint8_t response_code = VTD_INV_DESC_PGRESP_RC(inv_desc->lo); + uint16_t rid = VTD_INV_DESC_PGRESP_RID(inv_desc->lo); + uint32_t pasid = VTD_INV_DESC_PGRESP_PASID(inv_desc->lo); + uint16_t prgi = VTD_INV_DESC_PGRESP_PRGI(inv_desc->hi); + + if (!pasid_present) { + error_report_once("Page group response without PASID is" + "not supported yet"); + return false; + } + + vtd_dev_as = vtd_get_as_by_sid_and_pasid(s, rid, pasid); + if (!vtd_dev_as) { + return true; + } + + IOMMUPRIResponse response = { + .prgi = prgi, + .response_code = response_code + }; + memory_region_notify_pri_iommu(&vtd_dev_as->iommu, &response); + + return true; +} + static bool vtd_process_device_iotlb_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc) { @@ -4486,6 +4528,13 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s) } break; + case VTD_INV_DESC_PGRESP: + trace_vtd_inv_desc("page group response", inv_desc.hi, inv_desc.lo); + if (!vtd_process_page_group_response_desc(s, &inv_desc)) { + return false; + } + break; + default: error_report_once("%s: invalid inv desc: hi=%"PRIx64", lo=%"PRIx64 " (unknown type)", __func__, inv_desc.hi, @@ -6138,6 +6187,191 @@ static uint64_t vtd_get_min_page_size(IOMMUMemoryRegion *iommu) return VTD_PAGE_SIZE; } +/* 11.4.11.3 : The number of entries in the page request queue is 2^(PQS + 7) */ +static inline uint64_t vtd_prq_size(IntelIOMMUState *s) +{ + return 1ULL << ((vtd_get_quad(s, DMAR_PQA_REG) & VTD_PQA_SIZE) + 7); +} + +/** + * Return true if the bit is accessible and correctly set, false otherwise + */ +static bool vtd_check_pre_bit(VTDAddressSpace *vtd_as, hwaddr addr, + uint16_t sid, bool is_write) +{ + int ret; + IntelIOMMUState *s = vtd_as->iommu_state; + uint8_t bus_n = pci_bus_num(vtd_as->bus); + VTDContextEntry ce; + bool is_fpd_set = false; + + ret = vtd_dev_to_context_entry(s, bus_n, vtd_as->devfn, &ce); + + if (ret) { + goto error_report; + } + + if (!VTD_CE_GET_PRE(&ce)) { + ret = -VTD_FR_SM_PRE_ABS; + goto error_get_fpd_and_report; + } + + return true; + +error_get_fpd_and_report: + /* Try to get fpd (may not work but we are already on an error path) */ + is_fpd_set = ce.lo & VTD_CONTEXT_ENTRY_FPD; + vtd_ce_get_pasid_fpd(s, &ce, &is_fpd_set, vtd_as->pasid); +error_report: + vtd_report_fault(s, -ret, is_fpd_set, sid, addr, is_write, + vtd_as->pasid != PCI_NO_PASID, vtd_as->pasid); + return false; +} + +/* Logic described in section 7.5 */ +static void vtd_generate_page_request_event(IntelIOMMUState *s, + uint32_t old_pr_status) +{ + uint32_t current_pectl = vtd_get_long(s, DMAR_PECTL_REG); + /* + * Hardware evaluates PPR and PRO fields in the Page Request Status Register + * and if any of them is set, Page Request Event is not generated + */ + if (old_pr_status & (VTD_PR_STATUS_PRO | VTD_PR_STATUS_PPR)) { + return; + } + + vtd_set_clear_mask_long(s, DMAR_PECTL_REG, 0, VTD_PR_PECTL_IP); + if (!(current_pectl & VTD_PR_PECTL_IM)) { + vtd_set_clear_mask_long(s, DMAR_PECTL_REG, VTD_PR_PECTL_IP, 0); + vtd_generate_interrupt(s, DMAR_PEADDR_REG, DMAR_PEDATA_REG); + } +} + +/* When calling this function, we known that we are in scalable mode */ +static int vtd_pri_perform_implicit_invalidation(VTDAddressSpace *vtd_as, + hwaddr addr) +{ + IntelIOMMUState *s = vtd_as->iommu_state; + VTDContextEntry ce; + VTDPASIDEntry pe; + uint16_t pgtt; + uint16_t domain_id; + int ret = vtd_dev_to_context_entry(s, pci_bus_num(vtd_as->bus), + vtd_as->devfn, &ce); + if (ret) { + return -EINVAL; + } + ret = vtd_ce_get_rid2pasid_entry(s, &ce, &pe, vtd_as->pasid); + if (ret) { + return -EINVAL; + } + pgtt = VTD_PE_GET_TYPE(&pe); + domain_id = VTD_SM_PASID_ENTRY_DID(pe.val[1]); + ret = 0; + switch (pgtt) { + case VTD_SM_PASID_ENTRY_FLT: + vtd_piotlb_page_invalidate(s, domain_id, vtd_as->pasid, addr, 0, false); + break; + /* Room for other pgtt values */ + default: + error_report_once("Translation type not supported yet : %d", pgtt); + ret = -EINVAL; + break; + } + + return ret; +} + +/* Page Request Descriptor : 7.4.1.1 */ +static int vtd_iommu_pri_request_page(IOMMUMemoryRegion *iommu, hwaddr addr, + bool lpig, uint16_t prgi, bool is_read, + bool is_write, bool exec_req, + bool priv_req) +{ + VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu); + IntelIOMMUState *s = vtd_as->iommu_state; + uint64_t queue_addr_reg = vtd_get_quad(s, DMAR_PQA_REG); + uint64_t queue_tail_offset_reg = vtd_get_quad(s, DMAR_PQT_REG); + uint64_t new_queue_tail_offset = ( + (queue_tail_offset_reg + VTD_PQA_ENTRY_SIZE) % + (vtd_prq_size(s) * VTD_PQA_ENTRY_SIZE)); + uint64_t queue_head_offset_reg = vtd_get_quad(s, DMAR_PQH_REG); + hwaddr queue_tail = (queue_addr_reg & VTD_PQA_ADDR) + queue_tail_offset_reg; + uint32_t old_pr_status = vtd_get_long(s, DMAR_PRS_REG); + uint16_t sid = PCI_BUILD_BDF(pci_bus_num(vtd_as->bus), vtd_as->devfn); + VTDPRDesc desc; + + if (!(s->ecap & VTD_ECAP_PRS)) { + return -EPERM; + } + + /* + * No need to check if scalable mode is enabled as we already known that + * VTD_ECAP_PRS is set (see vtd_decide_config) + */ + + /* We do not support PRI without PASID */ + if (vtd_as->pasid == PCI_NO_PASID) { + return -EPERM; + } + if (exec_req && !is_read) { + return -EINVAL; + } + + /* Check PRE bit in the scalable mode context entry */ + if (!vtd_check_pre_bit(vtd_as, addr, sid, is_write)) { + return -EPERM; + } + + if (old_pr_status & VTD_PR_STATUS_PRO) { + /* + * No action is taken by hardware to report a fault + * or generate an event + */ + return -ENOSPC; + } + + /* Check for overflow */ + if (new_queue_tail_offset == queue_head_offset_reg) { + vtd_set_clear_mask_long(s, DMAR_PRS_REG, 0, VTD_PR_STATUS_PRO); + vtd_generate_page_request_event(s, old_pr_status); + return -ENOSPC; + } + + if (vtd_pri_perform_implicit_invalidation(vtd_as, addr)) { + return -EINVAL; + } + + desc.lo = VTD_PRD_TYPE | VTD_PRD_PP(true) | VTD_PRD_RID(sid) | + VTD_PRD_PASID(vtd_as->pasid) | VTD_PRD_PMR(priv_req); + desc.hi = VTD_PRD_RDR(is_read) | VTD_PRD_WRR(is_write) | + VTD_PRD_LPIG(lpig) | VTD_PRD_PRGI(prgi) | VTD_PRD_ADDR(addr); + + desc.lo = cpu_to_le64(desc.lo); + desc.hi = cpu_to_le64(desc.hi); + if (dma_memory_write(&address_space_memory, queue_tail, &desc, sizeof(desc), + MEMTXATTRS_UNSPECIFIED)) { + error_report_once("IO error, the PQ tail cannot be updated"); + return -EIO; + } + + /* increment the tail register and set the pending request bit */ + vtd_set_quad(s, DMAR_PQT_REG, new_queue_tail_offset); + /* + * read status again so that the kernel does not miss a request. + * in some cases, we can trigger an unecessary interrupt but this strategy + * drastically improves performance as we don't need to take a lock. + */ + old_pr_status = vtd_get_long(s, DMAR_PRS_REG); + if (!(old_pr_status & VTD_PR_STATUS_PPR)) { + vtd_set_clear_mask_long(s, DMAR_PRS_REG, 0, VTD_PR_STATUS_PPR); + vtd_generate_page_request_event(s, old_pr_status); + } + + return 0; +} + static PCIIOMMUOps vtd_iommu_ops = { .get_address_space = vtd_host_dma_iommu, .get_address_space_pasid = vtd_host_dma_iommu_pasid, @@ -6346,6 +6580,7 @@ static void vtd_iommu_memory_region_class_init(ObjectClass *klass, imrc->replay = vtd_iommu_replay; imrc->iommu_ats_request_translation = vtd_iommu_ats_request_translation; imrc->get_min_page_size = vtd_get_min_page_size; + imrc->iommu_pri_request_page = vtd_iommu_pri_request_page; } static const TypeInfo vtd_iommu_memory_region_info = { diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h index 9e01251335..b2314c6a95 100644 --- a/hw/i386/intel_iommu_internal.h +++ b/hw/i386/intel_iommu_internal.h @@ -319,6 +319,8 @@ typedef enum VTDFaultReason { * request while disabled */ VTD_FR_IR_SID_ERR = 0x26, /* Invalid Source-ID */ + VTD_FR_SM_PRE_ABS = 0x47, /* SCT.8 : PRE bit in a present SM CE is 0 */ + VTD_FR_RTADDR_INV_TTM = 0x31, /* Invalid TTM in RTADDR */ /* PASID directory entry access failure */ VTD_FR_PASID_DIR_ACCESS_ERR = 0x50,