b92ba50c616c4d1caa310d373c0d34578f5d1633
[mirror_edk2.git] / OvmfPkg / Library / BaseMemEncryptSevLib / MemEncryptSevLibInternal.c
1 /** @file
2
3 Secure Encrypted Virtualization (SEV) library helper function
4
5 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
6
7 This program and the accompanying materials are licensed and made available
8 under the terms and conditions of the BSD License which accompanies this
9 distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17 #include <Library/BaseLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/MemEncryptSevLib.h>
20 #include <Library/PcdLib.h>
21 #include <Register/Amd/Cpuid.h>
22 #include <Register/Amd/Msr.h>
23 #include <Register/Cpuid.h>
24 #include <Register/QemuSmramSaveStateMap.h>
25 #include <Register/SmramSaveStateMap.h>
26 #include <Uefi/UefiBaseType.h>
27
28 STATIC BOOLEAN mSevStatus = FALSE;
29 STATIC BOOLEAN mSevStatusChecked = FALSE;
30
31 /**
32
33 Returns a boolean to indicate whether SEV is enabled
34
35 @retval TRUE SEV is enabled
36 @retval FALSE SEV is not enabled
37 **/
38 STATIC
39 BOOLEAN
40 EFIAPI
41 InternalMemEncryptSevIsEnabled (
42 VOID
43 )
44 {
45 UINT32 RegEax;
46 MSR_SEV_STATUS_REGISTER Msr;
47 CPUID_MEMORY_ENCRYPTION_INFO_EAX Eax;
48
49 //
50 // Check if memory encryption leaf exist
51 //
52 AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
53 if (RegEax >= CPUID_MEMORY_ENCRYPTION_INFO) {
54 //
55 // CPUID Fn8000_001F[EAX] Bit 1 (Sev supported)
56 //
57 AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, &Eax.Uint32, NULL, NULL, NULL);
58
59 if (Eax.Bits.SevBit) {
60 //
61 // Check MSR_0xC0010131 Bit 0 (Sev Enabled)
62 //
63 Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS);
64 if (Msr.Bits.SevBit) {
65 return TRUE;
66 }
67 }
68 }
69
70 return FALSE;
71 }
72
73 /**
74 Returns a boolean to indicate whether SEV is enabled
75
76 @retval TRUE SEV is enabled
77 @retval FALSE SEV is not enabled
78 **/
79 BOOLEAN
80 EFIAPI
81 MemEncryptSevIsEnabled (
82 VOID
83 )
84 {
85 if (mSevStatusChecked) {
86 return mSevStatus;
87 }
88
89 mSevStatus = InternalMemEncryptSevIsEnabled();
90 mSevStatusChecked = TRUE;
91
92 return mSevStatus;
93 }
94
95
96 /**
97 Locate the page range that covers the initial (pre-SMBASE-relocation) SMRAM
98 Save State Map.
99
100 @param[out] BaseAddress The base address of the lowest-address page that
101 covers the initial SMRAM Save State Map.
102
103 @param[out] NumberOfPages The number of pages in the page range that covers
104 the initial SMRAM Save State Map.
105
106 @retval RETURN_SUCCESS BaseAddress and NumberOfPages have been set on
107 output.
108
109 @retval RETURN_UNSUPPORTED SMM is unavailable.
110 **/
111 RETURN_STATUS
112 EFIAPI
113 MemEncryptSevLocateInitialSmramSaveStateMapPages (
114 OUT UINTN *BaseAddress,
115 OUT UINTN *NumberOfPages
116 )
117 {
118 UINTN MapStart;
119 UINTN MapEnd;
120 UINTN MapPagesStart; // MapStart rounded down to page boundary
121 UINTN MapPagesEnd; // MapEnd rounded up to page boundary
122 UINTN MapPagesSize; // difference between MapPagesStart and MapPagesEnd
123
124 if (!FeaturePcdGet (PcdSmmSmramRequire)) {
125 return RETURN_UNSUPPORTED;
126 }
127
128 MapStart = SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET;
129 MapEnd = MapStart + sizeof (QEMU_SMRAM_SAVE_STATE_MAP);
130 MapPagesStart = MapStart & ~(UINTN)EFI_PAGE_MASK;
131 MapPagesEnd = ALIGN_VALUE (MapEnd, EFI_PAGE_SIZE);
132 MapPagesSize = MapPagesEnd - MapPagesStart;
133
134 ASSERT ((MapPagesSize & EFI_PAGE_MASK) == 0);
135
136 *BaseAddress = MapPagesStart;
137 *NumberOfPages = MapPagesSize >> EFI_PAGE_SHIFT;
138
139 return RETURN_SUCCESS;
140 }