From nobody Mon Feb 9 18:18:24 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+73228+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+73228+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one); dmarc=fail(p=none dis=none) header.from=amd.com Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1616611754271274.8486301465408; Wed, 24 Mar 2021 11:49:14 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id WYqEYY1788612xXVPgg0zfzg; Wed, 24 Mar 2021 11:49:13 -0700 X-Received: from NAM04-DM6-obe.outbound.protection.outlook.com (NAM04-DM6-obe.outbound.protection.outlook.com []) by mx.groups.io with SMTP id smtpd.web09.26.1616599956611292901 for ; Wed, 24 Mar 2021 08:32:38 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Tyjx8Vl4CunvQLHStEWYh8t1Tity02i5/Xkh+XGxrlup6bdnfLprXof15S9YCcsU03eqkPV72U6Frn0EHtbiiRc1xOGkYJZiuvrTTgbw8uqOlwc9ED99w2BPI3PEm5UtZr8WsdSn7UC+cUs73clYUyYlVvQZI6dNrFhj/Hwz5+owuRuj/Pl9uqNi2uNmCJo/1YInjOsuOiDATQ6VStey1QOxV1zuLFiPFlQ9JvR98yv1G1q7p4iFelTYIgcIxJeNBoS+bO0Cx0KB7xjMVlKca1beWrplM1BsOR2L9KH5nozoskiTzfqJfqxz/ktc54BMoXcKsBTFdyIPSdCuxmckrw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=3LYDfNyea+/UUCeVXjkEVAQ1xVj6Nd4/veyDvmYraiw=; b=mjuklVPeLdZYRD8bF17INbsSiG6x1gBpZkZYIviLvfivMotLkkmzy8iOaYT0z2JaXT9APS0M3jtfNEyYPXH4w+PHtz1DNEqSDkxJ99wMmF+mG1C0e7muSPYRdpu/HmprwVYH9lzJlmfI9xm33EpXtkAx2ax/88tQO0+zyJ2LFgU5+9QfTAZysqK7sMSeuBtavEzEq4LGEpgwHye+axvn93J9li9qMI2h+CxZz+4tKh1iW/poiBapXn8iviP5kQoF237WicvdYGIhNOMxZmeyrU4hkzgl2M8ApYGECiQtOcniD9Q7KTTjM0e5foyqT6+CUQL9h9E/VTIuMOfipwszZA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=amd.com; dmarc=pass action=none header.from=amd.com; dkim=pass header.d=amd.com; arc=none X-Received: from SN6PR12MB2718.namprd12.prod.outlook.com (2603:10b6:805:6f::22) by SA0PR12MB4430.namprd12.prod.outlook.com (2603:10b6:806:70::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3955.18; Wed, 24 Mar 2021 15:32:36 +0000 X-Received: from SN6PR12MB2718.namprd12.prod.outlook.com ([fe80::30fb:2d6c:a0bf:2f1d]) by SN6PR12MB2718.namprd12.prod.outlook.com ([fe80::30fb:2d6c:a0bf:2f1d%3]) with mapi id 15.20.3955.027; Wed, 24 Mar 2021 15:32:36 +0000 From: "Brijesh Singh" To: devel@edk2.groups.io Cc: Brijesh Singh , James Bottomley , Min Xu , Jiewen Yao , Tom Lendacky , Jordan Justen , Ard Biesheuvel , Laszlo Ersek Subject: [edk2-devel] [RFC PATCH 12/19] OvmfPkg/MemEncryptSevLib: Add support to validate system RAM Date: Wed, 24 Mar 2021 10:32:08 -0500 Message-Id: <20210324153215.17971-13-brijesh.singh@amd.com> In-Reply-To: <20210324153215.17971-1-brijesh.singh@amd.com> References: <20210324153215.17971-1-brijesh.singh@amd.com> X-Originating-IP: [165.204.77.1] X-ClientProxiedBy: SA9PR11CA0006.namprd11.prod.outlook.com (2603:10b6:806:6e::11) To SN6PR12MB2718.namprd12.prod.outlook.com (2603:10b6:805:6f::22) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-Received: from sbrijesh-desktop.amd.com (165.204.77.1) by SA9PR11CA0006.namprd11.prod.outlook.com (2603:10b6:806:6e::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3955.18 via Frontend Transport; Wed, 24 Mar 2021 15:32:35 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: fc762277-d7de-467c-583a-08d8eeda0cb8 X-MS-TrafficTypeDiagnostic: SA0PR12MB4430: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:10000; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Message-Info: SgH3BkxI6nJO0pVJTq18rCLeKBtwt4qav37PJDC/lQGSDVI4YfQ+TbYaEKqlZ/0Ekk1RQi1k3gTifWpl0Tdp0MzTTi3R4nI2BPCPzZtsqIssOwPSVO0ONd+/GEh1Rii3LxbVGFXRhRDaSKuIaUWqIGVk9fJz9Fd4sAcOhFOHM9Gb4pcdcQzo5GP5gwFU8H6vnI46ptkLaxuSexmMqoByizviTcAMd6wU97WEmt3TyKVlh7XjFoVnvqkvcDVDgSxhf92E2yae0MFNcmNdfMHplX7dgKqJuZGhxdsrOZNw/MjSdYmoub/rjYYLSd8PrNM7oUpQAPkka8VLVjh5awlNqGExrHieY94ndfl2LNT4sxnDYVoi/4R1T42NH6GQi2AmdFewiimtsGmloLzpbtvO4HcaG4W+kC75aNqBxHeDNR8aJ67ReRLGyIBakCHw25KeQkHRaiTFqvBs5sZPOsKOnCcI05OWKHh2/zDUGBe/GGhSB3CvKhYLOpyDYoHPDjK31litRdoTVKSQYjvRGcoPdFbku4fXrsRJ/x2U5yLJrTdoT+HQHvgFvjPCi5usZP9h+MqjEQgJdhiWC0eUdc2fdT/hCKUJr5uuxdshl0kddp452WZdqwSmlIHhcoDhc83SGQzDSH4+e4gYIsTGQxEYjfUe8T/KxM+5dUPidUShzhuWgfWFagfSdLFwcjOBhuqZ+1fZNF6MXAzstv8qH97oTUbj76B0e7HQOOPjhpO3mmSKwscRuuvFu8yTbd+PEfMX X-MS-Exchange-AntiSpam-MessageData: =?us-ascii?Q?6BgmXue9UkWf0FqpMZ6HTdfLxZeK/8m8mcbyVNX7KCjYv8CdB8xEO1kc2IiC?= =?us-ascii?Q?UrFnmmEhqs2RnNZBcRiBNQCgeGkHoRUYF4HehB22Y8ulKghmai4f//+osaiP?= =?us-ascii?Q?e8MjJlKdfl8Z1/jekXkku+c/Sv8fRrwiFVf7bWfLP3HPwQ/0nVXjvVkFNDss?= =?us-ascii?Q?eLE56mgXaNCZ7mMmWE9yCkidr/XzVOwho+cYVF9KOc/IM3oHgQSV+MGwwerv?= =?us-ascii?Q?MT5Csj6I9LpUL2bfAd5bwJuHKt+b9DeN1ku9Ef2XdDLd7c6zT3Ul+OXcul+z?= =?us-ascii?Q?83fIpAPSBHA0y0QxtiYhCgch7tlfhxrQiVqrrB608nWIH8gok1y23bHXISiw?= =?us-ascii?Q?2+2SN1Um+J4GsHxqHGnHIvI0xPLGCB6Wel9jrgU69EgkXMLcPjze2suraHCb?= =?us-ascii?Q?2Aby7yv64N7QxgiP3ytUFmyiZuqKUvk1++0M5QpUXqbcPAXJgZnlT+pJUKtr?= =?us-ascii?Q?D8IMdhvtgjAn89YCa8ZlgqonDw01k4pvvMde3HttUC0e0dGqbViQzeUSC4D+?= =?us-ascii?Q?O2v2jc+4J1IwDJb1pE6mgo+owpDVcihzjOYS4qwuYZr++BCh+bAARBefKJm/?= =?us-ascii?Q?2L5YwijIzGkl8kty6wGi7fUcs/oyQgRERYWRCpiWg93Y66EdsIs3SGQgbhjK?= =?us-ascii?Q?6VM7XYCVWrzLmrc7V7TqJEidHNSjGwxg5V5pQ2cPW6/nVJC35H+B0XEBXxh6?= =?us-ascii?Q?M4qGVEA0xYLPr6LJrP/bfB/aDqAb0IA1eOifU+AphDyQ0GY1HoDXlpWHwgOb?= =?us-ascii?Q?P3ZuEyegCPdy0YCIPax5ythMJJKVmD3bPJA4Gk5upgQOULG5CcuUC967YSlW?= =?us-ascii?Q?dLxHlliprN5oEFj+VSoQbzmq51R3T1ncy+3mVQ6V13UheUAn5LD8785mxgvz?= =?us-ascii?Q?QyRDigpzMj7+n4g3mRSuWNly9sqwEVNMPJEeo6j7O8a4HA8sT7pHwOXJweV3?= =?us-ascii?Q?Y63RDhX3EfpKhbQaaStoV/pZ0FGhYow6+IgYuCx8xBrV8zJTPcQj4bKSmIXv?= =?us-ascii?Q?V9vuKkot2zzD3/5sld1ko4450KRwM0j1wvgLSx2sE0FNYTgFR0adH4alh8na?= =?us-ascii?Q?vg+PhyL1/B7I67kBRj7uAQmW6Id2vlr/ueknGQOo1L/uyfbKLd5L3km/3HzM?= =?us-ascii?Q?m0kP3gQdwC+6aEV1+vceO9ve0DqX4dCneajwddZBbTZrAsmmwcIYHC0VrMeM?= =?us-ascii?Q?IavhpBs/A0lQi4zGWdI/BhaogJQq+6/D+5CqWwi8W5wOh2JmfsAbj1ECz4iQ?= =?us-ascii?Q?cR1dmBYngPbDgeIaSLqsshtj9sHJ3jDtDXzZmhTa5q+7WSNSX1IerFlcDJxX?= =?us-ascii?Q?HE1eV09Nzose/wnm6SiKsnCb?= X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-Network-Message-Id: fc762277-d7de-467c-583a-08d8eeda0cb8 X-MS-Exchange-CrossTenant-AuthSource: SN6PR12MB2718.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Mar 2021 15:32:35.8063 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: CfFtDcpg/5ofY3UKyfXWWSTVG6eGwY6SMmMkHqGg2FBdH06Qayz+N1k4ybdX/vaIZtWasHDioCsfqoBmdgpDKw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA0PR12MB4430 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,brijesh.singh@amd.com X-Gm-Message-State: Nq80opSTwD0tMcWg8VDGjtaax1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1616611753; bh=mvIIjv2+gT06PvyzLcm2frEL3U3MgWElpmH14y3PNvg=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=BaYInc3ZYjjB/N2GxDuYpMzgCBK+In2pPNzj6KLd/Zyb0Ozn7sLEaux5wr8cbLGImy8 IFR0IWH6YKOzjaRqoI35F9zlrgnrZJNOnldaSodmTFWbddGGpMceSUzXDV4M97wF50OPh nA1vX8d5W2KeHKVdx0CgicBzYau/RJcmvyQ= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3275 Many of the integrity guarantees of SEV-SNP are enforced through the Reverse Map Table (RMP). Each RMP entry contains the GPA at which a particular page of DRAM should be mapped. The guest can request the hypervisor to add pages in the RMP table via the Page State Change VMGEXIT defined in the GHCB specification section 2.5.1 and 4.1.6. Inside each RMP entry is a Validated flag; this flag is automatically cleared to 0 by the CPU hardware when a new RMP entry is created for a guest. Each VM page can be either validated or invalidated, as indicated by the Validated flag in the RMP entry. Memory access to a private page that is not validated generates a #VC. A VM can use the PVALIDATE instruction to validate the private page before using it. During the guest creation, the boot ROM memory is pre-validated by the AMD-SEV firmware. The MemEncryptSevSnpValidateSystemRam() can be called during the SEC and PEI phase to validate the detected system RAM. One of the fields in the Page State Change NAE is the RMP page size. The page size input parameter indicates that either a 4KB or 2MB page should be used while adding the RMP entry. During the validation, when possible, the MemEncryptSevSnpValidateSystemRam() will use the 2MB entry. A hypervisor backing the memory may choose to use the different page size in the RMP entry. In those cases, the PVALIDATE instruction should return SIZEMISMATCH. If a SIZEMISMATCH is detected, then validate all 512-pages constituting a 2MB region. Upon completion, the PVALIDATE instruction sets the rFLAGS.CF to 0 if instruction changed the RMP entry and to 1 if the instruction did not change the RMP entry. The rFlags.CF will be 1 only when a memory region is already validated. We should not double validate a memory as it could lead to a security compromise. If double validation is detected, terminate the boot. Cc: James Bottomley Cc: Min Xu Cc: Jiewen Yao Cc: Tom Lendacky Cc: Jordan Justen Cc: Ard Biesheuvel Cc: Laszlo Ersek Signed-off-by: Brijesh Singh --- OvmfPkg/Include/Library/MemEncryptSevLib.h | 1= 5 ++ OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/SnpPageStateChange.c | 1= 7 ++ OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf | = 4 + OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c | 2= 0 ++ OvmfPkg/Library/BaseMemEncryptSevLib/SnpPageStateChange.h | 3= 7 +++ OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecSnpSystemRamValidate.c | 2= 3 ++ OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c | 25= 4 ++++++++++++++++++++ 7 files changed, 370 insertions(+) diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/L= ibrary/MemEncryptSevLib.h index 03d9eda392..47d6802b61 100644 --- a/OvmfPkg/Include/Library/MemEncryptSevLib.h +++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h @@ -215,4 +215,19 @@ MemEncryptSevGetAddressRangeState ( IN UINTN Length ); =20 +/** + If SEV-SNP is active then set the page state of the specified virtual + address range. This should be called in SEC and PEI phases only. + + @param[in] BaseAddress Base address + @param[in] NumPages Number of pages starting from the ba= se address + +**/ +VOID +EFIAPI +MemEncryptSevSnpValidateSystemRam ( + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages + ); + #endif // _MEM_ENCRYPT_SEV_LIB_H_ diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/SnpPageStateChange.c= b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/SnpPageStateChange.c new file mode 100644 index 0000000000..dace5c0bcf --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/SnpPageStateChange.c @@ -0,0 +1,17 @@ +#include + +#include "../SnpPageStateChange.h" + +/** + The function is used to set the page state when SEV-SNP is active. The pa= ge state + transition consist of changing the page ownership in the RMP table, and u= sing the + PVALIDATE instruction to update the Validated bit in RMP table. + + */ +VOID +SevSnpValidateSystemRamInternal ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages + ) +{ +} diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf b= /OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf index 279c38bfbc..8595e244c2 100644 --- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf @@ -31,15 +31,19 @@ =20 [Sources] SecMemEncryptSevLibInternal.c + SnpPageStateChange.h =20 [Sources.X64] X64/MemEncryptSevLib.c X64/SecVirtualMemory.c + X64/SecSnpSystemRamValidate.c + X64/SnpPageStateChangeInternal.c X64/VirtualMemory.c X64/VirtualMemory.h =20 [Sources.IA32] Ia32/MemEncryptSevLib.c + Ia32/SnpPageStateChange.c =20 [LibraryClasses] BaseLib diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibIntern= al.c b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c index 69852779e2..35a222e75e 100644 --- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c @@ -17,6 +17,8 @@ #include #include =20 +#include "SnpPageStateChange.h" + /** Reads and sets the status of SEV features. =20 @@ -172,3 +174,21 @@ MemEncryptSevLocateInitialSmramSaveStateMapPages ( { return RETURN_UNSUPPORTED; } + +/** + If SEV-SNP is active then set the page state of the specified virtual + address range. This should be called in SEC and PEI phases only. + + @param[in] BaseAddress Base address + @param[in] NumPages Number of pages starting from the ba= se address + +**/ +VOID +EFIAPI +MemEncryptSevSnpValidateSystemRam ( + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages + ) +{ + SevSnpValidateSystemRam (BaseAddress, NumPages); +} diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SnpPageStateChange.h b/Ov= mfPkg/Library/BaseMemEncryptSevLib/SnpPageStateChange.h new file mode 100644 index 0000000000..3040930999 --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SnpPageStateChange.h @@ -0,0 +1,37 @@ +/** @file + + SEV-SNP Page Validation functions. + + Copyright (c) 2020 - 2021, AMD Incorporated. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SNP_PAGE_STATE_INTERNAL_H_ +#define SNP_PAGE_STATE_INTERNAL_H_ + +// +// SEV-SNP Page states +// +typedef enum { + SevSnpPagePrivate, + SevSnpPageShared, + +} SEV_SNP_PAGE_STATE; + +VOID +SevSnpValidateSystemRam ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages + ); + +VOID +SetPageStateInternal ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages, + IN SEV_SNP_PAGE_STATE State, + IN BOOLEAN UseLargeEntry + ); + +#endif diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecSnpSystemRamValida= te.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecSnpSystemRamValidate.c new file mode 100644 index 0000000000..915706aad0 --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecSnpSystemRamValidate.c @@ -0,0 +1,23 @@ +/** @file + + SEV-SNP Page Validation functions. + + Copyright (c) 2020 - 2021, AMD Incorporated. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +#include "../SnpPageStateChange.h" + +VOID +SevSnpValidateSystemRam ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages + ) +{ + SetPageStateInternal (BaseAddress, NumPages, SevSnpPagePrivate, TRUE); +} diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInt= ernal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeIntern= al.c new file mode 100644 index 0000000000..5a34db33fe --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c @@ -0,0 +1,254 @@ +/** @file + + SEV-SNP Page Validation functions. + + Copyright (c) 2020 - 2021, AMD Incorporated. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "../SnpPageStateChange.h" + +#define IS_ALIGNED(x, y) ((((x) & (y - 1)) =3D=3D 0)) +#define PAGES_PER_LARGE_ENTRY 512 +#define EFI_LARGE_PAGE (EFI_PAGE_SIZE * PAGES_PER_LARGE_ENTRY) + +STATIC +UINTN +MemoryStateToGhcbOp ( + IN SEV_SNP_PAGE_STATE State + ) +{ + UINTN Cmd; + + switch (State) { + case SevSnpPageShared: Cmd =3D SNP_PAGE_STATE_SHARED; break; + case SevSnpPagePrivate: Cmd =3D SNP_PAGE_STATE_PRIVATE; break; + default: ASSERT(0); + } + + return Cmd; +} + +STATIC +VOID +SnpPageStateFailureTerminate ( + VOID + ) +{ + MSR_SEV_ES_GHCB_REGISTER Msr; + + // + // Use the GHCB MSR Protocol to request termination by the hypervisor + // + Msr.GhcbPhysicalAddress =3D 0; + Msr.GhcbTerminate.Function =3D GHCB_INFO_TERMINATE_REQUEST; + Msr.GhcbTerminate.ReasonCodeSet =3D GHCB_TERMINATE_GHCB; + Msr.GhcbTerminate.ReasonCode =3D GHCB_TERMINATE_GHCB_GENERAL; + AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress); + + AsmVmgExit (); + + ASSERT (FALSE); + CpuDeadLoop (); +} + +STATIC +UINTN +IssuePvalidate ( + IN UINTN Address, + IN UINTN RmpPageSize, + IN BOOLEAN Validate + ) +{ + IA32_EFLAGS32 EFlags; + UINTN Ret; + + Ret =3D AsmPvalidate (RmpPageSize, Validate, Address, &EFlags); + + // + // Check the rFlags.CF to verify that PVALIDATE updated the RMP + // entry. If there was a no change in the RMP entry then we are + // either double validating or invalidating the memory. This can + // lead to a security compromise. + // + if (EFlags.Bits.CF) { + DEBUG ((DEBUG_ERROR, "%a:%a: Double %a detected for address 0x%Lx\n", + gEfiCallerBaseName, + __FUNCTION__, + Validate ? "Validate" : "Invalidate", + Address)); + SnpPageStateFailureTerminate (); + } + + return Ret; +} + +/** + This function issues the PVALIDATE instruction to validate or invalidate = the memory + range specified. If PVALIDATE returns size mismatch then it tries validat= ing with + smaller page size. + + */ +STATIC +VOID +PvalidateRange ( + IN SNP_PAGE_STATE_CHANGE_INFO *Info, + IN UINTN StartIndex, + IN UINTN EndIndex, + IN BOOLEAN Validate + ) +{ + UINTN Address, RmpPageSize, Ret, i; + + for (; StartIndex < EndIndex; StartIndex++) { + Address =3D Info->Entry[StartIndex].GuestFrameNumber << EFI_PAGE_SHIFT; + RmpPageSize =3D Info->Entry[StartIndex].PageSize; + + Ret =3D IssuePvalidate (Address, RmpPageSize, Validate); + + // + // If we fail to validate due to size mismatch then try with the + // smaller page size. This senario will occur if the backing page in + // the RMP entry is 4K and we are validating it as a 2MB. + // + if ((Ret =3D=3D PVALIDATE_RET_FAIL_SIZEMISMATCH) && + (RmpPageSize =3D=3D PVALIDATE_PAGE_SIZE_2M)) { + for (i =3D 0; i < PAGES_PER_LARGE_ENTRY; i++) { + + Ret =3D IssuePvalidate (Address, PVALIDATE_PAGE_SIZE_4K, Validate); + if (Ret) { + break; + } + + Address =3D Address + EFI_PAGE_SIZE; + } + } + + if (Ret) { + DEBUG ((DEBUG_ERROR, "%a:%a: Failed to %a address 0x%Lx Error code %d\= n", + gEfiCallerBaseName, + __FUNCTION__, + Validate ? "Validate" : "Invalidate", + Address, + Ret)); + SnpPageStateFailureTerminate (); + } + } +} + +/** + The function is used to set the page state when SEV-SNP is active. The pa= ge state + transition consist of changing the page ownership in the RMP table, and u= sing the + PVALIDATE instruction to update the Validated bit in RMP table. + + When the UseLargeEntry is set to TRUE, then use the large RMP entry. + */ +VOID +SetPageStateInternal ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages, + IN SEV_SNP_PAGE_STATE State, + IN BOOLEAN UseLargeEntry + ) +{ + EFI_STATUS Status; + GHCB *Ghcb; + EFI_PHYSICAL_ADDRESS NextAddress, EndAddress; + MSR_SEV_ES_GHCB_REGISTER Msr; + BOOLEAN InterruptState; + SNP_PAGE_STATE_CHANGE_INFO *Info; + UINTN i, RmpPageSize; + + Msr.GhcbPhysicalAddress =3D AsmReadMsr64 (MSR_SEV_ES_GHCB); + Ghcb =3D Msr.Ghcb; + + EndAddress =3D BaseAddress + EFI_PAGES_TO_SIZE (NumPages); + + DEBUG ((DEBUG_VERBOSE, "%a:%a Address 0x%Lx - 0x%Lx State =3D %a LargeEn= try =3D %d\n", + gEfiCallerBaseName, + __FUNCTION__, + BaseAddress, + EndAddress, + State =3D=3D SevSnpPageShared ? "Shared" : "Private", + UseLargeEntry)); + + for (; BaseAddress < EndAddress; BaseAddress =3D NextAddress) { + + // + // Initialize the GHCB and setup scratch sw to point to shared buffer. + // + VmgInit (Ghcb, &InterruptState); + Info =3D (SNP_PAGE_STATE_CHANGE_INFO *) Ghcb->SharedBuffer; + + SetMem (Info, sizeof (*Info), 0); + + // + // Build page state change buffer + // + for (i =3D 0; (EndAddress > BaseAddress) && i < SNP_PAGE_STATE_MAX_ENT= RY; + BaseAddress =3D NextAddress, i++) { + // + // Is this a 2MB aligned page? Check if we can use the Large RMP ent= ry. + // + if (UseLargeEntry && + IS_ALIGNED (BaseAddress, EFI_LARGE_PAGE) && + ((EndAddress - BaseAddress) >> EFI_PAGE_SHIFT) >=3D PAGES_PER_LA= RGE_ENTRY) { + RmpPageSize =3D PVALIDATE_PAGE_SIZE_2M; + NextAddress =3D BaseAddress + EFI_LARGE_PAGE; + } else { + RmpPageSize =3D PVALIDATE_PAGE_SIZE_4K; + NextAddress =3D BaseAddress + EFI_PAGE_SIZE; + } + + Info->Entry[i].GuestFrameNumber =3D BaseAddress >> EFI_PAGE_SHIFT; + Info->Entry[i].PageSize =3D RmpPageSize; + Info->Entry[i].Op =3D MemoryStateToGhcbOp (State); + Info->Entry[i].CurrentPage =3D 0; + } + + Info->Header.CurrentEntry =3D 0; + Info->Header.EndEntry =3D i - 1; + + // + // If the request page state change is shared then invalidate the page= s before + // adding the page in the RMP table. + // + if (State =3D=3D SevSnpPageShared) { + PvalidateRange (Info, 0, i, FALSE); + } + + // + // Issue the VMGEXIT and retry if hypervisor failed to process all the= entries. + // + Ghcb->SaveArea.SwScratch =3D (UINT64) Ghcb->SharedBuffer; + VmgSetOffsetValid (Ghcb, GhcbSwScratch); + while (Info->Header.CurrentEntry <=3D Info->Header.EndEntry) { + Status =3D VmgExit (Ghcb, SVM_EXIT_SNP_PAGE_STATE_CHANGE, 0, 0); + if (EFI_ERROR (Status)) { + SnpPageStateFailureTerminate (); + } + } + + // + // If the request page state change is shared then invalidate the page= s before + // adding the page in the RMP table. + // + if (State =3D=3D SevSnpPagePrivate) { + PvalidateRange (Info, 0, i, TRUE); + } + + VmgDone (Ghcb, InterruptState); + } +} --=20 2.17.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#73228): https://edk2.groups.io/g/devel/message/73228 Mute This Topic: https://groups.io/mt/81584589/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-