From mboxrd@z Thu Jan 1 00:00:00 1970 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:39 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@amd.com header.s=selector1 header.b=B8Log6It; spf=permerror, err=parse error for token &{10 18 %{i}._ip.%{h}._ehlo.%{d}._spf.vali.email}: invalid domain name (domain: amd.com, ip: , mailfrom: brijesh.singh@amd.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=P+2FciMIBDazYPduTXxdLdcQwr1aif0xlq9JQ1nb1B+xECEZBuFcCazXsW4jnY342UpIiFRJsqfyWI7VXExqVNpytg0egZFtWHxLTSlnq+pUXR6mlr+pprTUbQvoxztheaRCo6WdEiZgdZ81zmOxyp74wWvLN22lGahjaEXTflyNEBV2CD/sr7Qa6M5Iq7OrhGEQ4VwKjECJLJaYj1ICQ84LCjgy4nYnSQHZDqBXusdCmlZRDDPAzc+DdqdSg6NmJWQTkLb2GjskIzm/zd45q9tyrgvaStKU6LVKnYUGwMRbpUCYHCAxDIZrt5R0i+JbBaPOFHNlO72TUNyNhl4paA== 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=6RUajI9WyJPb0IYKTkAHf21k6UmYRa5M+ANt7DGwT3s=; b=gqKsf1n+AQ9XFDnDPOq+AjnxJMJAnw1Th/ZLdyJ1VepjyskSUGjdris8dnNJI2veOQ9PcWcEXXMe7dy/GYFtf2YJR19Er0p7Snh/NOIlf+yL6Lxra1jNCOquyoJtSMzlz0gm9QQmVIyflyCxkU5dKIAG/SQIMv8alF429uTIupr7ohCos+d1OMXUODMlFirEQaL2C1R0kOBdGIdu5Jq3vDxu9aGR8+x7pps8xikLhVKnh7O2ryRHp/KZM8vEVUD6CWyVeixVEqh7Qn4dkBi9tD4UwJ4ZQ1QSvd5fHFUYlKzybikW6PPC4A1iO6jqV9qdU6idSWEtHrs28f3ZsRyZyQ== 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 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=6RUajI9WyJPb0IYKTkAHf21k6UmYRa5M+ANt7DGwT3s=; b=B8Log6ItoCvr9EYIwVU6A9fbAf4cTpgm1A3jCriQXZIy8xnF9ufw/cP0XO5XJ71jHIwmH035YoH9g/g2uqGTVUpFZeHKFPmOGyG0VWHFVjdbtwyQGG42eI7hW1O/8CIE3O/cfKZY0gOiKEZvvF2jv3SloXfCEhmm1EZmI8OtMWw= Authentication-Results: edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=none action=none header.from=amd.com; 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:37 +0000 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:37 +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: [RFC PATCH 14/19] OvmfPkg/MemEncryptSevLib: Add support to validate RAM in PEI phase Date: Wed, 24 Mar 2021 10:32:10 -0500 Message-Id: <20210324153215.17971-15-brijesh.singh@amd.com> X-Mailer: git-send-email 2.17.1 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) Return-Path: brijesh.singh@amd.com MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 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:36 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: c3c74531-3aa2-4a02-69a3-08d8eeda0d70 X-MS-TrafficTypeDiagnostic: SA0PR12MB4430: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:9508; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: +YxjdCPxcpox6o3WQAcWQUHovIovanjP5LU1r6glOLNiXVt8pzn9ZC4k69KOzggsaUkmewAY/8sRZiCjNEOVU7xu0H/ZNk3vub2AmK4BIbPBO4KV05Mua8eGduzu0k38KXjbhEDCU6dwTPptGb5RM0zbWVJZBrLlMQPIW24iuN7FhCNNdwpdcPPKqJyR+cBBzhDaTMJ9SmSbLqCkFAuziJSYag9KCME3egOIMWLpj4ElzKDWVwCINKBrQQZtvXyQiwX2yZDAiWPE/HjJlK1eNZFTVuo83plqXh5780erHTrxccQRbwFi+xWXQ17IJ8dpYSRDUoNy5QHZJh4Geav5Rtoau1oD/PM92nbl7Rpz5/YbayYcxI7aY3ddUPYi8l3Wrm7lsyrDPsm9oKHSrnWPmFwlSmqqczVp/qPy5IPM4WjhFnsOo+lZ6lHgUo9oCayNN3dk0+riDcP+97vfYH+qxoKY5+am3jzhGcawzxI6xoQrHIei6RZcCiKGdpwwPbFSo9xt3PMARvAIjjm045GN+TA2tjPzFOdCO5sInBXdnS//MAQcNi+vmYpzndH2A+ghMBL371D/o4fRcw54/Pn7eodSGOj7P7c1tHkfv7HKRPdaf/og58NqzlQ0u3NZoeroaSmtg0iQgIQBFkfxZyoGfoIbguRuSbtwHcl6uPOv4EcBUUAr2t22HF7xU1axkWKPoDGmTBFu7YZCcIdB8j1U+UEcJGIQpgs8hFrgaWbV1eIUibTUFBMGnfbvtOcy6Eh5 X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SN6PR12MB2718.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(4636009)(366004)(39860400002)(136003)(376002)(346002)(396003)(2616005)(83380400001)(66476007)(15650500001)(4326008)(44832011)(1076003)(6486002)(2906002)(86362001)(66946007)(478600001)(316002)(66556008)(966005)(16526019)(6666004)(26005)(30864003)(54906003)(19627235002)(6916009)(186003)(5660300002)(8676002)(7696005)(956004)(8936002)(38100700001)(36756003)(52116002);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: =?us-ascii?Q?Yw0lceQU+GMO9kLiQ0xjBAqVt6obEcFPRoB2JufyLt+eAxN5pbqOvhAUrC1g?= =?us-ascii?Q?sez0VHLlTmXI+TPLtoWNsCwKICXUerDln7/9SmCkoPP6l8njNgjHxv6F97lQ?= =?us-ascii?Q?Ly29BVHgQshv5+U/TSRdFZk3gV3Y6mLyXQxhhWFD+Qbrq/Ziq+l6pvyRp2nn?= =?us-ascii?Q?Hy1VWUZGrUkCW8ew4zAYakSxeJqnTJsB51k190d6HbZDcRrV5I6kpx1c+nbt?= =?us-ascii?Q?lhusTmzdmoCUWroLgkNAC7onCOfor6jgc7gCtGPDIr6CbVax9OP5wsgVzMQG?= =?us-ascii?Q?kHFiFeI4YM6D/ykc+D67BHRc/SlTNwfxrMmGQwZdCr1lt5Ofll24RCqg+M/g?= =?us-ascii?Q?YhWgDJq4U8cqewrHlKFiHii6TKocZqDMKKhUDfKSzupYaYash7khdmNxkgng?= =?us-ascii?Q?YjBfMquRYVD5y7iyP4H8NG0rbieLOAGC1934g1rcRT+/Y08iVseSmFS7h1s0?= =?us-ascii?Q?4NxST9ulwei51Ob/Vsd8EGHRZXSaJNOvXEK7nqff3pdpsRgcbw3Sy+lhgCEV?= =?us-ascii?Q?g4Kc/0OIg3EOQz6EVML2+8yJqvGSAViVmjQCV0a5YT2sFqkR8lZ8FXyucZcM?= =?us-ascii?Q?brTWdmtEwxArsddTHEXXDkGIAxhm7+DMnmZnmwZ+mkG3nWsmzqj0epc3eUVe?= =?us-ascii?Q?S/DWsFrajJL5wWgyz9QjzIWH7dyv8x8QRfzS24tHCrfVOjEsdJqyQG50h06H?= =?us-ascii?Q?lfT86Vhr0RnVX13hHUKdM937AUDXR3QG5JrBu+dJo/4vUStfohEnKfzi7/sd?= =?us-ascii?Q?oijxwt/J3lNaCXGqY6eQDJJIz48EZGmO0o60VbnsBO1nJlRYffJd1Il0Fkwv?= =?us-ascii?Q?XAjq0M51Z1CHig8xLRhp9ycsBXnOUMb3sFttqy0F5k//Mh6myxNrLUUq93iZ?= =?us-ascii?Q?B6qqZvLwEVzI4jPC/lZYSppbEf9oQtZEiE30GMLBJAg5FcQ8vu/AkmD1oj/y?= =?us-ascii?Q?bxBcSBv7WLKuXWsT815KM5fIaTaA9hzql8u51mBZGYZdZ8tnVjgPNCrbDyh3?= =?us-ascii?Q?jRj8/JQy1dGBjkbBjtB8BoXB2U6+WvQwfERzmQiu3SxTv/J1PDYPV5uAZUcr?= =?us-ascii?Q?bPAI8gFFXx6CgvgV5eYsSAIwfFtudxNQ2LpZc1xX2UBU8IPNPJCo7nL7qDXv?= =?us-ascii?Q?r7TmOSUUXj30Id5yGkmXgMX9zNLzaCK3H9col0BIAlgc5z4FpotGYGqSQgUq?= =?us-ascii?Q?Aaoa6r45UEnxSbtknd2BlZFiqDzOERpZXNuwwAxnM6JK+hT9NI4LdyNAiujN?= =?us-ascii?Q?ziY6xS+OUTL7T8auQD4uqhmUifoqd4aJ4qudBt6ai8JMFkcTSWhXDQQx3CvI?= =?us-ascii?Q?TeWY8Z0GoYgG5wzZQeTrnyss?= X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-Network-Message-Id: c3c74531-3aa2-4a02-69a3-08d8eeda0d70 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:37.1685 (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: oxwl4t29xXaAKPOGxCpKhi50HGlY116wELPgB1WjoQsR+u6kGjcqhtBt5+CerRpE0m/XvYURiNUv0mxBSb6b/A== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA0PR12MB4430 Content-Type: text/plain BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275 MemEncryptSevSnpValidateSystemRam() is used for validating the system RAM. During the validation process, we must avoid double validation cases. The double validation can lead to security issues. Extend the MemEncryptSevSnpValidateSystemRam() to use the interval search tree to keep track of the validated range; if the requested range is already validated, then do nothing. If the requested range overlaps with the previous validation, then validate only non-overlapped ranges. 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/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf | 8 ++ OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c | 20 ++++ OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c | 105 +++++++++++++++++ OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateTrack.c | 119 ++++++++++++++++++++ OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateTrack.h | 36 ++++++ 5 files changed, 288 insertions(+) diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf index 03a78c32df..cb9dd2bb21 100644 --- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf @@ -32,10 +32,15 @@ [Sources] PeiDxeMemEncryptSevLibInternal.c PeiMemEncryptSevLibInternal.c + SnpPageStateChange.h [Sources.X64] X64/MemEncryptSevLib.c X64/PeiDxeVirtualMemory.c + X64/PeiSnpSystemRamValidate.c + X64/SnpPageStateTrack.c + X64/SnpPageStateChangeInternal.c + X64/SnpPageStateTrack.h X64/VirtualMemory.c X64/VirtualMemory.h @@ -49,9 +54,12 @@ DebugLib MemoryAllocationLib PcdLib + VmgExitLib [FeaturePcd] gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire [FixedPcd] + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c index b561f211f5..9863722e9d 100644 --- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c @@ -17,6 +17,8 @@ #include #include +#include "SnpPageStateChange.h" + STATIC BOOLEAN mSevStatus = FALSE; STATIC BOOLEAN mSevEsStatus = FALSE; STATIC BOOLEAN mSevSnpStatus = FALSE; @@ -184,3 +186,21 @@ MemEncryptSevGetEncryptionMask ( return mSevEncryptionMask; } + +/** + 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 base address + +**/ +VOID +EFIAPI +MemEncryptSevSnpValidateSystemRam ( + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages + ) +{ + SevSnpValidateSystemRam (BaseAddress, NumPages); +} diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c new file mode 100644 index 0000000000..ce8a05bb1f --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c @@ -0,0 +1,105 @@ +/** @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 "../SnpPageStateChange.h" +#include "SnpPageStateTrack.h" + +STATIC SNP_VALIDATED_RANGE *mRootNode; + +STATIC +SNP_VALIDATED_RANGE * +SetPageStateChangeInitialize ( + VOID + ) +{ + UINTN StartAddress, EndAddress; + SNP_VALIDATED_RANGE *RootNode; + + // + // The memory range from PcdOvmfSnpCpuidBase to PcdOvmfDecompressionScratchEnd is + // prevalidated before we enter into the Pei phase. The pre-validation breakdown + // looks like this: + // + // SnpCpuidBase (VMM) + // SnpSecretBase (VMM) + // SnpLaunchValidatedStart - SnpLaunchValidatedEnd (VMM) + // SnpLaunchValidatedEnd - DecompressionScratchEnd (SecMain) + // + // Add the range in system ram region tracker interval tree. The interval tree will + // used to check whether there is an overlap with the pre-validated region. We will + // skip validating the pre-validated region. + // + StartAddress = (UINTN) PcdGet32 (PcdOvmfSnpCpuidBase); + EndAddress = (UINTN) PcdGet32 (PcdOvmfDecompressionScratchEnd); + + RootNode = AddRangeToIntervalTree (NULL, StartAddress, EndAddress); + if (RootNode == NULL) { + DEBUG ((DEBUG_ERROR, "Failed to add range to interval tree\n")); + ASSERT (FALSE); + } + + return RootNode; +} + +VOID +SevSnpValidateSystemRam ( + IN UINTN BaseAddress, + IN UINTN NumPages + ) +{ + UINTN EndAddress; + SNP_VALIDATED_RANGE *Range; + + EndAddress = BaseAddress + EFI_PAGES_TO_SIZE (NumPages); + + // + // If the Root is NULL then its the first call. Lets initialize the List before + // we process the request. + // + if (mRootNode == NULL) { + mRootNode = SetPageStateChangeInitialize (); + } + + // + // Check if the range is already validated + // + EndAddress = BaseAddress + EFI_PAGES_TO_SIZE(NumPages); + Range = FindOverlapRange (mRootNode, BaseAddress, EndAddress); + + // + // Range is not validated + if (Range == NULL) { + SetPageStateInternal (BaseAddress, NumPages, SevSnpPagePrivate, TRUE); + AddRangeToIntervalTree (mRootNode, BaseAddress, EndAddress); + return; + } + + // + // The input range overlaps with the pre-validated range. Calculate the non-overlap + // region and validate them. + // + if (BaseAddress < Range->StartAddress) { + NumPages = EFI_SIZE_TO_PAGES (Range->StartAddress - BaseAddress); + SetPageStateInternal (BaseAddress, NumPages, SevSnpPagePrivate, TRUE); + AddRangeToIntervalTree (mRootNode, BaseAddress, Range->StartAddress); + } + + if (EndAddress > Range->EndAddress) { + NumPages = EFI_SIZE_TO_PAGES (EndAddress - Range->EndAddress); + SetPageStateInternal (Range->EndAddress, NumPages, SevSnpPagePrivate, TRUE); + AddRangeToIntervalTree (mRootNode, Range->StartAddress, EndAddress); + } +} diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateTrack.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateTrack.c new file mode 100644 index 0000000000..91b4fc8db4 --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateTrack.c @@ -0,0 +1,119 @@ +/** @file + + Provides a simple interval search tree implementation that will be used + by the SnpValidateSystemRam() to keep track of the memory range validated + during the SEC/PEI phases. + + Copyright (c) 2020 - 2021, AMD Incorporated. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include "SnpPageStateTrack.h" + +STATIC +SNP_VALIDATED_RANGE * +AllocNewNode ( + IN UINTN StartAddress, + IN UINTN EndAddress + ) +{ + SNP_VALIDATED_RANGE *Node; + + Node = AllocatePool (sizeof (SNP_VALIDATED_RANGE)); + if (Node == NULL) { + return NULL; + } + + Node->StartAddress = StartAddress; + Node->EndAddress = EndAddress; + Node->MaxAddress = Node->EndAddress; + Node->Left = Node->Right = NULL; + + return Node; +} + +STATIC +BOOLEAN +RangeIsOverlap ( + IN SNP_VALIDATED_RANGE *Node, + IN UINTN StartAddress, + IN UINTN EndAddress + ) +{ + if (Node->StartAddress < EndAddress && StartAddress < Node->EndAddress) { + return TRUE; + } + + return FALSE; +} + + +/** + Function to find the overlapping range within the interval tree. If range is not + found then NULL is returned. + + */ +SNP_VALIDATED_RANGE * +FindOverlapRange ( + IN SNP_VALIDATED_RANGE *RootNode, + IN UINTN StartAddress, + IN UINTN EndAddress + ) +{ + // Tree is empty or no overlap found + if (RootNode == NULL) { + return NULL; + } + + // Check with the range exist in the root node + if (RangeIsOverlap(RootNode, StartAddress, EndAddress)) { + return RootNode; + } + + // + // If the left child of root is present and the max of the left child is + // greater than or equal to a given range then requested range will overlap + // with left subtree + // + if (RootNode->Left != NULL && (RootNode->Left->MaxAddress >= StartAddress)) { + return FindOverlapRange (RootNode->Left, StartAddress, EndAddress); + } + + // The range can only overlap with the right subtree + return FindOverlapRange (RootNode->Right, StartAddress, EndAddress); +} + +/** + Function to insert the validated range in the interval search tree. + + */ +SNP_VALIDATED_RANGE * +AddRangeToIntervalTree ( + IN SNP_VALIDATED_RANGE *RootNode, + IN UINTN StartAddress, + IN UINTN EndAddress + ) +{ + // Tree is empty or we reached to the leaf + if (RootNode == NULL) { + return AllocNewNode (StartAddress, EndAddress); + } + + // If the StartAddress is smaller then the BaseAddress then go to the left in the tree. + if (StartAddress < RootNode->StartAddress) { + RootNode->Left = AddRangeToIntervalTree (RootNode->Left, StartAddress, EndAddress); + } else { + RootNode->Right = AddRangeToIntervalTree (RootNode->Right, StartAddress, EndAddress); + } + + // Update the max value of the ancestor if needed + if (RootNode->MaxAddress < EndAddress) { + RootNode->MaxAddress = EndAddress; + } + + return RootNode; +} diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateTrack.h b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateTrack.h new file mode 100644 index 0000000000..106c3411f0 --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateTrack.h @@ -0,0 +1,36 @@ +/** @file + + + Copyright (c) 2020 - 2021, AMD Incorporated. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SNP_PAGE_STATE_TRACK_INTERNAL_H_ +#define SNP_PAGE_STATE_TRACK_INTERNAL_H_ + +#include + +typedef struct SNP_VALIDATED_RANGE { + UINT64 StartAddress, EndAddress; + UINT64 MaxAddress; + + struct SNP_VALIDATED_RANGE *Left, *Right; +} SNP_VALIDATED_RANGE; + +SNP_VALIDATED_RANGE * +FindOverlapRange ( + IN SNP_VALIDATED_RANGE *RootNode, + IN UINTN StartAddress, + IN UINTN EndAddress + ); + +SNP_VALIDATED_RANGE * +AddRangeToIntervalTree ( + IN SNP_VALIDATED_RANGE *RootNode, + IN UINTN StartAddress, + IN UINTN EndAddress + ); + +#endif -- 2.17.1