From patchwork Tue Feb 18 11:09:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Kardashevskiy X-Patchwork-Id: 866260 Received: from NAM10-MW2-obe.outbound.protection.outlook.com (mail-mw2nam10on2052.outbound.protection.outlook.com [40.107.94.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7FE672397AA; Tue, 18 Feb 2025 11:11:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.94.52 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877062; cv=fail; b=arTMWsEdW6jPsrDzWRiAsLmppAaXxx/j+gwajEQH1+50y3li37/IyVOwqfoinigUIe6ikyrUCTyZMBkff7+QhIf+dxnfFejG0FZ77xve+v4hGVBXywMA+dam8DnsFkaDqT789FBVM9kkWPyOezM6HWcpAWf4rk7QIlOFr4W0DYE= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877062; c=relaxed/simple; bh=yZDw9GrHj+wqH8ZY1ceCx4TX2m9lzWnKAUnHNfCXXPQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BkrgjbBWelHXm+nrL/shLv16xTwpwN7gvwp/FNImEXfs9bEovpbBR1Jn86JrL0PYHvv03QFYG7plSPAMtlgOyv84MicHy+0/WVjR+HdqADbvII8oFa8QPq9DTiLcWLEI2ow0vq/rvt6eorPpWeLKdsg4WJQ7T9F69dqieBKeVnw= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=oQbaNl24; arc=fail smtp.client-ip=40.107.94.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="oQbaNl24" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=S+j8tWiSoWlW8Xr4RkZUnMo7+A659Pgxpr1NJmPg5oJuK9A6pwlSQune5iuyPtYQHT34aGgcvnDTIdmJ9TAEyspChVX6Yp68DZi2ksotRotfdPS6NwdWKsUmieudVGQIL1QymoGXRjSe7jVgyLaZkS76K/A7LozHFRcNEEObGHdznBdNz4CLm6vXytPfiG4iUoUGaA0qS4D1QylqhoHtvoCATN/I70gTnQU/+tdnEOq3nb7Mn6qgGStHrN+nvQI3mHaB2gm+54B0AkSsuFG7X0ejf19f7jRSCvFSgHqD1DhpT7e4LF+4IM95+2ohVdu9yIGe2a1LJ9KGbbWI1Ukkiw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=PCAwqqUdJ+HI/4UA+HiyjrghrqXWy4ML5tMIao2i0oY=; b=u0vPnSA+wozMOyO7ehpHXTNTinT3jwEXXkX5h4u4UWFLMZKHdsq7DXubwmSa/18/Y/qKbPVQ1fEyIu9yIMy0nLQJV/9Y82jbMjUKykw1fPiyuf/5OczVtKJbj97sXIdRBcSw2nOSn8TKJozggdGU7Qe/eiL+3JxXlnt1GKWaivs36y6UmTU+tKLn/gCvM84SU8Q5IJFd9QhF/4JzwLqugh16vS6bMtua2p/DXup626uh7dgQu3OqLKF2efQD41QS1rJZfF7rPiYNJMLTvDoogFGcA+wHMGrKeWv5uJ+6MPZ2hPnuEDr6iW3eI3lFC4fAYRgkn6/vziiwGZvhqgZNkw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=PCAwqqUdJ+HI/4UA+HiyjrghrqXWy4ML5tMIao2i0oY=; b=oQbaNl248Z+Y5mbhxVDkWyW5CQ+493EP4KBgX9gKYn+e55jnvjGDxK0k6ty6qjcePa3X5LJOvXKUI/6IoqulGnJqBNHIaF7nRS9Tqqi7fjiJLelIIJPl8bxxBPVIyEiYZHRQAdyhLwwest6AsCHSTj/t3NmV1zPpRbwe+hFcdW0= Received: from BN7PR06CA0062.namprd06.prod.outlook.com (2603:10b6:408:34::39) by IA0PPFAF883AE17.namprd12.prod.outlook.com (2603:10b6:20f:fc04::be1) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8466.14; Tue, 18 Feb 2025 11:10:58 +0000 Received: from BN3PEPF0000B072.namprd04.prod.outlook.com (2603:10b6:408:34:cafe::7c) by BN7PR06CA0062.outlook.office365.com (2603:10b6:408:34::39) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8445.19 via Frontend Transport; Tue, 18 Feb 2025 11:10:58 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by BN3PEPF0000B072.mail.protection.outlook.com (10.167.243.117) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8466.11 via Frontend Transport; Tue, 18 Feb 2025 11:10:57 +0000 Received: from aiemdee.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Tue, 18 Feb 2025 05:10:49 -0600 From: Alexey Kardashevskiy To: CC: , , , , "Sean Christopherson" , Paolo Bonzini , "Tom Lendacky" , Ashish Kalra , Joerg Roedel , Suravee Suthikulpanit , Robin Murphy , "Jason Gunthorpe" , Kevin Tian , Bjorn Helgaas , Dan Williams , "Christoph Hellwig" , Nikunj A Dadhania , Michael Roth , Vasant Hegde , Joao Martins , Nicolin Chen , Lu Baolu , Steve Sistare , "Lukas Wunner" , Jonathan Cameron , Suzuki K Poulose , Dionna Glaze , Yi Liu , , , Zhi Wang , AXu Yilun , "Aneesh Kumar K . V" , Alexey Kardashevskiy Subject: [RFC PATCH v2 01/22] pci/doe: Define protocol types and make those public Date: Tue, 18 Feb 2025 22:09:48 +1100 Message-ID: <20250218111017.491719-2-aik@amd.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250218111017.491719-1-aik@amd.com> References: <20250218111017.491719-1-aik@amd.com> Precedence: bulk X-Mailing-List: linux-crypto@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN3PEPF0000B072:EE_|IA0PPFAF883AE17:EE_ X-MS-Office365-Filtering-Correlation-Id: 8d95f68a-e84a-412b-8ac7-08dd500ceb8f X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|82310400026|376014|7416014|1800799024|36860700013; X-Microsoft-Antispam-Message-Info: xSDgf5X64mDvQhLM2LNrUf443uSbJMgRnvkg7g24Vqjrd8Hov5OryqpqzlOmkEPM1vmy+84rxIxXqu58h5bsW13TDFzIn/McXYCtEcwtyRgMaKI7LVUn9d/GYPHRAESe1hgnS5HYFpaBkCeuKWhAokZIEv3K//39gAQliGfM9aPjRXyMPoUDw63M2YEHg0opfc/JEwrNmgWVGPuFWg4GOmK5p/6dyvyQw4TR8duIKDFyS2s+VUa8lPlUqQBu0+KoK/qhBg/c/rmNpDUxPH9QSUVeO/0ksTF2yClfLTYln65pPhpH+WJoY+lLYWhD4NoruY6tOpTR6YoaQ9ZnhIgg3qhxQ520JZ+jAdhvLH22Sbh7+4m9M8CtKaLuZxYkkx/EJ41fOvoPCLqjvpsgrVBWQmnOsdtEuWAIfi2jmYpmUoY+JBe6F8V8RrSueOe1vtwF7pvtX8Qr4V4mx/jgr0Kis6FWFHG6+yDFPNta09Xjq32ZBjN4I8kMhTUcCelby7CFrO9+EtJ2L9nQFKXbC/wF2ZAjbEbyEqKQrgKA32BgYIdNTddFbvAQqVYemH6HZs6eGbWkBvF906SWHwLcroBpOafkpQlX7FcrTlMmo3OUFA//ceMSM/3ixpP25ajyuqEZDt6JCpi+X5YgpLhvq6HvQ/Ez7o0ChOu+/Kn2JvEcoo3FNsGha8QzWOt0Zsjgt14qMLPA0ojDarZSNXRj38C/vc5/qY3VgNqvHRMDJZHy0OY7BUmeAUojISvDd/Dvs1Qyeuog46ntWNlivtxG/YiGa0STxPD5HP7sEGDqyzc9lGkwdG1H1NMIoI/xpz075icC/3MgsVUOC8I6qFDpzwVbPhWSBTJSZAtvWw1YlO1F6uJBsOAcFZRppe166zvBLyXm5HeKW3ZQKjIFp92UmLu609z7cwIocVYt37u9PoHW4M9cT9QB1YgeY3Z9ZY+iCKbnFVYfMuXLBE91VgseLvP+ZNQS6kwWL6eVbFXSl81FGoBJER7tAGU/0UIe86G1EjTqgIr4XgsT0rdsVnxP1qoOvna3tNpdDSpCwflpRPeKFw2dANcSahs0sJJz85M+qYUn+VFxaic4fx1/NGK65XFYMgy0yZMK9L8DLQtmfuSzYc5IKHMtVNxkoDX+AwFfcekMkxnt+M40yNdW3xtzIwS/t6ug7MvfuVHQjlkLt1tM9snrb4D4TxVVitJA7F76wynu/tskJogP1Ws+tdDZLZJcCZXc1EV200zx5EZH6dA7ZYb9FOvARlaHd6zmMGNOwdSdoFGq6VMyG0emKwKud0bklUDV181Ck8Ny3SBB9i9Ehuj600qa5yMVWvAWgGnD2JHNpmt0Y1RiDgFabJVg6gx7RZWpOqFT5Q5hcMYbsBnZ824KW2FFpTU2aFi80OQQ+EyzUfCHLLITNLVncHd8gmZGXm85fsHt8oGNyCTozBJb8Wzr4Cnl8LmFe0CXY/AoUbJ0oKfJLJlKWi3VqE2wI/mZ6Se1JwSWQjwtIlVJBMuq+Fg= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(82310400026)(376014)(7416014)(1800799024)(36860700013); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Feb 2025 11:10:57.7736 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 8d95f68a-e84a-412b-8ac7-08dd500ceb8f X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN3PEPF0000B072.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: IA0PPFAF883AE17 Already public pci_doe() takes a protocol type argument. PCIe 6.0 defines three, define them in a header for use with pci_doe(). Signed-off-by: Alexey Kardashevskiy --- include/linux/pci-doe.h | 4 ++++ drivers/pci/doe.c | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/linux/pci-doe.h b/include/linux/pci-doe.h index 0d3d7656c456..82e393ba5465 100644 --- a/include/linux/pci-doe.h +++ b/include/linux/pci-doe.h @@ -13,6 +13,10 @@ #ifndef LINUX_PCI_DOE_H #define LINUX_PCI_DOE_H +#define PCI_DOE_PROTOCOL_DISCOVERY 0 +#define PCI_DOE_PROTOCOL_CMA_SPDM 1 +#define PCI_DOE_PROTOCOL_SECURED_CMA_SPDM 2 + struct pci_doe_mb; /* Max data object length is 2^18 dwords (including 2 dwords for header) */ diff --git a/drivers/pci/doe.c b/drivers/pci/doe.c index e4b609f613da..98fd86fae8d8 100644 --- a/drivers/pci/doe.c +++ b/drivers/pci/doe.c @@ -22,8 +22,6 @@ #include "pci.h" -#define PCI_DOE_PROTOCOL_DISCOVERY 0 - /* Timeout of 1 second from 6.30.2 Operation, PCI Spec r6.0 */ #define PCI_DOE_TIMEOUT HZ #define PCI_DOE_POLL_INTERVAL (PCI_DOE_TIMEOUT / 128) From patchwork Tue Feb 18 11:09:50 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Kardashevskiy X-Patchwork-Id: 866259 Received: from NAM11-BN8-obe.outbound.protection.outlook.com (mail-bn8nam11on2083.outbound.protection.outlook.com [40.107.236.83]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D895522DF92; Tue, 18 Feb 2025 11:11:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.236.83 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877104; cv=fail; b=mlc0HncPvEPLl5Ngp+cm8EEDZ1lF1WQC76nOsV2DIkTms3BIyzNhtvJXkw1LGqrVm3TeghClaty52KyaT+0hlXQb/mR0KtRxm5zHaCfZY7XQQYrss7dxem3jXI7bM6WMEXsPudisXoaVezLYdKxVE6r6bazZzQsgWfG4zj7nY88= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877104; c=relaxed/simple; bh=1KVx7VYiVA/8sBupT6NnqbQAau2zF5M+T4XuMdB4EQM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=H3/Vdz9gI9L5GImgQDYxLTf36QR5KWDgT+c7wqfMZ+BJhWRWVSX/Pyl4wnpYy6nqG4V+cuRZsKY/nOFfPfVXfSgvhpt6gWGRSFWBueq65A58EIgBDQxUBLv9DAcSWzOmeey79VOJQ2R1PUfyB2gZ4QihXqIXUrdyIjoK3n8O3f4= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=1mxrknL8; arc=fail smtp.client-ip=40.107.236.83 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="1mxrknL8" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=eoyIkPlIIqIlALP0KlRDwj6chMX8vtWfqSzh/R6GSXjPzk2hOl+qtE3hal0MLB4oKHBLnCP9UP54YdRH4oDeohdmJOKF3Z3jTXnfqBz1hHJAIDnUQL2z89NyYh2rQcojDQNm90Y6efH31m/aclP3ykSyxyciBCilq/QKucVknCfU7w+7zVYAnyBCV5hFDQ/QV4lEUwvE0/2XJrkW+jqZf3fFluXhWg5Hzxj6OB5lt4B7H6gUmyD9yJiiJK56hQZAsK8XZ1bCh5ht9egoNFfhHNzKQZdz5Z7iihxLmTqhqVDkuAlS1NrSGbw3MVmOurs8DQQwkx6sS9tNXHVBpH7a2A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=W3eqTs5hcL57MwXtdZf9Bn5hgb4AIxLs8NtJy7oIKfE=; b=y8ffkDWIFXXhUI1sR6QivZ9E7bxwcOciOSV9BL01JIfX3qFsnNi9CZ+VKSJI1tlIDha7i2JW8jpgr/H0I4YItgWmrWfhIrEDw/zc8GtIfXr0bNSM+T0GSK8Gg3Dsup4EpFf+U7gVL4/P5JDSvhezFNM6zogpLGmBtTg1KOjD3dgK7zj+agHqItu6L1tQmstB5lM7codf7uDDen9bBSRu1Hy6IyqM28YIYJl2+f76/E3SZbk/YnqqXsP5RdzSQ6pXX/Lzymf0k44D7WwS6XFQR9Kw2F4f7NsnXz0vNDToW2T+1uzuv6kK/zTJ1B6UwZAoGnQ6Z+Vq9Of7FtdS6ZDMSw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=W3eqTs5hcL57MwXtdZf9Bn5hgb4AIxLs8NtJy7oIKfE=; b=1mxrknL8Z9p/ERv/YzncgesTKb95yylnTpVn9Gd/BUyWLYU3VzXL6rw7Mly/92jB97GY7fZqFIa3me1EiPgx9FHEN/sY7RXwt/K8/f2X1AgSUl3bG9h1C82qjvf2goUyhvRrFDuJhjBYua8l4XTDLh2l+4isXLqglagTJ+dHu0A= Received: from BLAPR05CA0009.namprd05.prod.outlook.com (2603:10b6:208:36e::16) by SJ0PR12MB7007.namprd12.prod.outlook.com (2603:10b6:a03:486::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8445.19; Tue, 18 Feb 2025 11:11:39 +0000 Received: from BN3PEPF0000B078.namprd04.prod.outlook.com (2603:10b6:208:36e:cafe::13) by BLAPR05CA0009.outlook.office365.com (2603:10b6:208:36e::16) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8466.13 via Frontend Transport; Tue, 18 Feb 2025 11:11:38 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by BN3PEPF0000B078.mail.protection.outlook.com (10.167.243.123) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8466.11 via Frontend Transport; Tue, 18 Feb 2025 11:11:38 +0000 Received: from aiemdee.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Tue, 18 Feb 2025 05:11:30 -0600 From: Alexey Kardashevskiy To: CC: , , , , "Sean Christopherson" , Paolo Bonzini , "Tom Lendacky" , Ashish Kalra , Joerg Roedel , Suravee Suthikulpanit , Robin Murphy , "Jason Gunthorpe" , Kevin Tian , Bjorn Helgaas , Dan Williams , "Christoph Hellwig" , Nikunj A Dadhania , Michael Roth , Vasant Hegde , Joao Martins , Nicolin Chen , Lu Baolu , Steve Sistare , "Lukas Wunner" , Jonathan Cameron , Suzuki K Poulose , Dionna Glaze , Yi Liu , , , Zhi Wang , AXu Yilun , "Aneesh Kumar K . V" , Alexey Kardashevskiy Subject: [RFC PATCH v2 03/22] PCI/IDE: Init IDs on all IDE streams beforehand Date: Tue, 18 Feb 2025 22:09:50 +1100 Message-ID: <20250218111017.491719-4-aik@amd.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250218111017.491719-1-aik@amd.com> References: <20250218111017.491719-1-aik@amd.com> Precedence: bulk X-Mailing-List: linux-crypto@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN3PEPF0000B078:EE_|SJ0PR12MB7007:EE_ X-MS-Office365-Filtering-Correlation-Id: 318a83ba-b4d2-4c9d-81b3-08dd500d03de X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|82310400026|1800799024|36860700013|376014|7416014; X-Microsoft-Antispam-Message-Info: DECNRsKf+vt9Z6fG7iY/R4mBhR9Krl/kqZukcwJYNTUSxvqQQvXImcanCObO+YZtTfzEW43AUMn5Ohesy17U3qaTgsRuE4UO/7Xkk/WySxXvjICG2E+RUMsEWQ9aVOh3N2doAON3rmOmM6j8ZCbhe/VLh/tCzRD9CU0RODlr8/JtsbbeV9L7bBp1Vx5tGX/iTdR3PUAv5dd4O19E0k+xaGBh5LMd9wAydrXDWfxm1BHwiifA73ajW60qICnF4fJWgY0fpRuFI+FI4A4HZ7qeWTtLtm4vJE0Td6Oi6LSqu1pqh/2lTf74j3tScIZ1NW1di7TwDuo/NW9TDlzCX2kzgBN2i/OpT8yQPuadCOjPbPZaqfuvxmLY9dlrYh5qB/85w+dr8USevYqpjIDp6NYmRiGt8g4YP/q3YGZ5CRNAKM+99vvlWOqoKdafsNWJJWayuSBnTJfaBn/KqNwNhEr5jTSY46uuxusD38QQoG0bhRluI3gs573+sEQKs9xoSik83Z1drg5cueLvYgLK4raP12sOCyubFC1FRTCmsZ6c7Zc2VUcWl4EFiXJ7W2gAEO5hcWD8l02YnuW2Ffqzzy6e3E8e9+ztxLo95rKK8ybeCoVzFN5DkQuoexkDBgVyEQ32u+F1nWcU5v7Ci4r0Pfp9wrgw1A9cHRaZQ2syfCXsUKj3dSjju0yg593M/zY6v78IJWaBDQwKc2xtstsXTHl8LKLRWzgR5iIriPyrjl2V8gaDuw3zWUYszSgnnUdvalhNdbjZVo8/+zBrnSE6cD+T3B+sxlns58KuAO1Pp6TpKMfNoPoYj1jqxneQmVx6BfZPAiCL1P7uVKyV5xjq6ewL0XMdP3t/AiWF5em1qFrCj3dQiyKOcBrkgFJxvRewb9+8Ma4gcW7r6SBbIDf5GwiOw2B0+46idXSpC+ftbTzmFBCEXSPaQboKun2+UMJtbN99pM8AeaC1pEOGstIfYCwtF61JRJOp2IP7YNAPpisajxm32T+5WtWp9UZkGGgtsjU6Q4PDRthKocnjcXxl/s+yGgDcqQTImFkyMOAY66ZCf3lPGr8kMrr1K78wulc0U6IxOqUvKOz78Ep2frlInsuD9zSLZLZANFMmlbhdm3CwtW/qav4oBj2IoDoBZpdgxYfHQfXEc4DlgYf+cf/yd57MPGuWBeCaTdjIHsjYz9zaYDT9noXW0RiMTxWO7EULBldrtU+PvX0VYGidwt2eMHpFLJmoArS6+4JWxPWmw8+5vXX9fJRyz1tx+3WUPXy9d1OJ/+3kGUP9LW6caFgnohclJbo3hZnkPFZkmi9tpjHInTD6XsqVmB4esasO6DacRzSh/JexRqN3rrCGZR5p3cBXZ+U1ly0Zv5r2dXT/MkjVtho/Kef8fujK2zPSE0sgtSxbMH7zupabwQWrToNJg6ObnM69oULzF/Xf3KkOHlvKZYi+1PdlcKhY5GaK99Wlt3IbZBzIuPEGTGmW9XrGOX4dASFxzW5W8o21QVs5Bf/hJRQ= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(82310400026)(1800799024)(36860700013)(376014)(7416014); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Feb 2025 11:11:38.5564 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 318a83ba-b4d2-4c9d-81b3-08dd500d03de X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN3PEPF0000B078.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ0PR12MB7007 The PCIe spec defines two types of streams - selective and link. Each stream has an ID from the same bucket so a stream ID does not tell the type. The spec defines an "enable" bit for every stream and required stream IDs to be unique among all enabled stream but there is no such requirement for disabled streams. However, when IDE_KM is programming keys, an IDE-capable device needs to know the type of stream being programmed to write it directly to the hardware as keys are relatively large, possibly many of them and devices often struggle with keeping around rather big data not being used. Walk through all streams on a device and initialize the IDs to some unique number, both link and selective. Probably should be a quirk if it turns out not to be a common issue. Signed-off-by: Alexey Kardashevskiy --- drivers/pci/ide.c | 29 ++++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/pci/ide.c b/drivers/pci/ide.c index 3c53b27f8447..5f1d5385d3a8 100644 --- a/drivers/pci/ide.c +++ b/drivers/pci/ide.c @@ -18,7 +18,7 @@ static int sel_ide_offset(u16 cap, int stream_id, int nr_ide_mem) void pci_ide_init(struct pci_dev *pdev) { u16 ide_cap, sel_ide_cap; - int nr_ide_mem = 0; + int nr_ide_mem = 0, i, link_num, sel_num, offset; u32 val = 0; if (!pci_is_pcie(pdev)) @@ -33,6 +33,7 @@ void pci_ide_init(struct pci_dev *pdev) * require consistent number of address association blocks */ pci_read_config_dword(pdev, ide_cap + PCI_IDE_CAP, &val); + if ((val & PCI_IDE_CAP_SELECTIVE) == 0) return; @@ -43,6 +44,9 @@ void pci_ide_init(struct pci_dev *pdev) return; } + link_num = PCI_IDE_CAP_LINK_TC_NUM(val) + 1; + sel_num = PCI_IDE_CAP_SELECTIVE_STREAMS_NUM(val) + 1; + if (val & PCI_IDE_CAP_LINK) sel_ide_cap = ide_cap + PCI_IDE_LINK_STREAM + (PCI_IDE_CAP_LINK_TC_NUM(val) + 1) * @@ -50,12 +54,13 @@ void pci_ide_init(struct pci_dev *pdev) else sel_ide_cap = ide_cap + PCI_IDE_LINK_STREAM; - for (int i = 0; i < PCI_IDE_CAP_SELECTIVE_STREAMS_NUM(val) + 1; i++) { + for (i = 0; i < PCI_IDE_CAP_SELECTIVE_STREAMS_NUM(val) + 1; i++) { if (i == 0) { + offset = 0; pci_read_config_dword(pdev, sel_ide_cap, &val); nr_ide_mem = PCI_IDE_SEL_CAP_ASSOC_NUM(val) + 1; } else { - int offset = sel_ide_offset(sel_ide_cap, i, nr_ide_mem); + offset = sel_ide_offset(sel_ide_cap, i, nr_ide_mem); pci_read_config_dword(pdev, offset, &val); @@ -68,6 +73,24 @@ void pci_ide_init(struct pci_dev *pdev) return; } } + + /* Some devices insist on streamid to be unique even for not enabled streams */ + val &= ~PCI_IDE_SEL_CTL_ID_MASK; + val |= FIELD_PREP(PCI_IDE_SEL_CTL_ID_MASK, i); + pci_write_config_dword(pdev, offset + PCI_IDE_SEL_CTL, val); + } + + if (val & PCI_IDE_CAP_LINK) { + /* Some devices insist on streamid to be unique even for not enabled streams */ + for (i = 0; i < link_num; ++i) { + offset = ide_cap + PCI_IDE_LINK_STREAM + i * PCI_IDE_LINK_BLOCK_SIZE; + + pci_read_config_dword(pdev, offset, &val); + val &= ~PCI_IDE_LINK_CTL_ID_MASK; + val |= FIELD_PREP(PCI_IDE_LINK_CTL_ID_MASK, i + sel_num); + + pci_write_config_dword(pdev, offset, val); + } } pdev->ide_cap = ide_cap; From patchwork Tue Feb 18 11:09:52 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Kardashevskiy X-Patchwork-Id: 866258 Received: from NAM04-BN8-obe.outbound.protection.outlook.com (mail-bn8nam04on2052.outbound.protection.outlook.com [40.107.100.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D3E4623AE66; Tue, 18 Feb 2025 11:12:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.100.52 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877146; cv=fail; b=t+IuYYcrY1955oAdJT8U+9Li/wLRxfSPTZ1Px/1IqGApePjHvB0jlMlKp1AyU5SJLj6F7pIXXFATMZNnLB1cqfHJfRcP/8Rs1lqFuJsO0SSnMvwexRh4zDOgYs4iN9n4VLWkc7FVVmglVeE3AEjgaVX+2Y1zmrGrOHZBONP4SpY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877146; c=relaxed/simple; bh=HpqxHwRu2ZZbs9lsavtmR++ODcwxzEgj7NfYwMIObLA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=m2S6J6Rr4zNBdxm+Yrg1nYrIMZ/hdIK7pSkjWxY8ntsbWIMkrbd+PGtA1JrmPJe6928kF4c8A16m/KfBVUjF/qcXC+pSVjzx9nribborZ//wKmbtb5ZJcD/JQc49CEQfQKn1BjXRjaW2Q8HLJHX6UgVbHzW5SQXQHcxbwp/lMZ0= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=jGDkGd08; arc=fail smtp.client-ip=40.107.100.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="jGDkGd08" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=fVFNIe4lGByLqZel1ONxi6lS69/1u0KMsLiqAAMp74WN3WmUgBU96dTQqtDy7tlUMY3XCmiBus4l6tOrznPL7HRiH46ozKxv0oYL3Fv9qQLvqjrLTgqEVc1DdVBrvVMyMP6nSBdLRySD+VpGLy1tScKGqiVBCcRkG2iwM71KVcfoDnbesR3d6mu1k1jO0JxUsDPnpZCIKrTavyqZEWHpBVYmXphLNMzZUNMCjirPGtxmA0o1cU1yadBefkO7YGC9vC3W4zl5Ukjl/lDweQMH6zMhU+X4rdkyUXS6JvIvh18mN+lwyGVBzI55jklGLWOigNXZ4eRLWQe6+b7C+smtbw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=ufoxHWke6ItB3sBesXZRtrjbsDVty9Kphlni7y3dSdE=; b=HhCUP3UorEbBgO/KmC9+YY3mBguWemU0zRkhyJpyRppFUaLXKWfPqRK8L7utG4jbflz0xrx+Or1ZOsL7SY7fhVS7P89l7qwZn5nBNkOjEQIsyw+m7ZUxdTv/Gld0jfoVOVVZRbRJyWn39pycexantbkk9XB5HwIpeV2Yc0S1bk/pfot3Z1sX+3fG7057rAJRzdX9AUZsNQ1t1zfVYuY26DOD+NAK4R4/w4y4taZSf0Fq4CrCfGpasHzA5KYn8D9o4WOxgyZLNb8iwyiKr8VJQvzwi1llZxHwcdkbSNA/8O4xCsPkjHo/feHMWKlYdFnMT2eCN0ufTdmQjCts/sFfNA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=ufoxHWke6ItB3sBesXZRtrjbsDVty9Kphlni7y3dSdE=; b=jGDkGd08yF2VBrUMioIPlijxBzuNi8wEKZb4Epa7RPyGeWMtF2lAOG3/YXoECtOIyGySo+/iSTDV68Zw/nS2OpITiTIt+aDMZIsVON93Yx8wKKcCk6TWca18uu7uCJTO1bKi+XkE7/HNdL0NKxH4q2Q/rSkrVWmXqciHofGvass= Received: from BN0PR03CA0038.namprd03.prod.outlook.com (2603:10b6:408:e7::13) by SJ0PR12MB8116.namprd12.prod.outlook.com (2603:10b6:a03:4ec::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8445.16; Tue, 18 Feb 2025 11:12:20 +0000 Received: from BN3PEPF0000B076.namprd04.prod.outlook.com (2603:10b6:408:e7:cafe::ce) by BN0PR03CA0038.outlook.office365.com (2603:10b6:408:e7::13) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8445.19 via Frontend Transport; Tue, 18 Feb 2025 11:12:19 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by BN3PEPF0000B076.mail.protection.outlook.com (10.167.243.121) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8466.11 via Frontend Transport; Tue, 18 Feb 2025 11:12:19 +0000 Received: from aiemdee.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Tue, 18 Feb 2025 05:12:11 -0600 From: Alexey Kardashevskiy To: CC: , , , , "Sean Christopherson" , Paolo Bonzini , "Tom Lendacky" , Ashish Kalra , Joerg Roedel , Suravee Suthikulpanit , Robin Murphy , "Jason Gunthorpe" , Kevin Tian , Bjorn Helgaas , Dan Williams , "Christoph Hellwig" , Nikunj A Dadhania , Michael Roth , Vasant Hegde , Joao Martins , Nicolin Chen , Lu Baolu , Steve Sistare , "Lukas Wunner" , Jonathan Cameron , Suzuki K Poulose , Dionna Glaze , Yi Liu , , , Zhi Wang , AXu Yilun , "Aneesh Kumar K . V" , Alexey Kardashevskiy Subject: [RFC PATCH v2 05/22] crypto: ccp: Enable SEV-TIO feature in the PSP when supported Date: Tue, 18 Feb 2025 22:09:52 +1100 Message-ID: <20250218111017.491719-6-aik@amd.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250218111017.491719-1-aik@amd.com> References: <20250218111017.491719-1-aik@amd.com> Precedence: bulk X-Mailing-List: linux-crypto@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN3PEPF0000B076:EE_|SJ0PR12MB8116:EE_ X-MS-Office365-Filtering-Correlation-Id: 6f7767ee-2a79-46d1-6a0b-08dd500d1c3a X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|36860700013|7416014|376014|82310400026|1800799024; X-Microsoft-Antispam-Message-Info: +voZlhN+3NRamuW5dTq36QHCiTh83cH+cM0S0tMrVDMrubSB5rSJMXw9eMEsDGEbdwZlc5ryLKVOQ4U1o/Cy1Qa5Z7OQmHm2QY5EfGYQp5MirjwzDD431r2DuwLd4SmCRdwEZ2QrZRbsvbFA5N5FCC+2ifP94CmY2fbKVWPxKqjClXgRxRhdmvEi+DQmEq5dLDl5UKhIBxgZmIaeaWP9pY7yF75kiWFBtm1Pd3/83uVp/PT29E+hlOUevYRf7CCsRpjqEKcJP4JFpMVzuUAlDg5YxkfqGWpITPiGNoF8RA7UuLQzA9fP6YmUlOytR3nKIecPS8Jr+bHir/zHh5PLfDXZj4m292KV8i2euel87ZY+w1YqfQ9Dju+4M78VQPBUJLT5vFdjSXeeyDxk9sIhRUmgSIooEZfvCaDZQmOAWiLWlArVZxUFzTE9XPIwXoDyR8VnJECj1pMlol/LrOksH3fOTNVrEQjDJOdV3exXdegJi2xmBI7k1mL3OXeh/gc+U0UQkDM7do6wcy31j2KLtzOCva7LW2hQ3oiM/g5O14LZDS7WuMg923fOAx+dT/33CvbHzPQwbPTyUhWR/qachegbrsK9X5w8Za8/WkFZKcd2uCqstDMrtiTH9lGTlP3n/3ymg0fnP8PgW47i11X/gJVApkgbjKAVH6gyM0f3dhgSJY62/xGwKDEZuAm63NgRO3tpNmEWPFFsorVsYGN30Y0dJwz/mvKO15o2lIPLlAftZncJxQZlnct6tMdA6QTZ+ec6awND4jcnjDmat54Pxw7ULOwqLB8XO3l8dP+FfKrXBEu5NzBpNv6ussLFy8r4DE7ocPEwuyQjF6RPesoi19rm0VTpO3hu+1XKroWj/DyubcPMkFCgPiTOxGVu3rxS7Ad6NUxTZdaUV/bjXfDXLxCGdtuHNKf+XsrBB7yWi7uxuKFUs/yIGVwOxTPulpxaMXLvcDw9Y1soobzgVIWCx1vO8/XjNJVPpCq4YTOfsf/Bd4pjpS8ugxsmc30k+iU6oRWgVQB59L2zNjnlzZWrGq2abdYyHb5BClWTnrB/pohOjpELiDwseCyaGb58B7I8+QBJzrAe0c1QxqYbeLVErq5ErtX/lyz9/s0VVyrGztLfQz2R08363hOZ30vqh7baIPRtMuBa3hGZgXiULnC9TgxEJpINdw5N5uYbM/ojEOsLQ1Mr9iFwp89285Ty2uApovxnivpfwPELYGaDknWypUtkyGAtI8t82jkXtL8Lh6r0KusayY2gZEBeRHvQMuM5jHoXErTMzrtp+Iy6OWgFUA2TWkoYI116QQ9qfEHZK6mTSecPDRH3w0PDCNulDh4aWZa3UDkimld707iEjPm40pJNVilwCpyy7bsbG1da0NS5uC9UYdF90rTiehTBj+yyR7XFNiql1ZXboWaNYDqVugCt65fSLfwuxU2V4dBip3eWrWZBbwR7ldqVZMVhFWQEKt4HVPdz7jGSnFysQzIM448s800CRBJ1kGvrt6DIdCY= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(36860700013)(7416014)(376014)(82310400026)(1800799024); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Feb 2025 11:12:19.4396 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 6f7767ee-2a79-46d1-6a0b-08dd500d1c3a X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN3PEPF0000B076.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ0PR12MB8116 The PSP advertises the SEV-TIO support via the FEATURE_INFO command support of which is advertised via SNP_PLATFORM_STATUS. Add FEATURE_INFO and use it to detect the TIO support in the PSP. If present, enable TIO in the SNP_INIT_EX call. While at this, add new bits to sev_data_snp_init_ex() from SEV-SNP 1.55. Note that this tests the PSP firmware support but not if the feature is enabled in the BIOS. While at this, add new sev_data_snp_shutdown_ex::x86_snp_shutdown Signed-off-by: Alexey Kardashevskiy --- drivers/crypto/ccp/sev-dev.h | 1 + include/linux/psp-sev.h | 32 +++++++- include/uapi/linux/psp-sev.h | 4 +- drivers/crypto/ccp/sev-dev.c | 84 +++++++++++++++++++- 4 files changed, 115 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/ccp/sev-dev.h b/drivers/crypto/ccp/sev-dev.h index d382a265350b..c87a312f7da6 100644 --- a/drivers/crypto/ccp/sev-dev.h +++ b/drivers/crypto/ccp/sev-dev.h @@ -71,6 +71,7 @@ struct sev_device { struct fw_upload *fwl; bool fw_cancel; #endif /* CONFIG_FW_UPLOAD */ + bool tio_en; }; bool sev_version_greater_or_equal(u8 maj, u8 min); diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h index 788505d46d25..103d9c161f41 100644 --- a/include/linux/psp-sev.h +++ b/include/linux/psp-sev.h @@ -107,6 +107,7 @@ enum sev_cmd { SEV_CMD_SNP_DOWNLOAD_FIRMWARE_EX = 0x0CA, SEV_CMD_SNP_COMMIT = 0x0CB, SEV_CMD_SNP_VLEK_LOAD = 0x0CD, + SEV_CMD_SNP_FEATURE_INFO = 0x0CE, SEV_CMD_MAX, }; @@ -146,6 +147,7 @@ struct sev_data_init_ex { } __packed; #define SEV_INIT_FLAGS_SEV_ES 0x01 +#define SEV_INIT_FLAGS_SEV_TIO_EN BIT(2) /** * struct sev_data_pek_csr - PEK_CSR command parameters @@ -601,6 +603,25 @@ struct sev_data_snp_addr { u64 address; /* In/Out */ } __packed; +/** + * struct sev_data_snp_feature_info - SEV_CMD_SNP_FEATURE_INFO command params + * + * @len: length of this struct + * @ecx_in: subfunction index of CPUID Fn8000_0024 + * @feature_info_paddr: physical address of a page with sev_snp_feature_info + */ +#define SNP_FEATURE_FN8000_0024_EBX_X00_SEVTIO 1 + +struct sev_snp_feature_info { + u32 eax, ebx, ecx, edx; /* Out */ +} __packed; + +struct sev_data_snp_feature_info { + u32 length; /* In */ + u32 ecx_in; /* In */ + u64 feature_info_paddr; /* In */ +} __packed; + /** * struct sev_data_snp_launch_start - SNP_LAUNCH_START command params * @@ -762,10 +783,14 @@ struct sev_data_snp_guest_request { struct sev_data_snp_init_ex { u32 init_rmp:1; u32 list_paddr_en:1; - u32 rsvd:30; + u32 rapl_dis:1; + u32 ciphertext_hiding_en:1; + u32 tio_en:1; + u32 rsvd:27; u32 rsvd1; u64 list_paddr; - u8 rsvd2[48]; + u16 max_snp_asid; + u8 rsvd2[46]; } __packed; /** @@ -804,7 +829,8 @@ struct sev_data_range_list { struct sev_data_snp_shutdown_ex { u32 len; u32 iommu_snp_shutdown:1; - u32 rsvd1:31; + u32 x86_snp_shutdown:1; + u32 rsvd1:30; } __packed; /** diff --git a/include/uapi/linux/psp-sev.h b/include/uapi/linux/psp-sev.h index b508b355a72e..affa65dcebd4 100644 --- a/include/uapi/linux/psp-sev.h +++ b/include/uapi/linux/psp-sev.h @@ -189,6 +189,7 @@ struct sev_user_data_get_id2 { * @mask_chip_id: whether chip id is present in attestation reports or not * @mask_chip_key: whether attestation reports are signed or not * @vlek_en: VLEK (Version Loaded Endorsement Key) hashstick is loaded + * @feature_info: Indicates that the SNP_FEATURE_INFO command is available * @rsvd1: reserved * @guest_count: the number of guest currently managed by the firmware * @current_tcb_version: current TCB version @@ -204,7 +205,8 @@ struct sev_user_data_snp_status { __u32 mask_chip_id:1; /* Out */ __u32 mask_chip_key:1; /* Out */ __u32 vlek_en:1; /* Out */ - __u32 rsvd1:29; + __u32 feature_info:1; /* Out */ + __u32 rsvd1:28; __u32 guest_count; /* Out */ __u64 current_tcb_version; /* Out */ __u64 reported_tcb_version; /* Out */ diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 7c9e6ca33bd2..b01e5f913727 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -74,6 +74,10 @@ static bool psp_init_on_probe = true; module_param(psp_init_on_probe, bool, 0444); MODULE_PARM_DESC(psp_init_on_probe, " if true, the PSP will be initialized on module init. Else the PSP will be initialized on the first command requiring it"); +/* enable/disable SEV-TIO support */ +static bool sev_tio_enabled = true; +module_param_named(sev_tio, sev_tio_enabled, bool, 0444); + MODULE_FIRMWARE("amd/amd_sev_fam17h_model0xh.sbin"); /* 1st gen EPYC */ MODULE_FIRMWARE("amd/amd_sev_fam17h_model3xh.sbin"); /* 2nd gen EPYC */ MODULE_FIRMWARE("amd/amd_sev_fam19h_model0xh.sbin"); /* 3rd gen EPYC */ @@ -228,6 +232,7 @@ static int sev_cmd_buffer_len(int cmd) case SEV_CMD_SNP_GUEST_REQUEST: return sizeof(struct sev_data_snp_guest_request); case SEV_CMD_SNP_CONFIG: return sizeof(struct sev_user_data_snp_config); case SEV_CMD_SNP_COMMIT: return sizeof(struct sev_data_snp_commit); + case SEV_CMD_SNP_FEATURE_INFO: return sizeof(struct sev_data_snp_feature_info); case SEV_CMD_SNP_DOWNLOAD_FIRMWARE_EX: return sizeof(struct sev_data_download_firmware_ex); default: return 0; } @@ -1055,7 +1060,7 @@ static int __sev_init_ex_locked(int *error) */ data.tmr_address = __pa(sev_es_tmr); - data.flags |= SEV_INIT_FLAGS_SEV_ES; + data.flags |= SEV_INIT_FLAGS_SEV_ES | SEV_INIT_FLAGS_SEV_TIO_EN; data.tmr_len = sev_es_tmr_size; } @@ -1226,6 +1231,77 @@ int sev_snp_guest_decommission(int asid, int *psp_ret) } EXPORT_SYMBOL_GPL(sev_snp_guest_decommission); +static int snp_feature_info_locked(struct sev_device *sev, u32 ecx, + struct sev_snp_feature_info *fi, int *psp_ret) +{ + struct sev_data_snp_feature_info buf = { + .length = sizeof(buf), + .ecx_in = ecx, + }; + struct page *status_page; + void *data; + int ret; + + status_page = alloc_page(GFP_KERNEL_ACCOUNT); + if (!status_page) + return -ENOMEM; + + data = page_address(status_page); + + if (sev->snp_initialized && rmp_mark_pages_firmware(__pa(data), 1, true)) { + ret = -EFAULT; + goto cleanup; + } + + buf.feature_info_paddr = __psp_pa(data); + ret = __sev_do_cmd_locked(SEV_CMD_SNP_FEATURE_INFO, &buf, psp_ret); + + if (sev->snp_initialized && snp_reclaim_pages(__pa(data), 1, true)) + ret = -EFAULT; + + if (!ret) + memcpy(fi, data, sizeof(*fi)); + +cleanup: + __free_pages(status_page, 0); + return ret; +} + +static int snp_get_feature_info(struct sev_device *sev, u32 ecx, struct sev_snp_feature_info *fi) +{ + struct sev_user_data_snp_status status = { 0 }; + int psp_ret = 0, ret; + + ret = snp_platform_status_locked(sev, &status, &psp_ret); + if (ret) + return ret; + if (ret != SEV_RET_SUCCESS) + return -EFAULT; + if (!status.feature_info) + return -ENOENT; + + ret = snp_feature_info_locked(sev, ecx, fi, &psp_ret); + if (ret) + return ret; + if (ret != SEV_RET_SUCCESS) + return -EFAULT; + + return 0; +} + +static bool sev_tio_present(struct sev_device *sev) +{ + struct sev_snp_feature_info fi = { 0 }; + bool present; + + if (snp_get_feature_info(sev, 0, &fi)) + return false; + + present = (fi.ebx & SNP_FEATURE_FN8000_0024_EBX_X00_SEVTIO) != 0; + dev_info(sev->dev, "SEV-TIO support is %s\n", present ? "present" : "not present"); + return present; +} + static int __sev_snp_init_locked(int *error) { struct psp_device *psp = psp_master; @@ -1290,6 +1366,8 @@ static int __sev_snp_init_locked(int *error) data.init_rmp = 1; data.list_paddr_en = 1; data.list_paddr = __psp_pa(snp_range_list); + data.tio_en = sev_tio_enabled && sev_tio_present(sev) && + amd_iommu_sev_tio_supported(); cmd = SEV_CMD_SNP_INIT_EX; } else { cmd = SEV_CMD_SNP_INIT; @@ -1319,7 +1397,9 @@ static int __sev_snp_init_locked(int *error) return rc; sev->snp_initialized = true; - dev_dbg(sev->dev, "SEV-SNP firmware initialized\n"); + sev->tio_en = data.tio_en; + dev_dbg(sev->dev, "SEV-SNP firmware initialized, SEV-TIO is %s\n", + sev->tio_en ? "enabled" : "disabled"); sev_es_tmr_size = SNP_TMR_SIZE; From patchwork Tue Feb 18 11:09:54 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alexey Kardashevskiy X-Patchwork-Id: 866257 Received: from NAM10-DM6-obe.outbound.protection.outlook.com (mail-dm6nam10on2082.outbound.protection.outlook.com [40.107.93.82]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C8F5A1A841C; Tue, 18 Feb 2025 11:13:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.93.82 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877189; cv=fail; b=huXaw5Zny2k63Tk7d/3nIarFgd9LmZgJ4PHL6xTxA4Q4E39FYYOIlj5pihBLxkd4R8EbHVcqOfJZFLZfBb6Nw4Zhz8JEn+G9M9a/Sh8UngjITDBxf+It/n1BINelnui1xnZgXNtKKmUl+jVb3t5InJZaWtkJm5v13+FPWi2OM70= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877189; c=relaxed/simple; bh=dYwuna3CkaI41eDgHHae4ltKWnjQQofcnsHfPAhTyDE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=duNDXF9ARBa5yveLDz3j2KZce+z2JPNFDDPX6362dH2pO00Rmn6YHTh7SuAHnt25Rs1X5an9aNE/5/f6cKkZRUjMkoJ6CSBpJMga0zVzkCAJNJLPMklU8+XmIaB17ZZ6OtbDG0y5Rdd1wmBDYOoF2QU/TCyLFGS6G9sd7/kssTw= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=UbfNnBcz; arc=fail smtp.client-ip=40.107.93.82 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="UbfNnBcz" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Pgpmf7YHMWF3UzWl1RtiADiIWPEunkUrWJ/o0nQowm1OYdP+v4OT347CfnKLUVMO5JyZim82D1drgii8vLg74BN3t+0CIuyLnkVjSRmmzT7wDtcuZ9vctEeYhKJ70nTzTfjUKvZGcjPwKUk5t9OGOh69S241ir2z6vSAuN+36IIVtRDKb8xMOOpBY7HT48wAF4W8yUFy9T6O2SxDJkW1rW4oYmCnLVMvacb4c8bxTVya0Ynk7B5g2h4xMRBpINCMPS7ocrblbmn3PhRy1+PwoknaTQH6XyFgXC3QxM3ZJBLWg9YLdqI3ChTSUeNccmcDboMIp62dcbLoS/D1Pw2f7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=YilQZM0RM9NQ00juV85NjA4o6LW+K9saVXHKI+fQc9Q=; b=E0glWxR8c2O2oJm3+ak9IXoZL7+OtrM2lPZFQPKS4PlcDSQUMa5CmxvLciS7g/vEydwCSkY0/x4m/8WUP2p/ViJAdg7e9xIivVUzAt+GlzjRDgd2tuJEWS2KleKfOVoe+EFDg0UA7oP3Cjt+0TFoffztdc8glASUoVgPKXX2jxmNNr0usvEpPluK6P5q+sWSPH/vNGd63/JKuw/enff4ALCotdtteGdECykss89P6rDfiOS/qskq+BaOr0vqCuel+LE4RBLmkXo3IRK1kFdrjbLKpQZMx1tJxDlw6LqRljIdhfeNyr1InE9Y2i8KaOX8eDWL5oPAPr5yvGwzz3PMBQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=YilQZM0RM9NQ00juV85NjA4o6LW+K9saVXHKI+fQc9Q=; b=UbfNnBczdcZP6ol5mVT9fZijeSEGxJt9kwwM0ptcVumczwAiBQ4iYyfu9EcMUjw7ltBbjUapXH1G0DADF9E2rIQj+/YS1PiozWKVPEfM0atczYkf+Gh372ufJ0mTx396yXaal08c3oGXhdOC5UYfa9SKgLw1jTtS+0OVS8K/SBg= Received: from BN9PR03CA0619.namprd03.prod.outlook.com (2603:10b6:408:106::24) by MN0PR12MB5810.namprd12.prod.outlook.com (2603:10b6:208:376::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8466.14; Tue, 18 Feb 2025 11:13:00 +0000 Received: from BN3PEPF0000B075.namprd04.prod.outlook.com (2603:10b6:408:106:cafe::9b) by BN9PR03CA0619.outlook.office365.com (2603:10b6:408:106::24) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8445.19 via Frontend Transport; Tue, 18 Feb 2025 11:13:00 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by BN3PEPF0000B075.mail.protection.outlook.com (10.167.243.120) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8466.11 via Frontend Transport; Tue, 18 Feb 2025 11:13:00 +0000 Received: from aiemdee.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Tue, 18 Feb 2025 05:12:52 -0600 From: Alexey Kardashevskiy To: CC: , , , , "Sean Christopherson" , Paolo Bonzini , "Tom Lendacky" , Ashish Kalra , Joerg Roedel , Suravee Suthikulpanit , Robin Murphy , "Jason Gunthorpe" , Kevin Tian , Bjorn Helgaas , Dan Williams , "Christoph Hellwig" , Nikunj A Dadhania , Michael Roth , Vasant Hegde , Joao Martins , Nicolin Chen , Lu Baolu , Steve Sistare , "Lukas Wunner" , Jonathan Cameron , Suzuki K Poulose , Dionna Glaze , Yi Liu , , , Zhi Wang , AXu Yilun , "Aneesh Kumar K . V" , Alexey Kardashevskiy Subject: [RFC PATCH v2 07/22] coco/tsm: Add tsm and tsm-host modules Date: Tue, 18 Feb 2025 22:09:54 +1100 Message-ID: <20250218111017.491719-8-aik@amd.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250218111017.491719-1-aik@amd.com> References: <20250218111017.491719-1-aik@amd.com> Precedence: bulk X-Mailing-List: linux-crypto@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN3PEPF0000B075:EE_|MN0PR12MB5810:EE_ X-MS-Office365-Filtering-Correlation-Id: ae546d0a-706b-4108-3eb7-08dd500d34b9 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|1800799024|376014|7416014|82310400026|36860700013; X-Microsoft-Antispam-Message-Info: =?utf-8?q?2Q7VShcXz6YCN2ZDWMr9+m9jCZezZlX?= =?utf-8?q?/DFO4qSlySgTLVZtlXZkrrj04d3TvoZsqy/GZxTGJWSim1FE1Ev+UElf7mOyx9QSE?= =?utf-8?q?uk9L7ijvH/cMuxvXJN3VgNByyAdpqET49HNr7U2eqD/ywsgDRzJqlcESmEH65SXSI?= =?utf-8?q?0zMbifGTBxyseAThBZ2vE4GWhwySKBYFcL0tiuEPSu2rjLwHArPtgkMVgrVaup8c4?= =?utf-8?q?k20ec3mXxg0gI/o3bak1EZ7+htwxsuqOTRbwldAcT4vV9rAwBPmUgrwUow21gBGfh?= =?utf-8?q?OjyTiXlG9/t561YPXt1XHkW4p6XWgEPYKzFWopSsTajE9yMgxPZZh/KHaFc0JJzg6?= =?utf-8?q?sQqmSoDRiA7dKQXC2jkUuulZluvXh3+YnqYzB874CIB5DxwiBcVWGFnCEJ7a0kfCY?= =?utf-8?q?AYJlXGvtu7zZXrcmgIHyKC9OJhg5PJtIPHY4AhPklL/tQX07zo97APbHPge124l0W?= =?utf-8?q?uIaP9sXpbxg02smi0gsGT92ZKqGwRJasNbXuKrUeGHSY5nZdmdZG1E6A8LyqOuNFD?= =?utf-8?q?JX4NKXsBTz2+LalDach3v1cbYVzvAB/iS0uEWAd8CEisIOXak28wAQXhPBBEISZr3?= =?utf-8?q?chvvsWOYefx+re2T6GxRq//Dls4uVl0wQXpFmUflc1hy0h8ZlCVWXrHry2Jo+FZzz?= =?utf-8?q?shNIJf4yGbI6PuaKzLCVzkNjUWV6GxGL1jZ1oXd7pIiCq0Y/a6rhhqZpWTaqVhIN1?= =?utf-8?q?47jsyMqY6qofIUTSX6R9PvuROr68b7AsmKDO9z9GJGjaXyxayWamOPsWG48eo3n1y?= =?utf-8?q?4uBffpqpCOUsHqmTivBKjb+usqWkFv9eBVdDujQhSvPiZ4wkGSRsRJj1CKkijkyNs?= =?utf-8?q?7pXbvN52KQGCmBf9WpqIZI4uL4AP/rxoddPNoXok0/s8RR5wyFWIAT10ZIWKYzWw8?= =?utf-8?q?spf6tvZZeDStNBFIbzwlGL771mHOrUc7J+Ic5qx6rtTRL1uqAxI2DRTpjS3yOEuAj?= =?utf-8?q?aB/NTpMJYQck3Fi03k1hT8bXsoZp8cS9OWM/lt/nsXXeykv5o3kqDdmnG3dgPh+f1?= =?utf-8?q?WcGfLUlYLOcDD1Kb0xNE9bGm73Hug2Zu4TU1zA+71ZSLQN+nnbeQP06a02s2x42q9?= =?utf-8?q?OgrdWROCWs0qNchZ73c2Zrk92z/NE2sfShV4zCXWFsWIf3mD8Yeh9I/Je1zwg6sO/?= =?utf-8?q?huE3rTwS1mZpOBhd1IsZG7U7rCPUTr0SmxdhF9a+OT5owMugLJ4iLRwEUhJwhdCm8?= =?utf-8?q?hmqBJ0TB/Zk87WGyeWwMQ2RJWgLvHnZG8/H82pdv0ZdxSJXnHlwfFeUfzl6NaRSj9?= =?utf-8?q?QdZesCS5Ifws5rLHZmS+VjIbkGcpAM/8JFbk40TWIcDF6+klyQxQ9NvD+wKiRdbx8?= =?utf-8?q?OpVIBm0nrgC52GrE93KsyTdj8GKrfShCsMAhg4ZZ5XdyqevZb9VkQAurYu2x8U9Q1?= =?utf-8?q?H91CDiF+u0hg76U5V1sw8YNOutyR7XoAVpVqs10MVzUC/dCkqJ0FG8=3D?= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(1800799024)(376014)(7416014)(82310400026)(36860700013); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Feb 2025 11:13:00.5362 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: ae546d0a-706b-4108-3eb7-08dd500d34b9 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN3PEPF0000B075.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN0PR12MB5810 The TSM module is a library to create sysfs nodes common for hypervisors and VMs. It also provides helpers to parse interface reports (required by VMs, visible to HVs). It registers 3 device classes: - tsm: one per platform, - tsm-dev: for physical functions, ("TDEV"); - tdm-tdi: for PCI functions being assigned to VMs ("TDI"). The library adds a child device of "tsm-dev" or/and "tsm-tdi" class for every capable PCI device. Note that the module is made bus-agnostic. New device nodes provide sysfs interface for fetching device certificates and measurements and TDI interface reports. Nodes with the "_user" suffix provide human-readable information, without that suffix it is raw binary data to be copied to a guest. The TSM-HOST module adds hypervisor-only functionality on top. At the moment it is: - "connect" to enable/disable IDE (a PCI link encryption); - "TDI bind" to manage a PCI function passed through to a secure VM. A platform is expected to register itself in TSM-HOST and provide necessary callbacks. No platform is added here, AMD SEV is coming in the next patches. Signed-off-by: Alexey Kardashevskiy --- drivers/virt/coco/Makefile | 2 + drivers/virt/coco/host/Makefile | 6 + include/linux/tsm.h | 295 +++++++++ drivers/virt/coco/host/tsm-host.c | 552 +++++++++++++++++ drivers/virt/coco/tsm.c | 636 ++++++++++++++++++++ Documentation/virt/coco/tsm.rst | 99 +++ drivers/virt/coco/Kconfig | 14 + drivers/virt/coco/host/Kconfig | 6 + 8 files changed, 1610 insertions(+) diff --git a/drivers/virt/coco/Makefile b/drivers/virt/coco/Makefile index 885c9ef4e9fc..670f77c564e8 100644 --- a/drivers/virt/coco/Makefile +++ b/drivers/virt/coco/Makefile @@ -2,9 +2,11 @@ # # Confidential computing related collateral # +obj-$(CONFIG_TSM) += tsm.o obj-$(CONFIG_EFI_SECRET) += efi_secret/ obj-$(CONFIG_ARM_PKVM_GUEST) += pkvm-guest/ obj-$(CONFIG_SEV_GUEST) += sev-guest/ obj-$(CONFIG_INTEL_TDX_GUEST) += tdx-guest/ obj-$(CONFIG_ARM_CCA_GUEST) += arm-cca-guest/ obj-$(CONFIG_TSM_REPORTS) += guest/ +obj-$(CONFIG_TSM_HOST) += host/ diff --git a/drivers/virt/coco/host/Makefile b/drivers/virt/coco/host/Makefile new file mode 100644 index 000000000000..c5e216b6cb1c --- /dev/null +++ b/drivers/virt/coco/host/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# TSM (TEE Security Manager) Common infrastructure and host drivers + +obj-$(CONFIG_TSM_HOST) += tsm_host.o +tsm_host-y += tsm-host.o diff --git a/include/linux/tsm.h b/include/linux/tsm.h index 431054810dca..486e386d90fc 100644 --- a/include/linux/tsm.h +++ b/include/linux/tsm.h @@ -5,6 +5,11 @@ #include #include #include +#include +#include +#include +#include +#include #define TSM_REPORT_INBLOB_MAX 64 #define TSM_REPORT_OUTBLOB_MAX SZ_32K @@ -109,4 +114,294 @@ struct tsm_report_ops { int tsm_report_register(const struct tsm_report_ops *ops, void *priv); int tsm_report_unregister(const struct tsm_report_ops *ops); + +/* SPDM control structure for DOE */ +struct tsm_spdm { + unsigned long req_len; + void *req; + unsigned long rsp_len; + void *rsp; +}; + +/* Data object for measurements/certificates/attestationreport */ +struct tsm_blob { + void *data; + size_t len; +}; + +struct tsm_blob *tsm_blob_new(void *data, size_t len); +static inline void tsm_blob_free(struct tsm_blob *b) +{ + kfree(b); +} + +/** + * struct tdisp_interface_id - TDISP INTERFACE_ID Definition + * + * @function_id: Identifies the function of the device hosting the TDI + * 15:0: @rid: Requester ID + * 23:16: @rseg: Requester Segment (Reserved if Requester Segment Valid is Clear) + * 24: @rseg_valid: Requester Segment Valid + * 31:25 – Reserved + * 8B - Reserved + */ +struct tdisp_interface_id { + u32 function_id; /* TSM_TDISP_IID_xxxx */ + u8 reserved[8]; +} __packed; + +#define TSM_TDISP_IID_REQUESTER_ID GENMASK(15, 0) +#define TSM_TDISP_IID_RSEG GENMASK(23, 16) +#define TSM_TDISP_IID_RSEG_VALID BIT(24) + +/* + * Measurement block as defined in SPDM DSP0274. + */ +struct spdm_measurement_block_header { + u8 index; + u8 spec; /* MeasurementSpecification */ + u16 size; +} __packed; + +struct dmtf_measurement_block_header { + u8 type; /* DMTFSpecMeasurementValueType */ + u16 size; /* DMTFSpecMeasurementValueSize */ +} __packed; + +struct dmtf_measurement_block_device_mode { + u32 opmode_cap; /* OperationalModeCapabilties */ + u32 opmode_sta; /* OperationalModeState */ + u32 devmode_cap; /* DeviceModeCapabilties */ + u32 devmode_sta; /* DeviceModeState */ +} __packed; + +struct spdm_certchain_block_header { + u16 length; + u16 reserved; +} __packed; + +/* + * TDI Report Structure as defined in TDISP. + */ +struct tdi_report_header { + u16 interface_info; /* TSM_TDI_REPORT_xxx */ + u16 reserved2; + u16 msi_x_message_control; + u16 lnr_control; + u32 tph_control; + u32 mmio_range_count; +} __packed; + +#define _BITSH(x) (1 << (x)) +#define TSM_TDI_REPORT_NO_FW_UPDATE _BITSH(0) /* not updates in CONFIG_LOCKED or RUN */ +#define TSM_TDI_REPORT_DMA_NO_PASID _BITSH(1) /* TDI generates DMA requests without PASID */ +#define TSM_TDI_REPORT_DMA_PASID _BITSH(2) /* TDI generates DMA requests with PASID */ +#define TSM_TDI_REPORT_ATS _BITSH(3) /* ATS supported and enabled for the TDI */ +#define TSM_TDI_REPORT_PRS _BITSH(4) /* PRS supported and enabled for the TDI */ + +/* + * Each MMIO Range of the TDI is reported with the MMIO reporting offset added. + * Base and size in units of 4K pages + */ +struct tdi_report_mmio_range { + u64 first_page; /* First 4K page with offset added */ + u32 num; /* Number of 4K pages in this range */ + u32 range_attributes; /* TSM_TDI_REPORT_MMIO_xxx */ +} __packed; + +#define TSM_TDI_REPORT_MMIO_MSIX_TABLE BIT(0) +#define TSM_TDI_REPORT_MMIO_PBA BIT(1) +#define TSM_TDI_REPORT_MMIO_IS_NON_TEE BIT(2) +#define TSM_TDI_REPORT_MMIO_IS_UPDATABLE BIT(3) +#define TSM_TDI_REPORT_MMIO_RESERVED GENMASK(15, 4) +#define TSM_TDI_REPORT_MMIO_RANGE_ID GENMASK(31, 16) + +struct tdi_report_footer { + u32 device_specific_info_len; + u8 device_specific_info[]; +} __packed; + +#define TDI_REPORT_HDR(rep) ((struct tdi_report_header *) ((rep)->data)) +#define TDI_REPORT_MR_NUM(rep) (TDI_REPORT_HDR(rep)->mmio_range_count) +#define TDI_REPORT_MR_OFF(rep) ((struct tdi_report_mmio_range *) (TDI_REPORT_HDR(rep) + 1)) +#define TDI_REPORT_MR(rep, rangeid) TDI_REPORT_MR_OFF(rep)[rangeid] +#define TDI_REPORT_FTR(rep) ((struct tdi_report_footer *) &TDI_REPORT_MR((rep), \ + TDI_REPORT_MR_NUM(rep))) + +struct tsm_bus_ops; + +/* Physical device descriptor responsible for IDE/TDISP setup */ +struct tsm_dev { + const struct attribute_group *ag; + struct device *physdev; /* Physical PCI function #0 */ + struct device dev; /* A child device of PCI function #0 */ + struct tsm_spdm spdm; + struct mutex spdm_mutex; + + u8 cert_slot; + u8 connected; + unsigned int bound; + + struct tsm_blob *meas; + struct tsm_blob *certs; +#define TSM_MAX_NONCE_LEN 64 + u8 nonce[TSM_MAX_NONCE_LEN]; + size_t nonce_len; + + void *data; /* Platform specific data */ + + struct tsm_subsys *tsm; + struct tsm_bus_subsys *tsm_bus; + /* Bus specific data follow this struct, see tsm_dev_to_bdata */ +}; + +#define tsm_dev_to_bdata(tdev) ((tdev)?((void *)&(tdev)[1]):NULL) + +/* PCI function for passing through, can be the same as tsm_dev::pdev */ +struct tsm_tdi { + const struct attribute_group *ag; + struct device dev; /* A child device of PCI VF */ + struct list_head node; + struct tsm_dev *tdev; + + u8 rseg; + u8 rseg_valid; + bool validated; + + struct tsm_blob *report; + + void *data; /* Platform specific data */ + + struct kvm *kvm; + u16 guest_rid; /* BDFn of PCI Fn in the VM (when PCI TDISP) */ +}; + +struct tsm_dev_status { + u8 ctx_state; + u8 tc_mask; + u8 certs_slot; + u16 device_id; + u16 segment_id; + u8 no_fw_update; + u16 ide_stream_id[8]; +}; + +enum tsm_spdm_algos { + TSM_SPDM_ALGOS_DHE_SECP256R1, + TSM_SPDM_ALGOS_DHE_SECP384R1, + TSM_SPDM_ALGOS_AEAD_AES_128_GCM, + TSM_SPDM_ALGOS_AEAD_AES_256_GCM, + TSM_SPDM_ALGOS_ASYM_TPM_ALG_RSASSA_3072, + TSM_SPDM_ALGOS_ASYM_TPM_ALG_ECDSA_ECC_NIST_P256, + TSM_SPDM_ALGOS_ASYM_TPM_ALG_ECDSA_ECC_NIST_P384, + TSM_SPDM_ALGOS_HASH_TPM_ALG_SHA_256, + TSM_SPDM_ALGOS_HASH_TPM_ALG_SHA_384, + TSM_SPDM_ALGOS_KEY_SCHED_SPDM_KEY_SCHEDULE, +}; + +enum tsm_tdisp_state { + TDISP_STATE_CONFIG_UNLOCKED, + TDISP_STATE_CONFIG_LOCKED, + TDISP_STATE_RUN, + TDISP_STATE_ERROR, +}; + +struct tsm_tdi_status { + bool valid; + u8 meas_digest_fresh:1; + u8 meas_digest_valid:1; + u8 all_request_redirect:1; + u8 bind_p2p:1; + u8 lock_msix:1; + u8 no_fw_update:1; + u16 cache_line_size; + u64 spdm_algos; /* Bitmask of TSM_SPDM_ALGOS */ + u8 certs_digest[48]; + u8 meas_digest[48]; + u8 interface_report_digest[48]; + u64 intf_report_counter; + struct tdisp_interface_id id; + enum tsm_tdisp_state state; +}; + +struct tsm_bus_ops { + int (*spdm_forward)(struct tsm_spdm *spdm, u8 type); +}; + +struct tsm_bus_subsys { + struct tsm_bus_ops *ops; + struct notifier_block notifier; + struct tsm_subsys *tsm; +}; + +struct tsm_bus_subsys *pci_tsm_register(struct tsm_subsys *tsm_subsys); +void pci_tsm_unregister(struct tsm_bus_subsys *subsys); + +/* tsm_hv_ops return codes for SPDM bouncing, when requested by the TSM */ +#define TSM_PROTO_CMA_SPDM 1 +#define TSM_PROTO_SECURED_CMA_SPDM 2 + +struct tsm_hv_ops { + int (*dev_connect)(struct tsm_dev *tdev, void *private_data); + int (*dev_disconnect)(struct tsm_dev *tdev); + int (*dev_status)(struct tsm_dev *tdev, struct tsm_dev_status *s); + int (*dev_measurements)(struct tsm_dev *tdev); + int (*tdi_bind)(struct tsm_tdi *tdi, u32 bdfn, u64 vmid); + int (*tdi_unbind)(struct tsm_tdi *tdi); + int (*guest_request)(struct tsm_tdi *tdi, u8 __user *req, size_t reqlen, + u8 __user *rsp, size_t rsplen, int *fw_err); + int (*tdi_status)(struct tsm_tdi *tdi, struct tsm_tdi_status *ts); +}; + +struct tsm_subsys { + struct device dev; + struct list_head tdi_head; + struct mutex lock; + const struct attribute_group *tdev_groups[3]; /* Common, host/guest, NULL */ + const struct attribute_group *tdi_groups[3]; /* Common, host/guest, NULL */ + int (*update_measurements)(struct tsm_dev *tdev); +}; + +struct tsm_subsys *tsm_register(struct device *parent, size_t extra, + const struct attribute_group *tdev_ag, + const struct attribute_group *tdi_ag, + int (*update_measurements)(struct tsm_dev *tdev)); +void tsm_unregister(struct tsm_subsys *subsys); + +struct tsm_host_subsys; +struct tsm_host_subsys *tsm_host_register(struct device *parent, + struct tsm_hv_ops *hvops, + void *private_data); +struct tsm_dev *tsm_dev_get(struct device *dev); +void tsm_dev_put(struct tsm_dev *tdev); +struct tsm_tdi *tsm_tdi_get(struct device *dev); +void tsm_tdi_put(struct tsm_tdi *tdi); + +struct pci_dev; +int pci_dev_tdi_validate(struct pci_dev *pdev, bool invalidate); +int pci_dev_tdi_mmio_config(struct pci_dev *pdev, u32 range_id, bool tee); + +int tsm_dev_init(struct tsm_bus_subsys *tsm_bus, struct device *parent, + size_t busdatalen, struct tsm_dev **ptdev); +void tsm_dev_free(struct tsm_dev *tdev); +int tsm_tdi_init(struct tsm_dev *tdev, struct device *dev); +void tsm_tdi_free(struct tsm_tdi *tdi); + +/* IOMMUFD vIOMMU helpers */ +int tsm_tdi_bind(struct tsm_tdi *tdi, u32 guest_rid, int kvmfd); +void tsm_tdi_unbind(struct tsm_tdi *tdi); +int tsm_guest_request(struct tsm_tdi *tdi, u8 __user *req, size_t reqlen, + u8 __user *res, size_t reslen, int *fw_err); + +/* Debug */ +ssize_t tsm_report_gen(struct tsm_blob *report, char *b, size_t len); + +/* IDE */ +int tsm_create_link(struct tsm_subsys *tsm, struct device *dev, const char *name); +void tsm_remove_link(struct tsm_subsys *tsm, const char *name); +#define tsm_register_ide_stream(tdev, ide) \ + tsm_create_link((tdev)->tsm, &(tdev)->dev, (ide)->name) +#define tsm_unregister_ide_stream(tdev, ide) \ + tsm_remove_link((tdev)->tsm, (ide)->name) + #endif /* __TSM_H */ diff --git a/drivers/virt/coco/host/tsm-host.c b/drivers/virt/coco/host/tsm-host.c new file mode 100644 index 000000000000..80f3315fb195 --- /dev/null +++ b/drivers/virt/coco/host/tsm-host.c @@ -0,0 +1,552 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include + +#define DRIVER_VERSION "0.1" +#define DRIVER_AUTHOR "aik@amd.com" +#define DRIVER_DESC "TSM host library" + +struct tsm_host_subsys { + struct tsm_subsys base; + struct tsm_hv_ops *ops; + void *private_data; +}; + +static int tsm_dev_connect(struct tsm_dev *tdev) +{ + struct tsm_host_subsys *hsubsys = (struct tsm_host_subsys *) tdev->tsm; + int ret; + + if (WARN_ON(!hsubsys->ops->dev_connect)) + return -EPERM; + + if (WARN_ON(!tdev->tsm_bus)) + return -EPERM; + + mutex_lock(&tdev->spdm_mutex); + while (1) { + ret = hsubsys->ops->dev_connect(tdev, hsubsys->private_data); + if (ret <= 0) + break; + + ret = tdev->tsm_bus->ops->spdm_forward(&tdev->spdm, ret); + if (ret < 0) + break; + } + mutex_unlock(&tdev->spdm_mutex); + + tdev->connected = (ret == 0); + + return ret; +} + +static int tsm_dev_reclaim(struct tsm_dev *tdev) +{ + struct tsm_host_subsys *hsubsys = (struct tsm_host_subsys *) tdev->tsm; + int ret; + + if (WARN_ON(!hsubsys->ops->dev_disconnect)) + return -EPERM; + + /* Do not disconnect with active TDIs */ + if (tdev->bound) + return -EBUSY; + + mutex_lock(&tdev->spdm_mutex); + while (1) { + ret = hsubsys->ops->dev_disconnect(tdev); + if (ret <= 0) + break; + + ret = tdev->tsm_bus->ops->spdm_forward(&tdev->spdm, ret); + if (ret < 0) + break; + } + mutex_unlock(&tdev->spdm_mutex); + + if (!ret) + tdev->connected = false; + + return ret; +} + +static int tsm_dev_status(struct tsm_dev *tdev, struct tsm_dev_status *s) +{ + struct tsm_host_subsys *hsubsys = (struct tsm_host_subsys *) tdev->tsm; + + if (WARN_ON(!hsubsys->ops->dev_status)) + return -EPERM; + + return hsubsys->ops->dev_status(tdev, s); +} + +static int tsm_tdi_measurements_locked(struct tsm_dev *tdev) +{ + struct tsm_host_subsys *hsubsys = (struct tsm_host_subsys *) tdev->tsm; + int ret; + + while (1) { + ret = hsubsys->ops->dev_measurements(tdev); + if (ret <= 0) + break; + + ret = tdev->tsm_bus->ops->spdm_forward(&tdev->spdm, ret); + if (ret < 0) + break; + } + + return ret; +} + +static void tsm_tdi_reclaim(struct tsm_tdi *tdi) +{ + struct tsm_dev *tdev = tdi->tdev; + struct tsm_host_subsys *hsubsys = (struct tsm_host_subsys *) tdev->tsm; + int ret; + + if (WARN_ON(!hsubsys->ops->tdi_unbind)) + return; + + mutex_lock(&tdi->tdev->spdm_mutex); + while (1) { + ret = hsubsys->ops->tdi_unbind(tdi); + if (ret <= 0) + break; + + ret = tdi->tdev->tsm_bus->ops->spdm_forward(&tdi->tdev->spdm, ret); + if (ret < 0) + break; + } + mutex_unlock(&tdi->tdev->spdm_mutex); +} + +static int tsm_tdi_status(struct tsm_tdi *tdi, void *private_data, struct tsm_tdi_status *ts) +{ + struct tsm_tdi_status tstmp = { 0 }; + struct tsm_dev *tdev = tdi->tdev; + struct tsm_host_subsys *hsubsys = (struct tsm_host_subsys *) tdev->tsm; + int ret; + + mutex_lock(&tdi->tdev->spdm_mutex); + while (1) { + ret = hsubsys->ops->tdi_status(tdi, &tstmp); + if (ret <= 0) + break; + + ret = tdi->tdev->tsm_bus->ops->spdm_forward(&tdi->tdev->spdm, ret); + if (ret < 0) + break; + } + mutex_unlock(&tdi->tdev->spdm_mutex); + + if (!ret) + *ts = tstmp; + + return ret; +} + +static ssize_t tsm_cert_slot_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct tsm_dev *tdev = container_of(dev, struct tsm_dev, dev); + ssize_t ret = count; + unsigned long val; + + if (kstrtoul(buf, 0, &val) < 0) + ret = -EINVAL; + else + tdev->cert_slot = val; + + return ret; +} + +static ssize_t tsm_cert_slot_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct tsm_dev *tdev = container_of(dev, struct tsm_dev, dev); + ssize_t ret = sysfs_emit(buf, "%u\n", tdev->cert_slot); + + return ret; +} + +static DEVICE_ATTR_RW(tsm_cert_slot); + +static ssize_t tsm_dev_connect_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct tsm_dev *tdev = container_of(dev, struct tsm_dev, dev); + unsigned long val; + ssize_t ret = -EIO; + + if (kstrtoul(buf, 0, &val) < 0) + ret = -EINVAL; + else if (val && !tdev->connected) + ret = tsm_dev_connect(tdev); + else if (!val && tdev->connected) + ret = tsm_dev_reclaim(tdev); + + if (!ret) + ret = count; + + return ret; +} + +static ssize_t tsm_dev_connect_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct tsm_dev *tdev = container_of(dev, struct tsm_dev, dev); + ssize_t ret = sysfs_emit(buf, "%u\n", tdev->connected); + + return ret; +} + +static DEVICE_ATTR_RW(tsm_dev_connect); + +static ssize_t tsm_dev_status_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct tsm_dev *tdev = container_of(dev, struct tsm_dev, dev); + struct tsm_dev_status s = { 0 }; + int ret = tsm_dev_status(tdev, &s); + ssize_t ret1; + + ret1 = sysfs_emit(buf, "ret=%d\n" + "ctx_state=%x\n" + "tc_mask=%x\n" + "certs_slot=%x\n" + "device_id=%x:%x.%d\n" + "segment_id=%x\n" + "no_fw_update=%x\n", + ret, + s.ctx_state, + s.tc_mask, + s.certs_slot, + (s.device_id >> 8) & 0xff, + (s.device_id >> 3) & 0x1f, + s.device_id & 0x07, + s.segment_id, + s.no_fw_update); + + tsm_dev_put(tdev); + return ret1; +} + +static DEVICE_ATTR_RO(tsm_dev_status); + +static struct attribute *host_dev_attrs[] = { + &dev_attr_tsm_cert_slot.attr, + &dev_attr_tsm_dev_connect.attr, + &dev_attr_tsm_dev_status.attr, + NULL, +}; +static const struct attribute_group host_dev_group = { + .attrs = host_dev_attrs, +}; + +static ssize_t tsm_tdi_bind_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct tsm_tdi *tdi = container_of(dev, struct tsm_tdi, dev); + + if (!tdi->kvm) + return sysfs_emit(buf, "not bound\n"); + + return sysfs_emit(buf, "VM=%p BDFn=%x:%x.%d\n", + tdi->kvm, + (tdi->guest_rid >> 8) & 0xff, + (tdi->guest_rid >> 3) & 0x1f, + tdi->guest_rid & 0x07); +} + +static DEVICE_ATTR_RO(tsm_tdi_bind); + +static char *spdm_algos_to_str(u64 algos, char *buf, size_t len) +{ + size_t n = 0; + + buf[0] = 0; +#define __ALGO(x) do { \ + if ((n < len) && (algos & (1ULL << (TSM_TDI_SPDM_ALGOS_##x)))) \ + n += snprintf(buf + n, len - n, #x" "); \ + } while (0) + + __ALGO(DHE_SECP256R1); + __ALGO(DHE_SECP384R1); + __ALGO(AEAD_AES_128_GCM); + __ALGO(AEAD_AES_256_GCM); + __ALGO(ASYM_TPM_ALG_RSASSA_3072); + __ALGO(ASYM_TPM_ALG_ECDSA_ECC_NIST_P256); + __ALGO(ASYM_TPM_ALG_ECDSA_ECC_NIST_P384); + __ALGO(HASH_TPM_ALG_SHA_256); + __ALGO(HASH_TPM_ALG_SHA_384); + __ALGO(KEY_SCHED_SPDM_KEY_SCHEDULE); +#undef __ALGO + return buf; +} + +static const char *tdisp_state_to_str(enum tsm_tdisp_state state) +{ + switch (state) { +#define __ST(x) case TDISP_STATE_##x: return #x + case TDISP_STATE_UNAVAIL: return "TDISP state unavailable"; + __ST(CONFIG_UNLOCKED); + __ST(CONFIG_LOCKED); + __ST(RUN); + __ST(ERROR); +#undef __ST + default: return "unknown"; + } +} + +static ssize_t tsm_tdi_status_user_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tsm_tdi *tdi = container_of(dev, struct tsm_tdi, dev); + struct tsm_dev *tdev = tdi->tdev; + struct tsm_host_subsys *hsubsys = (struct tsm_host_subsys *) tdev->tsm; + struct tsm_tdi_status ts = { 0 }; + char algos[256] = ""; + unsigned int n, m; + int ret; + + ret = tsm_tdi_status(tdi, hsubsys->private_data, &ts); + if (ret < 0) + return sysfs_emit(buf, "ret=%d\n\n", ret); + + if (!ts.valid) + return sysfs_emit(buf, "ret=%d\nstate=%d:%s\n", + ret, ts.state, tdisp_state_to_str(ts.state)); + + n = snprintf(buf, PAGE_SIZE, + "ret=%d\n" + "state=%d:%s\n" + "meas_digest_fresh=%x\n" + "meas_digest_valid=%x\n" + "all_request_redirect=%x\n" + "bind_p2p=%x\n" + "lock_msix=%x\n" + "no_fw_update=%x\n" + "cache_line_size=%d\n" + "algos=%#llx:%s\n" + "report_counter=%lld\n" + , + ret, + ts.state, tdisp_state_to_str(ts.state), + ts.meas_digest_fresh, + ts.meas_digest_valid, + ts.all_request_redirect, + ts.bind_p2p, + ts.lock_msix, + ts.no_fw_update, + ts.cache_line_size, + ts.spdm_algos, spdm_algos_to_str(ts.spdm_algos, algos, sizeof(algos) - 1), + ts.intf_report_counter); + + n += snprintf(buf + n, PAGE_SIZE - n, "Certs digest: "); + m = hex_dump_to_buffer(ts.certs_digest, sizeof(ts.certs_digest), 32, 1, + buf + n, PAGE_SIZE - n, false); + n += min(PAGE_SIZE - n, m); + n += snprintf(buf + n, PAGE_SIZE - n, "...\nMeasurements digest: "); + m = hex_dump_to_buffer(ts.meas_digest, sizeof(ts.meas_digest), 32, 1, + buf + n, PAGE_SIZE - n, false); + n += min(PAGE_SIZE - n, m); + n += snprintf(buf + n, PAGE_SIZE - n, "...\nInterface report digest: "); + m = hex_dump_to_buffer(ts.interface_report_digest, sizeof(ts.interface_report_digest), + 32, 1, buf + n, PAGE_SIZE - n, false); + n += min(PAGE_SIZE - n, m); + n += snprintf(buf + n, PAGE_SIZE - n, "...\n"); + + return n; +} + +static DEVICE_ATTR_RO(tsm_tdi_status_user); + +static ssize_t tsm_tdi_status_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct tsm_tdi *tdi = container_of(dev, struct tsm_tdi, dev); + struct tsm_dev *tdev = tdi->tdev; + struct tsm_host_subsys *hsubsys = (struct tsm_host_subsys *) tdev->tsm; + struct tsm_tdi_status ts = { 0 }; + u8 state; + int ret; + + ret = tsm_tdi_status(tdi, hsubsys->private_data, &ts); + if (ret) + return ret; + + state = ts.state; + memcpy(buf, &state, sizeof(state)); + + return sizeof(state); +} + +static DEVICE_ATTR_RO(tsm_tdi_status); + +static struct attribute *host_tdi_attrs[] = { + &dev_attr_tsm_tdi_bind.attr, + &dev_attr_tsm_tdi_status_user.attr, + &dev_attr_tsm_tdi_status.attr, + NULL, +}; + +static const struct attribute_group host_tdi_group = { + .attrs = host_tdi_attrs, +}; + +int tsm_tdi_bind(struct tsm_tdi *tdi, u32 guest_rid, int kvmfd) +{ + struct tsm_dev *tdev = tdi->tdev; + struct tsm_host_subsys *hsubsys = (struct tsm_host_subsys *) tdev->tsm; + struct fd f = fdget(kvmfd); + struct kvm *kvm; + u64 vmid; + int ret; + + if (!fd_file(f)) + return -EBADF; + + if (!file_is_kvm(fd_file(f))) { + ret = -EBADF; + goto out_fput; + } + + kvm = fd_file(f)->private_data; + if (!kvm || !kvm_get_kvm_safe(kvm)) { + ret = -EFAULT; + goto out_fput; + } + + vmid = kvm_arch_tsm_get_vmid(kvm); + if (!vmid) { + ret = -EFAULT; + goto out_kvm_put; + } + + if (WARN_ON(!hsubsys->ops->tdi_bind)) { + ret = -EPERM; + goto out_kvm_put; + } + + if (!tdev->connected) { + ret = -EIO; + goto out_kvm_put; + } + + mutex_lock(&tdi->tdev->spdm_mutex); + while (1) { + ret = hsubsys->ops->tdi_bind(tdi, guest_rid, vmid); + if (ret < 0) + break; + + if (!ret) + break; + + ret = tdi->tdev->tsm_bus->ops->spdm_forward(&tdi->tdev->spdm, ret); + if (ret < 0) + break; + } + mutex_unlock(&tdi->tdev->spdm_mutex); + + if (ret) { + tsm_tdi_unbind(tdi); + goto out_kvm_put; + } + + tdi->guest_rid = guest_rid; + tdi->kvm = kvm; + ++tdi->tdev->bound; + goto out_fput; + +out_kvm_put: + kvm_put_kvm(kvm); +out_fput: + fdput(f); + return ret; +} +EXPORT_SYMBOL_GPL(tsm_tdi_bind); + +void tsm_tdi_unbind(struct tsm_tdi *tdi) +{ + if (tdi->kvm) { + tsm_tdi_reclaim(tdi); + --tdi->tdev->bound; + kvm_put_kvm(tdi->kvm); + tdi->kvm = NULL; + } + + tdi->guest_rid = 0; + tdi->dev.parent->tdi_enabled = false; +} +EXPORT_SYMBOL_GPL(tsm_tdi_unbind); + +int tsm_guest_request(struct tsm_tdi *tdi, u8 __user *req, size_t reqlen, + u8 __user *res, size_t reslen, int *fw_err) +{ + struct tsm_dev *tdev = tdi->tdev; + struct tsm_host_subsys *hsubsys = (struct tsm_host_subsys *) tdev->tsm; + int ret; + + if (!hsubsys->ops->guest_request) + return -EPERM; + + mutex_lock(&tdi->tdev->spdm_mutex); + while (1) { + ret = hsubsys->ops->guest_request(tdi, req, reqlen, + res, reslen, fw_err); + if (ret <= 0) + break; + + ret = tdi->tdev->tsm_bus->ops->spdm_forward(&tdi->tdev->spdm, + ret); + if (ret < 0) + break; + } + + mutex_unlock(&tdi->tdev->spdm_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(tsm_guest_request); + +struct tsm_host_subsys *tsm_host_register(struct device *parent, + struct tsm_hv_ops *hvops, + void *private_data) +{ + struct tsm_subsys *subsys = tsm_register(parent, sizeof(struct tsm_host_subsys), + &host_dev_group, &host_tdi_group, + tsm_tdi_measurements_locked); + struct tsm_host_subsys *hsubsys; + + hsubsys = (struct tsm_host_subsys *) subsys; + + if (IS_ERR(hsubsys)) + return hsubsys; + + hsubsys->ops = hvops; + hsubsys->private_data = private_data; + + return hsubsys; +} +EXPORT_SYMBOL_GPL(tsm_host_register); + +static int __init tsm_init(void) +{ + int ret = 0; + + pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); + + return ret; +} + +static void __exit tsm_exit(void) +{ + pr_info(DRIVER_DESC " version: " DRIVER_VERSION " shutdown\n"); +} + +module_init(tsm_init); +module_exit(tsm_exit); + +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/virt/coco/tsm.c b/drivers/virt/coco/tsm.c new file mode 100644 index 000000000000..b6235d1210ca --- /dev/null +++ b/drivers/virt/coco/tsm.c @@ -0,0 +1,636 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include + +#define DRIVER_VERSION "0.1" +#define DRIVER_AUTHOR "aik@amd.com" +#define DRIVER_DESC "TSM library" + +static struct class *tsm_class, *tdev_class, *tdi_class; + +/* snprintf does not check for the size, hence this wrapper */ +static int tsmprint(char *buf, size_t size, const char *fmt, ...) +{ + va_list args; + size_t i; + + if (!size) + return 0; + + va_start(args, fmt); + i = vsnprintf(buf, size, fmt, args); + va_end(args); + + return min(i, size); +} + +struct tsm_blob *tsm_blob_new(void *data, size_t len) +{ + struct tsm_blob *b; + + if (!len || !data) + return NULL; + + b = kzalloc(sizeof(*b) + len, GFP_KERNEL); + if (!b) + return NULL; + + b->data = (void *)b + sizeof(*b); + b->len = len; + memcpy(b->data, data, len); + + return b; +} +EXPORT_SYMBOL_GPL(tsm_blob_new); + +static int match_class(struct device *dev, const void *data) +{ + return dev->class == data; +} + +struct tsm_dev *tsm_dev_get(struct device *parent) +{ + struct device *dev = device_find_child(parent, tdev_class, match_class); + + if (!dev) { + dev = device_find_child(parent, tdi_class, match_class); + if (dev) { + struct tsm_tdi *tdi = container_of(dev, struct tsm_tdi, dev); + + dev = &tdi->tdev->dev; + } + } + + if (!dev) + return NULL; + + /* device_find_child() does get_device() */ + return container_of(dev, struct tsm_dev, dev); +} +EXPORT_SYMBOL_GPL(tsm_dev_get); + +void tsm_dev_put(struct tsm_dev *tdev) +{ + put_device(&tdev->dev); +} +EXPORT_SYMBOL_GPL(tsm_dev_put); + +struct tsm_tdi *tsm_tdi_get(struct device *parent) +{ + struct device *dev = device_find_child(parent, tdi_class, match_class); + + if (!dev) + return NULL; + + /* device_find_child() does get_device() */ + return container_of(dev, struct tsm_tdi, dev); +} +EXPORT_SYMBOL_GPL(tsm_tdi_get); + +void tsm_tdi_put(struct tsm_tdi *tdi) +{ + put_device(&tdi->dev); +} +EXPORT_SYMBOL_GPL(tsm_tdi_put); + +static ssize_t blob_show(struct tsm_blob *blob, char *buf) +{ + unsigned int n, m; + size_t sz = PAGE_SIZE - 1; + + if (!blob) + return sysfs_emit(buf, "none\n"); + + n = tsmprint(buf, sz, "%lu %u\n", blob->len); + m = hex_dump_to_buffer(blob->data, blob->len, 32, 1, + buf + n, sz - n, false); + n += min(sz - n, m); + n += tsmprint(buf + n, sz - n, "...\n"); + return n; +} + +static ssize_t tsm_certs_gen(struct tsm_blob *certs, char *buf, size_t len) +{ + struct spdm_certchain_block_header *h; + unsigned int n = 0, m, i, off, o2; + u8 *p; + + for (i = 0, off = 0; off < certs->len; ++i) { + h = (struct spdm_certchain_block_header *) ((u8 *)certs->data + off); + if (WARN_ON_ONCE(h->length > certs->len - off)) + return 0; + + n += tsmprint(buf + n, len - n, "[%d] len=%d:\n", i, h->length); + + for (o2 = 0, p = (u8 *)&h[1]; o2 < h->length; o2 += 32) { + m = hex_dump_to_buffer(p + o2, h->length - o2, 32, 1, + buf + n, len - n, true); + n += min(len - n, m); + n += tsmprint(buf + n, len - n, "\n"); + } + + off += h->length; /* Includes the header */ + } + + return n; +} + +static ssize_t tsm_certs_user_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct tsm_dev *tdev = container_of(dev, struct tsm_dev, dev); + ssize_t n; + + mutex_lock(&tdev->spdm_mutex); + if (!tdev->certs) { + n = sysfs_emit(buf, "none\n"); + } else { + n = tsm_certs_gen(tdev->certs, buf, PAGE_SIZE - 1); + if (!n) + n = blob_show(tdev->certs, buf); + } + mutex_unlock(&tdev->spdm_mutex); + + return n; +} + +static DEVICE_ATTR_RO(tsm_certs_user); + +static ssize_t tsm_certs_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct tsm_dev *tdev = container_of(dev, struct tsm_dev, dev); + ssize_t n = 0; + + mutex_lock(&tdev->spdm_mutex); + if (tdev->certs) { + n = min(PAGE_SIZE, tdev->certs->len); + memcpy(buf, tdev->certs->data, n); + } + mutex_unlock(&tdev->spdm_mutex); + + return n; +} + +static DEVICE_ATTR_RO(tsm_certs); + +static ssize_t tsm_meas_gen(struct tsm_blob *meas, char *buf, size_t len) +{ + static const char * const whats[] = { + "ImmuROM", "MutFW", "HWCfg", "FWCfg", + "MeasMft", "DevDbg", "MutFWVer", "MutFWVerSec" + }; + struct dmtf_measurement_block_device_mode *dm; + struct spdm_measurement_block_header *mb; + struct dmtf_measurement_block_header *h; + unsigned int n, m, off, what; + bool dmtf; + + n = tsmprint(buf, len, "Len=%d\n", meas->len); + for (off = 0; off < meas->len; ) { + mb = (struct spdm_measurement_block_header *)(((u8 *) meas->data) + off); + dmtf = mb->spec & 1; + + n += tsmprint(buf + n, len - n, "#%d (%d) ", mb->index, mb->size); + if (dmtf) { + h = (void *) &mb[1]; + + if (WARN_ON_ONCE(mb->size != (sizeof(*h) + h->size))) + return -EINVAL; + + what = h->type & 0x7F; + n += tsmprint(buf + n, len - n, "%x=[%s %s]: ", + h->type, + h->type & 0x80 ? "digest" : "raw", + what < ARRAY_SIZE(whats) ? whats[what] : "reserved"); + + if (what == 5) { + dm = (struct dmtf_measurement_block_device_mode *) &h[1]; + n += tsmprint(buf + n, len - n, " %x %x %x %x", + dm->opmode_cap, dm->opmode_sta, + dm->devmode_cap, dm->devmode_sta); + } else { + m = hex_dump_to_buffer(&h[1], h->size, 32, 1, + buf + n, len - n, false); + n += min(len - n, m); + } + } else { + n += tsmprint(buf + n, len - n, "spec=%x: ", mb->spec); + m = hex_dump_to_buffer(&mb[1], min(len - off, mb->size), + 32, 1, buf + n, len - n, false); + n += min(len - n, m); + } + + off += sizeof(*mb) + mb->size; + n += tsmprint(buf + n, len - n, "...\n"); + } + + return n; +} + +static ssize_t tsm_meas_user_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct tsm_dev *tdev = container_of(dev, struct tsm_dev, dev); + ssize_t n; + + mutex_lock(&tdev->spdm_mutex); + n = tdev->tsm->update_measurements(tdev); + + if (!tdev->meas || n) { + n = sysfs_emit(buf, "none\n"); + } else { + n = tsm_meas_gen(tdev->meas, buf, PAGE_SIZE); + if (!n) + n = blob_show(tdev->meas, buf); + } + mutex_unlock(&tdev->spdm_mutex); + + return n; +} + +static DEVICE_ATTR_RO(tsm_meas_user); + +static ssize_t tsm_meas_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct tsm_dev *tdev = container_of(dev, struct tsm_dev, dev); + ssize_t n = 0; + + mutex_lock(&tdev->spdm_mutex); + n = tdev->tsm->update_measurements(tdev); + if (!n && tdev->meas) { + n = MIN(PAGE_SIZE, tdev->meas->len); + memcpy(buf, tdev->meas->data, n); + } + mutex_unlock(&tdev->spdm_mutex); + + return n; +} + +static DEVICE_ATTR_RO(tsm_meas); + +static ssize_t tsm_nonce_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct tsm_dev *tdev = tsm_dev_get(dev); + + if (!tdev) + return -EFAULT; + + tdev->nonce_len = min(count, sizeof(tdev->nonce)); + mutex_lock(&tdev->spdm_mutex); + memcpy(tdev->nonce, buf, tdev->nonce_len); + mutex_unlock(&tdev->spdm_mutex); + tsm_dev_put(tdev); + + return tdev->nonce_len; +} + +static ssize_t tsm_nonce_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct tsm_dev *tdev = tsm_dev_get(dev); + + if (!tdev) + return -EFAULT; + + mutex_lock(&tdev->spdm_mutex); + memcpy(buf, tdev->nonce, tdev->nonce_len); + mutex_unlock(&tdev->spdm_mutex); + tsm_dev_put(tdev); + + return tdev->nonce_len; +} + +static DEVICE_ATTR_RW(tsm_nonce); + +static struct attribute *dev_attrs[] = { + &dev_attr_tsm_certs_user.attr, + &dev_attr_tsm_meas_user.attr, + &dev_attr_tsm_certs.attr, + &dev_attr_tsm_meas.attr, + &dev_attr_tsm_nonce.attr, + NULL, +}; +static const struct attribute_group dev_group = { + .attrs = dev_attrs, +}; + + +ssize_t tsm_report_gen(struct tsm_blob *report, char *buf, size_t len) +{ + struct tdi_report_header *h = TDI_REPORT_HDR(report); + struct tdi_report_mmio_range *mr = TDI_REPORT_MR_OFF(report); + struct tdi_report_footer *f = TDI_REPORT_FTR(report); + unsigned int n, m, i; + + n = tsmprint(buf, len, + "no_fw_update=%u\ndma_no_pasid=%u\ndma_pasid=%u\nats=%u\nprs=%u\n", + FIELD_GET(TSM_TDI_REPORT_NO_FW_UPDATE, h->interface_info), + FIELD_GET(TSM_TDI_REPORT_DMA_NO_PASID, h->interface_info), + FIELD_GET(TSM_TDI_REPORT_DMA_PASID, h->interface_info), + FIELD_GET(TSM_TDI_REPORT_ATS, h->interface_info), + FIELD_GET(TSM_TDI_REPORT_PRS, h->interface_info)); + n += tsmprint(buf + n, len - n, + "msi_x_message_control=%#04x\nlnr_control=%#04x\n", + h->msi_x_message_control, h->lnr_control); + n += tsmprint(buf + n, len - n, "tph_control=%#08x\n", h->tph_control); + + for (i = 0; i < h->mmio_range_count; ++i) { +#define FIELD_CH(m, r) (FIELD_GET((m), (r)) ? '+':'-') + n += tsmprint(buf + n, len - n, + "[%i] #%lu %#016llx +%#lx MSIX%c PBA%c NonTEE%c Upd%c\n", + i, + FIELD_GET(TSM_TDI_REPORT_MMIO_RANGE_ID, mr[i].range_attributes), + mr[i].first_page << PAGE_SHIFT, + (unsigned long) mr[i].num << PAGE_SHIFT, + FIELD_CH(TSM_TDI_REPORT_MMIO_MSIX_TABLE, mr[i].range_attributes), + FIELD_CH(TSM_TDI_REPORT_MMIO_PBA, mr[i].range_attributes), + FIELD_CH(TSM_TDI_REPORT_MMIO_IS_NON_TEE, mr[i].range_attributes), + FIELD_CH(TSM_TDI_REPORT_MMIO_IS_UPDATABLE, mr[i].range_attributes)); + + if (FIELD_GET(TSM_TDI_REPORT_MMIO_RESERVED, mr[i].range_attributes)) + n += tsmprint(buf + n, len - n, + "[%i] WARN: reserved=%#x\n", i, mr[i].range_attributes); + } + + if (f->device_specific_info_len) { + unsigned int num = report->len - ((u8 *)f->device_specific_info - (u8 *)h); + + num = min(num, f->device_specific_info_len); + n += tsmprint(buf + n, len - n, "DevSp len=%d%s", + f->device_specific_info_len, num ? ": " : ""); + m = hex_dump_to_buffer(f->device_specific_info, num, 32, 1, + buf + n, len - n, false); + n += min(len - n, m); + n += tsmprint(buf + n, len - n, m ? "\n" : "...\n"); + } + + return n; +} +EXPORT_SYMBOL_GPL(tsm_report_gen); + +static ssize_t tsm_report_user_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct tsm_tdi *tdi = container_of(dev, struct tsm_tdi, dev); + ssize_t n; + + mutex_lock(&tdi->tdev->spdm_mutex); + if (!tdi->report) { + n = sysfs_emit(buf, "none\n"); + } else { + n = tsm_report_gen(tdi->report, buf, PAGE_SIZE - 1); + if (!n) + n = blob_show(tdi->report, buf); + } + mutex_unlock(&tdi->tdev->spdm_mutex); + + return n; +} + +static DEVICE_ATTR_RO(tsm_report_user); + +static ssize_t tsm_report_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct tsm_tdi *tdi = container_of(dev, struct tsm_tdi, dev); + ssize_t n = 0; + + mutex_lock(&tdi->tdev->spdm_mutex); + if (tdi->report) { + n = min(PAGE_SIZE, tdi->report->len); + memcpy(buf, tdi->report->data, n); + } + mutex_unlock(&tdi->tdev->spdm_mutex); + + return n; +} +static DEVICE_ATTR_RO(tsm_report); + +static struct attribute *tdi_attrs[] = { + &dev_attr_tsm_report_user.attr, + &dev_attr_tsm_report.attr, + NULL, +}; + +static const struct attribute_group tdi_group = { + .attrs = tdi_attrs, +}; + +int tsm_tdi_init(struct tsm_dev *tdev, struct device *parent) +{ + struct tsm_tdi *tdi; + struct device *dev; + int ret = 0; + + dev_info(parent, "Initializing tdi\n"); + if (!tdev) + return -ENODEV; + + tdi = kzalloc(sizeof(*tdi), GFP_KERNEL); + if (!tdi) + return -ENOMEM; + + dev = &tdi->dev; + dev->groups = tdev->tsm->tdi_groups; + dev->parent = parent; + dev->class = tdi_class; + dev_set_name(dev, "tdi:%s", dev_name(parent)); + device_initialize(dev); + ret = device_add(dev); + if (ret) + return ret; + + ret = sysfs_create_link(&parent->kobj, &tdev->dev.kobj, "tsm_dev"); + if (ret) + goto free_exit; + + tdi->tdev = tdev; + + return 0; + +free_exit: + kfree(tdi); + + return ret; +} +EXPORT_SYMBOL_GPL(tsm_tdi_init); + +void tsm_tdi_free(struct tsm_tdi *tdi) +{ + struct device *parent = tdi->dev.parent; + + dev_notice(&tdi->dev, "Freeing tdi\n"); + sysfs_remove_link(&parent->kobj, "tsm_dev"); + device_unregister(&tdi->dev); +} +EXPORT_SYMBOL_GPL(tsm_tdi_free); + +int tsm_dev_init(struct tsm_bus_subsys *tsm_bus, struct device *parent, + size_t busdatalen, struct tsm_dev **ptdev) +{ + struct tsm_dev *tdev; + struct device *dev; + int ret = 0; + + dev_info(parent, "Initializing tdev\n"); + tdev = kzalloc(sizeof(*tdev) + busdatalen, GFP_KERNEL); + if (!tdev) + return -ENOMEM; + + tdev->physdev = get_device(parent); + mutex_init(&tdev->spdm_mutex); + + tdev->tsm = tsm_bus->tsm; + tdev->tsm_bus = tsm_bus; + + dev = &tdev->dev; + dev->groups = tdev->tsm->tdev_groups; + dev->parent = parent; + dev->class = tdev_class; + dev_set_name(dev, "tdev:%s", dev_name(parent)); + device_initialize(dev); + ret = device_add(dev); + + get_device(dev); + *ptdev = tdev; + return 0; +} +EXPORT_SYMBOL_GPL(tsm_dev_init); + +void tsm_dev_free(struct tsm_dev *tdev) +{ + dev_notice(&tdev->dev, "Freeing tdevice\n"); + device_unregister(&tdev->dev); +} +EXPORT_SYMBOL_GPL(tsm_dev_free); + +int tsm_create_link(struct tsm_subsys *tsm, struct device *dev, const char *name) +{ + return sysfs_create_link(&tsm->dev.kobj, &dev->kobj, name); +} +EXPORT_SYMBOL_GPL(tsm_create_link); + +void tsm_remove_link(struct tsm_subsys *tsm, const char *name) +{ + sysfs_remove_link(&tsm->dev.kobj, name); +} +EXPORT_SYMBOL_GPL(tsm_remove_link); + +static struct tsm_subsys *alloc_tsm_subsys(struct device *parent, size_t size) +{ + struct tsm_subsys *subsys; + struct device *dev; + + if (WARN_ON_ONCE(size < sizeof(*subsys))) + return ERR_PTR(-EINVAL); + + subsys = kzalloc(size, GFP_KERNEL); + if (!subsys) + return ERR_PTR(-ENOMEM); + + dev = &subsys->dev; + dev->parent = parent; + dev->class = tsm_class; + device_initialize(dev); + return subsys; +} + +struct tsm_subsys *tsm_register(struct device *parent, size_t size, + const struct attribute_group *tdev_ag, + const struct attribute_group *tdi_ag, + int (*update_measurements)(struct tsm_dev *tdev)) +{ + struct tsm_subsys *subsys = alloc_tsm_subsys(parent, size); + struct device *dev; + int rc; + + if (IS_ERR(subsys)) + return subsys; + + dev = &subsys->dev; + rc = dev_set_name(dev, "tsm0"); + if (rc) + return ERR_PTR(rc); + + rc = device_add(dev); + if (rc) + return ERR_PTR(rc); + + subsys->tdev_groups[0] = &dev_group; + subsys->tdev_groups[1] = tdev_ag; + subsys->tdi_groups[0] = &tdi_group; + subsys->tdi_groups[1] = tdi_ag; + subsys->update_measurements = update_measurements; + + return subsys; +} +EXPORT_SYMBOL_GPL(tsm_register); + +void tsm_unregister(struct tsm_subsys *subsys) +{ + device_unregister(&subsys->dev); +} +EXPORT_SYMBOL_GPL(tsm_unregister); + +static void tsm_release(struct device *dev) +{ + struct tsm_subsys *tsm = container_of(dev, typeof(*tsm), dev); + + dev_info(&tsm->dev, "Releasing TSM\n"); + kfree(tsm); +} + +static void tdev_release(struct device *dev) +{ + struct tsm_dev *tdev = container_of(dev, typeof(*tdev), dev); + + dev_info(&tdev->dev, "Releasing %s TDEV\n", + tdev->connected ? "connected":"disconnected"); + kfree(tdev); +} + +static void tdi_release(struct device *dev) +{ + struct tsm_tdi *tdi = container_of(dev, typeof(*tdi), dev); + + dev_info(&tdi->dev, "Releasing %s TDI\n", tdi->kvm ? "bound" : "unbound"); + sysfs_remove_link(&tdi->dev.parent->kobj, "tsm_dev"); + kfree(tdi); +} + +static int __init tsm_init(void) +{ + int ret = 0; + + pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); + + tsm_class = class_create("tsm"); + if (IS_ERR(tsm_class)) + return PTR_ERR(tsm_class); + tsm_class->dev_release = tsm_release; + + tdev_class = class_create("tsm-dev"); + if (IS_ERR(tdev_class)) + return PTR_ERR(tdev_class); + tdev_class->dev_release = tdev_release; + + tdi_class = class_create("tsm-tdi"); + if (IS_ERR(tdi_class)) + return PTR_ERR(tdi_class); + tdi_class->dev_release = tdi_release; + + return ret; +} + +static void __exit tsm_exit(void) +{ + pr_info(DRIVER_DESC " version: " DRIVER_VERSION " shutdown\n"); + class_destroy(tdi_class); + class_destroy(tdev_class); + class_destroy(tsm_class); +} + +module_init(tsm_init); +module_exit(tsm_exit); + +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/Documentation/virt/coco/tsm.rst b/Documentation/virt/coco/tsm.rst new file mode 100644 index 000000000000..7cb5f1862492 --- /dev/null +++ b/Documentation/virt/coco/tsm.rst @@ -0,0 +1,99 @@ +.. SPDX-License-Identifier: GPL-2.0 + +What it is +========== + +This is for PCI passthrough in confidential computing (CoCo: SEV-SNP, TDX, CoVE). +Currently passing through PCI devices to a CoCo VM uses SWIOTLB to pre-shared +memory buffers. + +PCIe IDE (Integrity and Data Encryption) and TDISP (TEE Device Interface Security +Protocol) are protocols to enable encryption over PCIe link and DMA to encrypted +memory. This doc is focused to DMAing to encrypted VM, the encrypted host memory is +out of scope. + + +Protocols +========= + +PCIe r6 DOE is a mailbox protocol to read/write object from/to device. +Objects are of plain SPDM or secure SPDM type. SPDM is responsible for authenticating +devices, creating a secure link between a device and TSM. +IDE_KM manages PCIe link encryption keys, it works on top of secure SPDM. +TDISP manages a passed through PCI function state, also works on top on secure SPDM. +Additionally, PCIe defines IDE capability which provides the host OS a way +to enable streams on the PCIe link. + + +TSM modules +=========== + +TSM is a library, shared among hosts and guests. + +TSM-HOST contains host-specific bits, controls IDE and TDISP bindings. + +TSM-GUEST contains guest-specific bits, controls enablement of encrypted DMA and +MMIO. + +TSM-PCI is PCI binding for TSM, calls the above libraries for setting up +sysfs nodes and corresponding data structures. + + +Flow +==== + +At the boot time the tsm.ko scans the PCI bus to find and setup TDISP-cabable +devices; it also listens to hotplug events. If setup was successful, tsm-prefixed +nodes will appear in sysfs. + +Then, the user enables IDE by writing to /sys/bus/pci/devices/0000:e1:00.0/tsm_dev_connect +and this is how PCIe encryption is enabled. + +To pass the device through, a modifined VMM is required. + +In the VM, the same tsm.ko loads. In addition to the host's setup, the VM wants +to receive the report and enable secure DMA or/and secure MMIO, via some VM<->HV +protocol (such as AMD GHCB). Once this is done, a VM can access validated MMIO +with the Cbit set and the device can DMA to encrypted memory. + +The sysfs example from a host with a TDISP capable device: + +~> find /sys -iname "*tsm*" +/sys/class/tsm-tdi +/sys/class/tsm +/sys/class/tsm/tsm0 +/sys/class/tsm-dev +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.1/tsm_dev +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.1/tsm-tdi +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.1/tsm-tdi/tdi:0000:e1:00.1/tsm_tdi_bind +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.1/tsm-tdi/tdi:0000:e1:00.1/tsm_tdi_status +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.1/tsm-tdi/tdi:0000:e1:00.1/tsm_tdi_status_user +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.1/tsm-tdi/tdi:0000:e1:00.1/tsm_report_user +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.1/tsm-tdi/tdi:0000:e1:00.1/tsm_report +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.0/tsm_dev +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.0/tsm-tdi +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.0/tsm-tdi/tdi:0000:e1:00.0/tsm_tdi_bind +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.0/tsm-tdi/tdi:0000:e1:00.0/tsm_tdi_status +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.0/tsm-tdi/tdi:0000:e1:00.0/tsm_tdi_status_user +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.0/tsm-tdi/tdi:0000:e1:00.0/tsm_report_user +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.0/tsm-tdi/tdi:0000:e1:00.0/tsm_report +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.0/tsm-dev +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.0/tsm-dev/tdev:0000:e1:00.0/tsm_certs +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.0/tsm-dev/tdev:0000:e1:00.0/tsm_nonce +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.0/tsm-dev/tdev:0000:e1:00.0/tsm_meas_user +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.0/tsm-dev/tdev:0000:e1:00.0/tsm_certs_user +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.0/tsm-dev/tdev:0000:e1:00.0/tsm_dev_status +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.0/tsm-dev/tdev:0000:e1:00.0/tsm_cert_slot +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.0/tsm-dev/tdev:0000:e1:00.0/tsm_dev_connect +/sys/devices/pci0000:e0/0000:e0:01.1/0000:e1:00.0/tsm-dev/tdev:0000:e1:00.0/tsm_meas +/sys/devices/pci0000:a0/0000:a0:07.1/0000:a9:00.5/tsm +/sys/devices/pci0000:a0/0000:a0:07.1/0000:a9:00.5/tsm/tsm0 + + +References +========== + +[1] TEE Device Interface Security Protocol - TDISP - v2022-07-27 +https://members.pcisig.com/wg/PCI-SIG/document/18268?downloadRevision=21500 +[2] Security Protocol and Data Model (SPDM) +https://www.dmtf.org/sites/default/files/standards/documents/DSP0274_1.2.1.pdf diff --git a/drivers/virt/coco/Kconfig b/drivers/virt/coco/Kconfig index 819a97e8ba99..e4385247440b 100644 --- a/drivers/virt/coco/Kconfig +++ b/drivers/virt/coco/Kconfig @@ -3,6 +3,18 @@ # Confidential computing related collateral # +config TSM + tristate "Platform support for TEE Device Interface Security Protocol (TDISP)" + default m + depends on AMD_MEM_ENCRYPT + select PCI_DOE + select PCI_IDE + help + Add a common place for user visible platform support for PCIe TDISP. + TEE Device Interface Security Protocol (TDISP) from PCI-SIG, + https://pcisig.com/tee-device-interface-security-protocol-tdisp + This is prerequisite for host and guest support. + source "drivers/virt/coco/efi_secret/Kconfig" source "drivers/virt/coco/pkvm-guest/Kconfig" @@ -14,3 +26,5 @@ source "drivers/virt/coco/tdx-guest/Kconfig" source "drivers/virt/coco/arm-cca-guest/Kconfig" source "drivers/virt/coco/guest/Kconfig" + +source "drivers/virt/coco/host/Kconfig" diff --git a/drivers/virt/coco/host/Kconfig b/drivers/virt/coco/host/Kconfig new file mode 100644 index 000000000000..3bde38b91fd4 --- /dev/null +++ b/drivers/virt/coco/host/Kconfig @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# TSM (TEE Security Manager) Common infrastructure and host drivers +# +config TSM_HOST + tristate From patchwork Tue Feb 18 11:09:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alexey Kardashevskiy X-Patchwork-Id: 866256 Received: from NAM02-BN1-obe.outbound.protection.outlook.com (mail-bn1nam02on2080.outbound.protection.outlook.com [40.107.212.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2299D1AAA10; Tue, 18 Feb 2025 11:13:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.212.80 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877232; cv=fail; b=YhsvpKkphzwEOyiZ80l8NGfGvStBVfZcJbLP0ZswtaZ2xh1CDotc6/Mc7LCqlY1EG+tHfrNsRa/bm79/R/5ufwmuaemgPYfR50XYL8wYp+aw8UHII8kdZ7CRtbH5ZMnng5zAE3wb5QLoweJp8z1VrmwG63OjWMNdR/p9UbG6COk= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877232; c=relaxed/simple; bh=1wMMQpvWZNz70ZAnTP1kuXEMbTM+Ji3WYy/ykgu7m/s=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=FElnyXBtvxMPPhWGLvImyg7B/ce5MsqzNmIpJ6WnR2BF05Z9PtExlQwOhrtocZLdJZ9aEfA6BMqnObPrUff8GTJ9UXegeZIENXDaDRP4UXkgYubRxeQ/stwRgTnim/nHTTo+MMjRDVlC47Ck/9WWGtM9DeduuK9MwtT5dHwrkG0= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=iMtexMVZ; arc=fail smtp.client-ip=40.107.212.80 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="iMtexMVZ" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=YwOr517ItULweB2X8naPpFZxWuHRH5pKSi9NquMKvL4IgE/4EyPmeDkvxH9vJVNtaa0DVnVWXfzmSNn7e/Zoyznt9M249J5DFee8f5nrFo3KG5i/7gUP8X5Fe+CMqzdrWRgroJp3sPXthV/eChohkqVQ+9ZYrMmkwk1YoQY0amyQ8Zc5EGrVIetnQT6i14oIrhYOt8Cj4rncRn0uEL0Igoo36LVrStg9Y+T7enQtW8V2WbAIe9/DAiQnlwF2OVlFKbi9ZhrUyS3On89cbMQGHBcgnJTIvdBOife88Z7lAHbCHDmrnAVb+upj9jV2R5VjcleI4/aPmC5Q8hLOPfGVLQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=o0bpBlCSa+fU72ncwwNisNntvm0wOihFAYgqCxT5Yi4=; b=ldTbRMl8mQKYQ54kVMkDdMslmwy180i8BTNIXgjBb4bjZOycwisiPVJhe+ZGRmRnm7wqLvuZ8fx5HH65v2H2rkGYbuQRD07t+UDwBPBN8VhVhCa7EdEG3u4T4y4V6qeEGK/YN2o+wtRn2CEkKUM2Q4nbOl00y1KzDTeTU6l8hPQr5gbexwFe8y+cfXJcfMLFSnyzbdUcecv0peKL40TbAmjVc0lYWYStkfQxgbN01bxHnGVd2r7Nemp4y/1r6V5+wgwWJP4gUxi/VH96Mx8jBplfv6lY3Ahqdwqg63WBPOOTNJ3LblobD7N20zeQpLpfcSvyjaTCnWpMy2eHR98b9A== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=o0bpBlCSa+fU72ncwwNisNntvm0wOihFAYgqCxT5Yi4=; b=iMtexMVZMG5qk+4N/h0RRoqf6COKvdQ2ubYYgx/RZFqhf0a3t5u3GCXZJ9+Fn/BeX0WRNxAxhArpdR2ZrqMhizqd+I/T183djiMg2x42GqfxrfGCWNFm0ZEyhuE8qj8XomMmvoWCjlbU/EQwk3KgsAEVBqccRX0bgNDXvrC7bs0= Received: from BL0PR01CA0017.prod.exchangelabs.com (2603:10b6:208:71::30) by DM4PR12MB8449.namprd12.prod.outlook.com (2603:10b6:8:17f::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8445.19; Tue, 18 Feb 2025 11:13:42 +0000 Received: from BN3PEPF0000B074.namprd04.prod.outlook.com (2603:10b6:208:71:cafe::fa) by BL0PR01CA0017.outlook.office365.com (2603:10b6:208:71::30) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8466.14 via Frontend Transport; Tue, 18 Feb 2025 11:13:42 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by BN3PEPF0000B074.mail.protection.outlook.com (10.167.243.119) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8466.11 via Frontend Transport; Tue, 18 Feb 2025 11:13:42 +0000 Received: from aiemdee.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Tue, 18 Feb 2025 05:13:33 -0600 From: Alexey Kardashevskiy To: CC: , , , , "Sean Christopherson" , Paolo Bonzini , "Tom Lendacky" , Ashish Kalra , Joerg Roedel , Suravee Suthikulpanit , Robin Murphy , "Jason Gunthorpe" , Kevin Tian , Bjorn Helgaas , Dan Williams , "Christoph Hellwig" , Nikunj A Dadhania , Michael Roth , Vasant Hegde , Joao Martins , Nicolin Chen , Lu Baolu , Steve Sistare , "Lukas Wunner" , Jonathan Cameron , Suzuki K Poulose , Dionna Glaze , Yi Liu , , , Zhi Wang , AXu Yilun , "Aneesh Kumar K . V" , Alexey Kardashevskiy Subject: [RFC PATCH v2 09/22] crypto/ccp: Implement SEV TIO firmware interface Date: Tue, 18 Feb 2025 22:09:56 +1100 Message-ID: <20250218111017.491719-10-aik@amd.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250218111017.491719-1-aik@amd.com> References: <20250218111017.491719-1-aik@amd.com> Precedence: bulk X-Mailing-List: linux-crypto@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN3PEPF0000B074:EE_|DM4PR12MB8449:EE_ X-MS-Office365-Filtering-Correlation-Id: 1b55741a-4ccb-482a-1d3f-08dd500d4d7b X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|36860700013|82310400026|376014|7416014|1800799024; X-Microsoft-Antispam-Message-Info: =?utf-8?q?lAZg50mmBVhRmPIZLSwJ0xV0GnPQraH?= =?utf-8?q?0CyByhqsLgyfU4Y18kHFxhvgX0Qh8PMOPOXBPmaK8qUOKAb5/PTqdPQznyvF4daii?= =?utf-8?q?DHw/V2uOl32m7lWWMFUAMSSfBh/7JWD1RYT+BxnMI5meGEYV7Apbw733+94vBkUu7?= =?utf-8?q?fKdJhAilOpGCNkyl1hYn/n55Qzu9BmM8ZgbWa5ZKyabPfwOeQvWFeBwcT5HBzmPv0?= =?utf-8?q?1I0K0u3sXe5csgnCoun/qK5J4tRYJss/WIbu7UDOzxPrNv6xxta3Mdkx66sdkakFL?= =?utf-8?q?9b5YwiKUVYv5rqFkxXTj9u1JZPc5z0yklu9O5UJlblne+8z8flTRmNtv8m3azgiyA?= =?utf-8?q?lvBFLQF36GoNIUlxM0kup8pQb/eCUZtwgjLHHK6xE2gnPoXibx6iwDS7HDiv4B57T?= =?utf-8?q?pP/KmxqP4By1hDbyoJKnnZ9JSMU9cZ1Eq2neTC+HlJY/osKSu1D78Ig+VW9b8IQhJ?= =?utf-8?q?dhx7pyFhu3C9qiQ/KdXq8mtKATZMgdI1YDTbhbz4g4AGDnZ467R9uGH8aL7hh9Bdq?= =?utf-8?q?zmsfoXijj+h/OUI9v8TbYAA697i8j9xEcS+kPuinVo24JQ8aOoHx9EKdlgP/xvER/?= =?utf-8?q?zQVuUbd2hspbcSpOXP1JxQmrXRf+rYMgAHliWThorkJQCjmjco1OtD9OyHX3taCEE?= =?utf-8?q?7pHRdPL7IQywv+hjJGB76GO/+jaTUO37R8XKccIsj9J1RMlEBFDLuDkgBIVoX6hyl?= =?utf-8?q?EQ3F5CPt8g89ZEVPneufZyT7fffKodKUyaD4q1lUZJEZDC+0nct6pwY6/vOsuf9kW?= =?utf-8?q?pgUhZUdqETHvWtHUa63MbXXHjND29PUHcYtQmhddatUslWibUUI0Xos4YNypjWlp3?= =?utf-8?q?JBKPmQmetW3VlKL9ADC9JbmbKliyhNKiwY9M9XGoqgbzpDW/+EJFNbJTQYu1iITAJ?= =?utf-8?q?DqHwOEVqPRWwNoEif1z+9JesVQkjTdFnl+EY959ld6oLIRFYxqNJXRQNi8F0Jg8bT?= =?utf-8?q?IMw1jyYIT14STHF0VOAl8+Oarrp5/iR+9eWovGmj46J6KOOZ1jTJw3Mfa0TWyeCzX?= =?utf-8?q?NFtoob0lUBL5Lc0WMUluNXDbYw5Mtsc1sRjXLxITqQl+llzX4xiOnHAUSQ99WOQdw?= =?utf-8?q?fHiqWkCDCJYk7ObttTHemwvW27JfZXVxxGmuTgXFV1w7sjzmWGA1iQRSuY386v+wo?= =?utf-8?q?ykMRNIb/6hMO4BzJi/5+rvRUXMVgLQJ2umEm9u0XpYdlVmGRImxJoSU8T2qaSaUbA?= =?utf-8?q?JUQcprDIKXX6CUM2ZhX/xU3t3kLSzSSj5jryeQvcu7+ErPP60UIRssd5zXblr8J9Z?= =?utf-8?q?pwf/zTyAJErZhyBZy1VvT2/L+QkztOd8ZOTh+t1W2Blke4i8jGHRhmFwU9zke9lU6?= =?utf-8?q?ScpoITAZHGOqX4cwvgwWtTc86k9457ZOeXoctay2E9+p1rPnU6xmlAmhUA1a1YJPm?= =?utf-8?q?/aTZP5ZcOM+lxDnMP+lH8/HXUvdLqn8G4RbKJM3IQrHhHtY8Y6+4Bw=3D?= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(36860700013)(82310400026)(376014)(7416014)(1800799024); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Feb 2025 11:13:42.0564 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 1b55741a-4ccb-482a-1d3f-08dd500d4d7b X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN3PEPF0000B074.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM4PR12MB8449 On AND SEV, the AMD PSP firmware acts as TSM (manages the security/trust). The CCP driver provides the interface to it and registers itself in the TSM-HOST subsystem. Implement SEV TIO PSP command wrappers in sev-dev-tio.c, these make SPDM calls and store the data in the SEV-TIO-specific structs. Implement TSM-HOST hooks in sev-dev-tsm.c. Signed-off-by: Alexey Kardashevskiy --- drivers/crypto/ccp/Makefile | 13 + arch/x86/include/asm/sev.h | 20 + drivers/crypto/ccp/sev-dev-tio.h | 111 ++ drivers/crypto/ccp/sev-dev.h | 18 + include/linux/psp-sev.h | 27 + include/uapi/linux/psp-sev.h | 2 + drivers/crypto/ccp/sev-dev-tio.c | 1664 ++++++++++++++++++++ drivers/crypto/ccp/sev-dev-tsm.c | 709 +++++++++ drivers/crypto/ccp/sev-dev.c | 10 +- drivers/virt/coco/host/tsm-host.c | 4 +- drivers/crypto/ccp/Kconfig | 2 + 11 files changed, 2576 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile index 5ce69134ec48..8868896f3fd5 100644 --- a/drivers/crypto/ccp/Makefile +++ b/drivers/crypto/ccp/Makefile @@ -14,6 +14,19 @@ ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o \ platform-access.o \ dbc.o \ hsti.o + +ifeq ($(CONFIG_CRYPTO_DEV_SP_PSP)$(CONFIG_PCI_TSM),yy) +ccp-y += sev-dev-tsm.o sev-dev-tio.o +endif + +ifeq ($(CONFIG_CRYPTO_DEV_SP_PSP)$(CONFIG_PCI_TSM),ym) +ccp-m += sev-dev-tsm.o sev-dev-tio.o +endif + +ifeq ($(CONFIG_CRYPTO_DEV_SP_PSP)$(CONFIG_PCI_TSM),mm) +ccp-m += sev-dev-tsm.o sev-dev-tio.o +endif + ccp-$(CONFIG_CRYPTO_DEV_SP_PSP_FW_UPLOAD) += sev-fw.o obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h index 46a7e5d45275..c5e9455df0dc 100644 --- a/arch/x86/include/asm/sev.h +++ b/arch/x86/include/asm/sev.h @@ -146,6 +146,14 @@ enum msg_type { SNP_MSG_ABSORB_RSP, SNP_MSG_VMRK_REQ, SNP_MSG_VMRK_RSP, + TIO_MSG_TDI_INFO_REQ = 0x81, + TIO_MSG_TDI_INFO_RSP = 0x01, + TIO_MSG_MMIO_VALIDATE_REQ = 0x82, + TIO_MSG_MMIO_VALIDATE_RSP = 0x02, + TIO_MSG_MMIO_CONFIG_REQ = 0x83, + TIO_MSG_MMIO_CONFIG_RSP = 0x03, + TIO_MSG_SDTE_WRITE_REQ = 0x84, + TIO_MSG_SDTE_WRITE_RSP = 0x04, SNP_MSG_TSC_INFO_REQ = 17, SNP_MSG_TSC_INFO_RSP, @@ -209,6 +217,18 @@ struct snp_guest_req { void *data; }; +/* SPDM algorithms used for TDISP, used in TIO_MSG_TDI_INFO_REQ */ +#define TIO_SPDM_ALGOS_DHE_SECP256R1 0 +#define TIO_SPDM_ALGOS_DHE_SECP384R1 1 +#define TIO_SPDM_ALGOS_AEAD_AES_128_GCM (0<<8) +#define TIO_SPDM_ALGOS_AEAD_AES_256_GCM (1<<8) +#define TIO_SPDM_ALGOS_ASYM_TPM_ALG_RSASSA_3072 (0<<16) +#define TIO_SPDM_ALGOS_ASYM_TPM_ALG_ECDSA_ECC_NIST_P256 (1<<16) +#define TIO_SPDM_ALGOS_ASYM_TPM_ALG_ECDSA_ECC_NIST_P384 (2<<16) +#define TIO_SPDM_ALGOS_HASH_TPM_ALG_SHA_256 (0<<24) +#define TIO_SPDM_ALGOS_HASH_TPM_ALG_SHA_384 (1<<24) +#define TIO_SPDM_ALGOS_KEY_SCHED_SPDM_KEY_SCHEDULE (0ULL<<32) + /* * The secrets page contains 96-bytes of reserved field that can be used by * the guest OS. The guest OS uses the area to save the message sequence diff --git a/drivers/crypto/ccp/sev-dev-tio.h b/drivers/crypto/ccp/sev-dev-tio.h new file mode 100644 index 000000000000..98d6797fea5e --- /dev/null +++ b/drivers/crypto/ccp/sev-dev-tio.h @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __PSP_SEV_TIO_H__ +#define __PSP_SEV_TIO_H__ + +#include +#include +#include + +#if defined(CONFIG_CRYPTO_DEV_SP_PSP) || defined(CONFIG_CRYPTO_DEV_SP_PSP_MODULE) + +struct sla_addr_t { + union { + u64 sla; + struct { + u64 page_type:1; + u64 page_size:1; + u64 reserved1:10; + u64 pfn:40; + u64 reserved2:12; + }; + }; +} __packed; + +#define SEV_TIO_MAX_COMMAND_LENGTH 128 +#define SEV_TIO_MAX_DATA_LENGTH 256 + +/* struct tsm_dev::data */ +struct tsm_dev_tio { + struct sla_addr_t dev_ctx; + struct sla_addr_t req; + struct sla_addr_t resp; + struct sla_addr_t scratch; + struct sla_addr_t output; + size_t output_len; + size_t scratch_len; + struct sla_buffer_hdr *reqbuf; /* vmap'ed @req for DOE */ + struct sla_buffer_hdr *respbuf; /* vmap'ed @resp for DOE */ + + int cmd; + int psp_ret; + u8 cmd_data[SEV_TIO_MAX_COMMAND_LENGTH]; + u8 *data_pg; /* Data page for SPDM-aware commands returning some data */ + + struct sev_tio_status *tio_status; + void *guest_req_buf; /* Bounce buffer for TIO Guest Request input */ + void *guest_resp_buf; /* Bounce buffer for TIO Guest Request output */ + + struct pci_ide ide; +}; + +/* struct tsm_tdi::data */ +struct tsm_tdi_tio { + struct sla_addr_t tdi_ctx; + u64 gctx_paddr; + u32 asid; +}; + +#define SPDM_DOBJ_ID_NONE 0 +#define SPDM_DOBJ_ID_REQ 1 +#define SPDM_DOBJ_ID_RESP 2 +#define SPDM_DOBJ_ID_CERTIFICATE 4 +#define SPDM_DOBJ_ID_MEASUREMENT 5 +#define SPDM_DOBJ_ID_REPORT 6 + +void sev_tio_cleanup(struct sev_device *sev); + +void tio_save_output(struct tsm_blob **blob, struct sla_addr_t sla, u32 dobjid); + +int sev_tio_status(struct sev_device *sev); +int sev_tio_continue(struct tsm_dev_tio *dev_data, struct tsm_spdm *spdm); + +int sev_tio_dev_measurements(struct tsm_dev_tio *dev_data, void *nonce, size_t nonce_len, + struct tsm_spdm *spdm); +int sev_tio_dev_certificates(struct tsm_dev_tio *dev_data, struct tsm_spdm *spdm); +int sev_tio_dev_create(struct tsm_dev_tio *dev_data, u16 device_id, u16 root_port_id, + u8 segment_id); +int sev_tio_dev_connect(struct tsm_dev_tio *dev_data, u8 tc_mask, u8 ids[8], u8 cert_slot, + struct tsm_spdm *spdm); +int sev_tio_dev_disconnect(struct tsm_dev_tio *dev_data, struct tsm_spdm *spdm); +int sev_tio_dev_reclaim(struct tsm_dev_tio *dev_data, struct tsm_spdm *spdm); +int sev_tio_dev_status(struct tsm_dev_tio *dev_data, struct tsm_dev_status *status); +int sev_tio_ide_refresh(struct tsm_dev_tio *dev_data, struct tsm_spdm *spdm); + +int sev_tio_tdi_create(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data, u16 dev_id, + u8 rseg, u8 rseg_valid); +void sev_tio_tdi_reclaim(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data); +int sev_tio_guest_request(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data, + void *req, void *res, struct tsm_spdm *spdm); + +int sev_tio_tdi_bind(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data, + u32 guest_rid, u64 gctx_paddr, u32 asid, bool force_run, + struct tsm_spdm *spdm); +int sev_tio_tdi_unbind(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data, + struct tsm_spdm *spdm); +int sev_tio_tdi_report(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data, + struct tsm_spdm *spdm); + +int sev_tio_asid_fence_clear(u16 device_id, u8 segment_id, u64 gctx_paddr, int *psp_ret); +int sev_tio_asid_fence_status(struct tsm_dev_tio *dev_data, u16 device_id, u8 segment_id, + u32 asid, bool *fenced); + +int sev_tio_tdi_info(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data, + struct tsm_tdi_status *ts); +int sev_tio_tdi_status(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data, + struct tsm_spdm *spdm); +int sev_tio_tdi_status_fin(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data, + enum tsm_tdisp_state *state); + +#endif /* CONFIG_CRYPTO_DEV_SP_PSP */ + +#endif /* __PSP_SEV_TIO_H__ */ diff --git a/drivers/crypto/ccp/sev-dev.h b/drivers/crypto/ccp/sev-dev.h index c87a312f7da6..342fcd42fa7c 100644 --- a/drivers/crypto/ccp/sev-dev.h +++ b/drivers/crypto/ccp/sev-dev.h @@ -43,6 +43,8 @@ struct sev_misc_dev { struct miscdevice misc; }; +struct sev_tio_status; + struct sev_device { struct device *dev; struct psp_device *psp; @@ -71,7 +73,13 @@ struct sev_device { struct fw_upload *fwl; bool fw_cancel; #endif /* CONFIG_FW_UPLOAD */ + bool tio_en; +#if defined(CONFIG_PCI_TSM) || defined(CONFIG_PCI_TSM_MODULE) + struct tsm_host_subsys *tsm; + struct tsm_bus_subsys *tsm_bus; + struct sev_tio_status *tio_status; +#endif }; bool sev_version_greater_or_equal(u8 maj, u8 min); @@ -102,4 +110,14 @@ static inline void sev_snp_destroy_firmware_upload(struct sev_device *sev) { } static inline int sev_snp_synthetic_error(struct sev_device *sev, int *psp_ret) { return 0; } #endif /* CONFIG_CRYPTO_DEV_SP_PSP_FW_UPLOAD */ +#if defined(CONFIG_PCI_TSM) || defined(CONFIG_PCI_TSM_MODULE) +void sev_tsm_init(struct sev_device *sev); +void sev_tsm_uninit(struct sev_device *sev); +int sev_tio_cmd_buffer_len(int cmd); +#else +static inline void sev_tsm_init(struct sev_device *sev) {} +static inline void sev_tsm_uninit(struct sev_device *sev) {} +static inline int sev_tio_cmd_buffer_len(int cmd) { return 0; } +#endif + #endif /* __SEV_DEV_H */ diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h index 103d9c161f41..5d276e2c2112 100644 --- a/include/linux/psp-sev.h +++ b/include/linux/psp-sev.h @@ -12,6 +12,7 @@ #ifndef __PSP_SEV_H__ #define __PSP_SEV_H__ +#include #include #define SEV_FW_BLOB_MAX_SIZE 0x4000 /* 16KB */ @@ -109,6 +110,27 @@ enum sev_cmd { SEV_CMD_SNP_VLEK_LOAD = 0x0CD, SEV_CMD_SNP_FEATURE_INFO = 0x0CE, + /* SEV-TIO commands */ + SEV_CMD_TIO_STATUS = 0x0D0, + SEV_CMD_TIO_INIT = 0x0D1, + SEV_CMD_TIO_DEV_CREATE = 0x0D2, + SEV_CMD_TIO_DEV_RECLAIM = 0x0D3, + SEV_CMD_TIO_DEV_CONNECT = 0x0D4, + SEV_CMD_TIO_DEV_DISCONNECT = 0x0D5, + SEV_CMD_TIO_DEV_STATUS = 0x0D6, + SEV_CMD_TIO_DEV_MEASUREMENTS = 0x0D7, + SEV_CMD_TIO_DEV_CERTIFICATES = 0x0D8, + SEV_CMD_TIO_TDI_CREATE = 0x0DA, + SEV_CMD_TIO_TDI_RECLAIM = 0x0DB, + SEV_CMD_TIO_TDI_BIND = 0x0DC, + SEV_CMD_TIO_TDI_UNBIND = 0x0DD, + SEV_CMD_TIO_TDI_REPORT = 0x0DE, + SEV_CMD_TIO_TDI_STATUS = 0x0DF, + SEV_CMD_TIO_GUEST_REQUEST = 0x0E0, + SEV_CMD_TIO_ASID_FENCE_CLEAR = 0x0E1, + SEV_CMD_TIO_ASID_FENCE_STATUS = 0x0E2, + SEV_CMD_TIO_TDI_INFO = 0x0E3, + SEV_CMD_TIO_ROLL_KEY = 0x0E4, SEV_CMD_MAX, }; @@ -770,6 +792,11 @@ struct sev_data_snp_guest_request { u64 res_paddr; /* In */ } __packed; +struct tio_guest_request { + struct sev_data_snp_guest_request data; + int fw_err; +}; + /** * struct sev_data_snp_init_ex - SNP_INIT_EX structure * diff --git a/include/uapi/linux/psp-sev.h b/include/uapi/linux/psp-sev.h index affa65dcebd4..a2fbc20c5db6 100644 --- a/include/uapi/linux/psp-sev.h +++ b/include/uapi/linux/psp-sev.h @@ -88,6 +88,8 @@ typedef enum { SEV_RET_RMP_INITIALIZATION_FAILED = 0x0026, SEV_RET_INVALID_KEY = 0x0027, SEV_RET_SHUTDOWN_INCOMPLETE = 0x0028, + SEV_RET_INCORRECT_BUFFER_LENGTH = 0x0030, + SEV_RET_EXPAND_BUFFER_LENGTH_REQUEST = 0x0031, SEV_RET_SPDM_REQUEST = 0x0032, SEV_RET_SPDM_ERROR = 0x0033, SEV_RET_IN_USE = 0x003A, diff --git a/drivers/crypto/ccp/sev-dev-tio.c b/drivers/crypto/ccp/sev-dev-tio.c new file mode 100644 index 000000000000..bd55ad6c5fb3 --- /dev/null +++ b/drivers/crypto/ccp/sev-dev-tio.c @@ -0,0 +1,1664 @@ +// SPDX-License-Identifier: GPL-2.0-only + +// Interface to PSP for CCP/SEV-TIO/SNP-VM + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "psp-dev.h" +#include "sev-dev.h" +#include "sev-dev-tio.h" + +static void *__prep_data_pg(struct tsm_dev_tio *dev_data, size_t len) +{ + void *r = dev_data->data_pg; + + if (snp_reclaim_pages(virt_to_phys(r), 1, false)) + return NULL; + + memset(r, 0, len); + + if (rmp_make_private(page_to_pfn(virt_to_page(r)), 0, PG_LEVEL_4K, 0, true)) + return NULL; + + return r; +} + +#define prep_data_pg(type, tdev) ((type *) __prep_data_pg((tdev), sizeof(type))) + +#define SLA_PAGE_TYPE_DATA 0 +#define SLA_PAGE_TYPE_SCATTER 1 +#define SLA_PAGE_SIZE_4K 0 +#define SLA_PAGE_SIZE_2M 1 +#define SLA_SZ(s) ((s).page_size == SLA_PAGE_SIZE_2M ? SZ_2M : SZ_4K) +#define SLA_SCATTER_LEN(s) (SLA_SZ(s) / sizeof(struct sla_addr_t)) +#define SLA_EOL ((struct sla_addr_t) { .pfn = 0xFFFFFFFFFFUL }) +#define SLA_NULL ((struct sla_addr_t) { 0 }) +#define IS_SLA_NULL(s) ((s).sla == SLA_NULL.sla) +#define IS_SLA_EOL(s) ((s).sla == SLA_EOL.sla) + +/* the BUFFER Structure */ +struct sla_buffer_hdr { + u32 capacity_sz; + u32 payload_sz; /* The size of BUFFER_PAYLOAD in bytes. Must be multiple of 32B */ + union { + u32 flags; + struct { + u32 encryption:1; + }; + }; + u32 reserved1; + u8 iv[16]; /* IV used for the encryption of this buffer */ + u8 authtag[16]; /* Authentication tag for this buffer */ + u8 reserved2[16]; +} __packed; + +struct spdm_dobj_hdr { + u32 id; /* Data object type identifier */ + u32 length; /* Length of the data object, INCLUDING THIS HEADER */ + union { + u16 ver; /* Version of the data object structure */ + struct { + u8 minor; + u8 major; + } version; + }; +} __packed; + +enum spdm_data_type_t { + DOBJ_DATA_TYPE_SPDM = 0x1, + DOBJ_DATA_TYPE_SECURE_SPDM = 0x2, +}; + +struct spdm_dobj_hdr_req { + struct spdm_dobj_hdr hdr; /* hdr.id == SPDM_DOBJ_ID_REQ */ + u8 data_type; /* spdm_data_type_t */ + u8 reserved2[5]; +} __packed; + +struct spdm_dobj_hdr_resp { + struct spdm_dobj_hdr hdr; /* hdr.id == SPDM_DOBJ_ID_RESP */ + u8 data_type; /* spdm_data_type_t */ + u8 reserved2[5]; +} __packed; + +struct spdm_dobj_hdr_cert { + struct spdm_dobj_hdr hdr; /* hdr.id == SPDM_DOBJ_ID_CERTIFICATE */ + u8 reserved1[6]; + u16 device_id; + u8 segment_id; + u8 type; /* 1h: SPDM certificate. 0h, 2h–FFh: Reserved. */ + u8 reserved2[12]; +} __packed; + +struct spdm_dobj_hdr_meas { + struct spdm_dobj_hdr hdr; /* hdr.id == SPDM_DOBJ_ID_MEASUREMENT */ + u8 reserved1[6]; + u16 device_id; + u8 segment_id; + u8 type; /* 1h: SPDM measurement. 0h, 2h–FFh: Reserved. */ + u8 reserved2[12]; +} __packed; + +struct spdm_dobj_hdr_report { + struct spdm_dobj_hdr hdr; /* hdr.id == SPDM_DOBJ_ID_REPORT */ + u8 reserved1[6]; + u16 device_id; + u8 segment_id; + u8 type; /* 1h: TDISP interface report. 0h, 2h–FFh: Reserved */ + u8 reserved2[12]; +} __packed; + +/* Used in all SPDM-aware TIO commands */ +struct spdm_ctrl { + struct sla_addr_t req; + struct sla_addr_t resp; + struct sla_addr_t scratch; + struct sla_addr_t output; +} __packed; + +static size_t sla_dobj_id_to_size(u8 id) +{ + size_t n; + + BUILD_BUG_ON(sizeof(struct spdm_dobj_hdr_resp) != 0x10); + switch (id) { + case SPDM_DOBJ_ID_REQ: + n = sizeof(struct spdm_dobj_hdr_req); + break; + case SPDM_DOBJ_ID_RESP: + n = sizeof(struct spdm_dobj_hdr_resp); + break; + case SPDM_DOBJ_ID_CERTIFICATE: + n = sizeof(struct spdm_dobj_hdr_cert); + break; + case SPDM_DOBJ_ID_MEASUREMENT: + n = sizeof(struct spdm_dobj_hdr_meas); + break; + case SPDM_DOBJ_ID_REPORT: + n = sizeof(struct spdm_dobj_hdr_report); + break; + default: + WARN_ON(1); + n = 0; + break; + } + + return n; +} + +#define SPDM_DOBJ_HDR_SIZE(hdr) sla_dobj_id_to_size((hdr)->id) +#define SPDM_DOBJ_DATA(hdr) ((u8 *)(hdr) + SPDM_DOBJ_HDR_SIZE(hdr)) +#define SPDM_DOBJ_LEN(hdr) ((hdr)->length - SPDM_DOBJ_HDR_SIZE(hdr)) + +#define sla_to_dobj_resp_hdr(buf) ((struct spdm_dobj_hdr_resp *) \ + sla_to_dobj_hdr_check((buf), SPDM_DOBJ_ID_RESP)) +#define sla_to_dobj_req_hdr(buf) ((struct spdm_dobj_hdr_req *) \ + sla_to_dobj_hdr_check((buf), SPDM_DOBJ_ID_REQ)) + +static struct spdm_dobj_hdr *sla_to_dobj_hdr(struct sla_buffer_hdr *buf) +{ + if (!buf) + return NULL; + + return (struct spdm_dobj_hdr *) &buf[1]; +} + +static struct spdm_dobj_hdr *sla_to_dobj_hdr_check(struct sla_buffer_hdr *buf, u32 check_dobjid) +{ + struct spdm_dobj_hdr *hdr = sla_to_dobj_hdr(buf); + + if (hdr && hdr->id == check_dobjid) + return hdr; + + pr_err("! ERROR: expected %d, found %d\n", check_dobjid, hdr->id); + return NULL; +} + +static void *sla_to_data(struct sla_buffer_hdr *buf, u32 dobjid) +{ + struct spdm_dobj_hdr *hdr = sla_to_dobj_hdr(buf); + + if (WARN_ON_ONCE(dobjid != SPDM_DOBJ_ID_REQ && dobjid != SPDM_DOBJ_ID_RESP)) + return NULL; + + if (!hdr) + return NULL; + + return (u8 *) hdr + sla_dobj_id_to_size(dobjid); +} + +/** + * struct sev_tio_status - TIO_STATUS command's info_paddr buffer + * + * @length: Length of this structure in bytes. + * @tio_init_done: Indicates TIO_INIT has been invoked + * @tio_en: Indicates that SNP_INIT_EX initialized the RMP for SEV-TIO. + * @spdm_req_size_min: Minimum SPDM request buffer size in bytes. + * @spdm_req_size_max: Maximum SPDM request buffer size in bytes. + * @spdm_scratch_size_min: Minimum SPDM scratch buffer size in bytes. + * @spdm_scratch_size_max: Maximum SPDM scratch buffer size in bytes. + * @spdm_out_size_min: Minimum SPDM output buffer size in bytes + * @spdm_out_size_max: Maximum for the SPDM output buffer size in bytes. + * @spdm_rsp_size_min: Minimum SPDM response buffer size in bytes. + * @spdm_rsp_size_max: Maximum SPDM response buffer size in bytes. + * @devctx_size: Size of a device context buffer in bytes. + * @tdictx_size: Size of a TDI context buffer in bytes. + */ +struct sev_tio_status { + u32 length; + union { + u32 flags; + struct { + u32 tio_en:1; + u32 tio_init_done:1; + }; + }; + u32 spdm_req_size_min; + u32 spdm_req_size_max; + u32 spdm_scratch_size_min; + u32 spdm_scratch_size_max; + u32 spdm_out_size_min; + u32 spdm_out_size_max; + u32 spdm_rsp_size_min; + u32 spdm_rsp_size_max; + u32 devctx_size; + u32 tdictx_size; +}; + +/** + * struct sev_data_tio_status - SEV_CMD_TIO_STATUS command + * + * @length: Length of this command buffer in bytes + * @status_paddr: SPA of the TIO_STATUS structure + */ +struct sev_data_tio_status { + u32 length; + u32 reserved; + u64 status_paddr; +} __packed; + +/* TIO_INIT */ +struct sev_data_tio_init { + u32 length; + u32 reserved[3]; +} __packed; + +void sev_tio_cleanup(struct sev_device *sev) +{ + kfree(sev->tio_status); + sev->tio_status = NULL; +} + +/** + * struct sev_data_tio_dev_create - TIO_DEV_CREATE command + * + * @length: Length in bytes of this command buffer. + * @dev_ctx_sla: A scatter list address pointing to a buffer to be used as a device context buffer. + * @device_id: The PCIe Routing Identifier of the device to connect to. + * @root_port_id: FiXME: The PCIe Routing Identifier of the root port of the device. + * @segment_id: The PCIe Segment Identifier of the device to connect to. + */ +struct sev_data_tio_dev_create { + u32 length; + u32 reserved1; + struct sla_addr_t dev_ctx_sla; + u16 device_id; + u16 root_port_id; + u8 segment_id; + u8 reserved2[11]; +} __packed; + +/** + * struct sev_data_tio_dev_connect - TIO_DEV_CONNECT + * + * @length: Length in bytes of this command buffer. + * @spdm_ctrl: SPDM control structure defined in Section 5.1. + * @device_id: The PCIe Routing Identifier of the device to connect to. + * @root_port_id: The PCIe Routing Identifier of the root port of the device. + * @segment_id: The PCIe Segment Identifier of the device to connect to. + * @dev_ctx_sla: Scatter list address of the device context buffer. + * @tc_mask: Bitmask of the traffic classes to initialize for SEV-TIO usage. + * Setting the kth bit of the TC_MASK to 1 indicates that the traffic + * class k will be initialized. + * @cert_slot: Slot number of the certificate requested for constructing the SPDM session. + * @ide_stream_id: IDE stream IDs to be associated with this device. + * Valid only if corresponding bit in TC_MASK is set. + */ +struct sev_data_tio_dev_connect { + u32 length; + u32 reserved1; + struct spdm_ctrl spdm_ctrl; + u8 reserved2[8]; + struct sla_addr_t dev_ctx_sla; + u8 tc_mask; + u8 cert_slot; + u8 reserved3[6]; + u8 ide_stream_id[8]; + u8 reserved4[8]; +} __packed; + +/** + * struct sev_data_tio_dev_disconnect - TIO_DEV_DISCONNECT + * + * @length: Length in bytes of this command buffer. + * @force: Force device disconnect without SPDM traffic. + * @spdm_ctrl: SPDM control structure defined in Section 5.1. + * @dev_ctx_sla: Scatter list address of the device context buffer. + */ +struct sev_data_tio_dev_disconnect { + u32 length; + union { + u32 flags; + struct { + u32 force:1; + }; + }; + struct spdm_ctrl spdm_ctrl; + struct sla_addr_t dev_ctx_sla; +} __packed; + +/** + * struct sev_data_tio_dev_meas - TIO_DEV_MEASUREMENTS + * + * @length: Length in bytes of this command buffer + * @raw_bitstream: 0: Requests the digest form of the attestation report + * 1: Requests the raw bitstream form of the attestation report + * @spdm_ctrl: SPDM control structure defined in Section 5.1. + * @dev_ctx_sla: Scatter list address of the device context buffer. + */ +struct sev_data_tio_dev_meas { + u32 length; + union { + u32 flags; + struct { + u32 raw_bitstream:1; + }; + }; + struct spdm_ctrl spdm_ctrl; + struct sla_addr_t dev_ctx_sla; + u8 meas_nonce[32]; +} __packed; + +/** + * struct sev_data_tio_dev_certs - TIO_DEV_CERTIFICATES + * + * @length: Length in bytes of this command buffer + * @spdm_ctrl: SPDM control structure defined in Section 5.1. + * @dev_ctx_sla: Scatter list address of the device context buffer. + */ +struct sev_data_tio_dev_certs { + u32 length; + u32 reserved; + struct spdm_ctrl spdm_ctrl; + struct sla_addr_t dev_ctx_sla; +} __packed; + +/** + * struct sev_data_tio_dev_reclaim - TIO_DEV_RECLAIM command + * + * @length: Length in bytes of this command buffer + * @dev_ctx_paddr: SPA of page donated by hypervisor + */ +struct sev_data_tio_dev_reclaim { + u32 length; + u32 reserved; + struct sla_addr_t dev_ctx_sla; +} __packed; + +/** + * struct sev_tio_dev_status - sev_data_tio_dev_status::status_paddr of + * TIO_DEV_STATUS command + * + */ +struct sev_tio_dev_status { + u32 length; + u8 ctx_state; + u8 reserved1; + union { + u8 p1; + struct { + u8 request_pending:1; + u8 request_pending_tdi:1; + }; + }; + u8 certs_slot; + u16 device_id; + u8 segment_id; + u8 tc_mask; + u16 request_pending_command; + u16 reserved2; + struct tdisp_interface_id request_pending_interface_id; + union { + u8 p2; + struct { + u8 meas_digest_valid:1; + u8 no_fw_update:1; + }; + }; + u8 reserved3[3]; + u8 ide_stream_id[8]; + u8 reserved4[8]; + u8 certs_digest[48]; + u8 meas_digest[48]; + u32 tdi_count; + u32 bound_tdi_count; + u8 reserved5[8]; +} __packed; + +/** + * struct sev_data_tio_dev_status - TIO_DEV_STATUS command + * + * @length: Length in bytes of this command buffer + * @dev_ctx_paddr: SPA of a device context page + * @status_length: Length in bytes of the sev_tio_dev_status buffer + * @status_paddr: SPA of the status buffer. See Table 16 + */ +struct sev_data_tio_dev_status { + u32 length; /* In */ + u32 reserved; + struct sla_addr_t dev_ctx_paddr; /* In */ + u32 status_length; /* In */ + u64 status_paddr; /* In */ +} __packed; + +/** + * struct sev_data_tio_tdi_create - TIO_TDI_CREATE command + * + * @length: Length in bytes of this command buffer + * @spdm_ctrl: SPDM control structure + * @dev_ctx_paddr: SPA of a device context page + * @tdi_ctx_paddr: SPA of page donated by hypervisor + * @interface_id: Interface ID of the TDI as defined by TDISP (host PCIID) + */ +struct sev_data_tio_tdi_create { + u32 length; /* In */ + u32 reserved; + struct sla_addr_t dev_ctx_sla; /* In */ + struct sla_addr_t tdi_ctx_sla; /* In */ + struct tdisp_interface_id interface_id; /* In */ + u8 reserved2[12]; +} __packed; + +struct sev_data_tio_tdi_reclaim { + u32 length; /* In */ + u32 reserved; + struct sla_addr_t dev_ctx_sla; /* In */ + struct sla_addr_t tdi_ctx_sla; /* In */ + u64 reserved2; +} __packed; + +/* + * struct sev_data_tio_tdi_bind - TIO_TDI_BIND command + * + * @length: Length in bytes of this command buffer + * @spdm_ctrl: SPDM control structure defined in Chapter 2. + * @tdi_ctx_paddr: SPA of page donated by hypervisor + * @guest_ctx_paddr: SPA of guest context page + * @flags: + * 4 ALL_REQUEST_REDIRECT Requires ATS translated requests to route through + * the root complex. Must be 1. + * 3 BIND_P2P Enables direct P2P. Must be 0 + * 2 LOCK_MSIX Lock the MSI-X table and PBA. + * 1 CACHE_LINE_SIZE Indicates the cache line size. 0 indicates 64B. 1 indicates 128B. + * Must be 0. + * 0 NO_FW_UPDATE Indicates that no firmware updates are allowed while the interface + * is locked. + * @mmio_reporting_offset: Offset added to the MMIO range addresses in the interface + * report. + * @guest_interface_id: Hypervisor provided identifier used by the guest to identify + * the TDI in guest messages + */ +struct sev_data_tio_tdi_bind { + u32 length; /* In */ + u32 reserved; + struct spdm_ctrl spdm_ctrl; /* In */ + struct sla_addr_t dev_ctx_sla; + struct sla_addr_t tdi_ctx_sla; + u64 gctx_paddr; + u16 guest_device_id; + union { + u16 flags; + /* These are TDISP's LOCK_INTERFACE_REQUEST flags */ + struct { + u16 no_fw_update:1; + u16 reservedf1:1; + u16 lock_msix:1; + u16 bind_p2p:1; + u16 all_request_redirect:1; + }; + } tdisp_lock_if; + u16 run:1; + u16 reserved2:15; + u8 reserved3[2]; +} __packed; + +/* + * struct sev_data_tio_tdi_unbind - TIO_TDI_UNBIND command + * + * @length: Length in bytes of this command buffer + * @spdm_ctrl: SPDM control structure defined in Chapter 2. + * @tdi_ctx_paddr: SPA of page donated by hypervisor + */ +struct sev_data_tio_tdi_unbind { + u32 length; /* In */ + u32 reserved; + struct spdm_ctrl spdm_ctrl; /* In */ + struct sla_addr_t dev_ctx_sla; + struct sla_addr_t tdi_ctx_sla; + u64 gctx_paddr; /* In */ +} __packed; + +/* + * struct sev_data_tio_tdi_report - TIO_TDI_REPORT command + * + * @length: Length in bytes of this command buffer + * @spdm_ctrl: SPDM control structure defined in Chapter 2. + * @dev_ctx_sla: Scatter list address of the device context buffer + * @tdi_ctx_paddr: Scatter list address of a TDI context buffer + * @guest_ctx_paddr: System physical address of a guest context page + */ +struct sev_data_tio_tdi_report { + u32 length; + u32 reserved; + struct spdm_ctrl spdm_ctrl; + struct sla_addr_t dev_ctx_sla; + struct sla_addr_t tdi_ctx_sla; + u64 gctx_paddr; +} __packed; + +struct sev_data_tio_asid_fence_clear { + u32 length; /* In */ + u32 reserved1; + u64 gctx_paddr; /* In */ + u16 device_id; + u8 segment_id; + u8 reserved[13]; +} __packed; + +struct sev_data_tio_asid_fence_status { + u32 length; /* In */ + u32 asid; /* In */ + u64 status_pa; + u16 device_id; + u8 segment_id; + u8 reserved[13]; +} __packed; + +/** + * struct sev_data_tio_guest_request - TIO_GUEST_REQUEST command + * + * @length: Length in bytes of this command buffer + * @spdm_ctrl: SPDM control structure defined in Chapter 2. + * @gctx_paddr: system physical address of guest context page + * @tdi_ctx_paddr: SPA of page donated by hypervisor + * @req_paddr: system physical address of request page + * @res_paddr: system physical address of response page + */ +struct sev_data_tio_guest_request { + u32 length; /* In */ + u32 reserved; + struct spdm_ctrl spdm_ctrl; /* In */ + struct sla_addr_t dev_ctx_sla; + struct sla_addr_t tdi_ctx_sla; + u64 gctx_paddr; + u64 req_paddr; /* In */ + u64 res_paddr; /* In */ +} __packed; + +struct sev_data_tio_roll_key { + u32 length; /* In */ + u32 reserved; + struct spdm_ctrl spdm_ctrl; /* In */ + struct sla_addr_t dev_ctx_sla; /* In */ +} __packed; + +static struct sla_buffer_hdr *sla_buffer_map(struct sla_addr_t sla) +{ + struct sla_buffer_hdr *buf; + + BUILD_BUG_ON(sizeof(struct sla_buffer_hdr) != 0x40); + if (IS_SLA_NULL(sla)) + return NULL; + + if (sla.page_type == SLA_PAGE_TYPE_SCATTER) { + struct sla_addr_t *scatter = __va((u64)sla.pfn << PAGE_SHIFT); + unsigned int i, npages = 0; + struct page **pp; + + for (i = 0; i < SLA_SCATTER_LEN(sla); ++i) { + if (WARN_ON_ONCE(SLA_SZ(scatter[i]) > SZ_4K)) + return NULL; + + if (WARN_ON_ONCE(scatter[i].page_type == SLA_PAGE_TYPE_SCATTER)) + return NULL; + + if (IS_SLA_EOL(scatter[i])) { + npages = i; + break; + } + } + if (WARN_ON_ONCE(!npages)) + return NULL; + + pp = kmalloc_array(npages, sizeof(pp[0]), GFP_KERNEL); + if (!pp) + return NULL; + + for (i = 0; i < npages; ++i) + pp[i] = pfn_to_page(scatter[i].pfn); + + buf = vm_map_ram(pp, npages, 0); + kfree(pp); + } else { + struct page *pg = pfn_to_page(sla.pfn); + + buf = vm_map_ram(&pg, 1, 0); + } + + return buf; +} + +static void sla_buffer_unmap(struct sla_addr_t sla, struct sla_buffer_hdr *buf) +{ + if (!buf) + return; + + if (sla.page_type == SLA_PAGE_TYPE_SCATTER) { + struct sla_addr_t *scatter = __va((u64)sla.pfn << PAGE_SHIFT); + unsigned int i, npages = 0; + + for (i = 0; i < SLA_SCATTER_LEN(sla); ++i) { + if (IS_SLA_EOL(scatter[i])) { + npages = i; + break; + } + } + if (!npages) + return; + + vm_unmap_ram(buf, npages); + } else { + vm_unmap_ram(buf, 1); + } +} + +static void dobj_response_init(struct sla_buffer_hdr *buf) +{ + struct spdm_dobj_hdr *dobj = sla_to_dobj_hdr(buf); + + dobj->id = SPDM_DOBJ_ID_RESP; + dobj->version.major = 0x1; + dobj->version.minor = 0; + dobj->length = 0; + buf->payload_sz = sla_dobj_id_to_size(dobj->id) + dobj->length; +} + +static void sla_free(struct sla_addr_t sla, size_t len, bool firmware_state) +{ + unsigned int npages = PAGE_ALIGN(len) >> PAGE_SHIFT; + struct sla_addr_t *scatter = NULL; + int ret = 0, i; + + if (IS_SLA_NULL(sla)) + return; + + if (firmware_state) { + if (sla.page_type == SLA_PAGE_TYPE_SCATTER) { + scatter = __va((u64)sla.pfn << PAGE_SHIFT); + + for (i = 0; i < npages; ++i) { + if (IS_SLA_EOL(scatter[i])) + break; + + ret = snp_reclaim_pages( + (u64)scatter[i].pfn << PAGE_SHIFT, + 1, false); + if (ret) + break; + } + } else { + pr_err("Reclaiming %llx\n", (u64)sla.pfn << PAGE_SHIFT); + ret = snp_reclaim_pages((u64)sla.pfn << PAGE_SHIFT, 1, false); + } + } + + if (WARN_ON(ret)) + return; + + if (scatter) { + for (i = 0; i < npages; ++i) { + if (IS_SLA_EOL(scatter[i])) + break; + free_page((unsigned long)__va((u64)scatter[i].pfn << PAGE_SHIFT)); + } + } + + free_page((unsigned long)__va((u64)sla.pfn << PAGE_SHIFT)); +} + +static struct sla_addr_t sla_alloc(size_t len, bool firmware_state) +{ + unsigned long i, npages = PAGE_ALIGN(len) >> PAGE_SHIFT; + struct sla_addr_t *scatter = NULL; + struct sla_addr_t ret = SLA_NULL; + struct sla_buffer_hdr *buf; + struct page *pg; + + if (npages == 0) + return ret; + + if (WARN_ON_ONCE(npages > ((PAGE_SIZE / sizeof(struct sla_addr_t)) + 1))) + return ret; + + BUILD_BUG_ON(PAGE_SIZE < SZ_4K); + + if (npages > 1) { + pg = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!pg) + return SLA_NULL; + + ret.pfn = page_to_pfn(pg); + ret.page_size = SLA_PAGE_SIZE_4K; + ret.page_type = SLA_PAGE_TYPE_SCATTER; + + scatter = page_to_virt(pg); + for (i = 0; i < npages; ++i) { + pg = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!pg) + goto no_reclaim_exit; + + scatter[i].pfn = page_to_pfn(pg); + scatter[i].page_type = SLA_PAGE_TYPE_DATA; + scatter[i].page_size = SLA_PAGE_SIZE_4K; + } + scatter[i] = SLA_EOL; + } else { + pg = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!pg) + return SLA_NULL; + + ret.pfn = page_to_pfn(pg); + ret.page_size = SLA_PAGE_SIZE_4K; + ret.page_type = SLA_PAGE_TYPE_DATA; + } + + buf = sla_buffer_map(ret); + if (!buf) + goto no_reclaim_exit; + + buf->capacity_sz = (npages << PAGE_SHIFT); + sla_buffer_unmap(ret, buf); + + if (firmware_state) { + if (scatter) { + for (i = 0; i < npages; ++i) { + if (rmp_make_private(scatter[i].pfn, 0, PG_LEVEL_4K, 0, true)) + goto free_exit; + } + } else { + if (rmp_make_private(ret.pfn, 0, PG_LEVEL_4K, 0, true)) + goto no_reclaim_exit; + } + } + + return ret; + +no_reclaim_exit: + firmware_state = false; +free_exit: + sla_free(ret, len, firmware_state); + return SLA_NULL; +} + +/* Expands a buffer, only firmware owned buffers allowed for now */ +static int sla_expand(struct sla_addr_t *sla, size_t *len) +{ + struct sla_buffer_hdr *oldbuf = sla_buffer_map(*sla), *newbuf; + struct sla_addr_t oldsla = *sla, newsla; + size_t oldlen = *len, newlen; + + if (!oldbuf) + return -EFAULT; + + newlen = oldbuf->capacity_sz; + if (oldbuf->capacity_sz == oldlen) { + /* This buffer does not require expansion, must be another buffer */ + sla_buffer_unmap(oldsla, oldbuf); + return 1; + } + + pr_notice("Expanding BUFFER from %ld to %ld bytes\n", oldlen, newlen); + + newsla = sla_alloc(newlen, true); + if (IS_SLA_NULL(newsla)) + return -ENOMEM; + + newbuf = sla_buffer_map(newsla); + if (!newbuf) { + sla_free(newsla, newlen, true); + return -EFAULT; + } + + memcpy(newbuf, oldbuf, oldlen); + + sla_buffer_unmap(newsla, newbuf); + sla_free(oldsla, oldlen, true); + *sla = newsla; + *len = newlen; + + return 0; +} + +void tio_save_output(struct tsm_blob **blob, struct sla_addr_t sla, u32 check_dobjid) +{ + struct sla_buffer_hdr *buf; + struct spdm_dobj_hdr *hdr; + + tsm_blob_free(*blob); + *blob = NULL; + + buf = sla_buffer_map(sla); + if (!buf) + return; + + hdr = sla_to_dobj_hdr_check(buf, check_dobjid); + if (hdr) + *blob = tsm_blob_new(SPDM_DOBJ_DATA(hdr), hdr->length); + + sla_buffer_unmap(sla, buf); +} + +static int sev_tio_do_cmd(int cmd, void *data, size_t data_len, int *psp_ret, + struct tsm_dev_tio *dev_data, struct tsm_spdm *spdm) +{ + int rc; + + *psp_ret = 0; + rc = sev_do_cmd(cmd, data, psp_ret); + + if (WARN_ON(!spdm && !rc && *psp_ret == SEV_RET_SPDM_REQUEST)) + return -EIO; + + if (rc == 0 && *psp_ret == SEV_RET_EXPAND_BUFFER_LENGTH_REQUEST) { + int rc1, rc2; + + rc1 = sla_expand(&dev_data->output, &dev_data->output_len); + if (rc1 < 0) + return rc1; + + rc2 = sla_expand(&dev_data->scratch, &dev_data->scratch_len); + if (rc2 < 0) + return rc2; + + if (!rc1 && !rc2) + /* Neither buffer requires expansion, this is wrong */ + return -EFAULT; + + *psp_ret = 0; + rc = sev_do_cmd(cmd, data, psp_ret); + } + + if (spdm && (rc == 0 || rc == -EIO) && *psp_ret == SEV_RET_SPDM_REQUEST) { + struct spdm_dobj_hdr_resp *resp_hdr; + struct spdm_dobj_hdr_req *req_hdr; + size_t resp_len = dev_data->tio_status->spdm_req_size_max - + (sla_dobj_id_to_size(SPDM_DOBJ_ID_RESP) + sizeof(struct sla_buffer_hdr)); + + if (!dev_data->cmd) { + if (WARN_ON_ONCE(!data_len || (data_len != *(u32 *) data))) + return -EINVAL; + if (WARN_ON(data_len > sizeof(dev_data->cmd_data))) + return -EFAULT; + memcpy(dev_data->cmd_data, data, data_len); + memset(&dev_data->cmd_data[data_len], 0xFF, + sizeof(dev_data->cmd_data) - data_len); + dev_data->cmd = cmd; + } + + req_hdr = sla_to_dobj_req_hdr(dev_data->reqbuf); + resp_hdr = sla_to_dobj_resp_hdr(dev_data->respbuf); + switch (req_hdr->data_type) { + case DOBJ_DATA_TYPE_SPDM: + rc = TSM_PROTO_CMA_SPDM; + break; + case DOBJ_DATA_TYPE_SECURE_SPDM: + rc = TSM_PROTO_SECURED_CMA_SPDM; + break; + default: + rc = -EINVAL; + return rc; + } + resp_hdr->data_type = req_hdr->data_type; + spdm->req_len = req_hdr->hdr.length; + spdm->rsp_len = resp_len; + } else if (dev_data && dev_data->cmd) { + /* For either error or success just stop the bouncing */ + memset(dev_data->cmd_data, 0, sizeof(dev_data->cmd_data)); + dev_data->cmd = 0; + } + + return rc; +} + +int sev_tio_continue(struct tsm_dev_tio *dev_data, struct tsm_spdm *spdm) +{ + struct spdm_dobj_hdr_resp *resp_hdr; + int ret; + + if (!dev_data || !dev_data->cmd) + return -EINVAL; + + resp_hdr = sla_to_dobj_resp_hdr(dev_data->respbuf); + resp_hdr->hdr.length = ALIGN(sla_dobj_id_to_size(SPDM_DOBJ_ID_RESP) + spdm->rsp_len, 32); + dev_data->respbuf->payload_sz = resp_hdr->hdr.length; + + ret = sev_tio_do_cmd(dev_data->cmd, dev_data->cmd_data, 0, + &dev_data->psp_ret, dev_data, spdm); + + return ret; +} + +static int spdm_ctrl_init(struct tsm_spdm *spdm, struct spdm_ctrl *ctrl, + struct tsm_dev_tio *dev_data) +{ + ctrl->req = dev_data->req; + ctrl->resp = dev_data->resp; + ctrl->scratch = dev_data->scratch; + ctrl->output = dev_data->output; + + spdm->req = sla_to_data(dev_data->reqbuf, SPDM_DOBJ_ID_REQ); + spdm->rsp = sla_to_data(dev_data->respbuf, SPDM_DOBJ_ID_RESP); + if (!spdm->req || !spdm->rsp) + return -EFAULT; + + return 0; +} + +static void spdm_ctrl_free(struct tsm_dev_tio *dev_data, struct tsm_spdm *spdm) +{ + size_t len = dev_data->tio_status->spdm_req_size_max - + (sla_dobj_id_to_size(SPDM_DOBJ_ID_RESP) + + sizeof(struct sla_buffer_hdr)); + + sla_buffer_unmap(dev_data->resp, dev_data->respbuf); + sla_buffer_unmap(dev_data->req, dev_data->reqbuf); + spdm->rsp = NULL; + spdm->req = NULL; + sla_free(dev_data->req, len, true); + sla_free(dev_data->resp, len, false); + sla_free(dev_data->scratch, dev_data->tio_status->spdm_scratch_size_max, true); + + dev_data->req.sla = 0; + dev_data->resp.sla = 0; + dev_data->scratch.sla = 0; + dev_data->respbuf = NULL; + dev_data->reqbuf = NULL; + sla_free(dev_data->output, dev_data->tio_status->spdm_out_size_max, true); +} + +static int spdm_ctrl_alloc(struct tsm_dev_tio *dev_data, struct tsm_spdm *spdm) +{ + struct sev_tio_status *tio_status = dev_data->tio_status; + int ret; + + dev_data->req = sla_alloc(tio_status->spdm_req_size_max, true); + dev_data->resp = sla_alloc(tio_status->spdm_req_size_max, false); + dev_data->scratch_len = tio_status->spdm_scratch_size_max; + dev_data->scratch = sla_alloc(dev_data->scratch_len, true); + dev_data->output_len = tio_status->spdm_out_size_max; + dev_data->output = sla_alloc(dev_data->output_len, true); + + if (IS_SLA_NULL(dev_data->req) || IS_SLA_NULL(dev_data->resp) || + IS_SLA_NULL(dev_data->scratch) || IS_SLA_NULL(dev_data->dev_ctx)) { + ret = -ENOMEM; + goto free_spdm_exit; + } + + dev_data->reqbuf = sla_buffer_map(dev_data->req); + dev_data->respbuf = sla_buffer_map(dev_data->resp); + if (!dev_data->reqbuf || !dev_data->respbuf) { + ret = -EFAULT; + goto free_spdm_exit; + } + + dobj_response_init(dev_data->respbuf); + + return 0; + +free_spdm_exit: + spdm_ctrl_free(dev_data, spdm); + return ret; +} + +int sev_tio_status(struct sev_device *sev) +{ + struct sev_data_tio_status data_status = { + .length = sizeof(data_status), + }; + struct sev_tio_status *tio_status; + int ret = 0, psp_ret = 0; + + if (!sev_version_greater_or_equal(1, 55)) + return -EPERM; + + WARN_ON(tio_status); + + tio_status = snp_alloc_firmware_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO); + if (!tio_status) + return -ENOMEM; + + data_status.status_paddr = __psp_pa(tio_status); + ret = sev_do_cmd(SEV_CMD_TIO_STATUS, &data_status, &psp_ret); + if (ret) + goto err_msg_exit; + + if (tio_status->flags & 0xFFFFFF00) { + ret = -EFAULT; + goto err_msg_exit; + } + + if (!tio_status->tio_en && !tio_status->tio_init_done) { + ret = -ENOENT; + goto err_msg_exit; + } + + if (tio_status->tio_en && !tio_status->tio_init_done) { + struct sev_data_tio_init ti = { .length = sizeof(ti) }; + + ret = sev_do_cmd(SEV_CMD_TIO_INIT, &ti, &psp_ret); + if (ret) + goto err_msg_exit; + + ret = sev_do_cmd(SEV_CMD_TIO_STATUS, &data_status, &psp_ret); + if (ret) + goto err_msg_exit; + + print_hex_dump(KERN_INFO, "TIO_ST ", DUMP_PREFIX_OFFSET, 16, 1, tio_status, + sizeof(*tio_status), false); + } + + sev->tio_status = kmemdup(tio_status, sizeof(*tio_status), GFP_KERNEL); + if (!sev->tio_status) { + ret = -ENOMEM; + goto err_msg_exit; + } + + pr_notice("SEV-TIO status: EN=%d INIT_DONE=%d rq=%d..%d rs=%d..%d scr=%d..%d out=%d..%d dev=%d tdi=%d\n", + tio_status->tio_en, tio_status->tio_init_done, + tio_status->spdm_req_size_min, tio_status->spdm_req_size_max, + tio_status->spdm_rsp_size_min, tio_status->spdm_rsp_size_max, + tio_status->spdm_scratch_size_min, tio_status->spdm_scratch_size_max, + tio_status->spdm_out_size_min, tio_status->spdm_out_size_max, + tio_status->devctx_size, tio_status->tdictx_size); + + goto free_exit; + +err_msg_exit: + pr_err("Failed to enable SEV-TIO: ret=%d en=%d initdone=%d SEV=%d\n", + ret, tio_status->tio_en, tio_status->tio_init_done, + boot_cpu_has(X86_FEATURE_SEV)); + pr_err("Check BIOS for: SMEE, SEV Control, SEV-ES ASID Space Limit=99,\n" + "SNP Memory (RMP Table) Coverage, RMP Coverage for 64Bit MMIO Ranges\n" + "SEV-SNP Support, SEV-TIO Support, PCIE IDE Capability\n"); + if (cc_platform_has(CC_ATTR_MEM_ENCRYPT)) + pr_err("mem_encrypt=on is currently broken\n"); + +free_exit: + snp_free_firmware_page(tio_status); + return ret; +} + +int sev_tio_dev_create(struct tsm_dev_tio *dev_data, u16 device_id, + u16 root_port_id, u8 segment_id) +{ + struct sev_tio_status *tio_status = dev_data->tio_status; + struct sev_data_tio_dev_create create = { + .length = sizeof(create), + .device_id = device_id, + .root_port_id = root_port_id, + .segment_id = segment_id, + }; + void *data_pg; + int ret; + + dev_data->dev_ctx = sla_alloc(tio_status->devctx_size, true); + if (IS_SLA_NULL(dev_data->dev_ctx)) + return -ENOMEM; + + /* Alloc data page for TDI_STATUS, TDI_INFO, the PSP or prep_data_pg() will zero it */ + data_pg = snp_alloc_firmware_page(GFP_KERNEL_ACCOUNT); + if (!data_pg) { + ret = -ENOMEM; + goto free_ctx_exit; + } + + create.dev_ctx_sla = dev_data->dev_ctx; + ret = sev_tio_do_cmd(SEV_CMD_TIO_DEV_CREATE, &create, sizeof(create), + &dev_data->psp_ret, dev_data, NULL); + if (ret) + goto free_data_pg_exit; + + dev_data->data_pg = data_pg; + + return ret; + +free_data_pg_exit: + snp_free_firmware_page(data_pg); +free_ctx_exit: + sla_free(create.dev_ctx_sla, tio_status->devctx_size, true); + return ret; +} + +int sev_tio_dev_reclaim(struct tsm_dev_tio *dev_data, struct tsm_spdm *spdm) +{ + struct sev_tio_status *tio_status = dev_data->tio_status; + struct sev_data_tio_dev_reclaim r = { + .length = sizeof(r), + .dev_ctx_sla = dev_data->dev_ctx, + }; + int ret; + + if (dev_data->data_pg) { + snp_free_firmware_page(dev_data->data_pg); + dev_data->data_pg = NULL; + } + + if (IS_SLA_NULL(dev_data->dev_ctx)) + return 0; + + ret = sev_do_cmd(SEV_CMD_TIO_DEV_RECLAIM, &r, &dev_data->psp_ret); + + sla_free(dev_data->dev_ctx, tio_status->devctx_size, true); + dev_data->dev_ctx = SLA_NULL; + + spdm_ctrl_free(dev_data, spdm); + + return ret; +} + +int sev_tio_dev_connect(struct tsm_dev_tio *dev_data, u8 tc_mask, u8 ids[8], u8 cert_slot, + struct tsm_spdm *spdm) +{ + struct sev_data_tio_dev_connect connect = { + .length = sizeof(connect), + .tc_mask = tc_mask, + .cert_slot = cert_slot, + .dev_ctx_sla = dev_data->dev_ctx, + .ide_stream_id = { + ids[0], ids[1], ids[2], ids[3], + ids[4], ids[5], ids[6], ids[7] + }, + }; + int ret; + + if (WARN_ON(IS_SLA_NULL(dev_data->dev_ctx))) + return -EFAULT; + if (!(tc_mask & 1)) + return -EINVAL; + + ret = spdm_ctrl_alloc(dev_data, spdm); + if (ret) + return ret; + ret = spdm_ctrl_init(spdm, &connect.spdm_ctrl, dev_data); + if (ret) + return ret; + + ret = sev_tio_do_cmd(SEV_CMD_TIO_DEV_CONNECT, &connect, sizeof(connect), + &dev_data->psp_ret, dev_data, spdm); + + return ret; +} + +int sev_tio_dev_disconnect(struct tsm_dev_tio *dev_data, struct tsm_spdm *spdm) +{ + struct sev_data_tio_dev_disconnect dc = { + .length = sizeof(dc), + .dev_ctx_sla = dev_data->dev_ctx, + }; + int ret; + + if (WARN_ON_ONCE(IS_SLA_NULL(dev_data->dev_ctx))) + return -EFAULT; + + ret = spdm_ctrl_init(spdm, &dc.spdm_ctrl, dev_data); + if (ret) + return ret; + + ret = sev_tio_do_cmd(SEV_CMD_TIO_DEV_DISCONNECT, &dc, sizeof(dc), + &dev_data->psp_ret, dev_data, spdm); + + return ret; +} + +int sev_tio_dev_measurements(struct tsm_dev_tio *dev_data, void *nonce, size_t nonce_len, + struct tsm_spdm *spdm) +{ + struct sev_data_tio_dev_meas meas = { + .length = sizeof(meas), + .raw_bitstream = 1, + }; + + if (nonce_len > sizeof(meas.meas_nonce)) + return -EINVAL; + + if (WARN_ON(IS_SLA_NULL(dev_data->dev_ctx))) + return -EFAULT; + + spdm_ctrl_init(spdm, &meas.spdm_ctrl, dev_data); + meas.dev_ctx_sla = dev_data->dev_ctx; + memcpy(meas.meas_nonce, nonce, nonce_len); + + return sev_tio_do_cmd(SEV_CMD_TIO_DEV_MEASUREMENTS, &meas, sizeof(meas), + &dev_data->psp_ret, dev_data, spdm); +} + +int sev_tio_dev_certificates(struct tsm_dev_tio *dev_data, struct tsm_spdm *spdm) +{ + struct sev_data_tio_dev_certs c = { + .length = sizeof(c), + }; + + if (WARN_ON(IS_SLA_NULL(dev_data->dev_ctx))) + return -EFAULT; + + spdm_ctrl_init(spdm, &c.spdm_ctrl, dev_data); + c.dev_ctx_sla = dev_data->dev_ctx; + + return sev_tio_do_cmd(SEV_CMD_TIO_DEV_CERTIFICATES, &c, sizeof(c), + &dev_data->psp_ret, dev_data, spdm); +} + +int sev_tio_dev_status(struct tsm_dev_tio *dev_data, struct tsm_dev_status *s) +{ + struct sev_tio_dev_status *status = + prep_data_pg(struct sev_tio_dev_status, dev_data); + struct sev_data_tio_dev_status data_status = { + .length = sizeof(data_status), + .dev_ctx_paddr = dev_data->dev_ctx, + .status_length = sizeof(*status), + .status_paddr = __psp_pa(status), + }; + int ret; + + if (!dev_data) + return -ENODEV; + + if (IS_SLA_NULL(dev_data->dev_ctx)) + return -ENXIO; + + ret = sev_do_cmd(SEV_CMD_TIO_DEV_STATUS, &data_status, &dev_data->psp_ret); + if (ret) + return ret; + + s->ctx_state = status->ctx_state; + s->device_id = status->device_id; + s->tc_mask = status->tc_mask; + memcpy(s->ide_stream_id, status->ide_stream_id, sizeof(status->ide_stream_id)); + s->certs_slot = status->certs_slot; + s->no_fw_update = status->no_fw_update; + + return 0; +} + +int sev_tio_ide_refresh(struct tsm_dev_tio *dev_data, struct tsm_spdm *spdm) +{ + struct sev_data_tio_roll_key rk = { + .length = sizeof(rk), + .dev_ctx_sla = dev_data->dev_ctx, + }; + int ret; + + if (WARN_ON(IS_SLA_NULL(dev_data->dev_ctx))) + return -EFAULT; + + ret = spdm_ctrl_init(spdm, &rk.spdm_ctrl, dev_data); + if (ret) + return ret; + + ret = sev_tio_do_cmd(SEV_CMD_TIO_ROLL_KEY, &rk, sizeof(rk), + &dev_data->psp_ret, dev_data, spdm); + + return ret; +} + +int sev_tio_tdi_create(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data, u16 dev_id, + u8 rseg, u8 rseg_valid) +{ + struct sev_tio_status *tio_status = dev_data->tio_status; + struct sev_data_tio_tdi_create c = { + .length = sizeof(c), + }; + int ret; + + if (!dev_data || !tdi_data) /* Device is not "connected" */ + return -EPERM; + + if (WARN_ON_ONCE(IS_SLA_NULL(dev_data->dev_ctx) || !IS_SLA_NULL(tdi_data->tdi_ctx))) + return -EFAULT; + + tdi_data->tdi_ctx = sla_alloc(tio_status->tdictx_size, true); + if (IS_SLA_NULL(tdi_data->tdi_ctx)) + return -ENOMEM; + + c.dev_ctx_sla = dev_data->dev_ctx; + c.tdi_ctx_sla = tdi_data->tdi_ctx; + c.interface_id.function_id = + FIELD_PREP(TSM_TDISP_IID_REQUESTER_ID, dev_id) | + FIELD_PREP(TSM_TDISP_IID_RSEG, rseg) | + FIELD_PREP(TSM_TDISP_IID_RSEG_VALID, rseg_valid); + + ret = sev_do_cmd(SEV_CMD_TIO_TDI_CREATE, &c, &dev_data->psp_ret); + if (ret) + goto free_exit; + + return 0; + +free_exit: + sla_free(tdi_data->tdi_ctx, tio_status->tdictx_size, true); + tdi_data->tdi_ctx = SLA_NULL; + return ret; +} + +void sev_tio_tdi_reclaim(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data) +{ + struct sev_tio_status *tio_status = dev_data->tio_status; + struct sev_data_tio_tdi_reclaim r = { + .length = sizeof(r), + }; + + if (WARN_ON(!dev_data || !tdi_data)) + return; + if (IS_SLA_NULL(dev_data->dev_ctx) || IS_SLA_NULL(tdi_data->tdi_ctx)) + return; + + r.dev_ctx_sla = dev_data->dev_ctx; + r.tdi_ctx_sla = tdi_data->tdi_ctx; + + sev_do_cmd(SEV_CMD_TIO_TDI_RECLAIM, &r, &dev_data->psp_ret); + + sla_free(tdi_data->tdi_ctx, tio_status->tdictx_size, true); + tdi_data->tdi_ctx = SLA_NULL; +} + +int sev_tio_tdi_bind(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data, + u32 guest_rid, u64 gctx_paddr, u32 asid, bool force_run, + struct tsm_spdm *spdm) +{ + struct sev_data_tio_tdi_bind b = { + .length = sizeof(b), + }; + + if (WARN_ON_ONCE(IS_SLA_NULL(dev_data->dev_ctx) || IS_SLA_NULL(tdi_data->tdi_ctx))) + return -EFAULT; + + spdm_ctrl_init(spdm, &b.spdm_ctrl, dev_data); + b.dev_ctx_sla = dev_data->dev_ctx; + b.tdi_ctx_sla = tdi_data->tdi_ctx; + b.guest_device_id = guest_rid; + b.gctx_paddr = gctx_paddr; + b.run = force_run; + + tdi_data->gctx_paddr = gctx_paddr; + tdi_data->asid = asid; + + return sev_tio_do_cmd(SEV_CMD_TIO_TDI_BIND, &b, sizeof(b), + &dev_data->psp_ret, dev_data, spdm); +} + +int sev_tio_tdi_unbind(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data, + struct tsm_spdm *spdm) +{ + struct sev_data_tio_tdi_unbind ub = { + .length = sizeof(ub), + }; + + if (WARN_ON(!tdi_data || !dev_data)) + return 0; + + if (WARN_ON(!tdi_data->gctx_paddr)) + return -EFAULT; + + spdm_ctrl_init(spdm, &ub.spdm_ctrl, dev_data); + ub.dev_ctx_sla = dev_data->dev_ctx; + ub.tdi_ctx_sla = tdi_data->tdi_ctx; + ub.gctx_paddr = tdi_data->gctx_paddr; + + return sev_tio_do_cmd(SEV_CMD_TIO_TDI_UNBIND, &ub, sizeof(ub), + &dev_data->psp_ret, dev_data, spdm); +} + +int sev_tio_tdi_report(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data, + struct tsm_spdm *spdm) +{ + struct sev_data_tio_tdi_report r = { + .length = sizeof(r), + .dev_ctx_sla = dev_data->dev_ctx, + .tdi_ctx_sla = tdi_data->tdi_ctx, + .gctx_paddr = tdi_data->gctx_paddr, + }; + + if (WARN_ON_ONCE(IS_SLA_NULL(dev_data->dev_ctx) || IS_SLA_NULL(tdi_data->tdi_ctx))) + return -EFAULT; + + spdm_ctrl_init(spdm, &r.spdm_ctrl, dev_data); + + return sev_tio_do_cmd(SEV_CMD_TIO_TDI_REPORT, &r, sizeof(r), + &dev_data->psp_ret, dev_data, spdm); +} + +int sev_tio_asid_fence_clear(u16 device_id, u8 segment_id, u64 gctx_paddr, int *psp_ret) +{ + struct sev_data_tio_asid_fence_clear c = { + .length = sizeof(c), + .gctx_paddr = gctx_paddr, + .device_id = device_id, + .segment_id = segment_id, + }; + + return sev_do_cmd(SEV_CMD_TIO_ASID_FENCE_CLEAR, &c, psp_ret); +} + +int sev_tio_asid_fence_status(struct tsm_dev_tio *dev_data, u16 device_id, u8 segment_id, + u32 asid, bool *fenced) +{ + u64 *status = prep_data_pg(u64, dev_data); + struct sev_data_tio_asid_fence_status s = { + .length = sizeof(s), + .asid = asid, + .status_pa = __psp_pa(status), + .device_id = device_id, + .segment_id = segment_id, + }; + int ret; + + ret = sev_do_cmd(SEV_CMD_TIO_ASID_FENCE_STATUS, &s, &dev_data->psp_ret); + + if (ret == SEV_RET_SUCCESS) { + switch (*status) { + case 0: + *fenced = false; + break; + case 1: + *fenced = true; + break; + default: + pr_err("%04x:%x:%x.%d: undefined fence state %#llx\n", + segment_id, PCI_BUS_NUM(device_id), + PCI_SLOT(device_id), PCI_FUNC(device_id), *status); + *fenced = true; + break; + } + } + + return ret; +} + +int sev_tio_guest_request(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data, + void *req, void *res, struct tsm_spdm *spdm) +{ + struct sev_data_tio_guest_request gr = { + .length = sizeof(gr), + .dev_ctx_sla = dev_data->dev_ctx, + .tdi_ctx_sla = tdi_data->tdi_ctx, + .gctx_paddr = tdi_data->gctx_paddr, + .req_paddr = __psp_pa(req), + .res_paddr = __psp_pa(res), + }; + int ret; + + if (WARN_ON(!tdi_data || !dev_data)) + return -EINVAL; + + spdm_ctrl_init(spdm, &gr.spdm_ctrl, dev_data); + + ret = sev_tio_do_cmd(SEV_CMD_TIO_GUEST_REQUEST, &gr, sizeof(gr), + &dev_data->psp_ret, dev_data, spdm); + + return ret; +} + +struct sev_tio_tdi_info_data { + u32 length; + struct tdisp_interface_id interface_id; + union { + u32 p1; + struct { + u32 meas_digest_valid:1; + u32 meas_digest_fresh:1; + u32 tdi_status:2; /* 0: TDI_UNBOUND 1: TDI_BIND_LOCKED 2: TDI_BIND_RUN */ + }; + }; + union { + u32 p2; + struct { + u32 no_fw_update:1; + u32 cache_line_size:1; + u32 lock_msix:1; + u32 bind_p2p:1; + u32 all_request_redirect:1; + }; + }; + u64 spdm_algos; + u8 certs_digest[48]; + u8 meas_digest[48]; + u8 interface_report_digest[48]; + u64 intf_report_counter; + u32 asid; /* ASID of the guest that this device is assigned to. Valid if CTX_STATE=1 */ + u8 reserved2[4]; +} __packed; + +struct sev_data_tio_tdi_info { + u32 length; + u32 reserved1; + struct sla_addr_t dev_ctx_sla; + struct sla_addr_t tdi_ctx_sla; + u64 status_paddr; + u8 reserved2[16]; +} __packed; + +int sev_tio_tdi_info(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data, + struct tsm_tdi_status *ts) +{ + struct sev_tio_tdi_info_data *data = + prep_data_pg(struct sev_tio_tdi_info_data, dev_data); + struct sev_data_tio_tdi_info info = { + .length = sizeof(info), + .dev_ctx_sla = dev_data->dev_ctx, + .tdi_ctx_sla = tdi_data->tdi_ctx, + .status_paddr = __psp_pa(data), + }; + int ret; + + if (IS_SLA_NULL(dev_data->dev_ctx) || IS_SLA_NULL(tdi_data->tdi_ctx)) + return -ENXIO; + + ret = sev_do_cmd(SEV_CMD_TIO_TDI_INFO, &info, &dev_data->psp_ret); + if (ret) + return ret; + + ts->id = data->interface_id; + ts->meas_digest_valid = data->meas_digest_valid; + ts->meas_digest_fresh = data->meas_digest_fresh; + ts->no_fw_update = data->no_fw_update; + ts->cache_line_size = data->cache_line_size == 0 ? 64 : 128; + ts->lock_msix = data->lock_msix; + ts->bind_p2p = data->bind_p2p; + ts->all_request_redirect = data->all_request_redirect; + +#define __ALGO(x, n, y) \ + ((((x) & (0xFFULL << (n))) == TIO_SPDM_ALGOS_##y) ? \ + (1ULL << TSM_SPDM_ALGOS_##y) : 0) + ts->spdm_algos = + __ALGO(data->spdm_algos, 0, DHE_SECP256R1) | + __ALGO(data->spdm_algos, 0, DHE_SECP384R1) | + __ALGO(data->spdm_algos, 8, AEAD_AES_128_GCM) | + __ALGO(data->spdm_algos, 8, AEAD_AES_256_GCM) | + __ALGO(data->spdm_algos, 16, ASYM_TPM_ALG_RSASSA_3072) | + __ALGO(data->spdm_algos, 16, ASYM_TPM_ALG_ECDSA_ECC_NIST_P256) | + __ALGO(data->spdm_algos, 16, ASYM_TPM_ALG_ECDSA_ECC_NIST_P384) | + __ALGO(data->spdm_algos, 24, HASH_TPM_ALG_SHA_256) | + __ALGO(data->spdm_algos, 24, HASH_TPM_ALG_SHA_384) | + __ALGO(data->spdm_algos, 32, KEY_SCHED_SPDM_KEY_SCHEDULE); +#undef __ALGO + memcpy(ts->certs_digest, data->certs_digest, sizeof(ts->certs_digest)); + memcpy(ts->meas_digest, data->meas_digest, sizeof(ts->meas_digest)); + memcpy(ts->interface_report_digest, data->interface_report_digest, + sizeof(ts->interface_report_digest)); + ts->intf_report_counter = data->intf_report_counter; + ts->valid = true; + + return 0; +} + +struct sev_tio_tdi_status_data { + u32 length; + u8 tdisp_state; + u8 reserved1[3]; +} __packed; + +struct sev_data_tio_tdi_status { + u32 length; + u32 reserved1; + struct spdm_ctrl spdm_ctrl; + struct sla_addr_t dev_ctx_sla; + struct sla_addr_t tdi_ctx_sla; + u64 status_paddr; +} __packed; + +int sev_tio_tdi_status(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data, + struct tsm_spdm *spdm) +{ + struct sev_tio_tdi_status_data *data = + prep_data_pg(struct sev_tio_tdi_status_data, dev_data); + struct sev_data_tio_tdi_status status = { + .length = sizeof(status), + .dev_ctx_sla = dev_data->dev_ctx, + .tdi_ctx_sla = tdi_data->tdi_ctx, + .status_paddr = __psp_pa(data), + }; + + if (IS_SLA_NULL(dev_data->dev_ctx) || IS_SLA_NULL(tdi_data->tdi_ctx)) + return -ENXIO; + + spdm_ctrl_init(spdm, &status.spdm_ctrl, dev_data); + + return sev_tio_do_cmd(SEV_CMD_TIO_TDI_STATUS, &status, sizeof(status), + &dev_data->psp_ret, dev_data, spdm); +} + +#define TIO_TDISP_STATE_CONFIG_UNLOCKED 0 +#define TIO_TDISP_STATE_CONFIG_LOCKED 1 +#define TIO_TDISP_STATE_RUN 2 +#define TIO_TDISP_STATE_ERROR 3 + +int sev_tio_tdi_status_fin(struct tsm_dev_tio *dev_data, struct tsm_tdi_tio *tdi_data, + enum tsm_tdisp_state *state) +{ + struct sev_tio_tdi_status_data *data = (struct sev_tio_tdi_status_data *) dev_data->data_pg; + + switch (data->tdisp_state) { +#define __TDISP_STATE(y) case TIO_TDISP_STATE_##y: *state = TDISP_STATE_##y; break + __TDISP_STATE(CONFIG_UNLOCKED); + __TDISP_STATE(CONFIG_LOCKED); + __TDISP_STATE(RUN); + __TDISP_STATE(ERROR); +#undef __TDISP_STATE + } + + return 0; +} + +int sev_tio_cmd_buffer_len(int cmd) +{ + switch (cmd) { + case SEV_CMD_TIO_STATUS: return sizeof(struct sev_data_tio_status); + case SEV_CMD_TIO_INIT: return sizeof(struct sev_data_tio_init); + case SEV_CMD_TIO_DEV_CREATE: return sizeof(struct sev_data_tio_dev_create); + case SEV_CMD_TIO_DEV_RECLAIM: return sizeof(struct sev_data_tio_dev_reclaim); + case SEV_CMD_TIO_DEV_CONNECT: return sizeof(struct sev_data_tio_dev_connect); + case SEV_CMD_TIO_DEV_DISCONNECT: return sizeof(struct sev_data_tio_dev_disconnect); + case SEV_CMD_TIO_DEV_STATUS: return sizeof(struct sev_data_tio_dev_status); + case SEV_CMD_TIO_DEV_MEASUREMENTS: return sizeof(struct sev_data_tio_dev_meas); + case SEV_CMD_TIO_DEV_CERTIFICATES: return sizeof(struct sev_data_tio_dev_certs); + case SEV_CMD_TIO_TDI_CREATE: return sizeof(struct sev_data_tio_tdi_create); + case SEV_CMD_TIO_TDI_RECLAIM: return sizeof(struct sev_data_tio_tdi_reclaim); + case SEV_CMD_TIO_TDI_BIND: return sizeof(struct sev_data_tio_tdi_bind); + case SEV_CMD_TIO_TDI_UNBIND: return sizeof(struct sev_data_tio_tdi_unbind); + case SEV_CMD_TIO_TDI_REPORT: return sizeof(struct sev_data_tio_tdi_report); + case SEV_CMD_TIO_TDI_STATUS: return sizeof(struct sev_data_tio_tdi_status); + case SEV_CMD_TIO_GUEST_REQUEST: return sizeof(struct sev_data_tio_guest_request); + case SEV_CMD_TIO_ASID_FENCE_CLEAR: return sizeof(struct sev_data_tio_asid_fence_clear); + case SEV_CMD_TIO_ASID_FENCE_STATUS: return sizeof(struct sev_data_tio_asid_fence_status); + case SEV_CMD_TIO_TDI_INFO: return sizeof(struct sev_data_tio_tdi_info); + case SEV_CMD_TIO_ROLL_KEY: return sizeof(struct sev_data_tio_roll_key); + default: return 0; + } +} diff --git a/drivers/crypto/ccp/sev-dev-tsm.c b/drivers/crypto/ccp/sev-dev-tsm.c new file mode 100644 index 000000000000..db34fce3126b --- /dev/null +++ b/drivers/crypto/ccp/sev-dev-tsm.c @@ -0,0 +1,709 @@ +// SPDX-License-Identifier: GPL-2.0-only + +// Interface to CCP/SEV-TIO for generic PCIe TDISP module + +#include +#include +#include + +#include +#include + +#include "psp-dev.h" +#include "sev-dev.h" +#include "sev-dev-tio.h" + +#define tdi_to_pci_dev(tdi) (to_pci_dev(tdi->dev.parent)) + +static void pr_ide_state(struct pci_dev *pdev, struct pci_ide *ide) +{ + struct pci_dev *rp = pcie_find_root_port(pdev); + u32 devst = 0xffffffff, rcst = 0xffffffff; + int ret = pci_ide_stream_state(pdev, ide, &devst, &rcst); + + pci_notice(pdev, "%x%s <-> %s: %x%s ret=%d", + devst, + PCI_IDE_SEL_STS_STATUS(devst) == 2 ? "=SECURE" : "", + pci_name(rp), + rcst, + PCI_IDE_SEL_STS_STATUS(rcst) == 2 ? "=SECURE" : "", + ret); +} + +static int mkret(int ret, struct tsm_dev_tio *dev_data) +{ + if (ret) + return ret; + + if (dev_data->psp_ret == SEV_RET_SUCCESS) + return 0; + + pr_err("PSP returned an error %d\n", dev_data->psp_ret); + return -EINVAL; +} + +static int ide_refresh(struct tsm_dev *tdev) +{ + struct tsm_dev_tio *dev_data = tdev->data; + int ret; + + if (dev_data->cmd == 0) { + ret = sev_tio_ide_refresh(dev_data, &tdev->spdm); + ret = mkret(ret, dev_data); + if (ret) + return ret; + } + + if (dev_data->cmd == SEV_CMD_TIO_ROLL_KEY) { + ret = sev_tio_continue(dev_data, &tdev->spdm); + ret = mkret(ret, dev_data); + } + + return ret; +} + +static int dev_create(struct tsm_dev *tdev, void *private_data) +{ + struct pci_dev *pdev = to_pci_dev(tdev->physdev); + u8 segment_id = pdev->bus ? pci_domain_nr(pdev->bus) : 0; + struct pci_dev *rootport = pdev->bus->self; + struct sev_device *sev = private_data; + u16 device_id = pci_dev_id(pdev); + struct tsm_dev_tio *dev_data; + struct page *req_page; + u16 root_port_id; + u32 lnkcap = 0; + int ret; + + if (pci_read_config_dword(rootport, pci_pcie_cap(rootport) + PCI_EXP_LNKCAP, + &lnkcap)) + return -ENODEV; + + root_port_id = FIELD_GET(PCI_EXP_LNKCAP_PN, lnkcap); + + dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL); + if (!dev_data) + return -ENOMEM; + + dev_data->tio_status = sev->tio_status; + + req_page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO); + if (!req_page) { + ret = -ENOMEM; + goto free_dev_data_exit; + } + dev_data->guest_req_buf = page_address(req_page); + + dev_data->guest_resp_buf = snp_alloc_firmware_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO); + if (!dev_data->guest_resp_buf) { + ret = -EIO; + goto free_req_exit; + } + + ret = sev_tio_dev_create(dev_data, device_id, root_port_id, segment_id); + if (ret) + goto free_resp_exit; + + tdev->data = dev_data; + + return 0; + +free_resp_exit: + snp_free_firmware_page(dev_data->guest_resp_buf); +free_req_exit: + __free_page(req_page); +free_dev_data_exit: + kfree(dev_data); + return ret; +} + +static int dev_connect(struct tsm_dev *tdev, void *private_data) +{ + struct pci_dev *pdev = to_pci_dev(tdev->physdev); + struct tsm_dev_tio *dev_data = tdev->data; + u8 tc_mask = 1, ids[8] = { 0 }; + int ret; + + if (tdev->connected) + return ide_refresh(tdev); + + if (!dev_data) { + struct pci_ide ide1 = { 0 }; + struct pci_ide *ide = &ide1; + + pci_ide_stream_probe(pdev, ide); + ide->stream_id = ids[0]; + ide->nr_mem = 1; + ide->mem[0] = (struct range) { 0, 0xFFFFFFFFFFF00000ULL }; + ide->dev_sel_ctl = FIELD_PREP(PCI_IDE_SEL_CTL_TEE_LIMITED, 1); + ide->rootport_sel_ctl = FIELD_PREP(PCI_IDE_SEL_CTL_CFG_EN, 1); + ide->devid_start = 0; + ide->devid_end = 0xffff; + ide->rpid_start = 0; + ide->rpid_end = 0xffff; + + ret = pci_ide_stream_setup(pdev, ide, PCI_IDE_SETUP_ROOT_PORT); + if (ret) + return ret; + + pci_ide_enable_stream(pdev, ide); + pr_ide_state(pdev, ide); + + ret = dev_create(tdev, private_data); + if (ret) + return ret; + + dev_data = tdev->data; + dev_data->ide = *ide; + } + + if (dev_data->cmd == 0) { + ret = sev_tio_dev_connect(dev_data, tc_mask, ids, tdev->cert_slot, &tdev->spdm); + ret = mkret(ret, dev_data); + if (ret > 0) + return ret; + if (ret < 0) + goto free_exit; + + tio_save_output(&tdev->certs, dev_data->output, SPDM_DOBJ_ID_CERTIFICATE); + } + + if (dev_data->cmd == SEV_CMD_TIO_DEV_CONNECT) { + ret = sev_tio_continue(dev_data, &tdev->spdm); + ret = mkret(ret, dev_data); + if (ret > 0) + return ret; + if (ret < 0) + goto free_exit; + + tio_save_output(&tdev->certs, dev_data->output, SPDM_DOBJ_ID_CERTIFICATE); + } + + if (dev_data->cmd == 0) { + ret = sev_tio_dev_measurements(dev_data, tdev->nonce, tdev->nonce_len, &tdev->spdm); + ret = mkret(ret, dev_data); + if (ret > 0) + return ret; + if (ret < 0) { + pci_warn(pdev, "Reading measurements failed ret=%d\n", ret); + ret = 0; + } else { + tio_save_output(&tdev->meas, dev_data->output, SPDM_DOBJ_ID_MEASUREMENT); + } + } + + if (dev_data->cmd == SEV_CMD_TIO_DEV_MEASUREMENTS) { + ret = sev_tio_continue(dev_data, &tdev->spdm); + ret = mkret(ret, dev_data); + if (ret > 0) + return ret; + if (ret < 0) { + pci_warn(pdev, "Reading measurements failed ret=%d\n", ret); + ret = 0; + } else { + tio_save_output(&tdev->meas, dev_data->output, SPDM_DOBJ_ID_MEASUREMENT); + } + } +#if 0 + /* Uncomment to verify SEV_CMD_TIO_DEV_CERTIFICATES work */ + if (dev_data->cmd == 0) { + ret = sev_tio_dev_certificates(dev_data, &tdev->spdm); + ret = mkret(ret, dev_data); + if (ret > 0) + return ret; + if (ret < 0) + goto free_exit; + + tio_save_output(&tdev->certs, dev_data->output, SPDM_DOBJ_ID_CERTIFICATE); + } + + if (dev_data->cmd == SEV_CMD_TIO_DEV_CERTIFICATES) { + ret = sev_tio_continue(dev_data, &tdev->spdm); + ret = mkret(ret, dev_data); + if (ret > 0) + return ret; + if (ret < 0) + goto free_exit; + + tio_save_output(&tdev->certs, dev_data->output, SPDM_DOBJ_ID_CERTIFICATE); + } +#endif + ret = tsm_register_ide_stream(tdev, &dev_data->ide); + if (ret) + goto free_exit; + + try_module_get(THIS_MODULE); + pr_ide_state(pdev, &dev_data->ide); + return 0; + +free_exit: + sev_tio_dev_reclaim(dev_data, &tdev->spdm); + kfree(dev_data); + tdev->data = NULL; + if (ret > 0) + ret = -EFAULT; + + return ret; +} + +static int dev_disconnect(struct tsm_dev *tdev) +{ + struct tsm_dev_tio *dev_data = tdev->data; + int ret; + + if (!dev_data) + return -ENODEV; + + if (dev_data->cmd == 0) { + ret = sev_tio_dev_disconnect(dev_data, &tdev->spdm); + ret = mkret(ret, dev_data); + if (ret) + return ret; + } else if (dev_data->cmd == SEV_CMD_TIO_DEV_DISCONNECT) { + ret = sev_tio_continue(dev_data, &tdev->spdm); + ret = mkret(ret, dev_data); + if (ret) + return ret; + } else { + dev_err(&tdev->dev, "Wrong state, cmd 0x%x in flight\n", + dev_data->cmd); + } + + ret = sev_tio_dev_reclaim(dev_data, &tdev->spdm); + ret = mkret(ret, dev_data); + + tsm_blob_free(tdev->meas); + tdev->meas = NULL; + tsm_blob_free(tdev->certs); + tdev->certs = NULL; + kfree(tdev->data); + tdev->data = NULL; + + if (dev_data->guest_resp_buf) + snp_free_firmware_page(dev_data->guest_resp_buf); + + if (dev_data->guest_req_buf) + __free_page(virt_to_page(dev_data->guest_req_buf)); + + dev_data->guest_req_buf = NULL; + dev_data->guest_resp_buf = NULL; + + struct pci_dev *pdev = to_pci_dev(tdev->physdev); + struct pci_ide *ide = &dev_data->ide; + + pr_ide_state(pdev, &dev_data->ide); + pci_ide_disable_stream(pdev, ide); + tsm_unregister_ide_stream(tdev, ide); + pci_ide_stream_teardown(pdev, ide); + pr_ide_state(pdev, &dev_data->ide); + + module_put(THIS_MODULE); + + return ret; +} + +static int dev_status(struct tsm_dev *tdev, struct tsm_dev_status *s) +{ + struct tsm_dev_tio *dev_data = tdev->data; + int ret; + + if (!dev_data) + return -ENODEV; + + ret = sev_tio_dev_status(dev_data, s); + ret = mkret(ret, dev_data); + if (!ret) + WARN_ON(s->device_id != pci_dev_id(to_pci_dev(tdev->physdev))); + + return ret; +} + +static int dev_measurements(struct tsm_dev *tdev) +{ + struct tsm_dev_tio *dev_data = tdev->data; + int ret; + + if (!dev_data) + return -ENODEV; + + if (dev_data->cmd == 0) { + ret = sev_tio_dev_measurements(dev_data, tdev->nonce, tdev->nonce_len, &tdev->spdm); + ret = mkret(ret, dev_data); + if (ret > 0) + return ret; + if (ret < 0) + return ret; + + tio_save_output(&tdev->meas, dev_data->output, SPDM_DOBJ_ID_MEASUREMENT); + } + + if (dev_data->cmd == SEV_CMD_TIO_DEV_MEASUREMENTS) { + ret = sev_tio_continue(dev_data, &tdev->spdm); + ret = mkret(ret, dev_data); + if (ret > 0) + return ret; + if (ret < 0) + return ret; + + tio_save_output(&tdev->meas, dev_data->output, SPDM_DOBJ_ID_MEASUREMENT); + } + + return 0; +} + +static void tdi_share_mmio(struct pci_dev *pdev); + +static int tdi_unbind(struct tsm_tdi *tdi) +{ + struct tsm_dev_tio *dev_data; + int ret; + + if (!tdi->data) + return -ENODEV; + + dev_data = tdi->tdev->data; + if (tdi->kvm) { + if (dev_data->cmd == 0) { + ret = sev_tio_tdi_unbind(tdi->tdev->data, tdi->data, &tdi->tdev->spdm); + ret = mkret(ret, dev_data); + if (ret) + return ret; + } else if (dev_data->cmd == SEV_CMD_TIO_TDI_UNBIND) { + ret = sev_tio_continue(dev_data, &tdi->tdev->spdm); + ret = mkret(ret, dev_data); + if (ret) + return ret; + } + } + + /* The hunk to verify transitioning to CONFIG_UNLOCKED */ + if (dev_data->cmd == 0) { + ret = sev_tio_tdi_status(tdi->tdev->data, tdi->data, &tdi->tdev->spdm); + ret = mkret(ret, dev_data); + if (ret > 0) + return ret; + + } else if (dev_data->cmd == SEV_CMD_TIO_TDI_STATUS) { + enum tsm_tdisp_state state = TDISP_STATE_CONFIG_UNLOCKED; + static const char * const sstate[] = { + "CONFIG_UNLOCKED", "CONFIG_LOCKED", "RUN", "ERROR"}; + + ret = sev_tio_continue(dev_data, &tdi->tdev->spdm); + ret = mkret(ret, dev_data); + if (ret > 0) + return ret; + + if (ret) { + dev_err(&tdi->dev, "TDI status failed to read, ret=%d\n", ret); + } else { + ret = sev_tio_tdi_status_fin(tdi->tdev->data, tdi->data, &state); + dev_notice(&tdi->dev, "TDI status %d=\"%s\"\n", + state, state < ARRAY_SIZE(sstate) ? sstate[state] : sstate[0]); + } + } + + /* Reclaim TDI if DEV is connected */ + if (tdi->tdev->data) { + struct tsm_tdi_tio *tdi_data = tdi->data; + struct tsm_dev *tdev = tdi->tdev; + struct pci_dev *pdev = to_pci_dev(tdev->physdev); + struct pci_dev *rootport = pdev->bus->self; + u8 segment_id = pci_domain_nr(rootport->bus); + u16 device_id = pci_dev_id(rootport); + bool fenced = false; + + sev_tio_tdi_reclaim(tdi->tdev->data, tdi->data); + + if (!sev_tio_asid_fence_status(dev_data, device_id, segment_id, + tdi_data->asid, &fenced)) { + if (fenced) { + ret = sev_tio_asid_fence_clear(device_id, segment_id, + tdi_data->gctx_paddr, &dev_data->psp_ret); + pci_notice(rootport, "Unfenced VM=%llx ASID=%d ret=%d %d", + tdi_data->gctx_paddr, tdi_data->asid, ret, + dev_data->psp_ret); + } + } + + tsm_blob_free(tdi->report); + tdi->report = NULL; + } + + pr_ide_state(to_pci_dev(tdi->tdev->physdev), &dev_data->ide); + kfree(tdi->data); + tdi->data = NULL; + + tdi_share_mmio(tdi_to_pci_dev(tdi)); + + return 0; +} + +static int tdi_create(struct tsm_tdi *tdi) +{ + struct tsm_tdi_tio *tdi_data = tdi->data; + int ret; + + if (tdi_data) + return -EBUSY; + + tdi_data = kzalloc(sizeof(*tdi_data), GFP_KERNEL); + if (!tdi_data) + return -ENOMEM; + + ret = sev_tio_tdi_create(tdi->tdev->data, tdi_data, pci_dev_id(tdi_to_pci_dev(tdi)), + tdi->rseg, tdi->rseg_valid); + if (ret) + kfree(tdi_data); + else + tdi->data = tdi_data; + + return ret; +} + +static int tdi_bind(struct tsm_tdi *tdi, u32 bdfn, u64 vmid) +{ + enum tsm_tdisp_state state = TDISP_STATE_CONFIG_UNLOCKED; + struct tsm_dev_tio *dev_data = tdi->tdev->data; + u64 gctx = __psp_pa(vmid & PAGE_MASK); /* see SVM's sev_tio_vmid() */ + u32 asid = vmid & ~PAGE_MASK; + int ret = 0; + + if (dev_data->cmd == SEV_CMD_TIO_TDI_UNBIND) { + ret = sev_tio_continue(dev_data, &tdi->tdev->spdm); + return mkret(ret, dev_data); + } + + if (!tdi->data) { + ret = tdi_create(tdi); + if (ret) + return ret; + } + + if (dev_data->cmd == 0) { + ret = sev_tio_tdi_bind(dev_data, tdi->data, bdfn, gctx, asid, + false, &tdi->tdev->spdm); + ret = mkret(ret, dev_data); + if (ret < 0) { + ret = sev_tio_tdi_bind(dev_data, tdi->data, bdfn, gctx, asid, + true, &tdi->tdev->spdm); + ret = mkret(ret, dev_data); + } + if (ret < 0) + goto error_exit; + if (ret) + return ret; + + tio_save_output(&tdi->report, dev_data->output, SPDM_DOBJ_ID_REPORT); + } + + if (dev_data->cmd == SEV_CMD_TIO_TDI_BIND) { + ret = sev_tio_continue(dev_data, &tdi->tdev->spdm); + ret = mkret(ret, dev_data); + if (ret < 0) + goto error_exit; + if (ret) + return ret; + + tio_save_output(&tdi->report, dev_data->output, SPDM_DOBJ_ID_REPORT); + } + + if (dev_data->cmd == 0) { + ret = sev_tio_tdi_status(tdi->tdev->data, tdi->data, &tdi->tdev->spdm); + ret = mkret(ret, dev_data); + if (ret) + return ret; + + ret = sev_tio_tdi_status_fin(tdi->tdev->data, tdi->data, &state); + } else if (dev_data->cmd == SEV_CMD_TIO_TDI_STATUS) { + ret = sev_tio_continue(dev_data, &tdi->tdev->spdm); + ret = mkret(ret, dev_data); + if (ret) + return ret; + + ret = sev_tio_tdi_status_fin(tdi->tdev->data, tdi->data, &state); + } + + if (ret < 0) + goto error_exit; + if (ret) + return ret; + + if (dev_data->cmd == 0 && state == TDISP_STATE_CONFIG_LOCKED) { + ret = sev_tio_tdi_bind(dev_data, tdi->data, bdfn, gctx, asid, + true, &tdi->tdev->spdm); + ret = mkret(ret, dev_data); + if (ret < 0) + goto error_exit; + if (ret) + return ret; + + tio_save_output(&tdi->report, dev_data->output, SPDM_DOBJ_ID_REPORT); + } + + pr_ide_state(to_pci_dev(tdi->tdev->physdev), &dev_data->ide); + + return ret; + +error_exit: + return sev_tio_tdi_unbind(tdi->tdev->data, tdi->data, &tdi->tdev->spdm); +} + +static int guest_request(struct tsm_tdi *tdi, u8 __user *req, size_t reqlen, + u8 __user *rsp, size_t rsplen, int *fw_err) +{ + struct tsm_dev_tio *dev_data = tdi->tdev->data; + int ret; + + if (!tdi->data) + return -EFAULT; + + if (dev_data->cmd == 0) { + ret = copy_from_user(dev_data->guest_req_buf, req, reqlen); + if (ret) + return ret; + + ret = sev_tio_guest_request(dev_data, tdi->data, dev_data->guest_req_buf, + dev_data->guest_resp_buf, &tdi->tdev->spdm); + ret = mkret(ret, dev_data); + if (ret > 0) + return ret; + *fw_err = dev_data->psp_ret; + ret = copy_to_user(rsp, dev_data->guest_resp_buf, rsplen); + + } else if (dev_data->cmd == SEV_CMD_TIO_GUEST_REQUEST) { + ret = sev_tio_continue(dev_data, &tdi->tdev->spdm); + ret = mkret(ret, dev_data); + if (ret > 0) + return ret; + *fw_err = dev_data->psp_ret; + ret = copy_to_user(rsp, dev_data->guest_resp_buf, rsplen); + } + + return ret; +} + +static int tdi_status(struct tsm_tdi *tdi, struct tsm_tdi_status *ts) +{ + struct tsm_dev_tio *dev_data = tdi->tdev->data; + int ret; + + if (!tdi->data) + return -ENODEV; + + if (dev_data->cmd == 0) { + ret = sev_tio_tdi_info(tdi->tdev->data, tdi->data, ts); + ret = mkret(ret, dev_data); + if (ret) + return ret; + } + + if (dev_data->cmd == 0) { + ret = sev_tio_tdi_status(tdi->tdev->data, tdi->data, &tdi->tdev->spdm); + ret = mkret(ret, dev_data); + if (ret) + return ret; + + ret = sev_tio_tdi_status_fin(tdi->tdev->data, tdi->data, &ts->state); + } else if (dev_data->cmd == SEV_CMD_TIO_TDI_STATUS) { + ret = sev_tio_continue(dev_data, &tdi->tdev->spdm); + ret = mkret(ret, dev_data); + if (ret) + return ret; + + ret = sev_tio_tdi_status_fin(tdi->tdev->data, tdi->data, &ts->state); + } else { + dev_err(tdi->dev.parent, "Wrong state, cmd 0x%x in flight\n", + dev_data->cmd); + } + + return ret; +} + +struct tsm_hv_ops sev_tsm_ops = { + .dev_connect = dev_connect, + .dev_disconnect = dev_disconnect, + .dev_status = dev_status, + .dev_measurements = dev_measurements, + .tdi_bind = tdi_bind, + .tdi_unbind = tdi_unbind, + .guest_request = guest_request, + .tdi_status = tdi_status, +}; + +void sev_tsm_init(struct sev_device *sev) +{ + int ret; + + if (!sev->tio_en) + return; + + ret = sev_tio_status(sev); + if (ret) { + pr_warn("SEV-TIO STATUS failed with %d\n", ret); + return; + } + + sev->tsm = tsm_host_register(sev->dev, &sev_tsm_ops, sev); + sev->tsm_bus = pci_tsm_register((struct tsm_subsys *) sev->tsm); +} + +void sev_tsm_uninit(struct sev_device *sev) +{ + if (!sev->tio_en) + return; + if (sev->tsm_bus) + pci_tsm_unregister(sev->tsm_bus); + if (sev->tsm) + tsm_unregister((struct tsm_subsys *) sev->tsm); + sev->tsm_bus = NULL; + sev->tsm = NULL; + sev_tio_cleanup(sev); + sev->tio_en = false; +} + + +static int rmpupdate(u64 pfn, struct rmp_state *state) +{ + unsigned long paddr = pfn << PAGE_SHIFT; + int ret, level; + + if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) + return -ENODEV; + + level = RMP_TO_PG_LEVEL(state->pagesize); + + do { + /* Binutils version 2.36 supports the RMPUPDATE mnemonic. */ + asm volatile(".byte 0xF2, 0x0F, 0x01, 0xFE" + : "=a" (ret) + : "a" (paddr), "c" ((unsigned long)state) + : "memory", "cc"); + } while (ret == RMPUPDATE_FAIL_OVERLAP); + + if (ret) { + pr_err("MMIO RMPUPDATE failed for PFN %llx, pg_level: %d, ret: %d\n", + pfn, level, ret); + return -EFAULT; + } + + return 0; +} + +static void tdi_share_mmio(struct pci_dev *pdev) +{ + struct resource *res; + + pci_dev_for_each_resource(pdev, res) { + if (!res) + continue; + + pr_err("___K___ %s %u: Sharing %s %llx..%llx\n", __func__, __LINE__, + res->name ? res->name : "(null)", res->start, res->end); + for (resource_size_t off = res->start; off < res->end; off += PAGE_SIZE) { + struct rmp_state state = {}; + + state.pagesize = PG_LEVEL_TO_RMP(PG_LEVEL_4K); + rmpupdate(off >> PAGE_SHIFT, &state); + } + } +} diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index b01e5f913727..d59d74d3aaca 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -37,6 +37,7 @@ #include "psp-dev.h" #include "sev-dev.h" +#include "sev-dev-tio.h" #define DEVICE_NAME "sev" #define SEV_FW_FILE "amd/sev.fw" @@ -234,7 +235,7 @@ static int sev_cmd_buffer_len(int cmd) case SEV_CMD_SNP_COMMIT: return sizeof(struct sev_data_snp_commit); case SEV_CMD_SNP_FEATURE_INFO: return sizeof(struct sev_data_snp_feature_info); case SEV_CMD_SNP_DOWNLOAD_FIRMWARE_EX: return sizeof(struct sev_data_download_firmware_ex); - default: return 0; + default: return sev_tio_cmd_buffer_len(cmd); } return 0; @@ -2631,6 +2632,8 @@ void sev_pci_init(void) atomic_notifier_chain_register(&panic_notifier_list, &snp_panic_notifier); + sev_tsm_init(sev); + return; err: @@ -2647,6 +2650,11 @@ void sev_pci_exit(void) return; sev_firmware_shutdown(sev); + /* + * sev_tsm_uninit needs to clear tio_en after sev_firmware_shutdown to let it + * do proper cleanup. + */ + sev_tsm_uninit(sev); atomic_notifier_chain_unregister(&panic_notifier_list, &snp_panic_notifier); diff --git a/drivers/virt/coco/host/tsm-host.c b/drivers/virt/coco/host/tsm-host.c index 80f3315fb195..5d23a3871009 100644 --- a/drivers/virt/coco/host/tsm-host.c +++ b/drivers/virt/coco/host/tsm-host.c @@ -265,7 +265,7 @@ static char *spdm_algos_to_str(u64 algos, char *buf, size_t len) buf[0] = 0; #define __ALGO(x) do { \ - if ((n < len) && (algos & (1ULL << (TSM_TDI_SPDM_ALGOS_##x)))) \ + if ((n < len) && (algos & (1ULL << (TSM_SPDM_ALGOS_##x)))) \ n += snprintf(buf + n, len - n, #x" "); \ } while (0) @@ -287,7 +287,6 @@ static const char *tdisp_state_to_str(enum tsm_tdisp_state state) { switch (state) { #define __ST(x) case TDISP_STATE_##x: return #x - case TDISP_STATE_UNAVAIL: return "TDISP state unavailable"; __ST(CONFIG_UNLOCKED); __ST(CONFIG_LOCKED); __ST(RUN); @@ -475,7 +474,6 @@ void tsm_tdi_unbind(struct tsm_tdi *tdi) } tdi->guest_rid = 0; - tdi->dev.parent->tdi_enabled = false; } EXPORT_SYMBOL_GPL(tsm_tdi_unbind); diff --git a/drivers/crypto/ccp/Kconfig b/drivers/crypto/ccp/Kconfig index 40be991f15d2..459bc339e651 100644 --- a/drivers/crypto/ccp/Kconfig +++ b/drivers/crypto/ccp/Kconfig @@ -25,6 +25,7 @@ config CRYPTO_DEV_CCP_CRYPTO default m depends on CRYPTO_DEV_CCP_DD depends on CRYPTO_DEV_SP_CCP + depends on PCI_TSM select CRYPTO_HASH select CRYPTO_SKCIPHER select CRYPTO_AUTHENC @@ -39,6 +40,7 @@ config CRYPTO_DEV_SP_PSP bool "Platform Security Processor (PSP) device" default y depends on CRYPTO_DEV_CCP_DD && X86_64 && AMD_IOMMU + select TSM_HOST help Provide support for the AMD Platform Security Processor (PSP). The PSP is a dedicated processor that provides support for key From patchwork Tue Feb 18 11:09:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Kardashevskiy X-Patchwork-Id: 866255 Received: from NAM12-DM6-obe.outbound.protection.outlook.com (mail-dm6nam12on2071.outbound.protection.outlook.com [40.107.243.71]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2B8A223BF9E; Tue, 18 Feb 2025 11:14:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.243.71 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877268; cv=fail; b=aeaRNzVQtvAoQS4Rnz1NckKLYtO6jnMyxx07/nsTPhhJ4fA1EwsEj64PBi6O2bNsarC7E6Qank9eg+UrdnpEDV9acJdD54P3SxT7FWRByZjH5zd1vEh2REPf9qF4i9X3LzAAFzVh3nfyrYxI/jRFbHPr1pxF6y+W0x2W3wvnMI4= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877268; c=relaxed/simple; bh=WCPL9rVr4j2Pb2uKP2Xa/RLtbkNnn3GWjdl/4E9pb00=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BXy2cb7gf3KSDP7b4bsspWldi1sJ8LI8eO4ZKjM3oIOP9e9rPvgYwFJqoj7ZFUC1H0e6ZFb8jdg3kuSs7D2O1DZHi2myRjdwasWgpK1mZRgmJYO9A7FmCLoDpvTds2MCf/x2xmnNJ2uzdeR6fHz0F+mTkHDHUgdBxwVB2ad0LKU= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=faa1OBJs; arc=fail smtp.client-ip=40.107.243.71 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="faa1OBJs" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=FWh6+hI5lYne5wdgh0KDcKhgmgvCK4D+ygfnKFhyhsrpLgRpwznON7cXzxWffKk/JaxWsej2kCBpMjkUn3FEyUpMase3YsPUuOKpukYlJWk7eC0zGfXJsebSzaNtC6m2Y656fV4z6Dvj5xlpFXbdToh6+3D6cot0yELQE445/mFWQp7gurSg0VdFUBwOyYlv8B3ImfgeSjyCMa6U/QZvqLOqsW5cPAD+8eOIjWsnR8wFBwZVGqfyfGafgNcWPeigAeYgwkdXmartVMASFtpzfEOR1xX7lvuvVpk3JKyCQ2kYDYpbZRdAHCaRNwrGJqbtM9F3t+2COVP/+U8ZOTH7Nw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=KgaHBRP+oQfuGsFY+h4i5BGvzxvLvSYi1+FCYp43Xck=; b=Xj+l3E7vSNh+96iDm9SNoOZb1HPjh8RfJwWv+4kSZDS7hCWP4wRtgaA7FJiwIlDNda6spovpkTbKjMkz13yIGdkgEwcmCANdyS2I9uZTawh6Ak0pQKXa8iuR00r6fi1K/e8Pe6XtcHFkuEgmMcq4pLPqwkUt+Wu6V7n2g7W6BhSNqc1hfhkvj7XqEegMjygw2NMLwhifqoTdQYLWfhX3AvuTpz8N7k9Plo6zdJIvnFPhw2nvtfPvyJRD3VylRieKwaeM6bN00SEq18fh3qvJUQNJy48E07mepUqq1ehF4J8eUHUckiFv0fABr9uoOuJBHyuURaALy6xHe/X+ab+wiw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=KgaHBRP+oQfuGsFY+h4i5BGvzxvLvSYi1+FCYp43Xck=; b=faa1OBJsVctqfwG+siIYnpRI8/NHzxyah6BEKM5/LNHcw4Uka7TTVMQ/i7Wxf9hyVlLBPbWl/0JWwMxiB/kG1bEaApskmmcknmHWepPls7Zrriu5XLq1LJGKF/nRrwcL59Cnufw1nUImikKiy0bQkwdBtu7+/bw8kMuM4QIOH94= Received: from MN2PR01CA0023.prod.exchangelabs.com (2603:10b6:208:10c::36) by PH8PR12MB7422.namprd12.prod.outlook.com (2603:10b6:510:22a::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8445.17; Tue, 18 Feb 2025 11:14:23 +0000 Received: from BN3PEPF0000B078.namprd04.prod.outlook.com (2603:10b6:208:10c:cafe::be) by MN2PR01CA0023.outlook.office365.com (2603:10b6:208:10c::36) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8445.19 via Frontend Transport; Tue, 18 Feb 2025 11:14:22 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by BN3PEPF0000B078.mail.protection.outlook.com (10.167.243.123) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8466.11 via Frontend Transport; Tue, 18 Feb 2025 11:14:22 +0000 Received: from aiemdee.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Tue, 18 Feb 2025 05:14:14 -0600 From: Alexey Kardashevskiy To: CC: , , , , "Sean Christopherson" , Paolo Bonzini , "Tom Lendacky" , Ashish Kalra , Joerg Roedel , Suravee Suthikulpanit , Robin Murphy , "Jason Gunthorpe" , Kevin Tian , Bjorn Helgaas , Dan Williams , "Christoph Hellwig" , Nikunj A Dadhania , Michael Roth , Vasant Hegde , Joao Martins , Nicolin Chen , Lu Baolu , Steve Sistare , "Lukas Wunner" , Jonathan Cameron , Suzuki K Poulose , Dionna Glaze , Yi Liu , , , Zhi Wang , AXu Yilun , "Aneesh Kumar K . V" , Alexey Kardashevskiy Subject: [RFC PATCH v2 11/22] KVM: SEV: Add TIO VMGEXIT Date: Tue, 18 Feb 2025 22:09:58 +1100 Message-ID: <20250218111017.491719-12-aik@amd.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250218111017.491719-1-aik@amd.com> References: <20250218111017.491719-1-aik@amd.com> Precedence: bulk X-Mailing-List: linux-crypto@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN3PEPF0000B078:EE_|PH8PR12MB7422:EE_ X-MS-Office365-Filtering-Correlation-Id: 6c256334-0578-4c51-a172-08dd500d65bb X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|7416014|82310400026|36860700013|1800799024|376014; X-Microsoft-Antispam-Message-Info: 8/3ht+RFmZcYiZfoSPDltyFOeZiksGX2a97W5qqYQFRdLi2pXWID6HZu8loIVIwZ5GbegQIB7zaTijVI+HVVHeyDUpFPKtmpVbKgRG6t7EKXlw3vVZx3GmCFw8rdtVq0XEYTd889Qym7W0fZ5In8+QDR/IQ70N8c75xRygK2v1BrcITUBwxb46JIMbqmQiu0X+11g0Jllf2J4Cw7RF/uO5yTr2E/i1bLI0p4sfhC0mS8cBFh4hgvofSpAJ5gWreQelnDpxxUI3uv7xM5YxVr9LDe/KwDPrL3ZQjvzQTcn/tiUDiVCQzo6TKOzbKVAbd1kp2DeX86I2lplbFJjLwyECyB6og6texu2hViC/lNvitSqq4ULmUKyRiTTahre5cSjl4m2tyXJhcn9nWK9CCKR9HubUCZUcn56m2DeIy9LP6cj1b0JwBZoPez37b9Yn2Dv6aMhbcaZ42sTFVGIeaiRM1To7/wWQBP3Iz0DNUDpX2N6rxH/Vg/lGMRjC8DaNPxaxIH3OKKsuqiAs2Tjmlm1FT04V+VPe9VMkHuqHHWBskrwARiEZcoSK/zmG64is2SAezOigjB4pHlntFeDXlyjZcwSB6mvJZg7OTeeyjzo4xw5JueCvsvSNv/n86j5zwgdyYMcejAeWifAtQUbnQ6xFMHon6HbXdrFg9VggbjvIxBxxKw0MmdTUy0lj5aIV1F4taen6McNNOIOiI0LzQmybOTEyLe30gWylGbxca0DCG5p/f2YrtkPtWJyjR51uE47lsfJwyghX4wrL3oAOUalmQ4v+qOgFqyPvLmhwlGqkAHQNAJpGPW0W6GOEDg01UHD8ZU22UiH4M0wiTPMCVjopaukiBUK8++nlk3gjh209gIMehh0Hi/DdWz7hFxaDW2XGc+mr0AYOnQxMD9sFi71Y987ZHH3mvTklgjFFq60LA+aAE8QCnfDdxjfm6M20OqWEkpEK3gA9eQ2yk8YgEb9wrFm3nwJBCFdUmvrDVTvCsXUycuQMgoihh2+iB/lw4VV6R7y/gbWwxXTICI68c6KPvziP9G5sqTdK+6XeRN+OBbYOae+Q9x7d1Aa8SGPI8/6wn5IICFMFp1LDBF+gb9uEuPHs9gQQpNmcdijVsjJKK7k5F9EInwCmu39mqvzgR7n9bwAUTQyDSK5Q0uT/Oan295Z7cujehpVgdO8f0MkvWHlGpC2ZcvMlbH/gZ8/kOW7ywWnxdxxPZ5Nb0aUmihuRaryQl0Q7xs9MsSlKocyDJ1t/i11UrvGmzCSb9rvyLyXuqALWIwXEnCD2VzgjfXuGqH6XIGM54oF8HYL7YLvISgjhV20t8Q343tIWzu5+ECDaiuqxtf4o/2dDwbfjR9QQFIO4NgPdsvTN4knm5IC4GFaLaMHlBxBFY2txEHlNJOdw8zUH0Gtf4YyXcZlTL1pxUZTRLDiG4wED4tpFJto/7CfmZe0JwmWcrmS/hdCM9x7ha23olSyDUjkEFc8GCzNWaY73q1PSF5eiEWtyB45v8= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(7416014)(82310400026)(36860700013)(1800799024)(376014); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Feb 2025 11:14:22.7602 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 6c256334-0578-4c51-a172-08dd500d65bb X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN3PEPF0000B078.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH8PR12MB7422 The SEV TIO spec defines a new TIO_GUEST_MESSAGE message to provide a secure communication channel between a SNP VM and the PSP, very similar to the GHCB GUEST MESSAGE. However the new call requires additional information about the host and guest PCI BDFn and the VM id (which is GCTX==guest context page). Since KVM does not know PCI, it exits to QEMU which has all the pieces to make the call to the PSP. This relies on necessary additional ioctl() are implemented separately, such as: - IOMMUFD "TDI bind" to bind a secure VF to a CoCo VM; - IOMMUFD "Guest Request" to manage secure DMA and MMIO; - SEV KVM ioctl() to call RMPUPDATE on MMIO ranges. Define new VMGEXIT code - SEV_TIO_GUEST_REQUEST. Define its parameters in kvm_run::kvm_user_vmgexit. These include: - guest BDFn, - GHCB request/response buffers (encrypted guest pages), - space for certificate/measurements/interface repors (non encrypted guest pages). Some numeric values are out of order because numbers in between have been used at different stages of KVM SEV-SNP upstreaming process. Signed-off-by: Alexey Kardashevskiy --- arch/x86/include/uapi/asm/svm.h | 2 + include/uapi/linux/kvm.h | 24 +++++++ arch/x86/kvm/svm/sev.c | 70 ++++++++++++++++++++ 3 files changed, 96 insertions(+) diff --git a/arch/x86/include/uapi/asm/svm.h b/arch/x86/include/uapi/asm/svm.h index 1814b413fd57..ac90a69e6327 100644 --- a/arch/x86/include/uapi/asm/svm.h +++ b/arch/x86/include/uapi/asm/svm.h @@ -116,6 +116,7 @@ #define SVM_VMGEXIT_AP_CREATE 1 #define SVM_VMGEXIT_AP_DESTROY 2 #define SVM_VMGEXIT_SNP_RUN_VMPL 0x80000018 +#define SVM_VMGEXIT_SEV_TIO_GUEST_REQUEST 0x80000020 #define SVM_VMGEXIT_HV_FEATURES 0x8000fffd #define SVM_VMGEXIT_TERM_REQUEST 0x8000fffe #define SVM_VMGEXIT_TERM_REASON(reason_set, reason_code) \ @@ -237,6 +238,7 @@ { SVM_VMGEXIT_GUEST_REQUEST, "vmgexit_guest_request" }, \ { SVM_VMGEXIT_EXT_GUEST_REQUEST, "vmgexit_ext_guest_request" }, \ { SVM_VMGEXIT_AP_CREATION, "vmgexit_ap_creation" }, \ + { SVM_VMGEXIT_SEV_TIO_GUEST_REQUEST, "vmgexit_sev_tio_guest_request" }, \ { SVM_VMGEXIT_HV_FEATURES, "vmgexit_hypervisor_feature" }, \ { SVM_EXIT_ERR, "invalid_guest_state" } diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 45e6d8fca9b9..cb3bc5b9c1e0 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -135,6 +135,28 @@ struct kvm_xen_exit { } u; }; +struct kvm_user_vmgexit { +#define KVM_USER_VMGEXIT_TIO_REQ 4 + __u32 type; /* KVM_USER_VMGEXIT_* type */ + union { + struct { + __u32 guest_rid; /* in */ + __u16 ret; /* out */ +#define KVM_USER_VMGEXIT_TIO_REQ_FLAG_STATUS BIT(0) +#define KVM_USER_VMGEXIT_TIO_REQ_FLAG_MMIO_VALIDATE BIT(1) +#define KVM_USER_VMGEXIT_TIO_REQ_FLAG_MMIO_CONFIG BIT(2) + __u8 flags; /* in */ + __u8 tdi_status; /* out */ + __u64 data_gpa; /* in */ + __u64 data_npages; /* in/out */ + __u64 req_spa; /* in */ + __u64 rsp_spa; /* in */ + __u64 mmio_gpa; /* in */ + __s32 fw_err; /* out */ + } tio_req; + }; +} __packed; + #define KVM_S390_GET_SKEYS_NONE 1 #define KVM_S390_SKEYS_MAX 1048576 @@ -178,6 +200,7 @@ struct kvm_xen_exit { #define KVM_EXIT_NOTIFY 37 #define KVM_EXIT_LOONGARCH_IOCSR 38 #define KVM_EXIT_MEMORY_FAULT 39 +#define KVM_EXIT_VMGEXIT 40 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -446,6 +469,7 @@ struct kvm_run { __u64 gpa; __u64 size; } memory_fault; + struct kvm_user_vmgexit vmgexit; /* Fix the size of the union. */ char padding[256]; }; diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 4916b916c20a..ea1cf33191b5 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -3390,6 +3390,8 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm) control->exit_info_1 == control->exit_info_2) goto vmgexit_err; break; + case SVM_VMGEXIT_SEV_TIO_GUEST_REQUEST: + break; default: reason = GHCB_ERR_INVALID_EVENT; goto vmgexit_err; @@ -4250,6 +4252,71 @@ static int snp_mmio_rmp_update(struct kvm *kvm, struct kvm_sev_cmd *argp) return ret; } +static int snp_complete_sev_tio_guest_request(struct kvm_vcpu *vcpu) +{ + struct vcpu_svm *svm = to_svm(vcpu); + struct vmcb_control_area *control = &svm->vmcb->control; + gpa_t req_gpa = control->exit_info_1; + struct kvm *kvm = vcpu->kvm; + struct kvm_sev_info *sev; + u8 msg_type = 0; + + if (!sev_snp_guest(kvm)) + return -EINVAL; + + sev = &to_kvm_svm(kvm)->sev_info; + + if (kvm_read_guest(kvm, req_gpa + offsetof(struct snp_guest_msg_hdr, msg_type), + &msg_type, 1)) + return -EIO; + + if (msg_type == TIO_MSG_TDI_INFO_REQ) + vcpu->arch.regs[VCPU_REGS_RDX] = vcpu->run->vmgexit.tio_req.tdi_status; + + ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, + SNP_GUEST_ERR(0, vcpu->run->vmgexit.tio_req.fw_err)); + + return 1; /* Resume guest */ +} + +static int snp_sev_tio_guest_request(struct kvm_vcpu *vcpu, gpa_t req_gpa, gpa_t resp_gpa) +{ + struct kvm *kvm = vcpu->kvm; + struct kvm_sev_info *sev; + u8 msg_type; + + if (!sev_snp_guest(kvm)) + return SEV_RET_INVALID_GUEST; + + sev = &to_kvm_svm(kvm)->sev_info; + + if (kvm_read_guest(kvm, req_gpa + offsetof(struct snp_guest_msg_hdr, msg_type), + &msg_type, 1)) + return -EIO; + + vcpu->run->exit_reason = KVM_EXIT_VMGEXIT; + vcpu->run->vmgexit.type = KVM_USER_VMGEXIT_TIO_REQ; + vcpu->run->vmgexit.tio_req.guest_rid = vcpu->arch.regs[VCPU_REGS_RCX]; + vcpu->run->vmgexit.tio_req.flags = 0; + if (msg_type == TIO_MSG_TDI_INFO_REQ) + vcpu->run->vmgexit.tio_req.flags |= KVM_USER_VMGEXIT_TIO_REQ_FLAG_STATUS; + if (msg_type == TIO_MSG_MMIO_VALIDATE_REQ) { + vcpu->run->vmgexit.tio_req.flags |= KVM_USER_VMGEXIT_TIO_REQ_FLAG_MMIO_VALIDATE; + vcpu->run->vmgexit.tio_req.mmio_gpa = vcpu->arch.regs[VCPU_REGS_RDX]; + } + if (msg_type == TIO_MSG_MMIO_CONFIG_REQ) { + vcpu->run->vmgexit.tio_req.flags |= KVM_USER_VMGEXIT_TIO_REQ_FLAG_MMIO_CONFIG; + vcpu->run->vmgexit.tio_req.mmio_gpa = vcpu->arch.regs[VCPU_REGS_RDX]; + } + vcpu->run->vmgexit.tio_req.data_gpa = vcpu->arch.regs[VCPU_REGS_RAX]; + vcpu->run->vmgexit.tio_req.data_npages = vcpu->arch.regs[VCPU_REGS_RBX]; + vcpu->run->vmgexit.tio_req.req_spa = req_gpa; + vcpu->run->vmgexit.tio_req.rsp_spa = resp_gpa; + vcpu->arch.complete_userspace_io = snp_complete_sev_tio_guest_request; + + return 0; /* Exit KVM */ +} + static int sev_handle_vmgexit_msr_protocol(struct vcpu_svm *svm) { struct vmcb_control_area *control = &svm->vmcb->control; @@ -4530,6 +4597,9 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) case SVM_VMGEXIT_EXT_GUEST_REQUEST: ret = snp_handle_ext_guest_req(svm, control->exit_info_1, control->exit_info_2); break; + case SVM_VMGEXIT_SEV_TIO_GUEST_REQUEST: + ret = snp_sev_tio_guest_request(vcpu, control->exit_info_1, control->exit_info_2); + break; case SVM_VMGEXIT_UNSUPPORTED_EVENT: vcpu_unimpl(vcpu, "vmgexit: unsupported event - exit_info_1=%#llx, exit_info_2=%#llx\n", From patchwork Tue Feb 18 11:10:00 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Kardashevskiy X-Patchwork-Id: 866254 Received: from NAM11-DM6-obe.outbound.protection.outlook.com (mail-dm6nam11on2069.outbound.protection.outlook.com [40.107.223.69]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C1BCD24113A; Tue, 18 Feb 2025 11:15:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.223.69 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877308; cv=fail; b=nY779Gmkaj9vBAflNgpc832oUQBEa3wbcfbkIFVlcp70Ya33YN9E0zCzeBkVc/gfVi7qczYnSYvYuCVavIL2BjB1HL4HykAOrZOxB9iMArgkyQaCXGtG/5DwRffAlo3e/O6LQwmCJ+tPWHS7CGjme5484Abs3l/O+oDoLoVcqxw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877308; c=relaxed/simple; bh=BrMeEv7WnYjKShGr6ExNAUVOkBj62O3TNw2SUTUY+7Y=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=l4TzGTUXnWBEsFSuJhaz7rPNQPguvhNrCCOk6Zo+UgdAZgbZoo8eKFwv6JskMBUrvoX3EmfwCjRwlDIf8U8m121iL9nO4K0Mtx+TzhROchQCasdhIrz1ACcirzrRG3KydnXa/8eJ/O9zJsa2Ma1ax3ao6Dd272QDTx9JJ3Fyz0A= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=YNNmp3TI; arc=fail smtp.client-ip=40.107.223.69 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="YNNmp3TI" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=aev1AwpedKaVyUUNGnxNUYZ/COhKfBs2Vau8tuIzYjKQFLqShiRx87uoR3bjlsedcgxyjTj0XzBD/kwLIN68YJjI/e/roGPYXMrteN0qj+RlT42fV92X2YMTIyZyBGiiPPeX9aXkLwDMabBWdpM0mIJFCoawxbS/NNSRfi4VVIUNAj54dXQ8Dj4tWj2+OUKAdteiSvOb7F50Eyll8mKLkPhpDjwj2yK4bBbK81gYy35qxib+JpASLCBaddfX44vZeowmPj4x4XhMlQA1Hpt/sEleEfrkAkOEg4VgWVTRZJsgzou4M4+Y9Gq1nuThOaYle/814Jr2pYxu075Z3IKfjw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=NFI94yMUp3uMqVwPx+bM42w01VlVkpu30TsVeazsAJI=; b=lHsi3caO1qd3gzjjjlRgxX6qirt/BrBycfVYIQtQOvZteivy9T3XZCE7omr7YNHNJZ5yFEgHIiSNsKmySiKFZ7WBXgJzO6gP/BwL1o3a/9jwAERO3U8DxrX3niEBWjtCQ0C1wfS4JyyjBdpN/IZh/V0fcRB2j6nCQHZIrRZomt1Ww9bJvxottne3ZYW0pqCJ1f/RZDOTQ+5n2PdXw7Docgh8jwMUCrhkjZD/K0WNcdZLzq9vydJlMnkBalqU1T/ZninkN6oIKi3RS4EWm8BQAIGogVytw3EbN01bluaDkw/owkxrHU5H7ox9wm2EzPQQAC+q3A1k01lWqKMNpgOApw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=NFI94yMUp3uMqVwPx+bM42w01VlVkpu30TsVeazsAJI=; b=YNNmp3TIT6ncQYUKu7E7SpcPPvmZLq6/FGOy5Dru0yQOuUPSW4aeAe85hFYXoHvmn/d639m8DOc3h3awnajaS9rQI8+X2X0h3BLSGHPimNsK8adAxdpc3hLr78z6zF8LWwtmh382gx69GZhwADD8EvvygZoJNpgZjCjd34681IM= Received: from MN2PR01CA0024.prod.exchangelabs.com (2603:10b6:208:10c::37) by IA1PR12MB8405.namprd12.prod.outlook.com (2603:10b6:208:3d8::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8445.19; Tue, 18 Feb 2025 11:15:03 +0000 Received: from BN3PEPF0000B078.namprd04.prod.outlook.com (2603:10b6:208:10c:cafe::e8) by MN2PR01CA0024.outlook.office365.com (2603:10b6:208:10c::37) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8445.19 via Frontend Transport; Tue, 18 Feb 2025 11:15:03 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by BN3PEPF0000B078.mail.protection.outlook.com (10.167.243.123) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8466.11 via Frontend Transport; Tue, 18 Feb 2025 11:15:03 +0000 Received: from aiemdee.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Tue, 18 Feb 2025 05:14:55 -0600 From: Alexey Kardashevskiy To: CC: , , , , "Sean Christopherson" , Paolo Bonzini , "Tom Lendacky" , Ashish Kalra , Joerg Roedel , Suravee Suthikulpanit , Robin Murphy , "Jason Gunthorpe" , Kevin Tian , Bjorn Helgaas , Dan Williams , "Christoph Hellwig" , Nikunj A Dadhania , Michael Roth , Vasant Hegde , Joao Martins , Nicolin Chen , Lu Baolu , Steve Sistare , "Lukas Wunner" , Jonathan Cameron , Suzuki K Poulose , Dionna Glaze , Yi Liu , , , Zhi Wang , AXu Yilun , "Aneesh Kumar K . V" , Alexey Kardashevskiy Subject: [RFC PATCH v2 13/22] iommufd: amd-iommu: Add vdevice support Date: Tue, 18 Feb 2025 22:10:00 +1100 Message-ID: <20250218111017.491719-14-aik@amd.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250218111017.491719-1-aik@amd.com> References: <20250218111017.491719-1-aik@amd.com> Precedence: bulk X-Mailing-List: linux-crypto@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN3PEPF0000B078:EE_|IA1PR12MB8405:EE_ X-MS-Office365-Filtering-Correlation-Id: fc46e990-a82e-4474-b0c7-08dd500d7df9 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|36860700013|376014|1800799024|7416014|82310400026; X-Microsoft-Antispam-Message-Info: kJAf+TYVulPUbI2EDcbwqgRY2rdNX2NWrJmWXovjwXj1fC+Ved92OMSsU7OB9ASaBQcOCt9PfMGY2sjR+74s8AwQslJnjckPl3YZQ0vowE051JtoWIBQgwHxTAAdTGvnzj5z2VdrrVve5h4YPKAiuCEbk6tUU6lR7S9OVHSsVt1wahf69P04XdbefwUorpm9CQq7E1p0rIWOrx6rDQNCx+5bf4qPyJ+tjAXcg3KcQqAmWS99yZifi65flFRq67C9n7X+Gu8AfeLmnVsiPSqIdCDv2lHwF85fR7R5tQJ8UpKACt0qthDGsYiROVeiJQbOCiLmf8AxkNjNhLiWaXMnSjR41gEd0rs+DmJ5q5WaqPBut5FqLhZVLzm71Nu3c1OneIthKonMQ2CN4w0XYl0guqOIZNkHFKK1IBz6aA3UA3rtVvjMJnak3j4ca8axUsyBTX7mtVbslQiqzM6fi6orRoJvhCz/NP6E8jdWnjsr8zmbFTi61NAA/Ec6zQSaF1202XHvB/RFa3/sKWwZKaaCtNT4ai4UHWvEKvJjWy97jcMkL7K83338CCwz/D8hG/ZBRBXOCwpJliqym0CFTOjP7mALqRkU/LrxfEPbsRgT/FKEX+35jDKitoFjvMhAiL18cVmGCteEk7y3N8Kktm8TCTsdX0lyzvxOHpMHW5D0nlKYS0wAa2ZZpH3zk7xyoUR4ctxT2JfW7cksgK5oiBW9BFK4tSOl5tUJDe4vFyjudQ8BAZ6R+fQd8lDmWIJhthC+5PAvZykD4Yuj17w8L1DZI5/1orZxMbsXfJU1LDTfqbKbbsdgIaL67sO0VFcekNg/qWl3jT4M8EmGTBeBJsNCSgFqR3lSmFOJXvl6pVyqNk6sVMxEYdiqdgGYMTeQiO5VJrxrWEppPUn49bm2MdGJYXoTbE/ePQ2yLF6R8qnXniaVkCaWUuGB7F9qAf/1sbiJrR/6A7iX6O74MKu50Fg5uaf9Z1eTZTc/ZS0H886KwGcd4IU6drOyy6PvO8hzb5HmlNBZuSRsLwHnkqXiweXdXe+u0SQ2jRVDC+XrXUkzd3U58vnnaxGeG7bHV64qIrLYHwWn+b3X2Qnnh/brdhiRM8IJ5F7YWRVGl+TkPPLXQ+Yq8/ZvjYi0cWKDtLR8ft0+pypZ1v3HWqvTqw7CjeZtJXtBSPFFb+A37ymbYyBfW04dE5/LGYVN9OTNP6eJpiHuhZZCBH0lO8Eu3KxL7ukBWEalLaWRjO81SWAFiuxOOnyY23ZMlGYw6d6iBCg9+3B6WQ73AlE0KWqpNgrC6XAj5XUMZBpwompiIDCRQsPF/6Ql+D+kJBeYglrvFHbiXzFuhGYlDR33dJ2Y0OIPwBIzo0+7dR7/TvcFOxhmWMi/UJfJlwwsOjvI95rxHseNO6KXS4DTZyv+NKCuDm7hIdkmupfUpXx9an1WczEJZ3J9zmXF/fZ7JzSm9v2iawcg427QQWmUSlYQGEUzOIQ84bQ+/OIRPmVzxf8R3SCnVcyKWRM= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(36860700013)(376014)(1800799024)(7416014)(82310400026); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Feb 2025 11:15:03.4166 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: fc46e990-a82e-4474-b0c7-08dd500d7df9 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN3PEPF0000B078.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: IA1PR12MB8405 The new AMD SEV-TIO feature allows DMA to/from encrypted memory and encrypted MMIO for use in CoCo VMs (SEV-SNP). The secure part of IOMMU is called sDTE ("Secure DTE") which resides in private memory and controlled by the PSP. sDTEs of passed through devices are in the TCB of CoCo VMs and inaccessible by the host OS. Implement vdevice in the AMD IOMMU host OS to represent the host instance of a secure IOMMU which is visible to the guest. This will be used for GHCB TIO GUEST REQUEST to manage secure sDTE and MMIO. Most parts of insecure DTE move to sDTE so DTEs need to be adjusted. At the moment this includes "domain_id" (moves to sDTE) and "IOTLB enable" (should stay in sync with sDTE). Signed-off-by: Alexey Kardashevskiy --- drivers/iommu/amd/amd_iommu_types.h | 2 + include/uapi/linux/iommufd.h | 1 + drivers/iommu/amd/iommu.c | 60 +++++++++++++++++++- 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h index b086fb632990..b5513bf05b27 100644 --- a/drivers/iommu/amd/amd_iommu_types.h +++ b/drivers/iommu/amd/amd_iommu_types.h @@ -593,6 +593,8 @@ struct protection_domain { struct mmu_notifier mn; /* mmu notifier for the SVA domain */ struct list_head dev_data_list; /* List of pdom_dev_data */ + + struct amd_viommu *aviommu; }; /* diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h index 78747b24bd0f..b346fa11955c 100644 --- a/include/uapi/linux/iommufd.h +++ b/include/uapi/linux/iommufd.h @@ -939,6 +939,7 @@ struct iommu_fault_alloc { enum iommu_viommu_type { IOMMU_VIOMMU_TYPE_DEFAULT = 0, IOMMU_VIOMMU_TYPE_ARM_SMMUV3 = 1, + IOMMU_VIOMMU_TYPE_TSM = 2, }; /** diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index b48a72bd7b23..076c58d61d5e 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -2068,7 +2069,18 @@ static void set_dte_entry(struct amd_iommu *iommu, new.data[1] |= DTE_FLAG_IOTLB; old_domid = READ_ONCE(dte->data[1]) & DEV_DOMID_MASK; - new.data[1] |= domid; + + if (domain->aviommu) { + /* + * This runs when VFIO is bound to a device but TDI is not yet. + * Ideally TSM should change DTE only when TDI is bound. + */ + dev_info(dev_data->dev, "Skip DomainID=%x and set bit96\n", domid); + new.data[1] |= 1ULL << (96 - 64); + } else { + dev_info(dev_data->dev, "Not skip DomainID=%x and not set bit96\n", domid); + new.data[1] |= domid; + } /* * Restore cached persistent DTE bits, which can be set by information @@ -2549,12 +2561,15 @@ amd_iommu_domain_alloc_paging_flags(struct device *dev, u32 flags, { struct amd_iommu *iommu = get_amd_iommu_from_dev(dev); const u32 supported_flags = IOMMU_HWPT_ALLOC_DIRTY_TRACKING | + IOMMU_HWPT_ALLOC_PASID | + IOMMU_HWPT_ALLOC_NEST_PARENT; + const u32 supported_flags2 = IOMMU_HWPT_ALLOC_DIRTY_TRACKING | IOMMU_HWPT_ALLOC_PASID; if ((flags & ~supported_flags) || user_data) return ERR_PTR(-EOPNOTSUPP); - switch (flags & supported_flags) { + switch (flags & supported_flags2) { case IOMMU_HWPT_ALLOC_DIRTY_TRACKING: /* Allocate domain with v1 page table for dirty tracking */ if (!amd_iommu_hd_support(iommu)) @@ -3015,6 +3030,46 @@ static int amd_iommu_dev_disable_feature(struct device *dev, return ret; } +struct amd_viommu { + struct iommufd_viommu core; + struct protection_domain *domain; +}; + +static void amd_viommu_destroy(struct iommufd_viommu *viommu) +{ + struct amd_viommu *aviommu = container_of(viommu, struct amd_viommu, core); + + if (!aviommu->domain) + return; + aviommu->domain->aviommu = NULL; +} + + +static const struct iommufd_viommu_ops amd_viommu_ops = { + .destroy = amd_viommu_destroy, +}; + +static struct iommufd_viommu *amd_viommu_alloc(struct device *dev, + struct iommu_domain *parent, + struct iommufd_ctx *ictx, + unsigned int viommu_type) +{ + struct amd_viommu *aviommu; + struct protection_domain *domain = to_pdomain(parent); + + if (viommu_type != IOMMU_VIOMMU_TYPE_TSM) + return ERR_PTR(-EOPNOTSUPP); + + aviommu = iommufd_viommu_alloc(ictx, struct amd_viommu, core, &amd_viommu_ops); + if (IS_ERR(aviommu)) + return ERR_CAST(aviommu); + + aviommu->domain = domain; + domain->aviommu = aviommu; + + return &aviommu->core; +} + const struct iommu_ops amd_iommu_ops = { .capable = amd_iommu_capable, .blocked_domain = &blocked_domain, @@ -3031,6 +3086,7 @@ const struct iommu_ops amd_iommu_ops = { .dev_enable_feat = amd_iommu_dev_enable_feature, .dev_disable_feat = amd_iommu_dev_disable_feature, .page_response = amd_iommu_page_response, + .viommu_alloc = amd_viommu_alloc, .default_domain_ops = &(const struct iommu_domain_ops) { .attach_dev = amd_iommu_attach_device, .map_pages = amd_iommu_map_pages, From patchwork Tue Feb 18 11:10:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Kardashevskiy X-Patchwork-Id: 866253 Received: from NAM11-BN8-obe.outbound.protection.outlook.com (mail-bn8nam11on2056.outbound.protection.outlook.com [40.107.236.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AC95223FC48; Tue, 18 Feb 2025 11:15:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.236.56 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877351; cv=fail; b=D/TilqY92iEWHGoKo74uw/+ghAzAMywGKtJ1Ho5bVCzMBt4fronB8vB1Rf93T8cJbtYlqbXsYFFtgFGIab4XB3ryFrzN9qPkqEO6mkGhbbvQTmxlgPGQN4Jj/Xli57u5PBzN7C3nydX+zX8EokeTMfj7cIb0ATLPDwu00OLaYAo= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877351; c=relaxed/simple; bh=cMPPYYLs/xnnHWBhMUCDZDzcuSfSSxsrL68JUgj2uT0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=uKgAVjCfBehux8KaK2KVkvXazpCSc7AwWlpBPYTvrlnjP9DAXfedy1ksSYf0444y1qP2JSOy8Iad2zOuS2wgQ63eU9Cfe5WS7s1y7Am2iy/z5wtOFJkRuHZyXGYHhFvnYOt0+5/O0n9SGZF18yV4wLEBxZmzNKV+Tj8bzO4dq60= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=r0ZcI/z+; arc=fail smtp.client-ip=40.107.236.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="r0ZcI/z+" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=yVcErwU0vum8Ay3TUGuSjHrz6bFyoplTGmueM5ph1e8IlgbpS+IyjMp8J/zd6/+0TlRndVXfJ+pFeHF9toigTDWJZttRSsEwKa1P7zufmZ7wv73FDXKCyeFT4S8CfYjwu4l6fc6ltt+1vWHygPEGX1OnX/YGAZ1TUnpka8hUQFY4cFeX1cKYkVb9CPEnVl7wTaoAU0O2oVT1C5IUnFZEMrUz2ztRDXtEIbMUXhocsCi35PRnWgt4Ka3vQoLgSwu5xH+EZxKgPCMd4yrBGPMOeAZHITExQlbyjPx/yvDu9NmOWNlpwV6oiOHR2KPfDYPkjqtKqgS82RKYrlGOTPMLMQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=m7EGaCV/rM5+p1jaHlz8zossWnACeHWDNUzx7M9H0+0=; b=elbIe62WmuM0pqHag+8/4nYTEyupa2kwGio8Kh1iOBLmivctXWtZgPr6VRXsAHTdkKgz48jtErQ5i9lkOVavjK74kV4NDk/TrdDyFGa0BA9sCwoYJD3nVOtxGTN1jU+2G67JV4NuP/qN1z0TDHh7TOfdv3nXIEPr7xJNc76bRN2mrjsz8RJGZP24aB2UqZvkc0L6AHlO3duM02H4BQEXQsHdprUeNbRhoBBs+zFQaaW7ktPQY5Ilp9uGIC9mSnEEq5rF3Zmm97sW6FrfpAZw+wD3qQz8werccHFBQtfc6qGP9gzuo9RF4bNmD5d87mTR2A8yhGm4HaILMzjF5MWZgQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=m7EGaCV/rM5+p1jaHlz8zossWnACeHWDNUzx7M9H0+0=; b=r0ZcI/z+japhaJW6bM9EJ2nFYIW7eK4hdiZlWZMod7UJVs1M1DBbz8DABwW38KramIl+lP+cbZ0nVcp2hQxcn1faes3NwzroHh/Z61Olbd6+x4h5GndtwDZe41EFLTP3XyJYlX0NbvnVnsfnJBySVigqPctB2lpdsdHjI9g6LOw= Received: from BL0PR0102CA0041.prod.exchangelabs.com (2603:10b6:208:25::18) by SJ0PR12MB6688.namprd12.prod.outlook.com (2603:10b6:a03:47d::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8445.20; Tue, 18 Feb 2025 11:15:45 +0000 Received: from BN3PEPF0000B077.namprd04.prod.outlook.com (2603:10b6:208:25:cafe::26) by BL0PR0102CA0041.outlook.office365.com (2603:10b6:208:25::18) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8445.19 via Frontend Transport; Tue, 18 Feb 2025 11:15:44 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by BN3PEPF0000B077.mail.protection.outlook.com (10.167.243.122) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8466.11 via Frontend Transport; Tue, 18 Feb 2025 11:15:44 +0000 Received: from aiemdee.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Tue, 18 Feb 2025 05:15:36 -0600 From: Alexey Kardashevskiy To: CC: , , , , "Sean Christopherson" , Paolo Bonzini , "Tom Lendacky" , Ashish Kalra , Joerg Roedel , Suravee Suthikulpanit , Robin Murphy , "Jason Gunthorpe" , Kevin Tian , Bjorn Helgaas , Dan Williams , "Christoph Hellwig" , Nikunj A Dadhania , Michael Roth , Vasant Hegde , Joao Martins , Nicolin Chen , Lu Baolu , Steve Sistare , "Lukas Wunner" , Jonathan Cameron , Suzuki K Poulose , Dionna Glaze , Yi Liu , , , Zhi Wang , AXu Yilun , "Aneesh Kumar K . V" , Alexey Kardashevskiy Subject: [RFC PATCH v2 15/22] KVM: X86: Handle private MMIO as shared Date: Tue, 18 Feb 2025 22:10:02 +1100 Message-ID: <20250218111017.491719-16-aik@amd.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250218111017.491719-1-aik@amd.com> References: <20250218111017.491719-1-aik@amd.com> Precedence: bulk X-Mailing-List: linux-crypto@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN3PEPF0000B077:EE_|SJ0PR12MB6688:EE_ X-MS-Office365-Filtering-Correlation-Id: 856045c2-4b30-4bb4-2c80-08dd500d9654 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|82310400026|36860700013|7416014|1800799024|376014; X-Microsoft-Antispam-Message-Info: R4XgJJ6VHHFaS9tiutjaFInGxIXXLjsfvTL6dSfliULuWPN9a+iHuKPgKu7CyiFG0XPmxC/bj5T6T12uCnJAvCpQvOTSgPFlehY9bgPr8c79y1kM16l3SNHgbkjaqZwRoP+T09rv5K4vaKQe1Tqnik2vOU5I/EluwL7mvIdjH8ktud02XKZamADBHvdvEsoOnuZN1ttVYs/IKcAtANPPjdo0ULrehY6/06m6U4iLIUGbq7Yg5kP5+MXHYwIF7ZpnP+j53Boc7PTqIoOxynAbsoHDhHKhHugjVTxvzA6DtY+4zQeFbGyroDTznbXo/WDNb5w4eV2RiUJ+3NHPRvKKeC++Swjg2jdliyMh/PRgiS4pNy7uPCh2MplVgaixnxmGGzAV0705k+UGWMpF1vaEgCinDirqLgiYw9bj8DyEsPWyNnoO2cCRQdWjErTPQ0joqzLKjrc3NbfE/y+8FdLlvKoF+SDduTWhCYxKNRMR5WVCXovwgIXk6VgAlODvnZWcQzrtXiCZBdOO+k/7UjhiNwHgZL9kQYlCvXL6TfVYlAwUCes1/kONWELu/N1doYsCGPXXgRWBUw3Je56dK9JOtHevuVRA74MA2VnMn9ZB0tabqXQ8Zsc7W2K9IH5MfK3Z0VpiHoLMv6n3w6xax85hme/DUrPoHGsw2cgHV5H0Xt31biexLiLu6smnk/zXRJQvfwVmg/m7HfiJUZQY7l2qu8omYyuQ+KitBe8MbZS4oAjFDVhQbE52uS7kfi0hF6uQz7YPIRbNioBdMpRj0B9t6WcFSZWr8Rrr09WZ5aJMX9fkmLy8nrSzZL2vM5vl3NAjqB+7SX7dUXjaiRmz0FLTTupwwtgSDkFORnxAAQ6ynlcG0Hf+xVwJj0hTuV4OrSrO1cEjLHkDkS9Ko9ROWw136pJEb7zoaVmeZ+vQzbFZ/6j3kvHpcSYxht2xduZaeAcFEeX/ykH5D/6GJ9gl/JX5gD6zUTMZHDiz8U9/N5XJh26d80sP0IOAe/xI9BneuP7jHWmUgCqndb3wR8zSvoHDZa8hRuKOdR/FSfLqlU3Ncj1gku+JU6Rpopeqey0EzZqqUzRbFbztEDG79ka6IrfiTbB2cA5237QS6oYCKDSgPVWDspjnVfYQW8vQdkGyqLR4Eq4IDIDV8jHFKY+ZN3jDJLM3i85M/pLkhQPaJWxZz5jls9gUteaJlaa593Ep1gTYH2JzQagxdgOodh13VdkryEl9M5wGWVSMUy/wdgVK7n5hyGOGH64HTL/r+O+uzl/sQzWmwxX/2DGf11XsQKc+BJwlHA1g0GX1RcB8oHnCGO1fjBCFSbjoMLZDcEWEyPhq0DGklA4c6gwxVMmTbwUPj9Osm5ogjHi690unQdyPAS4+lTrg9mNZqmMivFBkwPdnJF7EjY7YnGMJW0QCtGPgARYz9c4II0fbQinEyKV/Wc5CPm9MijN+zSnJxSFsCvn/gL/t/64m0UiNyBe5aaDtpmBKCU0uuOJgu0rpPC3s1Xw= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(82310400026)(36860700013)(7416014)(1800799024)(376014); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Feb 2025 11:15:44.2749 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 856045c2-4b30-4bb4-2c80-08dd500d9654 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN3PEPF0000B077.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ0PR12MB6688 Currently private MMIO nested page faults are not expected so when such fault occurs, KVM tries moving the faulted page from private to shared which is not going to work as private MMIO is not backed by memfd. Handle private MMIO as shared: skip page state change and memfd page state tracking. The MMIO KVM memory slot is still marked as shared as the guest can access it as private or shared so marking the MMIO slot as private is not going to help. Signed-off-by: Alexey Kardashevskiy --- arch/x86/kvm/mmu/mmu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 74c20dbb92da..32e27080b1c7 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -4347,7 +4347,11 @@ static int __kvm_mmu_faultin_pfn(struct kvm_vcpu *vcpu, { unsigned int foll = fault->write ? FOLL_WRITE : 0; - if (fault->is_private) + if (fault->slot && fault->is_private && !kvm_slot_can_be_private(fault->slot) && + (vcpu->kvm->arch.vm_type == KVM_X86_SNP_VM)) + pr_warn("%s: private SEV TIO MMIO fault for fault->gfn=%llx\n", + __func__, fault->gfn); + else if (fault->is_private) return kvm_mmu_faultin_pfn_private(vcpu, fault); foll |= FOLL_NOWAIT; From patchwork Tue Feb 18 11:10:04 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Kardashevskiy X-Patchwork-Id: 866252 Received: from NAM11-BN8-obe.outbound.protection.outlook.com (mail-bn8nam11on2081.outbound.protection.outlook.com [40.107.236.81]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0905622E40E; Tue, 18 Feb 2025 11:16:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.236.81 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877392; cv=fail; b=ISTQ2tGCn+GZt4VPVEkhsT9nyBdHoA4aVp0Tdtz1akXfJzJWTs3kDQN01A2F93r2xA9c+vH2hqcMBayMrK62+LZIXJ4jXjVH4z7VcyI/ASr0pH58gUUyYZego5np9yxNnb++HAtUeSXlGGsMSoVdYimx3R/JL7nrG0sMR8digw8= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877392; c=relaxed/simple; bh=IgVnsOuxgvQPc8Q3asUR9P/fBAJJImXCyMZ3ZUiH/gw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mZJ9fD6KdMkYti1TffayDfAKw9ibQWhr0Q79NgE0ezIZVIZZNRCM/tJozy5Ps6thq/ZMfHnD5s3iLMEM6FRQqy/qvH0coParHBUO0DusMsd7n2cL8dIO0ltj4oSJNm9h9Wi5vIxR2sZKUx3poC4zxS69jg0hblsi/Y8Bg764bNk= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=tSrJBhN5; arc=fail smtp.client-ip=40.107.236.81 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="tSrJBhN5" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=tNl88Hdm9e4fwb4izE+cz1QDDFWZPhKO95cHwX+trKiEgbbdux58+xo/6ocaN46U1vm+S19lI46eYptVbgxT/pnZpfe4kFCXx18eydE9wLQBT3tGy3LUIH/jf/n0y6l8ud3r4s5INdFrRbWKmjeHQjJ37OTTrcR/ad8dMdOUjkvKmkwh3gLsVwZJ/Zb3oGBiOknxPxANw+EJ3govvl89FVVRuUMO91Li4KiwyR4Wzq4X4mNw77iLmMOzAR0yABwmr9n3gK4aBTHgJNU6tuIRuWnbv25FrKREeV/7G7w5v7VAgbUEukQSfPcGx2BNXR7AgJYl5qo9qcoE4MiBfKm9og== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Qyg3wrzrCLLnB8AeqaRVb9FZTULW+HDG8F1txBPC/XQ=; b=Shw/+ZwhHxKWaMW/tl7fGQrTYAq9szC9+vK4q+bT98hATCECp02mcyBXwwuFtIQSHYeh+E9dkudqQb0LNNURJSH0YhwoX0A0QFvaF7CPZFU6foHWv/zFr4h8FgbYSmhsF8UbZ+xWhVP9wwLP31mfIscykA615SrBkVYwPqSZPh6niGu6p/8w4rqy7xs/nZsFZlCiPHf5Pj5uG1W4O2BLqVu6rnEJPnBXRtMW8dNqcuWBze0M4SeNAQqS40QngX0s6/WhrAksHzWsC/qb7qNrIpBWE3V4ArMdRUqoCqFXNgBkZkNCJskqslqds7yMTPjFdIZ4VG3qU2C325hj8I9wAw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Qyg3wrzrCLLnB8AeqaRVb9FZTULW+HDG8F1txBPC/XQ=; b=tSrJBhN5Y0xwQsXLv5btZ7oJ2AazQRO97s1zGg8xaOeX60vHs8/0Vyl+9A622/0JvG6e3wEuUEDAdM7a7FhqbVGJeBxPzg8yh5iiMeOScs0LOBDr3OKPIcyz1LPhdEOrXng14sAdumh17VW6A3onTVzNajwRlI5ZV6KW3MJV7CU= Received: from CH2PR07CA0051.namprd07.prod.outlook.com (2603:10b6:610:5b::25) by PH7PR12MB5975.namprd12.prod.outlook.com (2603:10b6:510:1da::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8445.16; Tue, 18 Feb 2025 11:16:26 +0000 Received: from CH2PEPF00000146.namprd02.prod.outlook.com (2603:10b6:610:5b:cafe::42) by CH2PR07CA0051.outlook.office365.com (2603:10b6:610:5b::25) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8445.16 via Frontend Transport; Tue, 18 Feb 2025 11:16:25 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by CH2PEPF00000146.mail.protection.outlook.com (10.167.244.103) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8466.11 via Frontend Transport; Tue, 18 Feb 2025 11:16:25 +0000 Received: from aiemdee.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Tue, 18 Feb 2025 05:16:17 -0600 From: Alexey Kardashevskiy To: CC: , , , , "Sean Christopherson" , Paolo Bonzini , "Tom Lendacky" , Ashish Kalra , Joerg Roedel , Suravee Suthikulpanit , Robin Murphy , "Jason Gunthorpe" , Kevin Tian , Bjorn Helgaas , Dan Williams , "Christoph Hellwig" , Nikunj A Dadhania , Michael Roth , Vasant Hegde , Joao Martins , Nicolin Chen , Lu Baolu , Steve Sistare , "Lukas Wunner" , Jonathan Cameron , Suzuki K Poulose , Dionna Glaze , Yi Liu , , , Zhi Wang , AXu Yilun , "Aneesh Kumar K . V" , Alexey Kardashevskiy Subject: [RFC PATCH v2 17/22] resource: Mark encrypted MMIO resource on validation Date: Tue, 18 Feb 2025 22:10:04 +1100 Message-ID: <20250218111017.491719-18-aik@amd.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250218111017.491719-1-aik@amd.com> References: <20250218111017.491719-1-aik@amd.com> Precedence: bulk X-Mailing-List: linux-crypto@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PEPF00000146:EE_|PH7PR12MB5975:EE_ X-MS-Office365-Filtering-Correlation-Id: 29283913-f8c3-4ccc-f391-08dd500daee7 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|376014|7416014|36860700013|82310400026|1800799024; X-Microsoft-Antispam-Message-Info: 4yUo4rwM2786fc/Ab6z21UIU2rzaqMzY7dGNQlwfWZv0FzRE8VYLXAQCRvkVV5tD7pqtJe0Js+BgULC7TFVDtBIGoropVcysALt+R3tSRyk2NYh6rHNmtUSF/2z7sXDJK8Moca8c9dD4DCdvGBj2WA9chrUnTm0YlnkuOylbMSO1amJujYsVZymasfqDx4Jycfw7ZRFzcitaBQTXfvCmkvAhyZNfv4X5RoSDvNFyMLnJFUoiUcAX9lyV61qU5oSI9EtKgIruqYcUFF1SOhSAf2aWpt4h4ooGnl7fKBHHx7jxu9Nw/X+nZOD9pUflXs3QTx2yM5dI3cWJbZRBtFv496Oh+2oJ8yex1R4IIXlKcQy7SJp0mK8WNx/jKFT/4QIyB6zFweV+sVWi4IhcCe7O+lSgoYvxD8nSRbyxGzxW6ZIUd5aZ2QgsBqcOX11qhmu/sCqYunE6yKJZ+UYx463cUV9YnWsW5h/t1fy6zRQyILjImgfXZ/Y6P0VlxMrDprBnVtOg5MsbIyjZhzLq1lMVfMvHmjGpd4HvzECa/h/HUFAu/8xSdg+t0RjXKMNFgEX6owmciFsvdxgRsZaHnR4UJWCqWUrVYkY/RubdiDwfzALYGdy88Bur3RZ9PASlBFVSoxTfMeicPBqFi4DoSqH07i/mIM00U53IquXKHY/6wfCZiT/zg1AmgXp1cN5drrrFhPoRt7CL3/Pf/upZcwGINRqQtqzR60ziQ66h4OxAHuDykAN24EhlTjMNmslwRXr6d4/sBTpO/ab+Oqv+jTh7Cac25pDisM2YBrTUUo6r2NNTUyI049cZxLD554Zv8nN0BQniSebdoJPUh6fGlBkk55DweKyCajBlYITtR2USoKx47VR+Lq6uPfGSIKzN2/VBAgdQm8UVZEChATnHtP7U5vaclRG0b9qo4ZA6wDaQDeZwP2wL6SAoPojvYCGjjkXfkc0sHSjzXO+ZUzxEjavlb3srm/LAiFvqJUfPJrSOujN8Dpr9RRp/YuZ9r9XoXu3qfOrzi9OMLD5It0yiyW+e8wmNASxHiPWDhgF+xqvvFJfddWY/9DPr+xiCQ3o4ZHpr8htnM2GNY9hmBuzhXhEyyhPLgGVY4pVGWh9GYqoNI7/xaWDS0oTfGLyZFBhOGkvwGuTHa7jx2Lr4bRHPeXb/HECyoxqAwcsmNnH9Ord06AE0i1K9j5JmQwkg0lDf/gDjCWaqvw+tr+EKOvYaZeGpmcs1xSZS1FMgxaIDZf2+nWESA+S7N/S4/OVFOe57fojWuuBfthOTqIPUIVoBoK5hjgzl6Baw66rTvu32H1DHpTINTqhOQVp7AJL91OVbn9kX7VE2FKaV70oyDfp6tTJh+CqfkVcHzM76541+R1vsZJu0MGFJ3mlrw8QjyX1yeIMHjh5FaHEIv8Lh5/em2CMAdVGwizwZ6ka/3xuJzapi2jOhrkgN56t5lK1jSova+WI75q71jDSALbY2y+ZST36IJb/qCEC+Q+yInZ3dnfNWCTQ= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(376014)(7416014)(36860700013)(82310400026)(1800799024); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Feb 2025 11:16:25.4930 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 29283913-f8c3-4ccc-f391-08dd500daee7 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CH2PEPF00000146.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB5975 In order to allow encrypted MMIO, a TDISP device needs to have it set up as "TEE" (means "trusted") and the platform needs to allow accessing it as encrypted (which is "pvalidate"'ed in AMD terms). Once TDISP MMIO validation succeeded, a resource needs to be mapped as encrypted or the device will reject it. Add encrypt_resource() which marks the resource as "validated". The TSM module is going to call this API. Modify __ioremap_check_encrypted() to look for the new flag to allow ioremap() correctly map encrypted resources. Signed-off-by: Alexey Kardashevskiy --- Should it also be IORESOURCE_BUSY? --- include/linux/ioport.h | 2 + arch/x86/mm/ioremap.c | 2 + kernel/resource.c | 48 ++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 5385349f0b8a..f2e0b9f02373 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -55,6 +55,7 @@ struct resource { #define IORESOURCE_MEM_64 0x00100000 #define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */ #define IORESOURCE_MUXED 0x00400000 /* Resource is software muxed */ +#define IORESOURCE_VALIDATED 0x00800000 /* TDISP validated */ #define IORESOURCE_EXT_TYPE_BITS 0x01000000 /* Resource extended types */ #define IORESOURCE_SYSRAM 0x01000000 /* System RAM (modifier) */ @@ -248,6 +249,7 @@ extern int allocate_resource(struct resource *root, struct resource *new, struct resource *lookup_resource(struct resource *root, resource_size_t start); int adjust_resource(struct resource *res, resource_size_t start, resource_size_t size); +int encrypt_resource(struct resource *res, unsigned int flags); resource_size_t resource_alignment(struct resource *res); /** diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 38ff7791a9c7..748f39af127a 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -100,6 +100,8 @@ static unsigned int __ioremap_check_encrypted(struct resource *res) switch (res->desc) { case IORES_DESC_NONE: case IORES_DESC_RESERVED: + if (res->flags & IORESOURCE_VALIDATED) + return IORES_MAP_ENCRYPTED; break; default: return IORES_MAP_ENCRYPTED; diff --git a/kernel/resource.c b/kernel/resource.c index 12004452d999..c5a80da58033 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -503,6 +503,13 @@ int walk_mem_res(u64 start, u64 end, void *arg, { unsigned long flags = IORESOURCE_MEM | IORESOURCE_BUSY; + int ret = __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, arg, + func); + if (ret < 0) + return ret; + + flags = IORESOURCE_MEM | IORESOURCE_VALIDATED; + return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, arg, func); } @@ -1085,6 +1092,47 @@ int adjust_resource(struct resource *res, resource_size_t start, } EXPORT_SYMBOL(adjust_resource); +int encrypt_resource(struct resource *res, unsigned int flags) +{ + struct resource *p; + int result = 0; + + if (!res) + return -EINVAL; + + write_lock(&resource_lock); + + for_each_resource(&iomem_resource, p, false) { + /* If we passed the resource we are looking for, stop */ + if (p->start > res->end) { + p = NULL; + break; + } + + /* Skip until we find a range that matches what we look for */ + if (p->end < res->start) + continue; + + if (p->start == res->start && p->end == res->end) { + if ((p->flags & res->flags) != res->flags) + p = NULL; + break; + } + } + + if (p) { + p->flags = (p->flags & ~(IORESOURCE_VALIDATED)) | flags; + res->flags = (res->flags & ~(IORESOURCE_VALIDATED)) | flags; + } else { + result = -EINVAL; + } + + write_unlock(&resource_lock); + + return result; +} +EXPORT_SYMBOL(encrypt_resource); + static void __init __reserve_region_with_split(struct resource *root, resource_size_t start, resource_size_t end, const char *name) From patchwork Tue Feb 18 11:10:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Kardashevskiy X-Patchwork-Id: 866251 Received: from NAM10-BN7-obe.outbound.protection.outlook.com (mail-bn7nam10on2052.outbound.protection.outlook.com [40.107.92.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C34901AF0B7; Tue, 18 Feb 2025 11:17:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.92.52 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877432; cv=fail; b=iUzU3arUDAtrZo5UGvwgjndnDyZaWpWq8CasVIF+zeRx8+/js7Qmvf4KZPXCL7j9ZgmtJ4bEGBic+G5eUdbB+rykOlKxxrDi51Y2MyH3jUMM9jeGAq7Fh8wVDlb7Ia8K4lCLbg64gHdoh2mI4jdkhjzBy6xOOcafUAhQjIZBrVg= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877432; c=relaxed/simple; bh=z7iOm8bh9TghyXizwBavMmSXStHE7K2cEojmGvKOh4Q=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=QWYfTXPQyjWV7ld6BAhqBLRKkO6acX8g7EOj+pfGEahLg9j9Te/CpzmuOQL44XAaMP7xNRPyJqmaoVA3BZcj3tmNygX2Bc8uOBc1vvkzOEtzHPFQ1g1xrh3+4FV40Bh34lQPjkZIRREohPXseFbPRPPqUi/xS6n9N0fFZsW+oEQ= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=pML3E6iy; arc=fail smtp.client-ip=40.107.92.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="pML3E6iy" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=obH4btDPNSTJZbsvW1Q0TCpyDwzcfMEmdNnTNRU/O9FUWgWpo50tDRfZK00UEvs0jMJuVBLEV2O0VHCV7Zc3Vom6Xr0oR1pwtOH3IcTcrNuTqQLrO2UVbtry0n61ECKDiGsO/5b/JJvQXA33jbJQc03w5s20L4SwyfGBIhm+jYKL0DN8bl5QZf58CQ4Kona2qzGBwiNrrDhCXUK6Mu8UKXvZQuswJEq+H3OII0+BMGzGIT0esD97xCU+gopS5YN+97OWNmJsw11+QZIrplc6cI88dmLNZmhCI13X+wWnYLgu7H6iL6MGJMjLo5olYBRDmZZnp/BV8ZL6GjVSyofITA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=C3aM0ECW3j5gVBQRHwomwEGcCZJCz4L4ntXDbIc9/Z4=; b=bp4YqQUyMMcFjAUAh7tmpQsA7QkSfEGFfO1fNGbu6xETQz0lvjuD5+dhu3GpVYPb+sCr/UAmGS778iim34/Z+a+O3x7FbXUzNpRE7N7/bPkzkermcSkwZCkbWsl6LzS6s/ba+OJ86BjKOmSOz4wdiWGEiEya/pzlqa0KgJgp7Y/cPh2MnHb4S+fImrLpRoTc97npHHhRJJjxmqAb5WCafUmxFVhMeJspwc+dkvIAWH247a9TwXnMOsZSq37fl3gDsBlsoOIq5L1D55N10vlPUx8DlaxG5+eRRTmu/DaqM6pBKzepgzDkBUUqyQr+2VFF+TNwLWBogHk/ZG2EbhWjtQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=C3aM0ECW3j5gVBQRHwomwEGcCZJCz4L4ntXDbIc9/Z4=; b=pML3E6iyW1TRkp/a6y5sV66szoW1A3vz38FzO0UeEZBpWEu3eQhWce13iFrgAt5w/wcWGsY3M2FClETjcd/q/hN0/2q3H1dufSZ3xgtriPx2VD3mzRdAJjd3Qk0CSVaBlMdb6vMJ+jHBJbTL5V3lRV7BPzy+LOzfGDEmlvJuw+I= Received: from CH0PR13CA0029.namprd13.prod.outlook.com (2603:10b6:610:b1::34) by LV8PR12MB9271.namprd12.prod.outlook.com (2603:10b6:408:1ff::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8445.19; Tue, 18 Feb 2025 11:17:06 +0000 Received: from CH2PEPF00000147.namprd02.prod.outlook.com (2603:10b6:610:b1:cafe::d4) by CH0PR13CA0029.outlook.office365.com (2603:10b6:610:b1::34) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8398.24 via Frontend Transport; Tue, 18 Feb 2025 11:17:06 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by CH2PEPF00000147.mail.protection.outlook.com (10.167.244.104) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8466.11 via Frontend Transport; Tue, 18 Feb 2025 11:17:06 +0000 Received: from aiemdee.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Tue, 18 Feb 2025 05:16:58 -0600 From: Alexey Kardashevskiy To: CC: , , , , "Sean Christopherson" , Paolo Bonzini , "Tom Lendacky" , Ashish Kalra , Joerg Roedel , Suravee Suthikulpanit , Robin Murphy , "Jason Gunthorpe" , Kevin Tian , Bjorn Helgaas , Dan Williams , "Christoph Hellwig" , Nikunj A Dadhania , Michael Roth , Vasant Hegde , Joao Martins , Nicolin Chen , Lu Baolu , Steve Sistare , "Lukas Wunner" , Jonathan Cameron , Suzuki K Poulose , Dionna Glaze , Yi Liu , , , Zhi Wang , AXu Yilun , "Aneesh Kumar K . V" , Alexey Kardashevskiy Subject: [RFC PATCH v2 19/22] RFC: pci: Add BUS_NOTIFY_PCI_BUS_MASTER event Date: Tue, 18 Feb 2025 22:10:06 +1100 Message-ID: <20250218111017.491719-20-aik@amd.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250218111017.491719-1-aik@amd.com> References: <20250218111017.491719-1-aik@amd.com> Precedence: bulk X-Mailing-List: linux-crypto@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PEPF00000147:EE_|LV8PR12MB9271:EE_ X-MS-Office365-Filtering-Correlation-Id: 1e41e905-9905-4089-0920-08dd500dc749 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|82310400026|1800799024|36860700013|376014|7416014; X-Microsoft-Antispam-Message-Info: gJg9jMOek6eNg6STLeTALf/X0vGEUcTVHJDW/N7hEEalcmH1l59E+1g5GSBvpaZfOuoKrdASLolUMJ5Gtsw/guRJnBzbKfArvPBB2akmsuQpNBsXR5kUOnTufhNd5eHeLi6R/p+IL/3B/WwbwhD3ubOHVb3K1+z8EBKRz9dFowe6C3kVqHr1lWjOKNCAw3KfTz1GVCcf7Vt3yqyZFTHzkVPVCI8lZd2MnCJVuBQDUGlbokFsygkbBMOlrzm2DxtBJyGnr3OkDOWxECOnyq1DINYJehNsV3GZlqvwFMrsYO4iCy780Jwu7r2yMXJrWuoOB6sPBnjZpwvpQK7zq7S7G6toTQqVSf6NxsEJwKSkc0CE6iZO/8aP4ba8wkYJe1YF+yAxtkQ/FRreGMT4pUNrmGJlyT9CILVsv9Hf4o2RfA+RNLLTSmszcPifYMJORp/4gUXaUP51xuwaBQlOut50OQT0+zsAjYl/LQ1OczAF3on7BWpA7vRTqkelD4oq/vbqy9BFkP4inzJxZ+S0lUuDqil8ZJbPR+qNtW5SKBZyTHjhYZaXq0sowT5eyFEFoN1Vd/0zUXIF3qyjOVJI9gbIZeT6xhF762loYqOieBkrG8c32+vEjCOdr8FesxvLwouAcg4JjFMnBMFSSHRaGP21iD8oMBdnzTO+HRRIADacglvPU6gCc/b/m0qbhtswPBUgmuLw1S3hO0VE5Td3cZGk6HzR5o0Rfw0HJguTRwnQB5yqpBvig2CuMorBzy3N7K060jPZr7e5f+KyqlcaI6LY2cUpQGIFjAuX/060NIYFl+X23KSp9RN/lF0Ccj+uZvJtri1a+Mn7aPbhOSwP1ty1l74xj39OIUeFSS583RCQEndhaBcSUDvbS+v+Et3/+dJULTO/2abfAwTRRECD/3lZ+/pAlS3V4Ak504mjz/H8gai96WxINeOfQ+ZRVs6Fa+VX+qllN85afHqUebVm7JblJ/JRjwxLQ8X6bJc9yGMBdk8ZL1A5WEaj/gtB4nA0qO6LzMT2TzkaEgaiegRqbLAvqPhYCMNq6rV5Yuq9gbUT+fLl3J6urrQFEmqHNoxkZQxNilUvCsA131pkbTmlloSmYQbZbDD+5TOMuaa0d+CGc6YrsaEr0zu+iL7255KUk+/y8Q1Y6LEplO20saK/+gIA2zPYfrgxEb9kU8jhjQPHiHVxXtp0swcUgsY94bkI3No+JuiHfJ795o3VywYB0ijVIgyrNym7g1+rv8x9I3EFYzXc1MJNOmBIh8/LRyfhUrfMGsKVSNBf07rNM83wOIYGUlxZRNl6ypQMDG7N/QIhXrJwE5bhINFORPPrZdNW/ZVAFtG2K5HY0pjHB/ICELARdAmo1FlD+EyD43dRcrz2d/VWjuW7RZpMZTVXdNAHHzgzUTgw0/iB73mP6fydVE3TtBXUJCRUvwR8OHJM3r8XkBQzAHIUyMXu+IbtB4h+LZG8Tj7AqtecFyC5PnHfhA6YCYfIJAWqJ5gWw9YZXQ0wZh0= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(82310400026)(1800799024)(36860700013)(376014)(7416014); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Feb 2025 11:17:06.3946 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 1e41e905-9905-4089-0920-08dd500dc749 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CH2PEPF00000147.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: LV8PR12MB9271 TDISP allows secure MMIO access to a validated MMIO range. The validation is done in the TSM and after that point changing the device's Memory Space enable (MSE) or Bus Master enable (BME) transitions the device into the error state. For PCI device drivers which enable MSE, then BME, and then start using the device, enabling BME is a logical point to perform the MMIO range validation in the TSM. Define new event for a bus. TSM is going to listen to it in the TVM and do the validation for TEE ranges. This does not switch MMIO to private by default though as this is for the driver to decide (at least, for now). Signed-off-by: Alexey Kardashevskiy --- include/linux/device/bus.h | 3 ++ drivers/pci/pci.c | 3 ++ drivers/virt/coco/guest/tsm-guest.c | 35 ++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index f5a56efd2bd6..12f46ca69239 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -278,8 +278,11 @@ enum bus_notifier_event { BUS_NOTIFY_UNBIND_DRIVER, BUS_NOTIFY_UNBOUND_DRIVER, BUS_NOTIFY_DRIVER_NOT_BOUND, + BUS_NOTIFY_PCI_BUS_MASTER, }; +void bus_notify(struct device *dev, enum bus_notifier_event value); + struct kset *bus_get_kset(const struct bus_type *bus); struct device *bus_get_dev_root(const struct bus_type *bus); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index b462bab597f7..3aeaa583cd92 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4294,6 +4294,9 @@ static void __pci_set_master(struct pci_dev *dev, bool enable) pci_write_config_word(dev, PCI_COMMAND, cmd); } dev->is_busmaster = enable; + + if (enable) + bus_notify(&dev->dev, BUS_NOTIFY_PCI_BUS_MASTER); } /** diff --git a/drivers/virt/coco/guest/tsm-guest.c b/drivers/virt/coco/guest/tsm-guest.c index d3be089308e0..d30e49c154e0 100644 --- a/drivers/virt/coco/guest/tsm-guest.c +++ b/drivers/virt/coco/guest/tsm-guest.c @@ -2,6 +2,7 @@ #include #include +#include #define DRIVER_VERSION "0.1" #define DRIVER_AUTHOR "aik@amd.com" @@ -241,6 +242,36 @@ static const struct attribute_group tdi_group = { .attrs = tdi_attrs, }; +/* In case BUS_NOTIFY_PCI_BUS_MASTER is no good, a driver can call pci_dev_tdi_validate() */ +int pci_dev_tdi_validate(struct pci_dev *pdev, bool invalidate) +{ + struct tsm_tdi *tdi = tsm_tdi_get(&pdev->dev); + int ret; + + if (!tdi) + return -EFAULT; + + ret = tsm_tdi_validate(tdi, TDI_VALIDATE_DMA | TDI_VALIDATE_MMIO, invalidate); + + tsm_tdi_put(tdi); + return ret; +} +EXPORT_SYMBOL_GPL(pci_dev_tdi_validate); + +static int tsm_guest_pci_bus_notifier(struct notifier_block *nb, unsigned long action, void *data) +{ + switch (action) { + case BUS_NOTIFY_UNBOUND_DRIVER: + pci_dev_tdi_validate(to_pci_dev(data), true); + break; + case BUS_NOTIFY_PCI_BUS_MASTER: + pci_dev_tdi_validate(to_pci_dev(data), false); + break; + } + + return NOTIFY_OK; +} + struct tsm_guest_subsys *tsm_guest_register(struct device *parent, struct tsm_vm_ops *vmops, void *private_data) @@ -258,12 +289,16 @@ struct tsm_guest_subsys *tsm_guest_register(struct device *parent, gsubsys->ops = vmops; gsubsys->private_data = private_data; + gsubsys->notifier.notifier_call = tsm_guest_pci_bus_notifier; + bus_register_notifier(&pci_bus_type, &gsubsys->notifier); + return gsubsys; } EXPORT_SYMBOL_GPL(tsm_guest_register); void tsm_guest_unregister(struct tsm_guest_subsys *gsubsys) { + bus_unregister_notifier(&pci_bus_type, &gsubsys->notifier); tsm_unregister(&gsubsys->base); } EXPORT_SYMBOL_GPL(tsm_guest_unregister); From patchwork Tue Feb 18 11:10:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Kardashevskiy X-Patchwork-Id: 866250 Received: from NAM10-BN7-obe.outbound.protection.outlook.com (mail-bn7nam10on2067.outbound.protection.outlook.com [40.107.92.67]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8EA4B1AF0B7; Tue, 18 Feb 2025 11:17:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.92.67 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877473; cv=fail; b=ZKJsQw2+xUzd56NcfmtMu7ZlecXDLnsHc2AAMHDTdO2kMA3AycUHZ7ljW8/fyMwnuzYx9f+T2ZhrIPhQ7Cx6ylf48PvsxrStDc2vEqfryKqMBiPPBnQAHE/+mI09G7/3xVhbCeFbgrw++IJLCMGQu7q+fXmR1wPg0uOw2+MZpcw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739877473; c=relaxed/simple; bh=/2WT13l/W8Okz2thfVxg2Py+STQleJ3jD6xzMtfLyvk=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=avieuAfqaouyqfZTNa/RsiVIwEjj3CtUb6i2SdQvt8jRQaYa9w4FRnuxKTsX4hQBoYHwAjI64Xs+H460u/mtL7x64QFn5qFbatnATmKULYqD2RNNTHhuDQGo79MjvTcHm7ZGQj14xFF4cdRtXYNXbuuplXAiEDCXYO/kTmZGF/Y= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=ZJFGJtBX; arc=fail smtp.client-ip=40.107.92.67 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="ZJFGJtBX" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=at3ZuW2Nni4MkoI8X3AMQs1cH2zO1kMl+G26Kr9qKBoMJ4M7Pt5oh7g/pZN+clAkI84/aYplf9vXJKpCushrsZfJkq6E62/0zGm4c7H5Nc3+DnNMycSBP7vqILZGd4ujTnUfpNkVO0dx9XuYcHXH6jV9DCFghy7MK2TjpzqGOD0WEQ29JVsD7Tu90QngeCvAlaljMIhv/sFFJte8uqiDZgUImLH7C5sOTM4jVFMXvLyIpbZ4c1e022Yb3GrUr8TjwmFI9rOnL1AXfeeK1T0g+K65hoi+oiWXrMhQfwYHu0Cy1mFfhgX6L8nTzqoBnNIk/PABw/UDRC5Y6Ly/MdMqmw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=y6NGfW1CFdAgc4lpaqDg5VE0bJlzyxSJUAO8qXkrRhc=; b=ZirAltjk0hObA5CauSIPeypyqV4zzMv1FS6gJyzcSnSQ5o0PGB4+NqH418e/WxPEo3B6tEONYQ7CpsWipIT76HZpYt7insqIr5Gu0QNvrpysvNZr1W3q8/Zp+u0bqeXYkXk4SY2Qm2JvjhcluwJgmi8khXTDzsgeEyhlqXHDlgjoGLofi3+FBnsLHPsQJ55JDAzEZtzSdiVu8hd0s1Nkgu2lFeOBK/zUaDUA1ewU8Ha3RFWoIWOqx0cXuS9iqAUz0HP4GFSP9jWP7lXsN6gayudlkaTPgWVUH6VNbHgj46D7fvK7B10bmKlU3loGTeMci1FEzN6rCQexB9rEnUV8Ng== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=y6NGfW1CFdAgc4lpaqDg5VE0bJlzyxSJUAO8qXkrRhc=; b=ZJFGJtBXilfU8GZHYgcpGBgv5aVWHD2TMzsgRimDjVtkxXgFoC4wAnVgXJCBkgO/PEKzOs01LHSaHePGYkdh+xFkt+n8VzkzTYEwuElaBsO0wDPrNJM2yTcQCihqYwHv3HhhUAUPtSy5sDnrJq89LzeZPI+5jkFXrSaGFT0O1nk= Received: from CH0PR03CA0278.namprd03.prod.outlook.com (2603:10b6:610:e6::13) by MN2PR12MB4095.namprd12.prod.outlook.com (2603:10b6:208:1d1::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8445.19; Tue, 18 Feb 2025 11:17:47 +0000 Received: from CH2PEPF00000148.namprd02.prod.outlook.com (2603:10b6:610:e6:cafe::61) by CH0PR03CA0278.outlook.office365.com (2603:10b6:610:e6::13) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8445.18 via Frontend Transport; Tue, 18 Feb 2025 11:17:47 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by CH2PEPF00000148.mail.protection.outlook.com (10.167.244.105) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8466.11 via Frontend Transport; Tue, 18 Feb 2025 11:17:47 +0000 Received: from aiemdee.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Tue, 18 Feb 2025 05:17:39 -0600 From: Alexey Kardashevskiy To: CC: , , , , "Sean Christopherson" , Paolo Bonzini , "Tom Lendacky" , Ashish Kalra , Joerg Roedel , Suravee Suthikulpanit , Robin Murphy , "Jason Gunthorpe" , Kevin Tian , Bjorn Helgaas , Dan Williams , "Christoph Hellwig" , Nikunj A Dadhania , Michael Roth , Vasant Hegde , Joao Martins , Nicolin Chen , Lu Baolu , Steve Sistare , "Lukas Wunner" , Jonathan Cameron , Suzuki K Poulose , Dionna Glaze , Yi Liu , , , Zhi Wang , AXu Yilun , "Aneesh Kumar K . V" , Alexey Kardashevskiy Subject: [RFC PATCH v2 21/22] pci: Allow encrypted MMIO mapping via sysfs Date: Tue, 18 Feb 2025 22:10:08 +1100 Message-ID: <20250218111017.491719-22-aik@amd.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250218111017.491719-1-aik@amd.com> References: <20250218111017.491719-1-aik@amd.com> Precedence: bulk X-Mailing-List: linux-crypto@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PEPF00000148:EE_|MN2PR12MB4095:EE_ X-MS-Office365-Filtering-Correlation-Id: a94abe54-1f3b-4f63-02ac-08dd500ddf8e X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|36860700013|376014|82310400026|7416014|1800799024; X-Microsoft-Antispam-Message-Info: HXRwlDm+nLMA2QUbQfBITFM/RW/7MuwMWilBsU9VCf2xBBOT6iqmDELsn50MPdzbrL0ZIK/F3dOccL1XeUhEp5m30phgYIOg6AJcnl+HcsqRWZWitPCq24rsbkKHzfcKsP/0JVSEJb/E2wEZC9aSSh9+jo59kybBIMHayu3z5xdWDsMGUMrTVZGPhXXDZq3SiESPsdy4o1ukMON5EhHWuVcgQYp4VOEUhq5ArHHMyIBOt9/MWA9goMMgBk1X8Dtls506lECEPUF3/xsAUFvI2eHbmqnblQctDNu87WEZbQMACXqitsaYOOL/Tp/k+ojsAJ2OLAoxyfcOzq/3cIF1NobBM/xir4s4LR92mx0fIjT4Bmls5e1Y/BhSW2y6N9MHLWehgb8jaDG4r8BDwZ/lP5bgkYADalb/hHIMdOuHiF8RnSPdlTt6ZMi8SIsqjhU6EOSdnyq1m0s8sd99vqSsqMTn9M7sixKyYnovZUgSjqiiA/hEHbHFGEM/8pbPEhzEfy82ldWuMwgSi6I1pqF838Yd1Izy64kw0qs8loLCPPzCfrz8uoxJ4zwCe9LbQeAzHYHZoJsKMsoIG9rD4fI+kXgWQS2/WzJIjQKo137yDf5T1ap51OtTUBapFlKrSdQ/jZ6JzG37U8tiSpeDE6iXiraZvuNNw5OeBO8AbQf2V7LTR4myT+EOIaTo4YwfNF59eWw2CPoJd7afnyytEiYrk5WMyFJjEaXFH8Pc2ZkYGe2HLEBf/tqpZ8E/8nb5qvkvDZAr7Mbi7uUJfHbt2ljhsYFy7bPMWWZHCjmBSmIkwprXhjk+/fb0oWqpHbz2eqeGJlseESSoF5WV+KVfV4KJPwowgrdhXHFZPTt7T00VEucCbWr+FfXhoZs7HunJBb9lNimCFsKOCe+WbpoX8w2UAxAbCEukAHF+pNWZPktn3pyTK92EJ+YLb7PonjJ3ISA6ik/A4Hs7XxhsHkSoYkJkgo8DyVpfNIFwlEXBMVA5aK4Fr7lyguWiKmMm4wW1Q/boOWnWUzU3onep4pj2duVSOoZHiYKgrx1SR6Y95keGigimbPn8NxFlI1ttRQrRh/8gGXlFWeVqTIKP0LhUoGihwecBNXM+WJQUcuWB1BgOqZIVXo+sQpz5oZ8INU8XQtwn/LDoam3cg8iYtHXLyegsvE+4cgNxbUzGgmmOXuTDkfjLkOJBi+pYoq6VwHFXLBwjWuQw80W16Sr5QHGICeb84y96wb9i6/GNnBcXzzuBorr7ikrQQTi4EtxEP0lu/3W0PtdQd0cpUsTfbTh7BNUV3x9rJx10+77HfjLaUoKAZQxTyai4Q1LNI2S/aEJY/JEbw4bhPAYisrBqt+frkqr/FmIr9CEBAPUPzowLlPYsmUA4W4B5p9qNJZ/9yMrQ8AbDh8v27MU0DKVkEnYjohv7e7A8oO9bfAERx7vM689ujUShhv8h865zbKW5BolYQ3zphZiSFZ33T4c4p0Z8r7nfkDZnn20H7oXW257xWM7Bkz8= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(36860700013)(376014)(82310400026)(7416014)(1800799024); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Feb 2025 11:17:47.1276 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: a94abe54-1f3b-4f63-02ac-08dd500ddf8e X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CH2PEPF00000148.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4095 Add another resource#d_enc to allow mapping MMIO as an encrypted/private region. Unlike resourceN_wc, the node is added always as ability to map MMIO as private depends on negotiation with the TSM which happens quite late. Signed-off-by: Alexey Kardashevskiy --- include/linux/pci.h | 2 +- drivers/pci/mmap.c | 11 +++++++- drivers/pci/pci-sysfs.c | 27 +++++++++++++++----- drivers/pci/proc.c | 2 +- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/include/linux/pci.h b/include/linux/pci.h index 073f8f3aece8..862f63ef9bf9 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -2129,7 +2129,7 @@ pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, */ int pci_mmap_resource_range(struct pci_dev *dev, int bar, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine); + enum pci_mmap_state mmap_state, int write_combine, int enc); #ifndef arch_can_pci_mmap_wc #define arch_can_pci_mmap_wc() 0 diff --git a/drivers/pci/mmap.c b/drivers/pci/mmap.c index 8da3347a95c4..4fd522aeb767 100644 --- a/drivers/pci/mmap.c +++ b/drivers/pci/mmap.c @@ -23,7 +23,7 @@ static const struct vm_operations_struct pci_phys_vm_ops = { int pci_mmap_resource_range(struct pci_dev *pdev, int bar, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine) + enum pci_mmap_state mmap_state, int write_combine, int enc) { unsigned long size; int ret; @@ -46,6 +46,15 @@ int pci_mmap_resource_range(struct pci_dev *pdev, int bar, vma->vm_ops = &pci_phys_vm_ops; + /* + * Calling remap_pfn_range() directly as io_remap_pfn_range() + * enforces shared mapping. + */ + if (enc) + return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); + return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot); diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 4136889011c9..7b03daa13879 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -1062,7 +1062,7 @@ void pci_remove_legacy_files(struct pci_bus *b) * Use the regular PCI mapping routines to map a PCI resource into userspace. */ static int pci_mmap_resource(struct kobject *kobj, const struct bin_attribute *attr, - struct vm_area_struct *vma, int write_combine) + struct vm_area_struct *vma, int write_combine, int enc) { struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); int bar = (unsigned long)attr->private; @@ -1082,21 +1082,28 @@ static int pci_mmap_resource(struct kobject *kobj, const struct bin_attribute *a mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io; - return pci_mmap_resource_range(pdev, bar, vma, mmap_type, write_combine); + return pci_mmap_resource_range(pdev, bar, vma, mmap_type, write_combine, enc); } static int pci_mmap_resource_uc(struct file *filp, struct kobject *kobj, const struct bin_attribute *attr, struct vm_area_struct *vma) { - return pci_mmap_resource(kobj, attr, vma, 0); + return pci_mmap_resource(kobj, attr, vma, 0, 0); } static int pci_mmap_resource_wc(struct file *filp, struct kobject *kobj, const struct bin_attribute *attr, struct vm_area_struct *vma) { - return pci_mmap_resource(kobj, attr, vma, 1); + return pci_mmap_resource(kobj, attr, vma, 1, 0); +} + +static int pci_mmap_resource_enc(struct file *filp, struct kobject *kobj, + const struct bin_attribute *attr, + struct vm_area_struct *vma) +{ + return pci_mmap_resource(kobj, attr, vma, 0, 1); } static ssize_t pci_resource_io(struct file *filp, struct kobject *kobj, @@ -1190,7 +1197,7 @@ static void pci_remove_resource_files(struct pci_dev *pdev) } } -static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine) +static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine, int enc) { /* allocate attribute structure, piggyback attribute name */ int name_len = write_combine ? 13 : 10; @@ -1208,6 +1215,9 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine) if (write_combine) { sprintf(res_attr_name, "resource%d_wc", num); res_attr->mmap = pci_mmap_resource_wc; + } else if (enc) { + sprintf(res_attr_name, "resource%d_enc", num); + res_attr->mmap = pci_mmap_resource_enc; } else { sprintf(res_attr_name, "resource%d", num); if (pci_resource_flags(pdev, num) & IORESOURCE_IO) { @@ -1264,11 +1274,14 @@ static int pci_create_resource_files(struct pci_dev *pdev) if (!pci_resource_len(pdev, i)) continue; - retval = pci_create_attr(pdev, i, 0); + retval = pci_create_attr(pdev, i, 0, 0); /* for prefetchable resources, create a WC mappable file */ if (!retval && arch_can_pci_mmap_wc() && pdev->resource[i].flags & IORESOURCE_PREFETCH) - retval = pci_create_attr(pdev, i, 1); + retval = pci_create_attr(pdev, i, 1, 0); + /* Add node for private MMIO mapping */ + if (!retval) + retval = pci_create_attr(pdev, i, 0, 1); if (retval) { pci_remove_resource_files(pdev); return retval; diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index f967709082d6..62992c8234f1 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -284,7 +284,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) /* Adjust vm_pgoff to be the offset within the resource */ vma->vm_pgoff -= start >> PAGE_SHIFT; ret = pci_mmap_resource_range(dev, i, vma, - fpriv->mmap_state, write_combine); + fpriv->mmap_state, write_combine, 0); if (ret < 0) return ret;