]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c
2d2136f8054c6756a50cf281554958b20131e864
[mirror_edk2.git] / OvmfPkg / Library / BaseMemEncryptSevLib / X64 / PeiSnpSystemRamValidate.c
1 /** @file
2
3 SEV-SNP Page Validation functions.
4
5 Copyright (c) 2021 AMD Incorporated. All rights reserved.<BR>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include <Uefi/UefiBaseType.h>
12 #include <Library/BaseLib.h>
13 #include <Library/MemEncryptSevLib.h>
14
15 #include "SnpPageStateChange.h"
16
17 typedef struct {
18 UINT64 StartAddress;
19 UINT64 EndAddress;
20 } SNP_PRE_VALIDATED_RANGE;
21
22 STATIC SNP_PRE_VALIDATED_RANGE mPreValidatedRange[] = {
23 // The below address range was part of the SEV OVMF metadata, and range
24 // should be pre-validated by the Hypervisor.
25 {
26 FixedPcdGet32 (PcdOvmfSecPageTablesBase),
27 FixedPcdGet32 (PcdOvmfPeiMemFvBase),
28 },
29 };
30
31 STATIC
32 BOOLEAN
33 DetectPreValidatedOverLap (
34 IN PHYSICAL_ADDRESS StartAddress,
35 IN PHYSICAL_ADDRESS EndAddress,
36 OUT SNP_PRE_VALIDATED_RANGE *OverlapRange
37 )
38 {
39 UINTN i;
40
41 //
42 // Check if the specified address range exist in pre-validated array.
43 //
44 for (i = 0; i < ARRAY_SIZE (mPreValidatedRange); i++) {
45 if ((mPreValidatedRange[i].StartAddress < EndAddress) &&
46 (StartAddress < mPreValidatedRange[i].EndAddress))
47 {
48 OverlapRange->StartAddress = mPreValidatedRange[i].StartAddress;
49 OverlapRange->EndAddress = mPreValidatedRange[i].EndAddress;
50 return TRUE;
51 }
52 }
53
54 return FALSE;
55 }
56
57 /**
58 Pre-validate the system RAM when SEV-SNP is enabled in the guest VM.
59
60 @param[in] BaseAddress Base address
61 @param[in] NumPages Number of pages starting from the base address
62
63 **/
64 VOID
65 EFIAPI
66 MemEncryptSevSnpPreValidateSystemRam (
67 IN PHYSICAL_ADDRESS BaseAddress,
68 IN UINTN NumPages
69 )
70 {
71 PHYSICAL_ADDRESS EndAddress;
72 SNP_PRE_VALIDATED_RANGE OverlapRange;
73
74 if (!MemEncryptSevSnpIsEnabled ()) {
75 return;
76 }
77
78 EndAddress = BaseAddress + EFI_PAGES_TO_SIZE (NumPages);
79
80 while (BaseAddress < EndAddress) {
81 //
82 // Check if the range overlaps with the pre-validated ranges.
83 //
84 if (DetectPreValidatedOverLap (BaseAddress, EndAddress, &OverlapRange)) {
85 // Validate the non-overlap regions.
86 if (BaseAddress < OverlapRange.StartAddress) {
87 NumPages = EFI_SIZE_TO_PAGES (OverlapRange.StartAddress - BaseAddress);
88
89 InternalSetPageState (BaseAddress, NumPages, SevSnpPagePrivate, TRUE);
90 }
91
92 BaseAddress = OverlapRange.EndAddress;
93 continue;
94 }
95
96 // Validate the remaining pages.
97 NumPages = EFI_SIZE_TO_PAGES (EndAddress - BaseAddress);
98 InternalSetPageState (BaseAddress, NumPages, SevSnpPagePrivate, TRUE);
99 BaseAddress = EndAddress;
100 }
101 }