From nobody Sun Apr 12 15:23:48 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=1715757433; cv=pass; d=zohomail.com; s=zohoarc; b=Jgx8MUFWCPQbUHEiHUq//xUlUi53ga/w6FiPGQAQZHm9mdNY5ES/cgJ5P/FQOyTnTqpT8O2/riaCxv7dZ9PPaqyHFL+TK9rH9nSa9Oqg7TJYbZhwT3WhUQGgmh6PfPyOmvYp8YA/CVZcAIaQrLFKLHsLq1Cx6I0p2/Qq+B4PYy8= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1715757433; 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=fz6Qde44pAZARZPh4pD4Y74QvPWq0AhDSjUgpnKMgWE=; b=OfwA+pC3fmECKiallsBQlXuQzPcrRNucrSzNXmRAJarP9pA3cEIR8lrJrcMsuDUYOfmZUdX+uMGz2Ey6RrZx1lfVFB3UmnewXr5WNY31J1DUBfwYlTvaIBkaqj+dgMuNTU1UZ2XEieD47CwqR2hTxB0pq9Hi4s2KB772mkQWHi0= 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 1715757433476693.1643573280311; Wed, 15 May 2024 00:17:13 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1s78rf-0005VB-Ec; Wed, 15 May 2024 03:15:53 -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 1s78r5-00050U-BZ for qemu-devel@nongnu.org; Wed, 15 May 2024 03:15:19 -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 1s78qp-0000oi-Ik for qemu-devel@nongnu.org; Wed, 15 May 2024 03:15:14 -0400 Received: from mail-vi1eur03lp2105.outbound.protection.outlook.com (HELO EUR03-VI1-obe.outbound.protection.outlook.com) ([104.47.30.105]) by smarthost3.eviden.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 May 2024 09:14:22 +0200 Received: from AM8PR07MB7602.eurprd07.prod.outlook.com (2603:10a6:20b:24b::7) by PAXPR07MB8496.eurprd07.prod.outlook.com (2603:10a6:102:2b5::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7544.55; Wed, 15 May 2024 07:14:20 +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.7544.056; Wed, 15 May 2024 07:14:20 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=eviden.com; i=@eviden.com; q=dns/txt; s=mail; t=1715757299; x=1747293299; h=from:to:cc:subject:date:message-id:references: in-reply-to:content-id:content-transfer-encoding: mime-version; bh=fz6Qde44pAZARZPh4pD4Y74QvPWq0AhDSjUgpnKMgWE=; b=m8iT7pRwb+camtFGdUQzSusE1cvA3qxRDpINDHZoJDc05GpkHQ51qOKS gg03k80BIPcwdeR3M4oO/B65kf/cWJBEQZedJBVLvixs7Blso3CE1MdG+ 5cw0UkiFKiXfkT5z1DKHr6PAGOMoYYDeWBMKBGTu/xHduklKDzrpZTvij +GGnWazcS431Hl7WoF/kvPQBhR+ebuV17H6lgrWpU8XjrDuQdHoLYrGSp lg0FNctgESuNUesoXSQ/ykjKB3yc/5304jOQCHPNh3Aj3LgsJbMoYNNPN iBYfPbNL/i7t7fQcfSVIwkE7kVTdznsF5hDNfi+tVmDrO4vlMg/AtsTUt g==; X-IronPort-AV: E=Sophos;i="6.08,161,1712613600"; d="scan'208";a="12581813" X-MGA-submission: =?us-ascii?q?MDGz5Ud06yXhBtlayaMxGpDwPvnv0ijZdf/UkF?= =?us-ascii?q?ndBExENWIkj346+Iqkejq8PuSHPym7vhlNmFIWVa5emb38Melj8QchX5?= =?us-ascii?q?IeLrrHXrmju6J3Oomcy2QKHatnKHr2cvT9OSf2/KqoYCw6vSk/K9JaY3?= =?us-ascii?q?wxZzd3A9bRWIwgx+1r+/59Tw=3D=3D?= ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=KEWNxJ41ElHHBfA8G5nptXZp+7FKDYQV5NMxH/pBoaUE8Q4yTw1/tMqCgLCPUbsWLXVXL0fxiToyFhDnRLSHkOOYXvaslKqqFVk2vNATajOiKYrNDpyokgbJKEG1Mgn/2OavmFnPmn6Pv0mb2vaJlYwupDme8rl6/7DoZiyZ/cVAeLB16ZhmYlkS78xkXvqQHmKlBl++tTbA7tcFTsWGtS7mMkyPAEZ99f4TI2vFf//X2q8oH9VIGOmn7YxqDEMQLv7RPIExlKwBoaGUUH1OWcPH6saNob+tLR1GKMbZ3XX/K07PCROp16ToI0zL28pG/0VaVFkWJgvw2WbGdlVhog== 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=fz6Qde44pAZARZPh4pD4Y74QvPWq0AhDSjUgpnKMgWE=; b=XMXeFfKJ9F4YM1HfuPwHTjYk53gj9yc+8CGD5+Zrk/wSyuGuj8avgcb7FGPVOIWx1u5YGETQFusp1tjYuWDJLLqCg4IKPjVf1u9dSd4NlNbJeEaprj6YiLK9MrUz1111DRZnVAG2nyrgQmlSjiMLH0qbINyUWRH5TgmKb+U5mSxHFOSrkpa1W8ADMhtxlrhXYKCHfm4LuHMCt+m3Hiq9ld/HcSC3ihCyRk1+AfEG/lL6Nw/Mo1w+tzlDpdGFMlDWsrHI/Dez/BN8+i0aUZzeRMgAoRZO06ZH1IjyD0puqhAmyBoEiZCqdeHn3Ps02+JnR25bWM4HKoLweWvcu2p5hg== 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 v2 21/25] atc: generic ATC that can be used by PCIe devices that support SVM Thread-Topic: [PATCH ats_vtd v2 21/25] atc: generic ATC that can be used by PCIe devices that support SVM Thread-Index: AQHappeAjUdU2werkUaJiYxy8FgLhA== Date: Wed, 15 May 2024 07:14:20 +0000 Message-ID: <20240515071057.33990-22-clement.mathieu--drif@eviden.com> References: <20240515071057.33990-1-clement.mathieu--drif@eviden.com> In-Reply-To: <20240515071057.33990-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_|PAXPR07MB8496:EE_ x-ms-office365-filtering-correlation-id: 5992b2fc-2973-425e-5339-08dc74aea414 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; ARA:13230031|366007|1800799015|376005|38070700009; x-microsoft-antispam-message-info: =?utf-8?B?WEgxVEdPYVB4cW1YYytHbHNmTVkyTmJRd2xldXZvTStxakNMUnUwdm9XeEJh?= =?utf-8?B?N3dmV0d3MkVNTjA5cmZaUkRyTGRFTTF3Vzdkcy9LT0tUVlhScnZzRmZydC9X?= =?utf-8?B?R21yR1lTVGNycXdOU3Vxend1YWtORUxvQjlaVnZ1YmdmSlY4UHRzVlpPc2Vn?= =?utf-8?B?OVBjd1VSdCtQMFBvTlNPK2FSZHR1eU42alJualE2ejFHMllzZ2MyT0NWaXFU?= =?utf-8?B?ci8wcHZTQXZIa25nM0hpWWMvNUxKN0l5bENlQnN4MmFXaEhPT28yUjY5dXl6?= =?utf-8?B?WlAxZzFvSnBDb1RZUmI0dVZTR1lDSHZFL29pSHd3STVSc1d5NHJEamVEZER2?= =?utf-8?B?ck4zYUx2b0FEOUl2QldXK2ZKK0tGTHdtQWhyMEhHY3ZXTitDWUU4V1d5d0Mz?= =?utf-8?B?OTJkOUFudmFkRWtDYmZxMEI3Rm9XTmQzaUE0aTN6K2VqdHVvR0Y5MWZVT0xt?= =?utf-8?B?YXd5Qkpac1JGdSs3dlQvWWF3ZS9DMDQrMElPRmJiUlJDNlFKdDU3dUZ6dWV5?= =?utf-8?B?aDBlMms0YVE0U1JTNWhFYUcxYUJnQS9wR0ZXMVlCeGJWc2laM0VYQ1FrL2Q1?= =?utf-8?B?MGRUL0V4c2JYelBiZ2p2cVJqc3pQcC9rRGUrVTRLMDBFdTVMN29peElzRFNG?= =?utf-8?B?ZGtiZmwxREtoNHZ6SlQ2QmpOdENLa1ZUUzJ2RDF1b0pYeFVlc3pvMm8xVU5o?= =?utf-8?B?L1BzazYzMUpzeE9WVnVuQWJyYkp0czI1RDFMSXY3Y081SEI5bFUzT1RxZkox?= =?utf-8?B?S01hb1kxcEpHVFRUNjVKZ0V2V1FUd3NvMTYyeEUzY0IxV2tsYldRa0lCZGx4?= =?utf-8?B?U0cvSDVqa2Z3N1BVZ2hLTFBDYlRUNGJ3V3VoQm1UbWt1THh6RWpJNXVZb0t0?= =?utf-8?B?SjZtNlF1dnNycTV5cVhmR1dYckFRdm4rNEw3LzYra3VLRVZiY2pDVWovZ0tR?= =?utf-8?B?UVd5WGV5MXdLQ0o0T3gzZkpGdXpXYUZjdTlBUjhyVEFaR09Oa0hsbEQ1cHJv?= =?utf-8?B?U0hxUDcyM29hVTlNY2NmY3VuREl0MEpma2xrOC84eU9ZVlpHaFIzZGtDQndJ?= =?utf-8?B?VXp0YUtwS3hBSGZKaEFMcmF1cmI1d09jOEN6NlR0RFBDRlUwWjI3L0hYYndj?= =?utf-8?B?SlVTSDd6SllJdExrZXpIYXhVTkRwSHZpMnNKRDlqS0s2SnQvQmRJbWxZZXdh?= =?utf-8?B?cHJPeW8vVGI1YngzMktuYVRWdGc5SmNKK1FuUFRmSlNxeHBUTmkzVng4UkRo?= =?utf-8?B?UHpzMHl5Z2JtK3crcUxQRDRXQXB4S2o1TEl0TXNWazhEWVZOZjZJMEltSXpY?= =?utf-8?B?L2ptOGlPbVQ2dUc5K0p3aGwzcFRINmFXci9heXFEWC9NOFlDZEdoY0JOaTlp?= =?utf-8?B?d043R25ma0lkb09oVlFyU1JZWVVRQnlkRnFwZkk2MmNPZHljNis0YjFMMjB1?= =?utf-8?B?RlpIUW9tYVJtZlNUb091bU96QTJFeEoybUlQd0w4ZU5BOUdQdm9Qdno2YUt0?= =?utf-8?B?OUNybm9jdHNBRjdNMGdkTG9ncGVQSU85T3R2S280RnBmSUZWYW1pYlF0QzFJ?= =?utf-8?B?UGN6L2tUdXdLdzJHTFVtSUM1Wk5zcjI3K2QvTnUwNHRRakk5R3p5RVFGNnlK?= =?utf-8?B?QnByL3NKSFE0alJ5MEZFL1U2S0dCQXkzby9JSExJTDNqNmllM3pUclJqK09K?= =?utf-8?B?NmJ5cTN6RTJHb1pyRy90TFREMC9YZWZhdWxsTmlZZWZoZ0RDcUxHaFZBPT0=?= 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)(366007)(1800799015)(376005)(38070700009); DIR:OUT; SFP:1101; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?utf-8?B?Um1Bdnh4WGwwZ0RSbVgvd3VwandGcFBza3MxSVpISnR4cjNpWXRSUEI4MGFS?= =?utf-8?B?MU9zcnZxVkI0SGFadEpLbm9xZzRXTjRxc1FDbHVUTXNVd2gvdTNVZnZYS2hr?= =?utf-8?B?dGhLSjF0Z0hTVEFRTTFkNzZSaXBwWjVIOU1MTDVSYlVGcitrMFJ2NDJxQ0dq?= =?utf-8?B?WTlMNjN4OER5d1BtSW5pbWlCb3I3WEFtSk5JSkYwdE9MaDJlRk9hU2o4MWpq?= =?utf-8?B?d1FsRnd4N29nQjFBaHJCaFlTc0YwYnRNcDA2T3FmaWZxSUxRc2xzR2RIYmFv?= =?utf-8?B?UmZnanFGaXYwM2pmZlBzc1MwTytaRmxLdGxIUHVlQ2tBRm5sc0dlbmhWZHhN?= =?utf-8?B?YXBHMDF1SzBneTFMM0h3OFVrMVVTMUxhZlhkLzhaR3hEQmsweHJRdkplc0R4?= =?utf-8?B?MjVMMnEwZSttTDRwYUluVDl3em5KcjVVdjlvVlI3NHU3RW40QmMyWENibE85?= =?utf-8?B?Zk5rd2dIOEVDeWEwZ1Q5bVovOXpZWEZISVlrWVpFbmlqYWVwM3E4Ui8rcXcw?= =?utf-8?B?dXJ2TXZ0RnRhemxlOVhzQkF1cUFMb2tydGJtbzdsWVM4QmE4U0dsWW9oMXFU?= =?utf-8?B?NzdHa3p1M1c4T0xkdVIxVTdCNy9DazlhYnVEcFRMckRoSHhXY2JaNkNaY2VW?= =?utf-8?B?WlNybHRGYkVYSUZ3elVOaWY3bWRqQnlhTWFRSEtOZE1sZXd3b0ZoVG9pQnNz?= =?utf-8?B?ZDNVN1NkbTB2bkJTRWs5dndVWnY2dDJxeDAwZXA3R1ZiVnBhUDN4WmpHWTRV?= =?utf-8?B?dzg5WWFMbGVTc0YvY0I4QkVGcmtZWndHYnNodW5yaUZLWnIwYW1rOTFzK2hR?= =?utf-8?B?VVZHcmsyK25yTzJUZk9NL1ZkQTBJd3FKdTlZRGJzVllWSVZ0bU5JcGpWUy9B?= =?utf-8?B?ZkxqYWFLTDlaSXJPMTc4ME4rclJUSHBHOStSeWNtYnV6NmRFVy9VOUVRU1lY?= =?utf-8?B?eFI3M0c5d2FYSzJZVmlGWHI5YTFJVjQrMnBDQWd1ZkxGQVp2TVhVbmt4K1Fn?= =?utf-8?B?YnB3TU5DY1VxUjlzdmtPQmh2bUlxRTlWdmNsWjdyUWhtK0hndWx5dUZKbG8r?= =?utf-8?B?ejBpNWllcElJL2x0dlQyTjFiMUlYRk9PdndDQVhrL1MxeDlNcEt4WGRFaGJU?= =?utf-8?B?N2h6cmdYdWNkL0xjUlJmc0lvZnBHK2U2aFYvZkpPZEdUbzJJZmNZanYxenVp?= =?utf-8?B?YWNzdWZ1MFAwbjg1RHpnbkxWU2FpcHNJZUd1VnF4NkJXVW1sL2NIL3B6QXRG?= =?utf-8?B?YzVuTVhpM2ZTU3ZIUi84Um5ITTl5dzlLNERhKzNyUk9EejM4YUZqMXBySkY4?= =?utf-8?B?Z0FLOWVyZmN6bEQrMWR2TUJiY0V4N2hXQUZmYTc1dVJ1bHpWNkJKNldudDAz?= =?utf-8?B?TEtGR3puSUtNM1VZQnA4ZlhtZ1JHakgvOHN5cCtIRTMvNFoxNnh6ZUdadzZN?= =?utf-8?B?bXhOeUN6ZHBCb2c0Q3VqMHdMUU4vZWZUUDN4cStGSjFaMkljWjVETER6SWNU?= =?utf-8?B?NStaV1JyVmppOWxoc2NQQzU0TVVIdzFVNUQyU09WY0lFcXVjY1NSNUMwQVhE?= =?utf-8?B?cUc5aUJ5ZkkxRVhRZkZlZmlYTEtzZ05wK3J4UWdRSFNhVDJaL1g4OHIxMzRL?= =?utf-8?B?WkFVbkNyT3RPSTVrNDBWTXpRSkdnQVVXZUxldjZrTWZqUVEyUjdscmhZdWJU?= =?utf-8?B?SG5MaFRPVitVcWxOWEJvNkIvVHBWZFM4SDBNRElVSVppbkpFZDFxN0Zha295?= =?utf-8?B?cnUyaU1nNkNmNkR3UnZWaGI5SFNQekpUN3UxZHVmYkFqMVFLV0tScmJkZDBo?= =?utf-8?B?YlpmaUFacEI5TTN3ZHdlNTVsNEhKWUtNSElNZFZxeGxyMTBvMWpyWjJvUGZI?= =?utf-8?B?dG82QzVZM3JmTlNCNGxSNVBleXVhaTYwYVpzS3EvK0ZoWDFUeEd0QU9RMElS?= =?utf-8?B?VVB5MFVpN202b1ZTcnRBbFJaT3l1YlFFbTBUN1k3Mm92SEYyVFNpSkRKUnRH?= =?utf-8?B?Z0tuYTNlVHI3L1lCeWFLdzB1NlNrTHZqYWxlRENsSWdPSktNeXZ1aDg3Sy9o?= =?utf-8?B?dG11cTBoYnk3dVNLNUJmMzNWV0xMdjVpZUQ4bDdFWnJIMzNIcHczNDVzN2pp?= =?utf-8?B?MFhyVlpsZDRBL1NHWnJrRmlRNE9TS0lJY2xhNkRPc1dweEwzR01ZWkl4alpP?= =?utf-8?Q?OstOSaPhvPNQ18mw+pVM81U=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: 5992b2fc-2973-425e-5339-08dc74aea414 X-MS-Exchange-CrossTenant-originalarrivaltime: 15 May 2024 07:14:20.5619 (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: Xuge6VfKB2ljl4YTZQ/E/xZ8T5gRIVk0l43YQ07Io8PHZ7Y9M9+Oep++v/t0NeghCDVY7h1ASVtboaz2hBpC82RJIVzQactkFG658EeVFJA9Yz00EhKa+aEjuIFYgiD5 X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR07MB8496 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: 1715757433987100002 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..d951532e26 --- /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