]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/PlatformPei/AmdSev.c
4fd4534cabeab8730434d8ee563f6bd7a26ec745
[mirror_edk2.git] / OvmfPkg / PlatformPei / AmdSev.c
1 /**@file
2 Initialize Secure Encrypted Virtualization (SEV) support
3
4 Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9 //
10 // The package level header files this module uses
11 //
12 #include <IndustryStandard/Q35MchIch9.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/DebugLib.h>
15 #include <Library/HobLib.h>
16 #include <Library/MemEncryptSevLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/PcdLib.h>
19 #include <PiPei.h>
20 #include <Register/Amd/Cpuid.h>
21 #include <Register/Amd/Msr.h>
22 #include <Register/Cpuid.h>
23 #include <Register/Intel/SmramSaveStateMap.h>
24
25 #include "Platform.h"
26
27 /**
28
29 Initialize SEV-ES support if running as an SEV-ES guest.
30
31 **/
32 STATIC
33 VOID
34 AmdSevEsInitialize (
35 VOID
36 )
37 {
38 VOID *GhcbBase;
39 PHYSICAL_ADDRESS GhcbBasePa;
40 UINTN GhcbPageCount, PageCount;
41 RETURN_STATUS PcdStatus, DecryptStatus;
42
43 if (!MemEncryptSevEsIsEnabled ()) {
44 return;
45 }
46
47 PcdStatus = PcdSetBoolS (PcdSevEsIsEnabled, TRUE);
48 ASSERT_RETURN_ERROR (PcdStatus);
49
50 //
51 // Allocate GHCB and per-CPU variable pages.
52 //
53 GhcbPageCount = mMaxCpuCount * 2;
54 GhcbBase = AllocatePages (GhcbPageCount);
55 ASSERT (GhcbBase != NULL);
56
57 GhcbBasePa = (PHYSICAL_ADDRESS)(UINTN) GhcbBase;
58
59 //
60 // Each vCPU gets two consecutive pages, the first is the GHCB and the
61 // second is the per-CPU variable page. Loop through the allocation and
62 // only clear the encryption mask for the GHCB pages.
63 //
64 for (PageCount = 0; PageCount < GhcbPageCount; PageCount += 2) {
65 DecryptStatus = MemEncryptSevClearPageEncMask (
66 0,
67 GhcbBasePa + EFI_PAGES_TO_SIZE (PageCount),
68 1,
69 TRUE
70 );
71 ASSERT_RETURN_ERROR (DecryptStatus);
72 }
73
74 ZeroMem (GhcbBase, EFI_PAGES_TO_SIZE (GhcbPageCount));
75
76 PcdStatus = PcdSet64S (PcdGhcbBase, GhcbBasePa);
77 ASSERT_RETURN_ERROR (PcdStatus);
78 PcdStatus = PcdSet64S (PcdGhcbSize, EFI_PAGES_TO_SIZE (GhcbPageCount));
79 ASSERT_RETURN_ERROR (PcdStatus);
80
81 DEBUG ((DEBUG_INFO,
82 "SEV-ES is enabled, %lu GHCB pages allocated starting at 0x%p\n",
83 (UINT64)GhcbPageCount, GhcbBase));
84
85 AsmWriteMsr64 (MSR_SEV_ES_GHCB, GhcbBasePa);
86 }
87
88 /**
89
90 Function checks if SEV support is available, if present then it sets
91 the dynamic PcdPteMemoryEncryptionAddressOrMask with memory encryption mask.
92
93 **/
94 VOID
95 AmdSevInitialize (
96 VOID
97 )
98 {
99 CPUID_MEMORY_ENCRYPTION_INFO_EBX Ebx;
100 UINT64 EncryptionMask;
101 RETURN_STATUS PcdStatus;
102
103 //
104 // Check if SEV is enabled
105 //
106 if (!MemEncryptSevIsEnabled ()) {
107 return;
108 }
109
110 //
111 // CPUID Fn8000_001F[EBX] Bit 0:5 (memory encryption bit position)
112 //
113 AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, NULL, &Ebx.Uint32, NULL, NULL);
114 EncryptionMask = LShiftU64 (1, Ebx.Bits.PtePosBits);
115
116 //
117 // Set Memory Encryption Mask PCD
118 //
119 PcdStatus = PcdSet64S (PcdPteMemoryEncryptionAddressOrMask, EncryptionMask);
120 ASSERT_RETURN_ERROR (PcdStatus);
121
122 DEBUG ((DEBUG_INFO, "SEV is enabled (mask 0x%lx)\n", EncryptionMask));
123
124 //
125 // Set Pcd to Deny the execution of option ROM when security
126 // violation.
127 //
128 PcdStatus = PcdSet32S (PcdOptionRomImageVerificationPolicy, 0x4);
129 ASSERT_RETURN_ERROR (PcdStatus);
130
131 //
132 // When SMM is required, cover the pages containing the initial SMRAM Save
133 // State Map with a memory allocation HOB:
134 //
135 // There's going to be a time interval between our decrypting those pages for
136 // SMBASE relocation and re-encrypting the same pages after SMBASE
137 // relocation. We shall ensure that the DXE phase stay away from those pages
138 // until after re-encryption, in order to prevent an information leak to the
139 // hypervisor.
140 //
141 if (FeaturePcdGet (PcdSmmSmramRequire) && (mBootMode != BOOT_ON_S3_RESUME)) {
142 RETURN_STATUS LocateMapStatus;
143 UINTN MapPagesBase;
144 UINTN MapPagesCount;
145
146 LocateMapStatus = MemEncryptSevLocateInitialSmramSaveStateMapPages (
147 &MapPagesBase,
148 &MapPagesCount
149 );
150 ASSERT_RETURN_ERROR (LocateMapStatus);
151
152 if (mQ35SmramAtDefaultSmbase) {
153 //
154 // The initial SMRAM Save State Map has been covered as part of a larger
155 // reserved memory allocation in InitializeRamRegions().
156 //
157 ASSERT (SMM_DEFAULT_SMBASE <= MapPagesBase);
158 ASSERT (
159 (MapPagesBase + EFI_PAGES_TO_SIZE (MapPagesCount) <=
160 SMM_DEFAULT_SMBASE + MCH_DEFAULT_SMBASE_SIZE)
161 );
162 } else {
163 BuildMemoryAllocationHob (
164 MapPagesBase, // BaseAddress
165 EFI_PAGES_TO_SIZE (MapPagesCount), // Length
166 EfiBootServicesData // MemoryType
167 );
168 }
169 }
170
171 //
172 // Check and perform SEV-ES initialization if required.
173 //
174 AmdSevEsInitialize ();
175 }