From nobody Sat Nov 2 10:32:53 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Authentication-Results: mx.zoho.com; dkim=fail spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org; Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1494454195355691.2236806822693; Wed, 10 May 2017 15:09:55 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 95DD221A16E20; Wed, 10 May 2017 15:09:48 -0700 (PDT) Received: from NAM03-DM3-obe.outbound.protection.outlook.com (mail-dm3nam03on0613.outbound.protection.outlook.com [IPv6:2a01:111:f400:fe49::613]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 0C85021959D43 for ; Wed, 10 May 2017 15:09:47 -0700 (PDT) Received: from brijesh-build-machine.amd.com (165.204.77.1) by CY1PR12MB0149.namprd12.prod.outlook.com (10.161.173.19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1075.11; Wed, 10 May 2017 22:09:43 +0000 X-Original-To: edk2-devel@lists.01.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amdcloud.onmicrosoft.com; s=selector1-amd-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=srSJ3M4E9wbGe+CkEmWY8fV1bPqPOF5zHyfka1eeUMY=; b=MxWWHk3bfqgbeTVWudrYxbe9p+McwTi8TBFisp8ToA6Bhm47dc7mk0b8dYw5w/mFvaWbcne392EVp0afyPIE/JKY2NOrKV6A7VmfHPxuGAw2FXZwn4+N0mPZmjt9VBKu3wEOH/KXqjveJ9P0gd2KA8HNndE2XLTZIhR8vzxK3t8= Authentication-Results: lists.01.org; dkim=none (message not signed) header.d=none;lists.01.org; dmarc=none action=none header.from=amd.com; From: Brijesh Singh To: Date: Wed, 10 May 2017 18:09:13 -0400 Message-ID: <1494454162-9940-5-git-send-email-brijesh.singh@amd.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1494454162-9940-1-git-send-email-brijesh.singh@amd.com> References: <1494454162-9940-1-git-send-email-brijesh.singh@amd.com> MIME-Version: 1.0 X-Originating-IP: [165.204.77.1] X-ClientProxiedBy: MWHPR21CA0051.namprd21.prod.outlook.com (10.172.93.141) To CY1PR12MB0149.namprd12.prod.outlook.com (10.161.173.19) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 6f27c12c-ea4d-492c-e8d0-08d497f143fc X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(48565401081)(201703131423075)(201703031133081); SRVR:CY1PR12MB0149; X-Microsoft-Exchange-Diagnostics: 1; CY1PR12MB0149; 3:JlEG/V8s+NhjnlXqC006GhqIruDRGvG2B0Mn+Mdg3JZ9/8GbwajoQ1VsWBiMvKnYOHTxdU7MgifeNh9m5fSn969RZQ48njMzXEOvBokwSi+5NWthPo3EKjKA2NdNeQye/LsS8Xto+6Jd14cbQicSfyWOjrgT9hQezThwyLxThD5Ky0wlD1KpRibM4vMH+0e/PyVUDB5q1n8D9vJfKyY7+J72ALyei+EtrIUGuj9YxObESSowapZ3T3JP8U+Jn8DPSsYF0jHvI7xqUf04E80ZphU5ql19Ukokg7lY7CbOBatwGV2CPQWZ8R5Pd4fN4bZvpak2cKXuGwLcHJfyXr8NwvhEw9WVRCqqzxYeBEawcQU=; 25:FRGym4M/INo+D8a5sQpH/cTEp6k0YK408hKgxChVjcmqR16MzFazRLRgvMbbDfyG/2w/CZWEhC3k5vgFNs1brzjMQftmWUfya/qye3f/IWsDBjeHKTKQYFgIHft7rEsIEkUw16Om0YRxzYyXMqB3rOIh/JZyqNDVNi2Kn+siLkDsIQcliwlw5QON8fSSR8HxXnqOfcm0gnoXD/UTZtcQfyToNDJ9QGQelwQSMTK56G3/9s0Cydh90duD6cvhPbLmCNJsU73crdQReLx119a/SA6riQZmkJJLHHqV/MVHNlh2vMxi63Z97rrdCuLV2ZHsrxcQg++YpHpryX6gfDjehYCTpchc6u4vw62CKFUbMYSJFaCsl3K98gp9a0c+KByjl8vlGZcmg8G3hqvUPYpUYg0QPmCC3EyqSi5ITIg3lg7wj7Q8wlYnY/ACqDdnDPnEU6htEDmlrCtdx4teFiJbvxEMn+GL3upjMpAE3vfeA0k= X-Microsoft-Exchange-Diagnostics: 1; CY1PR12MB0149; 31:4twlqsB0AGML3zVcy6QYO10ofD6LHCirp0MHxPE1zHNc6LMQY1ThPXCVgTr9RNT3uPHQFQkSyI4duCu1ikYRvBxdK3/wGqHMhM54wxeA8bWiUyE8yaBG0uRTXxnOg7ti/l0smTnWruRgn3Hwnd9zT1blO+aF7zmZbwBYISWIfwB3PLUuJjWv63cCr3pwrsRwLxssIkqXkNpcCFFP8q4F1lgbMlZmMgpzkYz6OCDadinUl8v8mlNMdW6vF/I4Re9IaEoRIcaj8KCWFaqHCGo8mA==; 20:0Of1h6n/xoePPZ8ZN1pSEikPwzEL+jxfKWq4IbPvaDMO3/wLXqBI/hUJwe/qyGnsurBf4OqRh7ZNCvocRr5mZMErB2G8Fd/p15M9HXMtds/o2rtBL6K3f0qUroWVGBu8dDvux3oAWyhHvTtTzP1AKYtK/1fi6MI7Gjtt9qV7Z4RZur8V+jJhdvRMEDzZJg7+ZYi+Y9ihMUpygzLGNWbXaOToh1wh5paWxU/Ze/z/fPL+FAmMj7Nkr7iDbMfH5pkmrm2BTXTRLDw9KTl6jFtfR9Tn16aG0P5tGAhkaWCBsY8pkoxmTQvsD5qGGN9GgkvRxcAlS+xbWvEWSSr7CK5g0/2cPoqfeRXa175K1d0kRxV5pH3b3OHcPo15puGF+e14CgnZSK7bZTtCG//CJUDTt/LLnSKHA+txouBFKsQ0RSC/rU+wkXKfOjrRkzaJud4z78NxADRhy6wamNcvgxP6zwNmBPvZpArJte2TrtsI7s3dDQnuKyfG6iYE31C3YjK4 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(767451399110)(228905959029699); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040450)(601004)(2401047)(5005006)(8121501046)(93006095)(93001095)(10201501046)(3002001)(6055026)(6041248)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123562025)(20161123558100)(20161123560025)(20161123555025)(20161123564025)(6072148); SRVR:CY1PR12MB0149; BCL:0; PCL:0; RULEID:; SRVR:CY1PR12MB0149; X-Microsoft-Exchange-Diagnostics: 1; CY1PR12MB0149; 4:IKMrnN7vRYq5MKykAnWeYouVNNyXoLlwcUHcN83obp3Qvyr+F5N0plCMTNCZcNajrcnd4C4g0EY9taHzzYeapxooGw+YMVWN7dYTy+RXei872vdQy0VZ4gpWQQcl4dTZRlOuajQ7jGJJt48bdPhjhcwpfgmtudqhICJ4yJdtCJEnnwT3B37hp6Xte9gmE2KsvAlo5r1gzvIN+9dVVT5LMizgIzTRfYaevsciohVip/smgqZiUjM9ataeodE5aVE5v66uVGEgbhzRWi1io5OPzfzjyUYHCUsGuuTjk+vPsqaD6SjLL3J0PbJAafpPmGiJ6YD3BVfAF9QpRz/6b8FrUe6oiMxCrfojxsbmYKHChM95O2WYQnpwoWhvefAxR/pQ95sGu7XXz/A7U6sGv8Ri4xp0lfSSit/FLLpCdZ7yowovMPiM45m9KwdPxy8LpX1sHLtfRb5+FqAdC7e6/fWDvDGjfUZEp1uf4PnT9pOQEnqjNmRPdWgXBq+GOr039ZrJ7cYkDzzNFKLX5yh/I03kSYSHqvy6dw0j8bq4pPY2kEUiBDCJqnp03HCQj++jAabjc/vP2cvMMWwkAeIx1/+pn0+o+G2ac5YShUxHOKoPeYo7RI68QyG7RnxeNmN6GFU8p4eDjr8+ow2f1B0pgWVGjYk7TNrWcS5i8l9ANtySIQaipldhaaRUETpD0aZlEJIurPCGwLIwUG6Hrmi2jIXLQoMSnPuDuiIw2MARWCoUXnoeh0dZQQD+Foqlhc4hdyI/73lePESo0EkhcJ0u33HV1X7gpMjHNZc942f/NVs7LA668KLetuyI8fjisNaFrznUJKmpdejq7GWetk28xLUUlQ1k5AjHSi5oXVwmyrLctwwULQA77mCLHXgq+CvHCqNP X-Forefront-PRVS: 03030B9493 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4630300001)(6009001)(39840400002)(39400400002)(39410400002)(39850400002)(50986999)(2950100002)(6666003)(6916009)(6486002)(76176999)(50466002)(33646002)(478600001)(86362001)(189998001)(48376002)(110136004)(8676002)(4326008)(2906002)(6306002)(54906002)(38730400002)(53376002)(53946003)(53936002)(966004)(3846002)(6116002)(50226002)(25786009)(81166006)(5003940100001)(5660300001)(53416004)(36756003)(42186005)(66066001)(7736002)(15188155005)(305945005)(2351001)(16799955002)(579004)(19627235001); DIR:OUT; SFP:1101; SCL:1; SRVR:CY1PR12MB0149; H:brijesh-build-machine.amd.com; FPR:; SPF:None; MLV:sfv; LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; CY1PR12MB0149; 23:TtTMHncICcrjS41eZKJ+WrCO6oPMV5bO7GioMUwcj?= =?us-ascii?Q?LWpFmYg9xYqc0T/sJUgEMo1SIhF6BCWvPE5b7NgN9m7kSxv2AwoEdxSCq8tp?= =?us-ascii?Q?y0iFIrD6JCwivUlQeoJnfYg63rN8hUMokQOyi1MQDRTwwZoL4+Ci0/rDBUz0?= =?us-ascii?Q?fQPz6PDBlUkGsRO+hfPc2cNHwIwngeMUXASZktJcWe2FUWz42Txg6QkKIn3S?= =?us-ascii?Q?/oKgOdOEt8I6NqfU+vJscLvkXz5UbGqJk9dxckKNmJqnsoayxuEdJiTQ4yCs?= =?us-ascii?Q?OId2nlgZxf1qVSXpveG7vAf6DO+e7ZBttSMpsFF1VTamzoZegyAFhE89cnP6?= =?us-ascii?Q?JMEHnA8ZzChoJWtNadaUluw0tp09AeXZH0D317ybsfPIdTX9QVXh7OJYQe9G?= =?us-ascii?Q?l5psKwZfYq4jUCBn1VvAA1+JEROgaDjAP0+ct12LYIn9iv1U6uYKsr14Kl0K?= =?us-ascii?Q?9mUjLX4dDCm97E8fBTqswGvg8YQ9wRb6nz59G9mtAaTckxIeE0q/DbPrZbG6?= =?us-ascii?Q?Rv84LUgpLRwAZhjAtRcclrnDfuuYndaLeEoxOperR96joo3JpVljtDGpPJKD?= =?us-ascii?Q?wQRjx0LHSwtWgtPAaKLO3YP72/qUJthyiyOKWfwhNLRXkA+Q+YtOWX7tw12r?= =?us-ascii?Q?+17KbBraVfOBsDCziKYNXw0K/wgO13FMwtAYGJ+qDE9MsiwZE00V4iLXQMAw?= =?us-ascii?Q?p6c1/sh7K+EVDxyCQz1KVXACqseBJUyQVy4UbFF2ujtsAs/9TPXbJlSzU2AH?= =?us-ascii?Q?sk/902a9OscWY8nsFLwvGWV0rRNh1ez2IzCOdMi1bRvs+TErn8CNUTnfv7t+?= =?us-ascii?Q?9fUXpqYZ7507jo7T34civjMpmdhQef3sWu3NMmgv6GMgVzA9bJY/gFuuHKC7?= =?us-ascii?Q?03hWbJYHMshqsjcHADPBL75bScv8M/m9CJclya3fcQDE+EB7xT+2SnSyvUr2?= =?us-ascii?Q?L/eDF0alHpD909APqRVPFmcVjZJM6xxFTORvadZa/FT7CSnFYXMY3wfl4UNB?= =?us-ascii?Q?1gPQSdFgXULPIBGkTq7y36DG1kf5dWf36qa+M5CcNEvuw4FowXbTyEkYs+rO?= =?us-ascii?Q?BCVp5+AmJvI52yYw0NH+iDQc5jwHbi76Bbgi0oiVs5qRuHIOFLMQNcxzfQYf?= =?us-ascii?Q?z71lAccQpuQwgAWIc/1sJYMa5/x2a5SOzw9GfYLaCFOlYWMgdfvU/PlElB7k?= =?us-ascii?Q?I5NfdDs0egMcbI=3D?= X-Microsoft-Exchange-Diagnostics: 1; CY1PR12MB0149; 6:8FDrHd1sETy8GRvMBsKgBrsVN4CO+bwlRetEZ3j71PzuMAIbhaifTnrQt+HE0hgroij4CtMN+Qy3d30+oK9ULYsoxGWiTgI2zyTAZjDUj9w4gMpA+1C9bfCggxH3tG6tUxX0ooeDHLSbsNsouU8oJWczM4DvMgxyPzLJHb1NTIONl+wndlgevylnmHFzNU3gVFhnuE8gZiSoRTUehpGJhW0KGv+pIbSp4TBzv11INwP1KCzUMJT/Bik+U1cC4m5iIXsDfw1z1AdVkGmD3HYHylGbBeKQbfTubOC8E+qDVPoWVkid0xGAvVwWRSmUIWjG4zzvoYVsz/ztD1yPuLE55CM0j2e8bzeu+BpbcY8YIrFbNVT7vF8SeW7gwbr9/fO6cNH43TzeOa69RezZ3YVFybEhf8tTk+eq7hnbsHoZm4jv7VAV8VurdnbOcWemaggL13U0MdGp0kmyTI1A+xZSdXohmBqZ2Cv47tUmuSRi0AT1XK0gAOksAMyWhfMDc3Oe0szxgrm1siXVzwEkQ4c7T+VFL17JM1z5UgK6r4OgTSg=; 5:KR0qSmjDz9VjRmVfZtLFtYt0slkiMVZs1mj2ea3bOw3Q7s01GqII8amU/T5brL0CkM5FunjImT5kvGmaBEhxTwV7zqk8BFOh9xOJ8tblwCX84FLtEXfsUFIJUtfseAW7CFIvJQHYO27KG33ugc331A==; 24:X0NXmZOGQ3VDdrwj7T8ZF3vyG1APZQ0JA2WQPoOELPcamQ/zr9dAERK8oiBHTXEOHCMlJ5AFeIHifuKnjMbXXRfKS7vNyVTzPJ3q7rtQCLc= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; CY1PR12MB0149; 7:unDjS1nZkv+Efk81xccgjvpsu7HoYSDY5ubruMPENhP/piDtHTbsGs7QcyLZVM4gfgHBbfqD3dvHDpoNNvGvqVPXsGhchwkMU4QnRTl8q5vqhGbga00gEiPAuAj5+xuNUUa1PvOHz1Qg/CC6DYAdE26C/LvqjgKaTBDLpYu/nAiojiVhIymBXBMcNE2LuIqiScZOfUCva+MCrfqQVZ+XuCJsg/cxjsGXb9yv7cmVAr3kuyK2erPPhyzYe8ZpagGOG/YPDaSippMYNLsakTScNWi2fkKX83lU2/9SdhkrXBCtjlOJFrs8eGGzKB3xr92sV1TA7oYKHWoliPniR7Ucog==; 20:8RldSqFzjcAqPDQYEaFcqzWz3nS/HIuIzSTUsgbv+wR0JgPF9aLbCs80/vHgWAphF+v4KHbIu4U8pweML1a8XKlPuHxGJheksVgm6CbNlLP/7/WNdnXPtEX6t679YLqz7pvt1d8o66c+sdZmCBz8wiYbxyP7UwDYfTCT33TiL1VzU2E6Plvgv69exr5qS3J7P+rt6uHsHxt3f3fPOmjTL/Fn8DDvf6hLF4+O5pFSJX20X6G0HzGP1f5jrnunHwRw X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 10 May 2017 22:09:43.8925 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR12MB0149 Subject: [edk2] [RFC v4 04/13] OvmfPkg/BaseMemcryptSevLib: Add SEV helper library X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas.Lendacky@amd.com, leo.duran@amd.com, Laszlo Ersek , Jordan Justen Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Add Secure Encrypted Virtualization (SEV) helper library. The library provides the routines to: - set or clear memory encryption bit for a given memory region. - query whether SEV is enabled. Cc: Jordan Justen Cc: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh Reviewed-by: Laszlo Ersek --- OvmfPkg/OvmfPkgIa32.dsc | 1 + OvmfPkg/OvmfPkgIa32X64.dsc | 1 + OvmfPkg/OvmfPkgX64.dsc | 1 + OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf | 50 +++ OvmfPkg/Include/Library/MemEncryptSevLib.h | 81 ++++ OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.h | 34 ++ OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h | 184 ++++= +++++ OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c | 126 ++++= ++ OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c | 43 ++ OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c | 127 ++++= ++ OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c | 422 ++++= ++++++++++++++++ 11 files changed, 1070 insertions(+) diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index 6494ac5480b3..265f2d2b6d2f 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -143,6 +143,7 @@ [LibraryClasses] QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevL= ib.inf !if $(SMM_REQUIRE) =3D=3D FALSE LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf !endif diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index 20eb409a8d01..3b50a2dd2d2f 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -148,6 +148,7 @@ [LibraryClasses] QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevL= ib.inf !if $(SMM_REQUIRE) =3D=3D FALSE LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf !endif diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 2e5eaf631e9f..82c73331aa9f 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -148,6 +148,7 @@ [LibraryClasses] QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevL= ib.inf !if $(SMM_REQUIRE) =3D=3D FALSE LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf !endif diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf = b/OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf new file mode 100644 index 000000000000..949c430af61b --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf @@ -0,0 +1,50 @@ +## @file +# Library provides the helper functions for SEV guest +# +# Copyright (c) 2017 Advanced Micro Devices. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD +# License which accompanies this distribution. The full text of the licen= se +# may be found at http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED. +# +# +## + +[Defines] + INF_VERSION =3D 1.25 + BASE_NAME =3D MemEncryptSevLib + FILE_GUID =3D c1594631-3888-4be4-949f-9c630dbc842b + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D MemEncryptSevLib|PEIM DXE_DRIVER DXE_= RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 +# + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[Sources.X64] + X64/MemEncryptSevLib.c + X64/VirtualMemory.c + MemEncryptSevLibInternal.c + +[Sources.IA32] + Ia32/MemEncryptSevLib.c + MemEncryptSevLibInternal.c + +[LibraryClasses] + BaseLib + CpuLib + CacheMaintenanceLib + DebugLib + MemoryAllocationLib diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/L= ibrary/MemEncryptSevLib.h new file mode 100644 index 000000000000..b6753762423e --- /dev/null +++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h @@ -0,0 +1,81 @@ +/** @file + + Define Secure Encrypted Virtualization (SEV) base library helper function + + Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + This program and the accompanying materials are licensed and made availa= ble + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#ifndef _MEM_ENCRYPT_SEV_LIB_H_ +#define _MEM_ENCRYPT_SEV_LIB_H_ + +#include + +/** + Returns a boolean to indicate whether SEV is enabled + + @retval TRUE SEV is active + @retval FALSE SEV is not enabled + **/ +BOOLEAN +EFIAPI +MemEncryptSevIsEnabled ( + VOID + ); + +/** + This function clears memory encryption bit for the memory region specifi= ed + by BaseAddress and Number of pages from the current page table context. + + @param[in] BaseAddress The physical address that is the start= address + of a memory region. + @param[in] NumberOfPages The number of pages from start memory = region. + @param[in] Flush Flush the caches before clearing the b= it + (mostly TRUE except MMIO addresses) + + @retval RETURN_SUCCESS The attributes were cleared for the me= mory region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Clearing memory encryption attribute i= s not + supported + **/ +RETURN_STATUS +EFIAPI +MemEncryptSevClearPageEncMask ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumberOfPages, + IN BOOLEAN CacheFlush + ); + +/** + This function sets memory encryption bit for the memory region specified= by + BaseAddress and Number of pages from the current page table context. + + @param[in] BaseAddress The physical address that is the start= address + of a memory region. + @param[in] NumberOfPages The number of pages from start memory = region. + @param[in] Flush Flush the caches before clearing the b= it + (mostly TRUE except MMIO addresses) + + @retval RETURN_SUCCESS The attributes were set for the memory= region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Clearing memory encryption attribute i= s not + supported + **/ +RETURN_STATUS +EFIAPI +MemEncryptSevSetPageEncMask ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumberOfPages, + IN BOOLEAN CacheFlush + ); +#endif // _MEM_ENCRYPT_SEV_LIB_H_ diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.= h b/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.h new file mode 100644 index 000000000000..17f67b47dbee --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.h @@ -0,0 +1,34 @@ +/** @file + + Secure Encrypted Virtualization (SEV) library helper function + + Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the licen= se may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#ifndef _MEM_ENCRYPT_SEV_LIB_INTERNAL_H_ +#define _MEM_ENCRYPT_SEV_LIB_INTERNAL_H_ + +#include + +/** + Returns a boolean to indicate whether SEV is enabled + + @retval TRUE SEV is active + @retval FALSE SEV is not enabled + **/ +BOOLEAN +EFIAPI +InternalMemEncryptSevIsEnabled ( + VOID + ); + +#endif diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h b/Ovm= fPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h new file mode 100644 index 000000000000..ab5a6ddc3e85 --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h @@ -0,0 +1,184 @@ +/** @file + + Virtual Memory Management Services to set or clear the memory encryption= bit + +Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD = License +which accompanies this distribution. The full text of the license may be = found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +Code is derived from MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h + +**/ + +#ifndef __VIRTUAL_MEMORY__ +#define __VIRTUAL_MEMORY__ + +#include +#include +#include +#include +#include + +#include +#define SYS_CODE64_SEL 0x38 + +#pragma pack(1) + +// +// Page-Map Level-4 Offset (PML4) and +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB +// + +typedef union { + struct { + UINT64 Present:1; // 0 =3D Not present in memory, 1 = =3D Present in memory + UINT64 ReadWrite:1; // 0 =3D Read-Only, 1=3D Read/Write + UINT64 UserSupervisor:1; // 0 =3D Supervisor, 1=3DUser + UINT64 WriteThrough:1; // 0 =3D Write-Back caching, 1=3DWri= te-Through caching + UINT64 CacheDisabled:1; // 0 =3D Cached, 1=3DNon-Cached + UINT64 Accessed:1; // 0 =3D Not accessed, 1 =3D Accesse= d (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:2; // Must Be Zero + UINT64 Available:3; // Available for use by system softw= are + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system softw= are + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} PAGE_MAP_AND_DIRECTORY_POINTER; + +// +// Page Table Entry 4KB +// +typedef union { + struct { + UINT64 Present:1; // 0 =3D Not present in memory, 1 = =3D Present in memory + UINT64 ReadWrite:1; // 0 =3D Read-Only, 1=3D Read/Write + UINT64 UserSupervisor:1; // 0 =3D Supervisor, 1=3DUser + UINT64 WriteThrough:1; // 0 =3D Write-Back caching, 1=3DWri= te-Through caching + UINT64 CacheDisabled:1; // 0 =3D Cached, 1=3DNon-Cached + UINT64 Accessed:1; // 0 =3D Not accessed, 1 =3D Accesse= d (set by CPU) + UINT64 Dirty:1; // 0 =3D Not Dirty, 1 =3D written by= processor on access to page + UINT64 PAT:1; // + UINT64 Global:1; // 0 =3D Not global page, 1 =3D glob= al page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system softw= are + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system softw= are + UINT64 Nx:1; // 0 =3D Execute Code, 1 =3D No Code= Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_4K_ENTRY; + +// +// Page Table Entry 2MB +// +typedef union { + struct { + UINT64 Present:1; // 0 =3D Not present in memory, 1 = =3D Present in memory + UINT64 ReadWrite:1; // 0 =3D Read-Only, 1=3D Read/Write + UINT64 UserSupervisor:1; // 0 =3D Supervisor, 1=3DUser + UINT64 WriteThrough:1; // 0 =3D Write-Back caching, 1=3DWri= te-Through caching + UINT64 CacheDisabled:1; // 0 =3D Cached, 1=3DNon-Cached + UINT64 Accessed:1; // 0 =3D Not accessed, 1 =3D Accesse= d (set by CPU) + UINT64 Dirty:1; // 0 =3D Not Dirty, 1 =3D written by= processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 =3D Not global page, 1 =3D glob= al page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system softw= are + UINT64 PAT:1; // + UINT64 MustBeZero:8; // Must be zero; + UINT64 PageTableBaseAddress:31; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system softw= are + UINT64 Nx:1; // 0 =3D Execute Code, 1 =3D No Code= Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_ENTRY; + +// +// Page Table Entry 1GB +// +typedef union { + struct { + UINT64 Present:1; // 0 =3D Not present in memory, 1 = =3D Present in memory + UINT64 ReadWrite:1; // 0 =3D Read-Only, 1=3D Read/Write + UINT64 UserSupervisor:1; // 0 =3D Supervisor, 1=3DUser + UINT64 WriteThrough:1; // 0 =3D Write-Back caching, 1=3DWri= te-Through caching + UINT64 CacheDisabled:1; // 0 =3D Cached, 1=3DNon-Cached + UINT64 Accessed:1; // 0 =3D Not accessed, 1 =3D Accesse= d (set by CPU) + UINT64 Dirty:1; // 0 =3D Not Dirty, 1 =3D written by= processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 =3D Not global page, 1 =3D glob= al page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system softw= are + UINT64 PAT:1; // + UINT64 MustBeZero:17; // Must be zero; + UINT64 PageTableBaseAddress:22; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system softw= are + UINT64 Nx:1; // 0 =3D Execute Code, 1 =3D No Code= Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_1G_ENTRY; + +#pragma pack() + +#define IA32_PG_P BIT0 +#define IA32_PG_RW BIT1 + +#define PAGETABLE_ENTRY_MASK ((1UL << 9) - 1) +#define PML4_OFFSET(x) ( (x >> 39) & PAGETABLE_ENTRY_MASK) +#define PDP_OFFSET(x) ( (x >> 30) & PAGETABLE_ENTRY_MASK) +#define PDE_OFFSET(x) ( (x >> 21) & PAGETABLE_ENTRY_MASK) +#define PTE_OFFSET(x) ( (x >> 12) & PAGETABLE_ENTRY_MASK) +#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull + +/** + This function clears memory encryption bit for the memory region specifi= ed by PhysicalAddress + and length from the current page table context. + + @param[in] PhysicalAddress The physical address that is the sta= rt address of a memory region. + @param[in] Length The length of memory region + @param[in] Flush Flush the caches before applying the= encryption mask + + @retval RETURN_SUCCESS The attributes were cleared for the = memory region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Setting the memory encyrption attrib= ute is not supported +**/ +EFI_STATUS +EFIAPI +SetMemoryDecrypted ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN UINT64 Length, + IN BOOLEAN CacheFlush + ); + +/** + This function sets memory encryption bit for the memory region specified= by + PhysicalAddress and length from the current page table context. + + @param[in] PhysicalAddress The physical address that is the sta= rt address + of a memory region. + @param[in] Length The length of memory region + @param[in] Flush Flush the caches before applying the + encryption mask + + @retval RETURN_SUCCESS The attributes were cleared for the = memory region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Setting the memory encyrption attrib= ute is + not supported +**/ +EFI_STATUS +EFIAPI +SetMemoryEncrypted ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN UINT64 Length, + IN BOOLEAN CacheFlush + ); + +#endif diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b= /OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c new file mode 100644 index 000000000000..4b7f421475ac --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c @@ -0,0 +1,126 @@ +/** @file + + Secure Encrypted Virtualization (SEV) library helper function + + Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the licen= se may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#include "Uefi.h" +#include +#include +#include +#include +#include +#include + +#include "MemEncryptSevLibInternal.h" + +/** + + Returns a boolean to indicate whether SEV is enabled + + @retval TRUE SEV is enabled + @retval FALSE SEV is not enabled + **/ +BOOLEAN +EFIAPI +InternalMemEncryptSevIsEnabled ( + VOID + ) +{ + UINT32 RegEax; + MSR_SEV_STATUS_REGISTER Msr; + CPUID_MEMORY_ENCRYPTION_INFO_EAX Eax; + + // + // Check if memory encryption leaf exist + // + AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); + if (RegEax >=3D CPUID_MEMORY_ENCRYPTION_INFO) { + // + // CPUID Fn8000_001F[EAX] Bit 1 (Sev supported) + // + AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, &Eax.Uint32, NULL, NULL, NULL); + + if (Eax.Bits.SevBit) { + // + // Check MSR_0xC0010131 Bit 0 (Sev is Enabled) + // + Msr.Uint32 =3D AsmReadMsr32 (MSR_SEV_STATUS); + if (Msr.Bits.SevBit) { + return TRUE; + } + } + } + + return FALSE; +} + +/** + This function clears memory encryption bit for the memory region specifi= ed + by BaseAddress and Number of pages from the current page table context. + + @param[in] BaseAddress The physical address that is the start= address + of a memory region. + @param[in] NumberOfPages The number of pages from start memory = region. + @param[in] Flush Flush the caches before clearing the b= it + (mostly TRUE except MMIO addresses) + + @retval RETURN_SUCCESS The attributes were cleared for the me= mory region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Clearing memory encryption attribute i= s not + supported + **/ +RETURN_STATUS +EFIAPI +MemEncryptSevClearPageEncMask ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumberOfPages, + IN BOOLEAN Flush + ) +{ + // + // Memory encryption bit is not accessible in 32-bit mode + // + return RETURN_UNSUPPORTED; +} + +/** + This function sets memory encryption bit for the memory region specified= by + BaseAddress and Number of pages from the current page table context. + + @param[in] BaseAddress The physical address that is the start= address + of a memory region. + @param[in] NumberOfPages The number of pages from start memory = region. + @param[in] Flush Flush the caches before clearing the b= it + (mostly TRUE except MMIO addresses) + + @retval RETURN_SUCCESS The attributes were set for the memory= region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Clearing memory encryption attribute i= s not + supported + **/ +RETURN_STATUS +EFIAPI +MemEncryptSevSetPageEncMask ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumberOfPages, + IN BOOLEAN Flush + ) +{ + // + // Memory encryption bit is not accessible in 32-bit mode + // + return RETURN_UNSUPPORTED; +} diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.= c b/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c new file mode 100644 index 000000000000..43ecba7a28bb --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c @@ -0,0 +1,43 @@ +/** @file + + Secure Encrypted Virtualization (SEV) library helper function + + Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the licen= se may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#include "MemEncryptSevLibInternal.h" + +STATIC BOOLEAN mSevStatus =3D FALSE; +STATIC BOOLEAN mSevStatusChecked =3D FALSE; + +/** + + Returns a boolean to indicate whether SEV is enabled + + @retval TRUE SEV is enabled + @retval FALSE SEV is not enabled + **/ +BOOLEAN +EFIAPI +MemEncryptSevIsEnabled ( + VOID + ) +{ + if (mSevStatusChecked) { + return mSevStatus; + } + + mSevStatus =3D InternalMemEncryptSevIsEnabled(); + mSevStatusChecked =3D TRUE; + + return mSevStatus; +} diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/= OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c new file mode 100644 index 000000000000..92f701497ffb --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c @@ -0,0 +1,127 @@ +/** @file + + Secure Encrypted Virtualization (SEV) library helper function + + Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the licen= se may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#include "Uefi.h" +#include +#include +#include +#include +#include +#include + +#include "VirtualMemory.h" +#include "MemEncryptSevLibInternal.h" + +/** + + Returns a boolean to indicate whether SEV is enabled + + @retval TRUE SEV is enabled + @retval FALSE SEV is not enabled + **/ +BOOLEAN +EFIAPI +InternalMemEncryptSevIsEnabled ( + VOID + ) +{ + UINT32 RegEax; + MSR_SEV_STATUS_REGISTER Msr; + CPUID_MEMORY_ENCRYPTION_INFO_EAX Eax; + + // + // Check if memory encryption leaf exist + // + AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); + if (RegEax >=3D CPUID_MEMORY_ENCRYPTION_INFO) { + // + // CPUID Fn8000_001F[EAX] Bit 1 (Sev supported) + // + AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, &Eax.Uint32, NULL, NULL, NULL); + + if (Eax.Bits.SevBit) { + // + // Check MSR_0xC0010131 Bit 0 (Sev Enabled) + // + Msr.Uint32 =3D AsmReadMsr32 (MSR_SEV_STATUS); + if (Msr.Bits.SevBit) { + return TRUE; + } + } + } + + return FALSE; +} + +/** + + This function clears memory encryption bit for the memory region specifi= ed by + BaseAddress and Number of pages from the current page table context. + + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use c= urrent CR3) + @param[in] BaseAddress The physical address that is the sta= rt address + of a memory region. + @param[in] NumberOfPages The number of pages from start memor= y region. + @param[in] Flush Flush the caches before clearing the= bit + (mostly TRUE except MMIO addresses) + + @retval RETURN_SUCCESS The attributes were cleared for the = memory + region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Clearing the memory encryption attri= bute is + not supported + **/ +RETURN_STATUS +EFIAPI +MemEncryptSevClearPageEncMask ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages, + IN BOOLEAN Flush + ) +{ + return SetMemoryDecrypted (Cr3BaseAddress, BaseAddress, EFI_PAGES_TO_SIZ= E(NumPages), Flush); +} + +/** + + This function clears memory encryption bit for the memory region specifi= ed by + BaseAddress and Number of pages from the current page table context. + + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use c= urrent CR3) + @param[in] BaseAddress The physical address that is the sta= rt address + of a memory region. + @param[in] NumberOfPages The number of pages from start memor= y region. + @param[in] Flush Flush the caches before clearing the= bit + (mostly TRUE except MMIO addresses) + + @retval RETURN_SUCCESS The attributes were cleared for the = memory + region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Clearing the memory encryption attri= bute is + not supported + **/ +RETURN_STATUS +EFIAPI +MemEncryptSevSetPageEncMask ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages, + IN BOOLEAN Flush + ) +{ + return SetMemoryEncrypted (Cr3BaseAddress, BaseAddress, EFI_PAGES_TO_SIZ= E(NumPages), Flush); +} diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c b/Ovm= fPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c new file mode 100644 index 000000000000..51425830baa5 --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c @@ -0,0 +1,422 @@ +/** @file + + Virtual Memory Management Services to set or clear the memory encryption= bit + +Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD = License +which accompanies this distribution. The full text of the license may be = found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +Code is derived from MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c + +**/ + +#include +#include +#include + +#include "VirtualMemory.h" + +STATIC BOOLEAN mAddressEncMaskChecked =3D FALSE; +STATIC UINT64 mAddressEncMask; + +typedef enum { + SetCBit, + ClearCBit +} MAP_RANGE_MODE; + +/** + Get the memory encryption mask + + @param[out] EncryptionMask contains the pte mask. + +**/ +STATIC +UINT64 +GetMemEncryptionAddressMask ( + VOID + ) +{ + UINT64 EncryptionMask; + CPUID_MEMORY_ENCRYPTION_INFO_EBX Ebx; + + if (mAddressEncMaskChecked) { + return mAddressEncMask; + } + + // + // CPUID Fn8000_001F[EBX] Bit 0:5 (memory encryption bit position) + // + AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, NULL, &Ebx.Uint32, NULL, NULL); + EncryptionMask =3D LShiftU64 (1, Ebx.Bits.PtePosBits); + + mAddressEncMask =3D EncryptionMask & PAGING_1G_ADDRESS_MASK_64; + mAddressEncMaskChecked =3D TRUE; + + return mAddressEncMask; +} + +/** + Split 2M page to 4K. + + @param[in] PhysicalAddress Start physical address the 2M page= covered. + @param[in, out] PageEntry2M Pointer to 2M page entry. + @param[in] StackBase Stack base address. + @param[in] StackSize Stack size. + +**/ +STATIC +VOID +Split2MPageTo4K ( + IN PHYSICAL_ADDRESS PhysicalAddress, + IN OUT UINT64 *PageEntry2M, + IN PHYSICAL_ADDRESS StackBase, + IN UINTN StackSize + ) +{ + PHYSICAL_ADDRESS PhysicalAddress4K; + UINTN IndexOfPageTableEntries; + PAGE_TABLE_4K_ENTRY *PageTableEntry, *PageTableEntry1; + UINT64 AddressEncMask; + + PageTableEntry =3D AllocatePages(1); + + PageTableEntry1 =3D PageTableEntry; + + AddressEncMask =3D GetMemEncryptionAddressMask (); + + ASSERT (PageTableEntry !=3D NULL); + ASSERT (*PageEntry2M & AddressEncMask); + + PhysicalAddress4K =3D PhysicalAddress; + for (IndexOfPageTableEntries =3D 0; IndexOfPageTableEntries < 512; Index= OfPageTableEntries++, PageTableEntry++, PhysicalAddress4K +=3D SIZE_4KB) { + // + // Fill in the Page Table entries + // + PageTableEntry->Uint64 =3D (UINT64) PhysicalAddress4K | AddressEncMask; + PageTableEntry->Bits.ReadWrite =3D 1; + PageTableEntry->Bits.Present =3D 1; + if ((PhysicalAddress4K >=3D StackBase) && (PhysicalAddress4K < StackBa= se + StackSize)) { + // + // Set Nx bit for stack. + // + PageTableEntry->Bits.Nx =3D 1; + } + } + + // + // Fill in 2M page entry. + // + *PageEntry2M =3D (UINT64) (UINTN) PageTableEntry1 | IA32_PG_P | IA32_PG_= RW | AddressEncMask; +} + +/** + Split 1G page to 2M. + + @param[in] PhysicalAddress Start physical address the 1G page= covered. + @param[in, out] PageEntry1G Pointer to 1G page entry. + @param[in] StackBase Stack base address. + @param[in] StackSize Stack size. + +**/ +STATIC +VOID +Split1GPageTo2M ( + IN PHYSICAL_ADDRESS PhysicalAddress, + IN OUT UINT64 *PageEntry1G, + IN PHYSICAL_ADDRESS StackBase, + IN UINTN StackSize + ) +{ + PHYSICAL_ADDRESS PhysicalAddress2M; + UINTN IndexOfPageDirectoryEntries; + PAGE_TABLE_ENTRY *PageDirectoryEntry; + UINT64 AddressEncMask; + + PageDirectoryEntry =3D AllocatePages(1); + + AddressEncMask =3D GetMemEncryptionAddressMask (); + ASSERT (PageDirectoryEntry !=3D NULL); + ASSERT (*PageEntry1G & GetMemEncryptionAddressMask ()); + // + // Fill in 1G page entry. + // + *PageEntry1G =3D (UINT64) (UINTN) PageDirectoryEntry | IA32_PG_P | IA32_= PG_RW | AddressEncMask; + + PhysicalAddress2M =3D PhysicalAddress; + for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntries < 51= 2; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += =3D SIZE_2MB) { + if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress2M= + SIZE_2MB) > StackBase)) { + // + // Need to split this 2M page that covers stack range. + // + Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry, S= tackBase, StackSize); + } else { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry->Uint64 =3D (UINT64) PhysicalAddress2M | AddressE= ncMask; + PageDirectoryEntry->Bits.ReadWrite =3D 1; + PageDirectoryEntry->Bits.Present =3D 1; + PageDirectoryEntry->Bits.MustBe1 =3D 1; + } + } +} + + +/** + Set or Clear the memory encryption bit + + @param[in] PagetablePoint Page table entry pointer (PTE). + @param[in] Mode Set or Clear encryption bit + +**/ +STATIC VOID +SetOrClearCBit( + IN OUT UINT64* PageTablePointer, + IN MAP_RANGE_MODE Mode + ) +{ + UINT64 AddressEncMask; + + AddressEncMask =3D GetMemEncryptionAddressMask (); + + if (Mode =3D=3D SetCBit) { + *PageTablePointer |=3D AddressEncMask; + } else { + *PageTablePointer &=3D ~AddressEncMask; + } + +} + +/** + This function either sets or clears memory encryption bit for the memory= region + specified by PhysicalAddress and length from the current page table cont= ext. + + The function iterates through the physicalAddress one page at a time, an= d set + or clears the memory encryption mask in the page table. If it encounters + that a given physical address range is part of large page then it attemp= ts to + change the attribute at one go (based on size), otherwise it splits the + large pages into smaller (e.g 2M page into 4K pages) and then try to set= or + clear the encryption bit on the smallest page size. + + @param[in] PhysicalAddress The physical address that is the sta= rt + address of a memory region. + @param[in] Length The length of memory region + @param[in] Mode Set or Clear mode + @param[in] Flush Flush the caches before applying the + encryption mask + + @retval RETURN_SUCCESS The attributes were cleared for the = memory + region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Setting the memory encyrption attrib= ute is + not supported +**/ + +STATIC +EFI_STATUS +EFIAPI +SetMemoryEncDec ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN UINTN Length, + IN MAP_RANGE_MODE Mode, + IN BOOLEAN CacheFlush + ) +{ + PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry; + PAGE_MAP_AND_DIRECTORY_POINTER *PageUpperDirectoryPointerEntry; + PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; + PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry; + PAGE_TABLE_ENTRY *PageDirectory2MEntry; + PAGE_TABLE_4K_ENTRY *PageTableEntry; + UINT64 PgTableMask; + UINT64 AddressEncMask; + + // + // Check if we have a valid memory encryption mask + // + AddressEncMask =3D GetMemEncryptionAddressMask (); + if (!AddressEncMask) { + return RETURN_ACCESS_DENIED; + } + + PgTableMask =3D AddressEncMask | EFI_PAGE_MASK; + + if (Length =3D=3D 0) { + return EFI_INVALID_PARAMETER; + } + + // + // We are going to change the memory encryption attribute from C=3D0 -> = C=3D1 or + // vice versa Flush the caches to ensure that data is written into memor= y with + // correct C-bit + // + if (CacheFlush) { + WriteBackInvalidateDataCacheRange((VOID*) (UINTN)PhysicalAddress, Leng= th); + } + + while (Length) + { + // + // If Cr3BaseAddress is not specified then read the current CR3 + // + if (Cr3BaseAddress =3D=3D 0) { + Cr3BaseAddress =3D AsmReadCr3(); + } + + PageMapLevel4Entry =3D (VOID*) (Cr3BaseAddress & ~PgTableMask); + PageMapLevel4Entry +=3D PML4_OFFSET(PhysicalAddress); + if (!PageMapLevel4Entry->Bits.Present) { + DEBUG ((DEBUG_WARN, "ERROR bad PML4 for %lx\n", PhysicalAddress)); + return EFI_NO_MAPPING; + } + + PageDirectory1GEntry =3D (VOID*) ((PageMapLevel4Entry->Bits.PageTableB= aseAddress<<12) & ~PgTableMask); + PageDirectory1GEntry +=3D PDP_OFFSET(PhysicalAddress); + if (!PageDirectory1GEntry->Bits.Present) { + DEBUG ((DEBUG_WARN, "ERROR bad PDPE for %lx\n", PhysicalAddress)); + return EFI_NO_MAPPING; + } + + // + // If the MustBe1 bit is not 1, it's not actually a 1GB entry + // + if (PageDirectory1GEntry->Bits.MustBe1) { + // + // Valid 1GB page + // If we have at least 1GB to go, we can just update this entry + // + if (!(PhysicalAddress & (BIT30 - 1)) && Length >=3D BIT30) { + SetOrClearCBit(&PageDirectory1GEntry->Uint64, Mode); + DEBUG ((DEBUG_VERBOSE, "Updated 1GB entry for %lx\n", PhysicalAddr= ess)); + PhysicalAddress +=3D BIT30; + Length -=3D BIT30; + } else { + // + // We must split the page + // + DEBUG ((DEBUG_VERBOSE, "Spliting 1GB page\n")); + Split1GPageTo2M(((UINT64)PageDirectory1GEntry->Bits.PageTableBaseA= ddress)<<30, (UINT64*) PageDirectory1GEntry, 0, 0); + continue; + } + } else { + // + // Actually a PDP + // + PageUpperDirectoryPointerEntry =3D (PAGE_MAP_AND_DIRECTORY_POINTER*)= PageDirectory1GEntry; + PageDirectory2MEntry =3D (VOID*) ((PageUpperDirectoryPointerEntry->B= its.PageTableBaseAddress<<12) & ~PgTableMask); + PageDirectory2MEntry +=3D PDE_OFFSET(PhysicalAddress); + if (!PageDirectory2MEntry->Bits.Present) { + DEBUG ((DEBUG_WARN, "ERROR bad PDE for %lx\n", PhysicalAddress)); + return EFI_NO_MAPPING; + } + // + // If the MustBe1 bit is not a 1, it's not a 2MB entry + // + if (PageDirectory2MEntry->Bits.MustBe1) { + // + // Valid 2MB page + // If we have at least 2MB left to go, we can just update this ent= ry + // + if (!(PhysicalAddress & (BIT21-1)) && Length >=3D BIT21) { + SetOrClearCBit (&PageDirectory2MEntry->Uint64, Mode); + DEBUG ((DEBUG_VERBOSE, "Updated 2MB entry for %lx\n", PhysicalAd= dress)); + PhysicalAddress +=3D BIT21; + Length -=3D BIT21; + } else { + // + // We must split up this page into 4K pages + // + DEBUG ((DEBUG_VERBOSE, "Spliting 2MB page at %lx\n", PhysicalAdd= ress)); + Split2MPageTo4K (((UINT64)PageDirectory2MEntry->Bits.PageTableBa= seAddress) << 21, (UINT64*) PageDirectory2MEntry, 0, 0); + continue; + } + } else { + PageDirectoryPointerEntry =3D (PAGE_MAP_AND_DIRECTORY_POINTER*) Pa= geDirectory2MEntry; + PageTableEntry =3D (VOID*) (PageDirectoryPointerEntry->Bits.PageTa= bleBaseAddress<<12 & ~PgTableMask); + PageTableEntry +=3D PTE_OFFSET(PhysicalAddress); + if (!PageTableEntry->Bits.Present) { + DEBUG ((DEBUG_WARN, "ERROR bad PTE for %lx\n", PhysicalAddress)); + return EFI_NO_MAPPING; + } + SetOrClearCBit (&PageTableEntry->Uint64, Mode); + DEBUG ((DEBUG_VERBOSE, "Updated 4KB entry for %lx\n", PhysicalAddr= ess)); + PhysicalAddress +=3D EFI_PAGE_SIZE; + Length -=3D EFI_PAGE_SIZE; + } + } + } + + // + // Flush TLB + // + CpuFlushTlb(); + + return EFI_SUCCESS; +} + +/** + This function clears memory encryption bit for the memory region specifi= ed by + PhysicalAddress and length from the current page table context. + + @param[in] PhysicalAddress The physical address that is the sta= rt + address of a memory region. + @param[in] Length The length of memory region + @param[in] Flush Flush the caches before applying the + encryption mask + + @retval RETURN_SUCCESS The attributes were cleared for the = memory + region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Setting the memory encyrption attrib= ute is + not supported +**/ +EFI_STATUS +EFIAPI +SetMemoryDecrypted ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN UINTN Length, + IN BOOLEAN CacheFlush + ) +{ + + DEBUG ((DEBUG_VERBOSE, "Clear C-bit Base %Lx Length %Lx flush %d\n", Phy= sicalAddress, Length, CacheFlush)); + return SetMemoryEncDec (Cr3BaseAddress, PhysicalAddress, Length, ClearCB= it, CacheFlush); +} + +/** + This function sets memory encryption bit for the memory region specified= by + PhysicalAddress and length from the current page table context. + + @param[in] PhysicalAddress The physical address that is the sta= rt address + of a memory region. + @param[in] Length The length of memory region + @param[in] Flush Flush the caches before applying the + encryption mask + + @retval RETURN_SUCCESS The attributes were cleared for the = memory + region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Setting the memory encyrption attrib= ute is + not supported +**/ +EFI_STATUS +EFIAPI +SetMemoryEncrypted ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN UINTN Length, + IN BOOLEAN CacheFlush + ) +{ + DEBUG ((DEBUG_VERBOSE, "Set C-bit Base %Lx Length %Lx flush %d\n", Physi= calAddress, Length, CacheFlush)); + return SetMemoryEncDec (Cr3BaseAddress, PhysicalAddress, Length, SetCBit= , CacheFlush); +} --=20 2.7.4 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel