From nobody Sun Apr 12 13:54:29 2026 Delivered-To: importer2@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@eviden.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer2=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=eviden.com); dmarc=pass(p=reject dis=none) header.from=eviden.com ARC-Seal: i=2; a=rsa-sha256; t=1714663829; cv=pass; d=zohomail.com; s=zohoarc; b=ljZR19Fp5fy2YGPBKI7PlY/6B9TUornbp82BiJjCPYy7PBKj4MFmCcObdNwXUvFTmliaWY4vYnXxoN7d/vk5/YP2DK7dDtCtrARIErKVoeVlWRVno+AgL9ockozosJlwpDtdFD5/Ntbh4TBOL6HE5/AOtzNZq4GCC3pWzw6lkIU= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1714663829; h=Content-ID:Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=UM2oKYwJZ/PFCyVhG3rBpAgMLxmzRSRdT/0ePXifSdo=; b=JQnlXsg3pzYu3tyVADi+rM72WlyNONa7I74QDCRooOWjP2SMySj6Oh1BEBn1289XzcMvCJlFsKKv+Aa6UXEDxdUdxgeIB02ueDpqa2XkBRJL7uQ5vKFBNemqOjAw8niE8zO/V+Eg5f5aaJV17KsD41mQ8z8c2OI2hsNQ4GvBq9Y= ARC-Authentication-Results: i=2; mx.zohomail.com; dkim=pass header.i=@eviden.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer2=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=eviden.com); dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 171466382933329.316363851704864; Thu, 2 May 2024 08:30:29 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1s2YNk-0003vs-6a; Thu, 02 May 2024 11:30:00 -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 1s2YNb-0003pf-S1 for qemu-devel@nongnu.org; Thu, 02 May 2024 11:29:51 -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 1s2YNJ-0005zE-IP for qemu-devel@nongnu.org; Thu, 02 May 2024 11:29:51 -0400 Received: from mail-am6eur05lp2105.outbound.protection.outlook.com (HELO EUR05-AM6-obe.outbound.protection.outlook.com) ([104.47.18.105]) by smarthost3.eviden.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 May 2024 17:29:23 +0200 Received: from AM8PR07MB7602.eurprd07.prod.outlook.com (2603:10a6:20b:24b::7) by AS8PR07MB7768.eurprd07.prod.outlook.com (2603:10a6:20b:351::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7544.29; Thu, 2 May 2024 15:29:21 +0000 Received: from AM8PR07MB7602.eurprd07.prod.outlook.com ([fe80::fbd7:ca71:b636:6f9d]) by AM8PR07MB7602.eurprd07.prod.outlook.com ([fe80::fbd7:ca71:b636:6f9d%4]) with mapi id 15.20.7519.035; Thu, 2 May 2024 15:29:21 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=eviden.com; i=@eviden.com; q=dns/txt; s=mail; t=1714663773; x=1746199773; h=from:to:cc:subject:date:message-id:references: in-reply-to:content-id:content-transfer-encoding: mime-version; bh=UM2oKYwJZ/PFCyVhG3rBpAgMLxmzRSRdT/0ePXifSdo=; b=RUSDFaGlBNv0InvFShfQBQa6Ag24FC1M1xDx8acoO3O5qa63bIgbCeZ/ g/WmS7h+dHQ1dBhfeQgZNhoZnU+XbPbKvP5PVamfSAXV1IVYT6d2DWJQE rw9ajC6yrT2gkf8Bz6a+Yk79p5qQQFIga2H1th/saqgBQlNP8OCQJJeBt dsCksPfbPaaCII2zA+H827aDdYsNQffpTK2GQ43u03edh1JNQdSz6WzvM 4THOm7iWicjqchVqHbMCfaPnWTY8WDVsPOfdpnKhpX+wDaDXadFQguvWj kaSp1B6sTJ1/4WfgnsTpm12jPbiNkyVJQRT+SOFQRhAYq7kAXf/prCPki A==; X-IronPort-AV: E=Sophos;i="6.07,247,1708383600"; d="scan'208";a="11730624" X-MGA-submission: =?us-ascii?q?MDGBOW60AbjKHZcGtBbmMTOWRYeEI/3NL1PpJ3?= =?us-ascii?q?4PK7CB9abmHUXHRdu935Byd/hdcDWzNaZr1O11USRCEhLEG7Lbzv4727?= =?us-ascii?q?h8y46dQC4QqWSZKB/nveJy4Wi8/ck+spUEcOAS3X7rpP68LpzNyXmcmp?= =?us-ascii?q?hltNm2ZFTI8PdLafUha3mrQQ=3D=3D?= ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=NLp1qHviByVLChC0B6PFHPdtJ47W7EtQbndNJ0qHHyVzmRZNNaXCEuGfwODcmFviplgis6uVOIJ7/CF5EefXLqT6pZrsTbbK+bbKh+Xdc8D/SmdLX6TdnjfRP0oZ6SAMwDmUTOxGN0tZOA76WpeJJMMSmKZ954+vJ+oCg6OvN++daRRtO10Alsuw2IHEHtzjJAl501JUWJwgfFpSs1qpNFBdHiNARAwBC0pFCiXaKBC76VOEikU/WIH53A8+6tWZfkad8QwdjCIV2v2eBUOAaO9r6vq+VrdH8tS0vIw+J5py/HneKn1yr+RyxJe5lHq721RG+fUhlmLtfAYDzWObQw== 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=UM2oKYwJZ/PFCyVhG3rBpAgMLxmzRSRdT/0ePXifSdo=; b=J3Gugyghl/1lQRj7vSI6G1YAKbfgbvEzm8F6pzUeEveZbW1r0beLq/DcXq0YsZKCPhXTIsQcMnohtZz8Vqjw1+rKDtw9P/tDrIZRalbFQCglSx+NXDJF8JSFdu+3l6k7TwV6Q+9Oj+FxRYMu3MoS5IVMHtHzOXd5xu+xTr4pggwli7B+yWS3avnmxfPGpba8G/mSyQnSpa6t8ZjTlhUirRUC6yZp5R9guSbt2sE1szjIMYDpwR8F3L0YqouJRNm+VBIbRZxb5tQWkEMwQvM4vjQolXSG6b5+UvMq0F49LdjRnndjy2X4YuvEkXkX3v/LC9D3u13lazCUSW30MiAyVg== 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 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 ats_vtd v1 20/24] atc: generic ATC that can be used by PCIe devices that support SVM Thread-Topic: [PATCH ats_vtd v1 20/24] atc: generic ATC that can be used by PCIe devices that support SVM Thread-Index: AQHanKWByKvYDmYBd02klTL221t3Bg== Date: Thu, 2 May 2024 15:29:21 +0000 Message-ID: <20240502152810.187492-21-clement.mathieu--drif@eviden.com> References: <20240502152810.187492-1-clement.mathieu--drif@eviden.com> In-Reply-To: <20240502152810.187492-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_|AS8PR07MB7768:EE_ x-ms-office365-filtering-correlation-id: ec7ed4a8-e661-4cd5-b22e-08dc6abca3cf x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; ARA:13230031|1800799015|366007|376005|38070700009; x-microsoft-antispam-message-info: =?utf-8?B?c0w3Rm1TZk9OUS9NV2UweWNHVzAxTmZTNXF0ZUhvTUNoeWYvT01zWC91cklO?= =?utf-8?B?TU54ZXowRi82NGxNOTNVUlNLZWZqS2dZTXpwVXV5Z1A4S09LMy9IUUxRRnp6?= =?utf-8?B?TkpjZm0xcHpvVVR2RFNwclJrSjY3anFHdW15K0tadlMwVFhsZm81bHNuNVZr?= =?utf-8?B?UFBJeUVHaitGN0dHSXNqUFZqa2JOSjdrSWlrN1hzaTJ1RjdKVTBpMHk1MUlz?= =?utf-8?B?UWJOY05aamx0QURKTFdUK1o1NjZ3RDlMZFJyczhBVzZaMkVWRGQyeHJ0b0l2?= =?utf-8?B?VDQ1YVVRSDBPeitlNVlFV3pybDZOeU0zU2hRc0NoNzJPU0llQzU2aXdFZEJO?= =?utf-8?B?dnlJMWxTVWtXYTBURGowSDFwY0dYNTcyTlFaOGtmY2l0NW1xbjBMOFFiWm1y?= =?utf-8?B?RWlSTUY3dW14cXEzQzRMWlBTWWdDdW96bnNQdmFJNytxR3k1TDZnMFR0VDVx?= =?utf-8?B?Vml6dUgxRjc0elpnL2hNVTZHSGEzWWx0QW5yNzJTWjFaMkdTd213WHBCSHk3?= =?utf-8?B?WFhpZGJ5Tjd4clNWck1mclZYZ296RWRTWWtQS0VwZXN3ZEJtbEpMQXBmaHFa?= =?utf-8?B?d0UybDNEdGhvWUErdlliSTlJWXQxc0QwTTc5YUpZVnZadkdSWk9lZ2FhZUJE?= =?utf-8?B?dHVWbjVoSzVTdVBwQmhUcGFQWVVqbUpaS2FCY25CMlFFSFRZdEZwL0hJcnRP?= =?utf-8?B?dEdBTlpGR3pSOXRNdHcyTUpmbVVzR3REdDdoUEhQVUp2Mk4xcGdTV1NpUXg1?= =?utf-8?B?bzZST1NCTkJ1eDZJMDhJQnpoSUhIRStQMVFocmdyMEVjamFiYndiS3BqV1hT?= =?utf-8?B?bDFNZXJTR0txOUN3ME8rR1JjZ08vVlBZQ1VmUm9LR0ZIWmVlUGk2VHlpcDFW?= =?utf-8?B?Mkx5NmlDK2RRYzNqbjd6UjJYYnpsajRXQUFENXV6Nkg5bU5wQTJBZ2tWVHBq?= =?utf-8?B?M0NnRXVsejlMd2R6cjB6d1FKKzJRTFZwd3pwREtWQzY3enVoK3VGb3lYU1d0?= =?utf-8?B?UjFEeXF0MW43WloxODI2QlJKcFJVd1BDTDhjUHVRZXNDZUlldElOS2lEQXNL?= =?utf-8?B?cHZnQVgyblJMaGdWOWJqRm9WNEZWcU0wZlhsV1NOaXk5OExwTnJCYWpyeGZX?= =?utf-8?B?MlN1SmVYNi9RQXNTaUVGT3hjY09jOUtaL0dGaTl1cXd3bGdVUkt0N1JKS09Q?= =?utf-8?B?SnVkYnJxdmR0UThIenVrUTd1ZWJyMjAzM1E2S1d0aUF2MDdVWWxJdS9TcGJF?= =?utf-8?B?V1RBSXlWQXpob3ZOeVV2QWFvdDUycXg5YmNHVXUzQlZ5ZS9xWWN4emlIOVM3?= =?utf-8?B?Zk9nSDhYYnFwVUR1a2lXd2EwcFpoT0d6TXJLaXFVSWlWdWFhT1VCSEZEZDJ2?= =?utf-8?B?WjNKUFFLUGVXWDYvM1kzckNiaU5uL3JadWdONlIzRzY0RnJLbzVWK1BQT1E0?= =?utf-8?B?c3dsRitjQ3Ruc3VMNTlIaXJEa1VoTERMenNIanRsK0hPbjE5L21zUVV3MXkz?= =?utf-8?B?cWdBNmx1amJJRVIyalVRWC9jczErOU5aU3F6ZzZTN3Z3TkQ0RmRmaDlVNTNH?= =?utf-8?B?OWp6cWlrRFdWYlhlUnUvV0J5Y1prS0swc2RkUmx2ZkMrR2J2TFRZYW9GYmZ0?= =?utf-8?B?bjdERllVSXJnZW43Vm9IRER0MHhuQ09RUURlamtDSnA4UnBSSVQrZkV0bXBI?= =?utf-8?B?bG96UUpEQzFwQ2ZWU3pKWU1TQThoVmRVVWluTXNHNUJnWWp4aFE2c2tRPT0=?= 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)(1800799015)(366007)(376005)(38070700009); DIR:OUT; SFP:1101; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?utf-8?B?a0Q2dzJ2S3M4Z3puVkVKUlorRUpMTGlEVXQ5TEJxWGIrNlM2UlczM3VhelNx?= =?utf-8?B?aldnVzBKSm94dTVIejJMN1dmYzdtd2svMG91dUlIVGJlZUd3V1VYUGJyMG5i?= =?utf-8?B?S2ZMRWd5eFl2WUU3Z0pCZ1duWUZJc3VBWG0zZ2NVM0lMYzRmenkzV09Jb3dy?= =?utf-8?B?T1E1d2hDMHVHVkZFczQ3bVdjc3dNNnpZWEFmSzN6ZXJjUmlQVmlmMkthSEw0?= =?utf-8?B?bEJaUGVxcFRyMFIvUWlRVTJxN3dtN2JCb0NnbmFaamJ2ajVGbU91K3lRcUlV?= =?utf-8?B?aFNRYm1aRmhlLzFDN2UyVFJ3Sng3NWk3dUFxZUgwMkd1blkwT3loRE11eUZs?= =?utf-8?B?MzlCdWhWMkdLVnR1ZzM5S0hhMmllRmJZUHB1Z3h4ejQ2bEpXazM3RVJLSnV5?= =?utf-8?B?dCsveTNTR2ZCajJoYmtxOWdBSXR4SFRaMEVTQmpBTWRQbzZqblVsM2svQzNq?= =?utf-8?B?dE9lRmtXd3F6dUd0WThld0JJUG8yS2NQd3pFU2hsNGNHRG1kYXBMcTJXZ1Np?= =?utf-8?B?VUtIcFJETHI2aGl6dEtxKzFBSEt0L2QvSXRUbGkvdGpqSm5jS3V3bC8rUklI?= =?utf-8?B?T2xydVVDeHozajFCVHZ2OUZJSCsxUnJTSmt6ZmlLMVgwRUNLckdlK2JybEVJ?= =?utf-8?B?RFZNM1N5ejM4djYvdmhiSWRlRTd4dHJzeHF3RUxRNzhPVmo1Tnh3NC9jaHNJ?= =?utf-8?B?ZkFCcGxHMmxTc1lYNEVkWlBPWFV6ck9rUW5scnh4MFh1VnVJZVBhNUY1Zjlo?= =?utf-8?B?dEUwaEZldDBWVFdadXNKOVJaVFJhUnAzWURmcWUrT3h3Y2ZrbXJaKzlDajQr?= =?utf-8?B?Y21LZ3pjenArcXZpRG9QZnBCVVNNanM5aWpDWGE2dkpCVGFYQmdXNlFkZFFm?= =?utf-8?B?RU0zMzJnd1dPaTc1NDgrYnE3RjJ4RTJ6cVNFYUhXT1M0TWtxcVRTTnBXWTRF?= =?utf-8?B?Ry8rTHNnY2p2OUs3L0I0TGJHL1dDTzJWMGsrcVc0RndRbENzVzg0SmppaDRY?= =?utf-8?B?QXp0NHJmS2Z1TkdOTW4rS0FCWWJEZktXTHFGNUxaejgvVlkySU4yWFk4dVAx?= =?utf-8?B?bVNCbFREbGsvVVVldGdMalY1dkQ4enpoM3FUeDlkL24rbU5YSUplZnJUNDRR?= =?utf-8?B?MUY1OWRVZk9pc1NqUUp3SThRd3dSY2owKzFuWm9sUnFEcDUyMHZ6UTdUTDgr?= =?utf-8?B?eFlVd21jSWNBRzVCeHcwZmkyTU1DK2ExTXh3YlRsR0xPMmx3TG01Y0w1TWE0?= =?utf-8?B?K3B2SEUyc3FmOXl3MUtzTU1mdkN0ZVpJajFsaWhiVS9hdFFic0JxcC9oNERY?= =?utf-8?B?MHh4dnFOdUVZVitVaFhzS2Zza3g4MVR2YUlmL1A3SnFVQ010UWtLeUcva1kr?= =?utf-8?B?d1JiaTQxSEp2aW1STDRid1lDK0lNNlJNeDZlYy9TNWI4SDAra3Ywd3VKL3kx?= =?utf-8?B?T3d4Yk56bVduelU2VW5mWDhEVUVuY205VnVlZE1vV3RUSkxSUitoUkNiSXdE?= =?utf-8?B?SmtpeUk2SGJnK2Z3UlhFbXVFdXVvR003Zk50TnNqQTR6Qzk5dCtOUm1haG1q?= =?utf-8?B?YU1VTU9sZDNjY3VaN29SSDg4LysvK2J1MUNTdXJ2Y2tZYWJSMWllYjFGdzZy?= =?utf-8?B?M1c0UkcveWdwczNUMTB0RU1tcXhwd2dSL0wvZTVGUTBjeHJZZk5JWVV2ZTVr?= =?utf-8?B?U01EeEJicm9ZYkZGUVB5cEcydlN1Q2NDMXl6QjFNcC9kejZLcU9jTGFic2px?= =?utf-8?B?SjlkeFFZVGJvNk1yTTFGY3FCbG1MQ1BSemVVbW5HZExUd25BcVFjeitaVU9D?= =?utf-8?B?cUo0c0h2em9VTGxqcG5xdDZqTlFHSmR0R3ptVlNqU3Z1d0FhaFpEZDNJTzBD?= =?utf-8?B?SXdZM2pTemJDWWxMWnB0TkhHaTloU0sxK0VPNWJTd1NyOXlFMk1kMnJJa2Vx?= =?utf-8?B?elptRDJGNUxhQnE1ZDZ4YTc2QU5YU0puU3VYY1RBZGVDUDlRU1V2R0N1UEpV?= =?utf-8?B?Y2N3bjk5YWNwNGZZNFRCcVpSbGVHYUJLbWVHckl0NStlVVA2bjd0WUlld1Nl?= =?utf-8?B?RjA0SjU1WGlxeGxZMzZBRkI1Y2libzM5Y3BuTmZxaUNsRnhUV2s0TnFNTmQ1?= =?utf-8?B?YlBIdnN5VURvRDBTZ3RNclgwbkdaTUhTZ3V3ME8yMjJvTmV0WStldVlIeHp0?= =?utf-8?Q?I1YxjDwvop9csmCNQsRUBoM=3D?= Content-Type: text/plain; charset="utf-8" Content-ID: Content-Transfer-Encoding: quoted-printable 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: ec7ed4a8-e661-4cd5-b22e-08dc6abca3cf X-MS-Exchange-CrossTenant-originalarrivaltime: 02 May 2024 15:29:21.3993 (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: ySGOcTrVyw7Zv02b7SYp00JHLrdKU707IdGw6y8ADa+S0lggbdVEMt58G4XM9K8K57XVlxrEVZYk9EsYM871xEiG5qCqdPkkWvjuxQtlUFI1hkBfCpSIC8ri1gsXFKgW X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR07MB7768 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer2=patchew.org@nongnu.org; helo=lists.gnu.org; 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 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+importer2=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer2=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @eviden.com) X-ZM-MESSAGEID: 1714663830641100003 As the SVM-capable devices will need to cache translations, we provide an first implementation. This cache uses a two-level design based on hash tables. The first level is indexed by a PASID and the second by a virtual addresse. Signed-off-by: Cl=C3=A9ment Mathieu--Drif --- tests/unit/meson.build | 1 + tests/unit/test-atc.c | 502 +++++++++++++++++++++++++++++++++++++++++ util/atc.c | 211 +++++++++++++++++ util/atc.h | 117 ++++++++++ util/meson.build | 1 + 5 files changed, 832 insertions(+) create mode 100644 tests/unit/test-atc.c create mode 100644 util/atc.c create mode 100644 util/atc.h diff --git a/tests/unit/meson.build b/tests/unit/meson.build index 228a21d03c..5c9a6fe9f4 100644 --- a/tests/unit/meson.build +++ b/tests/unit/meson.build @@ -52,6 +52,7 @@ tests =3D { 'test-interval-tree': [], 'test-xs-node': [qom], 'test-virtio-dmabuf': [meson.project_source_root() / 'hw/display/virtio-= dmabuf.c'], + 'test-atc': [] } =20 if have_system or have_tools diff --git a/tests/unit/test-atc.c b/tests/unit/test-atc.c new file mode 100644 index 0000000000..60fa60924a --- /dev/null +++ b/tests/unit/test-atc.c @@ -0,0 +1,502 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#include "util/atc.h" + +static inline bool tlb_entry_equal(IOMMUTLBEntry *e1, IOMMUTLBEntry *e2) +{ + if (!e1 || !e2) { + return !e1 && !e2; + } + return e1->iova =3D=3D e2->iova && + e1->addr_mask =3D=3D e2->addr_mask && + e1->pasid =3D=3D e2->pasid && + e1->perm =3D=3D e2->perm && + e1->target_as =3D=3D e2->target_as && + e1->translated_addr =3D=3D e2->translated_addr; +} + +static void assert_lookup_equals(ATC *atc, IOMMUTLBEntry *target, + uint32_t pasid, hwaddr iova) +{ + IOMMUTLBEntry *result; + result =3D atc_lookup(atc, pasid, iova); + g_assert(tlb_entry_equal(result, target)); +} + +static void check_creation(uint64_t page_size, uint8_t address_width, + uint8_t levels, uint8_t level_offset, + bool should_work) { + ATC *atc =3D atc_new(page_size, address_width); + if (atc) { + if (atc->levels !=3D levels || atc->level_offset !=3D level_offset= ) { + g_assert(false); /* ATC created but invalid configuration : fa= il */ + } + atc_destroy(atc); + g_assert(should_work); + } else { + g_assert(!should_work); + } +} + +static void test_creation_parameters(void) +{ + check_creation(8, 39, 3, 9, false); + check_creation(4095, 39, 3, 9, false); + check_creation(4097, 39, 3, 9, false); + check_creation(8192, 48, 0, 0, false); + + check_creation(4096, 38, 0, 0, false); + check_creation(4096, 39, 3, 9, true); + check_creation(4096, 40, 0, 0, false); + check_creation(4096, 47, 0, 0, false); + check_creation(4096, 48, 4, 9, true); + check_creation(4096, 49, 0, 0, false); + check_creation(4096, 56, 0, 0, false); + check_creation(4096, 57, 5, 9, true); + check_creation(4096, 58, 0, 0, false); + + check_creation(16384, 35, 0, 0, false); + check_creation(16384, 36, 2, 11, true); + check_creation(16384, 37, 0, 0, false); + check_creation(16384, 46, 0, 0, false); + check_creation(16384, 47, 3, 11, true); + check_creation(16384, 48, 0, 0, false); + check_creation(16384, 57, 0, 0, false); + check_creation(16384, 58, 4, 11, true); + check_creation(16384, 59, 0, 0, false); +} + +static void test_single_entry(void) +{ + IOMMUTLBEntry entry =3D { + .iova =3D 0x123456789000ULL, + .addr_mask =3D 0xfffULL, + .pasid =3D 5, + .perm =3D IOMMU_RW, + .translated_addr =3D 0xdeadbeefULL, + }; + + ATC *atc =3D atc_new(4096, 48); + g_assert(atc); + + assert_lookup_equals(atc, NULL, entry.pasid, + entry.iova + (entry.addr_mask / 2)); + + atc_create_address_space_cache(atc, entry.pasid); + g_assert(atc_update(atc, &entry) =3D=3D 0); + + assert_lookup_equals(atc, NULL, entry.pasid + 1, + entry.iova + (entry.addr_mask / 2)); + assert_lookup_equals(atc, &entry, entry.pasid, + entry.iova + (entry.addr_mask / 2)); + + atc_destroy(atc); +} + +static void test_page_boundaries(void) +{ + static const uint32_t pasid =3D 5; + static const hwaddr page_size =3D 4096; + + /* 2 consecutive entries */ + IOMMUTLBEntry e1 =3D { + .iova =3D 0x123456789000ULL, + .addr_mask =3D page_size - 1, + .pasid =3D pasid, + .perm =3D IOMMU_RW, + .translated_addr =3D 0xdeadbeefULL, + }; + IOMMUTLBEntry e2 =3D { + .iova =3D e1.iova + page_size, + .addr_mask =3D page_size - 1, + .pasid =3D pasid, + .perm =3D IOMMU_RW, + .translated_addr =3D 0x900df00dULL, + }; + + ATC *atc =3D atc_new(page_size, 48); + + atc_create_address_space_cache(atc, e1.pasid); + /* creating the address space twice should not be a problem */ + atc_create_address_space_cache(atc, e1.pasid); + + atc_update(atc, &e1); + atc_update(atc, &e2); + + assert_lookup_equals(atc, NULL, e1.pasid, e1.iova - 1); + assert_lookup_equals(atc, &e1, e1.pasid, e1.iova); + assert_lookup_equals(atc, &e1, e1.pasid, e1.iova + e1.addr_mask); + g_assert((e1.iova + e1.addr_mask + 1) =3D=3D e2.iova); + assert_lookup_equals(atc, &e2, e2.pasid, e2.iova); + assert_lookup_equals(atc, &e2, e2.pasid, e2.iova + e2.addr_mask); + assert_lookup_equals(atc, NULL, e2.pasid, e2.iova + e2.addr_mask + 1); + + assert_lookup_equals(atc, NULL, e1.pasid + 10, e1.iova); + assert_lookup_equals(atc, NULL, e2.pasid + 10, e2.iova); + atc_destroy(atc); +} + +static void test_huge_page(void) +{ + static const uint32_t pasid =3D 5; + static const hwaddr page_size =3D 4096; + IOMMUTLBEntry e1 =3D { + .iova =3D 0x123456600000ULL, + .addr_mask =3D 0x1fffffULL, + .pasid =3D pasid, + .perm =3D IOMMU_RW, + .translated_addr =3D 0xdeadbeefULL, + }; + hwaddr addr; + + ATC *atc =3D atc_new(page_size, 48); + + atc_create_address_space_cache(atc, e1.pasid); + atc_update(atc, &e1); + + for (addr =3D e1.iova; addr <=3D e1.iova + e1.addr_mask; addr +=3D pag= e_size) { + assert_lookup_equals(atc, &e1, e1.pasid, addr); + } + /* addr is now out of the huge page */ + assert_lookup_equals(atc, NULL, e1.pasid, addr); + atc_destroy(atc); +} + +static void test_pasid(void) +{ + hwaddr addr =3D 0xaaaaaaaaa000ULL; + IOMMUTLBEntry e1 =3D { + .iova =3D addr, + .addr_mask =3D 0xfffULL, + .pasid =3D 8, + .perm =3D IOMMU_RW, + .translated_addr =3D 0xdeadbeefULL, + }; + IOMMUTLBEntry e2 =3D { + .iova =3D addr, + .addr_mask =3D 0xfffULL, + .pasid =3D 2, + .perm =3D IOMMU_RW, + .translated_addr =3D 0xb001ULL, + }; + uint16_t i; + + ATC *atc =3D atc_new(4096, 48); + + atc_create_address_space_cache(atc, e1.pasid); + atc_create_address_space_cache(atc, e2.pasid); + atc_update(atc, &e1); + atc_update(atc, &e2); + + for (i =3D 0; i <=3D MAX(e1.pasid, e2.pasid) + 1; ++i) { + if (i =3D=3D e1.pasid || i =3D=3D e2.pasid) { + continue; + } + assert_lookup_equals(atc, NULL, i, addr); + } + assert_lookup_equals(atc, &e1, e1.pasid, addr); + assert_lookup_equals(atc, &e1, e1.pasid, addr); + atc_destroy(atc); +} + +static void test_large_address(void) +{ + IOMMUTLBEntry e1 =3D { + .iova =3D 0xaaaaaaaaa000ULL, + .addr_mask =3D 0xfffULL, + .pasid =3D 8, + .perm =3D IOMMU_RW, + .translated_addr =3D 0x5eeeeeedULL, + }; + IOMMUTLBEntry e2 =3D { + .iova =3D 0x1f00baaaaabf000ULL, + .addr_mask =3D 0xfffULL, + .pasid =3D e1.pasid, + .perm =3D IOMMU_RW, + .translated_addr =3D 0xdeadbeefULL, + }; + + ATC *atc =3D atc_new(4096, 57); + + atc_create_address_space_cache(atc, e1.pasid); + atc_update(atc, &e1); + atc_update(atc, &e2); + + assert_lookup_equals(atc, &e1, e1.pasid, e1.iova); + assert_lookup_equals(atc, &e2, e2.pasid, e2.iova); + atc_destroy(atc); +} + +static void test_bigger_page(void) +{ + IOMMUTLBEntry e1 =3D { + .iova =3D 0xaabbccdde000ULL, + .addr_mask =3D 0x1fffULL, + .pasid =3D 1, + .perm =3D IOMMU_RW, + .translated_addr =3D 0x5eeeeeedULL, + }; + hwaddr i; + + ATC *atc =3D atc_new(8192, 43); + + atc_create_address_space_cache(atc, e1.pasid); + atc_update(atc, &e1); + + i =3D e1.iova & (~e1.addr_mask); + assert_lookup_equals(atc, NULL, e1.pasid, i - 1); + while (i <=3D e1.iova + e1.addr_mask) { + assert_lookup_equals(atc, &e1, e1.pasid, i); + ++i; + } + assert_lookup_equals(atc, NULL, e1.pasid, i); + atc_destroy(atc); +} + +static void test_unknown_pasid(void) +{ + IOMMUTLBEntry e1 =3D { + .iova =3D 0xaabbccfff000ULL, + .addr_mask =3D 0xfffULL, + .pasid =3D 1, + .perm =3D IOMMU_RW, + .translated_addr =3D 0x5eeeeeedULL, + }; + + ATC *atc =3D atc_new(4096, 48); + g_assert(atc_update(atc, &e1) !=3D 0); + assert_lookup_equals(atc, NULL, e1.pasid, e1.iova); +} + +static void test_invalidation(void) +{ + static uint64_t page_size =3D 4096; + IOMMUTLBEntry e1 =3D { + .iova =3D 0xaabbccddf000ULL, + .addr_mask =3D 0xfffULL, + .pasid =3D 1, + .perm =3D IOMMU_RW, + .translated_addr =3D 0x5eeeeeedULL, + }; + IOMMUTLBEntry e2 =3D { + .iova =3D 0xffe00000ULL, + .addr_mask =3D 0x1fffffULL, + .pasid =3D 1, + .perm =3D IOMMU_RW, + .translated_addr =3D 0xb000001ULL, + }; + IOMMUTLBEntry e3; + + ATC *atc =3D atc_new(page_size , 48); + atc_create_address_space_cache(atc, e1.pasid); + + atc_update(atc, &e1); + assert_lookup_equals(atc, &e1, e1.pasid, e1.iova); + atc_invalidate(atc, &e1); + assert_lookup_equals(atc, NULL, e1.pasid, e1.iova); + + atc_update(atc, &e1); + atc_update(atc, &e2); + assert_lookup_equals(atc, &e1, e1.pasid, e1.iova); + assert_lookup_equals(atc, &e2, e2.pasid, e2.iova); + atc_invalidate(atc, &e2); + assert_lookup_equals(atc, &e1, e1.pasid, e1.iova); + assert_lookup_equals(atc, NULL, e2.pasid, e2.iova); + + /* invalidate a huge page by invalidating a small region */ + for (hwaddr addr =3D e2.iova; addr <=3D (e2.iova + e2.addr_mask); + addr +=3D page_size) { + atc_update(atc, &e2); + assert_lookup_equals(atc, &e2, e2.pasid, e2.iova); + e3 =3D (IOMMUTLBEntry){ + .iova =3D addr, + .addr_mask =3D page_size - 1, + .pasid =3D e2.pasid, + .perm =3D IOMMU_RW, + .translated_addr =3D 0, + }; + atc_invalidate(atc, &e3); + assert_lookup_equals(atc, NULL, e2.pasid, e2.iova); + } +} + +static void test_delete_address_space_cache(void) +{ + static uint64_t page_size =3D 4096; + IOMMUTLBEntry e1 =3D { + .iova =3D 0xaabbccddf000ULL, + .addr_mask =3D 0xfffULL, + .pasid =3D 1, + .perm =3D IOMMU_RW, + .translated_addr =3D 0x5eeeeeedULL, + }; + IOMMUTLBEntry e2 =3D { + .iova =3D e1.iova, + .addr_mask =3D 0xfffULL, + .pasid =3D 2, + .perm =3D IOMMU_RW, + .translated_addr =3D 0x5eeeeeedULL, + }; + + ATC *atc =3D atc_new(page_size , 48); + atc_create_address_space_cache(atc, e1.pasid); + + atc_update(atc, &e1); + assert_lookup_equals(atc, &e1, e1.pasid, e1.iova); + atc_invalidate(atc, &e2); /* unkown pasid : is a nop*/ + assert_lookup_equals(atc, &e1, e1.pasid, e1.iova); + + atc_create_address_space_cache(atc, e2.pasid); + atc_update(atc, &e2); + assert_lookup_equals(atc, &e1, e1.pasid, e1.iova); + assert_lookup_equals(atc, &e2, e2.pasid, e2.iova); + atc_invalidate(atc, &e1); + /* e1 has been removed but e2 is still there */ + assert_lookup_equals(atc, NULL, e1.pasid, e1.iova); + assert_lookup_equals(atc, &e2, e2.pasid, e2.iova); + + atc_update(atc, &e1); + assert_lookup_equals(atc, &e1, e1.pasid, e1.iova); + assert_lookup_equals(atc, &e2, e2.pasid, e2.iova); + + atc_delete_address_space_cache(atc, e2.pasid); + assert_lookup_equals(atc, &e1, e1.pasid, e1.iova); + assert_lookup_equals(atc, NULL, e2.pasid, e2.iova); +} + +static void test_invalidate_entire_address_space(void) +{ + static uint64_t page_size =3D 4096; + IOMMUTLBEntry e1 =3D { + .iova =3D 0x1000ULL, + .addr_mask =3D 0xfffULL, + .pasid =3D 1, + .perm =3D IOMMU_RW, + .translated_addr =3D 0x5eedULL, + }; + IOMMUTLBEntry e2 =3D { + .iova =3D 0xfffffffff000ULL, + .addr_mask =3D 0xfffULL, + .pasid =3D 1, + .perm =3D IOMMU_RW, + .translated_addr =3D 0xbeefULL, + }; + IOMMUTLBEntry e3 =3D { + .iova =3D 0, + .addr_mask =3D 0xffffffffffffffffULL, + .pasid =3D 1, + .perm =3D IOMMU_RW, + .translated_addr =3D 0, + }; + + ATC *atc =3D atc_new(page_size , 48); + atc_create_address_space_cache(atc, e1.pasid); + + atc_update(atc, &e1); + atc_update(atc, &e2); + assert_lookup_equals(atc, &e1, e1.pasid, e1.iova); + assert_lookup_equals(atc, &e2, e2.pasid, e2.iova); + atc_invalidate(atc, &e3); + /* e1 has been removed but e2 is still there */ + assert_lookup_equals(atc, NULL, e1.pasid, e1.iova); + assert_lookup_equals(atc, NULL, e2.pasid, e2.iova); + + atc_destroy(atc); +} + +static void test_reset(void) +{ + static uint64_t page_size =3D 4096; + IOMMUTLBEntry e1 =3D { + .iova =3D 0x1000ULL, + .addr_mask =3D 0xfffULL, + .pasid =3D 1, + .perm =3D IOMMU_RW, + .translated_addr =3D 0x5eedULL, + }; + IOMMUTLBEntry e2 =3D { + .iova =3D 0xfffffffff000ULL, + .addr_mask =3D 0xfffULL, + .pasid =3D 2, + .perm =3D IOMMU_RW, + .translated_addr =3D 0xbeefULL, + }; + + ATC *atc =3D atc_new(page_size , 48); + atc_create_address_space_cache(atc, e1.pasid); + atc_create_address_space_cache(atc, e2.pasid); + atc_update(atc, &e1); + atc_update(atc, &e2); + + assert_lookup_equals(atc, &e1, e1.pasid, e1.iova); + assert_lookup_equals(atc, &e2, e2.pasid, e2.iova); + + atc_reset(atc); + + assert_lookup_equals(atc, NULL, e1.pasid, e1.iova); + assert_lookup_equals(atc, NULL, e2.pasid, e2.iova); +} + +static void test_get_max_number_of_pages(void) +{ + static uint64_t page_size =3D 4096; + hwaddr base =3D 0xc0fee000; /* aligned */ + ATC *atc =3D atc_new(page_size , 48); + g_assert(atc_get_max_number_of_pages(atc, base, page_size / 2) =3D=3D = 1); + g_assert(atc_get_max_number_of_pages(atc, base, page_size) =3D=3D 1); + g_assert(atc_get_max_number_of_pages(atc, base, page_size + 1) =3D=3D = 2); + + g_assert(atc_get_max_number_of_pages(atc, base + 10, 1) =3D=3D 1); + g_assert(atc_get_max_number_of_pages(atc, base + 10, page_size - 10) = =3D=3D 1); + g_assert(atc_get_max_number_of_pages(atc, base + 10, + page_size - 10 + 1) =3D=3D 2); + g_assert(atc_get_max_number_of_pages(atc, base + 10, + page_size - 10 + 2) =3D=3D 2); + + g_assert(atc_get_max_number_of_pages(atc, base + page_size - 1, 1) =3D= =3D 1); + g_assert(atc_get_max_number_of_pages(atc, base + page_size - 1, 2) =3D= =3D 2); + g_assert(atc_get_max_number_of_pages(atc, base + page_size - 1, 3) =3D= =3D 2); + + g_assert(atc_get_max_number_of_pages(atc, base + 10, page_size * 20) = =3D=3D 21); + g_assert(atc_get_max_number_of_pages(atc, base + 10, + (page_size * 20) + (page_size - 1= 0)) + =3D=3D 21); + g_assert(atc_get_max_number_of_pages(atc, base + 10, + (page_size * 20) + + (page_size - 10 + 1)) =3D=3D 22); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + g_test_add_func("/atc/test_creation_parameters", test_creation_paramet= ers); + g_test_add_func("/atc/test_single_entry", test_single_entry); + g_test_add_func("/atc/test_page_boundaries", test_page_boundaries); + g_test_add_func("/atc/test_huge_page", test_huge_page); + g_test_add_func("/atc/test_pasid", test_pasid); + g_test_add_func("/atc/test_large_address", test_large_address); + g_test_add_func("/atc/test_bigger_page", test_bigger_page); + g_test_add_func("/atc/test_unknown_pasid", test_unknown_pasid); + g_test_add_func("/atc/test_invalidation", test_invalidation); + g_test_add_func("/atc/test_delete_address_space_cache", + test_delete_address_space_cache); + g_test_add_func("/atc/test_invalidate_entire_address_space", + test_invalidate_entire_address_space); + g_test_add_func("/atc/test_reset", test_reset); + g_test_add_func("/atc/test_get_max_number_of_pages", + test_get_max_number_of_pages); + return g_test_run(); +} diff --git a/util/atc.c b/util/atc.c new file mode 100644 index 0000000000..3332d7e2b8 --- /dev/null +++ b/util/atc.c @@ -0,0 +1,211 @@ +/* + * QEMU emulation of an ATC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#include "util/atc.h" + + +#define PAGE_TABLE_ENTRY_SIZE 8 + +/* a pasid is hashed using the identity function */ +static guint atc_pasid_key_hash(gconstpointer v) +{ + return (guint)(uintptr_t)v; /* pasid */ +} + +/* pasid equality */ +static gboolean atc_pasid_key_equal(gconstpointer v1, gconstpointer v2) +{ + return v1 =3D=3D v2; +} + +/* Hash function for IOTLB entries */ +static guint atc_addr_key_hash(gconstpointer v) +{ + hwaddr addr =3D (hwaddr)v; + return (guint)((addr >> 32) ^ (addr & 0xffffffffU)); +} + +/* Equality test for IOTLB entries */ +static gboolean atc_addr_key_equal(gconstpointer v1, gconstpointer v2) +{ + return (hwaddr)v1 =3D=3D (hwaddr)v2; +} + +static void atc_address_space_free(void *as) +{ + g_hash_table_unref(as); +} + +/* return log2(val), or UINT8_MAX if val is not a power of 2 */ +static uint8_t ilog2(uint64_t val) +{ + uint8_t result =3D 0; + while (val !=3D 1) { + if (val & 1) { + return UINT8_MAX; + } + + val >>=3D 1; + result +=3D 1; + } + return result; +} + +ATC *atc_new(uint64_t page_size, uint8_t address_width) +{ + ATC *atc; + uint8_t log_page_size =3D ilog2(page_size); + /* number of bits each used to store all the intermediate indexes */ + uint64_t addr_lookup_indexes_size; + + if (log_page_size =3D=3D UINT8_MAX) { + return NULL; + } + /* + * We only support page table entries of 8 (PAGE_TABLE_ENTRY_SIZE) byt= es + * log2(page_size / 8) =3D log2(page_size) - 3 + * is the level offset + */ + if (log_page_size <=3D 3) { + return NULL; + } + + atc =3D g_new0(ATC, 1); + atc->address_spaces =3D g_hash_table_new_full(atc_pasid_key_hash, + atc_pasid_key_equal, + NULL, atc_address_space_fr= ee); + atc->level_offset =3D log_page_size - 3; + /* at this point, we know that page_size is a power of 2 */ + atc->min_addr_mask =3D page_size - 1; + addr_lookup_indexes_size =3D address_width - log_page_size; + if ((addr_lookup_indexes_size % atc->level_offset) !=3D 0) { + goto error; + } + atc->levels =3D addr_lookup_indexes_size / atc->level_offset; + atc->page_size =3D page_size; + return atc; + +error: + g_free(atc); + return NULL; +} + +static inline GHashTable *atc_get_address_space_cache(ATC *atc, uint32_t p= asid) +{ + return g_hash_table_lookup(atc->address_spaces, + (gconstpointer)(uintptr_t)pasid); +} + +void atc_create_address_space_cache(ATC *atc, uint32_t pasid) +{ + GHashTable *as_cache; + + as_cache =3D atc_get_address_space_cache(atc, pasid); + if (!as_cache) { + as_cache =3D g_hash_table_new_full(atc_addr_key_hash, + atc_addr_key_equal, + NULL, g_free); + g_hash_table_replace(atc->address_spaces, + (gpointer)(uintptr_t)pasid, as_cache); + } +} + +void atc_delete_address_space_cache(ATC *atc, uint32_t pasid) +{ + g_hash_table_remove(atc->address_spaces, (gpointer)(uintptr_t)pasid); +} + +int atc_update(ATC *atc, IOMMUTLBEntry *entry) +{ + IOMMUTLBEntry *value; + GHashTable *as_cache =3D atc_get_address_space_cache(atc, entry->pasid= ); + if (!as_cache) { + return -ENODEV; + } + value =3D g_memdup2(entry, sizeof(*value)); + g_hash_table_replace(as_cache, (gpointer)(entry->iova), value); + return 0; +} + +IOMMUTLBEntry *atc_lookup(ATC *atc, uint32_t pasid, hwaddr addr) +{ + IOMMUTLBEntry *entry; + hwaddr mask =3D atc->min_addr_mask; + hwaddr key =3D addr & (~mask); + GHashTable *as_cache =3D atc_get_address_space_cache(atc, pasid); + + if (!as_cache) { + return NULL; + } + + /* + * Iterate over the possible page sizes and try to find a hit + */ + for (uint8_t level =3D 0; level < atc->levels; ++level) { + entry =3D g_hash_table_lookup(as_cache, (gconstpointer)key); + if (entry) { + return entry; + } + mask =3D (mask << atc->level_offset) | ((1 << atc->level_offset) -= 1); + key =3D addr & (~mask); + } + + return NULL; +} + +static gboolean atc_invalidate_entry_predicate(gpointer key, gpointer valu= e, + gpointer user_data) +{ + IOMMUTLBEntry *entry =3D (IOMMUTLBEntry *)value; + IOMMUTLBEntry *target =3D (IOMMUTLBEntry *)user_data; + hwaddr target_mask =3D ~target->addr_mask; + hwaddr entry_mask =3D ~entry->addr_mask; + return ((target->iova & target_mask) =3D=3D (entry->iova & target_mask= )) || + ((target->iova & entry_mask) =3D=3D (entry->iova & entry_mask)); +} + +void atc_invalidate(ATC *atc, IOMMUTLBEntry *entry) +{ + GHashTable *as_cache =3D atc_get_address_space_cache(atc, entry->pasid= ); + if (!as_cache) { + return; + } + g_hash_table_foreach_remove(as_cache, + atc_invalidate_entry_predicate, + entry); +} + +void atc_destroy(ATC *atc) +{ + g_hash_table_unref(atc->address_spaces); +} + +size_t atc_get_max_number_of_pages(ATC *atc, hwaddr addr, size_t length) +{ + hwaddr page_mask =3D ~(atc->min_addr_mask); + size_t result =3D (length / atc->page_size); + if ((((addr & page_mask) + length - 1) & page_mask) !=3D + ((addr + length - 1) & page_mask)) { + result +=3D 1; + } + return result + (length % atc->page_size !=3D 0 ? 1 : 0); +} + +void atc_reset(ATC *atc) +{ + g_hash_table_remove_all(atc->address_spaces); +} diff --git a/util/atc.h b/util/atc.h new file mode 100644 index 0000000000..8be95f5cca --- /dev/null +++ b/util/atc.h @@ -0,0 +1,117 @@ +/* + * QEMU emulation of an ATC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef UTIL_ATC_H +#define UTIL_ATC_H + +#include "qemu/osdep.h" +#include "exec/memory.h" + +typedef struct ATC { + GHashTable *address_spaces; /* Key : pasid, value : GHashTable */ + hwaddr min_addr_mask; + uint64_t page_size; + uint8_t levels; + uint8_t level_offset; +} ATC; + +/* + * atc_new: Create an ATC. + * + * Return an ATC or NULL if the creation failed + * + * @page_size: #PCIDevice doing the memory access + * @address_width: width of the virtual addresses used by the IOMMU (in bi= ts) + */ +ATC *atc_new(uint64_t page_size, uint8_t address_width); + +/* + * atc_update: Insert or update an entry in the cache + * + * Return 0 if the operation succeeds, a negative error code otherwise + * + * The insertion will fail if the address space associated with this pasid + * has not been created with atc_create_address_space_cache + * + * @atc: the ATC to update + * @entry: the tlb entry to insert into the cache + */ +int atc_update(ATC *atc, IOMMUTLBEntry *entry); + +/* + * atc_create_address_space_cache: delare a new address space + * identified by a PASID + * + * @atc: the ATC to update + * @pasid: the pasid of the address space to be created + */ +void atc_create_address_space_cache(ATC *atc, uint32_t pasid); + +/* + * atc_delete_address_space_cache: delete an address space + * identified by a PASID + * + * @atc: the ATC to update + * @pasid: the pasid of the address space to be deleted + */ +void atc_delete_address_space_cache(ATC *atc, uint32_t pasid); + +/* + * atc_lookup: query the cache in a given address space + * + * @atc: the ATC to query + * @pasid: the pasid of the address space to query + * @addr: the virtual address to translate + */ +IOMMUTLBEntry *atc_lookup(ATC *atc, uint32_t pasid, hwaddr addr); + +/* + * atc_invalidate: invalidate an entry in the cache + * + * @atc: the ATC to update + * @entry: the entry to invalidate + */ +void atc_invalidate(ATC *atc, IOMMUTLBEntry *entry); + +/* + * atc_destroy: delete an ATC + * + * @atc: the cache to be deleted + */ +void atc_destroy(ATC *atc); + +/* + * atc_get_max_number_of_pages: get the number of pages a memory operation + * will access if all the pages concerned have the minimum size. + * + * This function can be used to determine the size of the result array to = be + * allocated when issuing an ATS request. + * + * @atc: the cache + * @addr: start address + * @length: number of bytes accessed from addr + */ +size_t atc_get_max_number_of_pages(ATC *atc, hwaddr addr, size_t length); + +/* + * atc_reset: invalidates all the entries stored in the ATC + * + * @atc: the cache + */ +void atc_reset(ATC *atc); + +#endif diff --git a/util/meson.build b/util/meson.build index 0ef9886be0..a2e0e9e5d7 100644 --- a/util/meson.build +++ b/util/meson.build @@ -94,6 +94,7 @@ if have_block util_ss.add(files('hbitmap.c')) util_ss.add(files('hexdump.c')) util_ss.add(files('iova-tree.c')) + util_ss.add(files('atc.c')) util_ss.add(files('iov.c', 'uri.c')) util_ss.add(files('nvdimm-utils.c')) util_ss.add(files('block-helpers.c')) --=20 2.44.0