2 Initialize Secure Encrypted Virtualization (SEV) support
4 Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 // The package level header files this module uses
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>
20 #include <Register/Amd/Cpuid.h>
21 #include <Register/Amd/Msr.h>
22 #include <Register/Cpuid.h>
23 #include <Register/Intel/SmramSaveStateMap.h>
29 Initialize SEV-ES support if running as an SEV-ES guest.
39 PHYSICAL_ADDRESS GhcbBasePa
;
40 UINTN GhcbPageCount
, PageCount
;
41 RETURN_STATUS PcdStatus
, DecryptStatus
;
43 if (!MemEncryptSevEsIsEnabled ()) {
47 PcdStatus
= PcdSetBoolS (PcdSevEsIsEnabled
, TRUE
);
48 ASSERT_RETURN_ERROR (PcdStatus
);
51 // Allocate GHCB and per-CPU variable pages.
53 GhcbPageCount
= mMaxCpuCount
* 2;
54 GhcbBase
= AllocatePages (GhcbPageCount
);
55 ASSERT (GhcbBase
!= NULL
);
57 GhcbBasePa
= (PHYSICAL_ADDRESS
)(UINTN
) GhcbBase
;
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.
64 for (PageCount
= 0; PageCount
< GhcbPageCount
; PageCount
+= 2) {
65 DecryptStatus
= MemEncryptSevClearPageEncMask (
67 GhcbBasePa
+ EFI_PAGES_TO_SIZE (PageCount
),
71 ASSERT_RETURN_ERROR (DecryptStatus
);
74 ZeroMem (GhcbBase
, EFI_PAGES_TO_SIZE (GhcbPageCount
));
76 PcdStatus
= PcdSet64S (PcdGhcbBase
, GhcbBasePa
);
77 ASSERT_RETURN_ERROR (PcdStatus
);
78 PcdStatus
= PcdSet64S (PcdGhcbSize
, EFI_PAGES_TO_SIZE (GhcbPageCount
));
79 ASSERT_RETURN_ERROR (PcdStatus
);
82 "SEV-ES is enabled, %lu GHCB pages allocated starting at 0x%p\n",
83 (UINT64
)GhcbPageCount
, GhcbBase
));
85 AsmWriteMsr64 (MSR_SEV_ES_GHCB
, GhcbBasePa
);
90 Function checks if SEV support is available, if present then it sets
91 the dynamic PcdPteMemoryEncryptionAddressOrMask with memory encryption mask.
99 CPUID_MEMORY_ENCRYPTION_INFO_EBX Ebx
;
100 UINT64 EncryptionMask
;
101 RETURN_STATUS PcdStatus
;
104 // Check if SEV is enabled
106 if (!MemEncryptSevIsEnabled ()) {
111 // CPUID Fn8000_001F[EBX] Bit 0:5 (memory encryption bit position)
113 AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO
, NULL
, &Ebx
.Uint32
, NULL
, NULL
);
114 EncryptionMask
= LShiftU64 (1, Ebx
.Bits
.PtePosBits
);
117 // Set Memory Encryption Mask PCD
119 PcdStatus
= PcdSet64S (PcdPteMemoryEncryptionAddressOrMask
, EncryptionMask
);
120 ASSERT_RETURN_ERROR (PcdStatus
);
122 DEBUG ((DEBUG_INFO
, "SEV is enabled (mask 0x%lx)\n", EncryptionMask
));
125 // Set Pcd to Deny the execution of option ROM when security
128 PcdStatus
= PcdSet32S (PcdOptionRomImageVerificationPolicy
, 0x4);
129 ASSERT_RETURN_ERROR (PcdStatus
);
132 // When SMM is required, cover the pages containing the initial SMRAM Save
133 // State Map with a memory allocation HOB:
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
141 if (FeaturePcdGet (PcdSmmSmramRequire
) && (mBootMode
!= BOOT_ON_S3_RESUME
)) {
142 RETURN_STATUS LocateMapStatus
;
146 LocateMapStatus
= MemEncryptSevLocateInitialSmramSaveStateMapPages (
150 ASSERT_RETURN_ERROR (LocateMapStatus
);
152 if (mQ35SmramAtDefaultSmbase
) {
154 // The initial SMRAM Save State Map has been covered as part of a larger
155 // reserved memory allocation in InitializeRamRegions().
157 ASSERT (SMM_DEFAULT_SMBASE
<= MapPagesBase
);
159 (MapPagesBase
+ EFI_PAGES_TO_SIZE (MapPagesCount
) <=
160 SMM_DEFAULT_SMBASE
+ MCH_DEFAULT_SMBASE_SIZE
)
163 BuildMemoryAllocationHob (
164 MapPagesBase
, // BaseAddress
165 EFI_PAGES_TO_SIZE (MapPagesCount
), // Length
166 EfiBootServicesData
// MemoryType
172 // Check and perform SEV-ES initialization if required.
174 AmdSevEsInitialize ();