]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c
OvmfPkg/SecMain: validate the memory used for decompressing Fv
[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/PcdLib.h>
14 #include <Library/DebugLib.h>
15 #include <Library/MemEncryptSevLib.h>
16
17 #include "SnpPageStateChange.h"
18 #include "VirtualMemory.h"
19
20 typedef struct {
21 UINT64 StartAddress;
22 UINT64 EndAddress;
23 } SNP_PRE_VALIDATED_RANGE;
24
25 STATIC SNP_PRE_VALIDATED_RANGE mPreValidatedRange[] = {
26 // The below address range was part of the SEV OVMF metadata, and range
27 // should be pre-validated by the Hypervisor.
28 {
29 FixedPcdGet32 (PcdOvmfSecPageTablesBase),
30 FixedPcdGet32 (PcdOvmfPeiMemFvBase),
31 },
32 // The below range is pre-validated by the Sec/SecMain.c
33 {
34 FixedPcdGet32 (PcdOvmfSecValidatedStart),
35 FixedPcdGet32 (PcdOvmfSecValidatedEnd)
36 },
37 };
38
39 STATIC
40 BOOLEAN
41 DetectPreValidatedOverLap (
42 IN PHYSICAL_ADDRESS StartAddress,
43 IN PHYSICAL_ADDRESS EndAddress,
44 OUT SNP_PRE_VALIDATED_RANGE *OverlapRange
45 )
46 {
47 UINTN i;
48
49 //
50 // Check if the specified address range exist in pre-validated array.
51 //
52 for (i = 0; i < ARRAY_SIZE (mPreValidatedRange); i++) {
53 if ((mPreValidatedRange[i].StartAddress < EndAddress) &&
54 (StartAddress < mPreValidatedRange[i].EndAddress))
55 {
56 OverlapRange->StartAddress = mPreValidatedRange[i].StartAddress;
57 OverlapRange->EndAddress = mPreValidatedRange[i].EndAddress;
58 return TRUE;
59 }
60 }
61
62 return FALSE;
63 }
64
65 /**
66 Pre-validate the system RAM when SEV-SNP is enabled in the guest VM.
67
68 @param[in] BaseAddress Base address
69 @param[in] NumPages Number of pages starting from the base address
70
71 **/
72 VOID
73 EFIAPI
74 MemEncryptSevSnpPreValidateSystemRam (
75 IN PHYSICAL_ADDRESS BaseAddress,
76 IN UINTN NumPages
77 )
78 {
79 PHYSICAL_ADDRESS EndAddress;
80 SNP_PRE_VALIDATED_RANGE OverlapRange;
81 EFI_STATUS Status;
82
83 if (!MemEncryptSevSnpIsEnabled ()) {
84 return;
85 }
86
87 EndAddress = BaseAddress + EFI_PAGES_TO_SIZE (NumPages);
88
89 //
90 // The page table used in PEI can address up to 4GB memory. If we are asked to
91 // validate a range above the 4GB, then create an identity mapping so that the
92 // PVALIDATE instruction can execute correctly. If the page table entry is not
93 // present then PVALIDATE will #GP.
94 //
95 if (BaseAddress >= SIZE_4GB) {
96 Status = InternalMemEncryptSevCreateIdentityMap1G (
97 0,
98 BaseAddress,
99 EFI_PAGES_TO_SIZE (NumPages)
100 );
101 if (EFI_ERROR (Status)) {
102 ASSERT (FALSE);
103 CpuDeadLoop ();
104 }
105 }
106
107 while (BaseAddress < EndAddress) {
108 //
109 // Check if the range overlaps with the pre-validated ranges.
110 //
111 if (DetectPreValidatedOverLap (BaseAddress, EndAddress, &OverlapRange)) {
112 // Validate the non-overlap regions.
113 if (BaseAddress < OverlapRange.StartAddress) {
114 NumPages = EFI_SIZE_TO_PAGES (OverlapRange.StartAddress - BaseAddress);
115
116 InternalSetPageState (BaseAddress, NumPages, SevSnpPagePrivate, TRUE);
117 }
118
119 BaseAddress = OverlapRange.EndAddress;
120 continue;
121 }
122
123 // Validate the remaining pages.
124 NumPages = EFI_SIZE_TO_PAGES (EndAddress - BaseAddress);
125 InternalSetPageState (BaseAddress, NumPages, SevSnpPagePrivate, TRUE);
126 BaseAddress = EndAddress;
127 }
128 }