TianoCore EDK2 master
Loading...
Searching...
No Matches
CpuMmuCommon.c
Go to the documentation of this file.
1
10#include "CpuDxe.h"
11
32 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
33 IN UINTN NumberOfDescriptors,
34 IN EFI_PHYSICAL_ADDRESS BaseAddress,
35 IN UINT64 Length,
36 OUT UINTN *StartIndex,
37 OUT UINTN *EndIndex
38 )
39{
40 UINTN Index;
41
42 *StartIndex = 0;
43 *EndIndex = 0;
44 for (Index = 0; Index < NumberOfDescriptors; Index++) {
45 if ((BaseAddress >= MemorySpaceMap[Index].BaseAddress) &&
46 (BaseAddress < (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length)))
47 {
48 *StartIndex = Index;
49 }
50
51 if (((BaseAddress + Length - 1) >= MemorySpaceMap[Index].BaseAddress) &&
52 ((BaseAddress + Length - 1) < (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length)))
53 {
54 *EndIndex = Index;
55 return EFI_SUCCESS;
56 }
57 }
58
59 return EFI_NOT_FOUND;
60}
61
80 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
81 IN UINTN NumberOfDescriptors,
82 IN EFI_PHYSICAL_ADDRESS BaseAddress,
83 IN UINT64 Length,
84 IN UINT64 Attributes
85 )
86{
87 EFI_STATUS Status;
88 UINTN Index;
89 UINTN StartIndex;
90 UINTN EndIndex;
91 EFI_PHYSICAL_ADDRESS RegionStart;
92 UINT64 RegionLength;
93 UINT64 Capabilities;
94
95 DEBUG ((
96 DEBUG_GCD,
97 "SetGcdMemorySpaceAttributes[0x%lX; 0x%lX] = 0x%lX\n",
98 BaseAddress,
99 BaseAddress + Length,
100 Attributes
101 ));
102
103 // We do not support a smaller granularity than 4KB on ARM Architecture
104 if ((Length & EFI_PAGE_MASK) != 0) {
105 DEBUG ((
106 DEBUG_WARN,
107 "Warning: We do not support smaller granularity than 4KB on ARM Architecture (passed length: 0x%lX).\n",
108 Length
109 ));
110 }
111
112 //
113 // Get all memory descriptors covered by the memory range
114 //
115 Status = SearchGcdMemorySpaces (
116 MemorySpaceMap,
117 NumberOfDescriptors,
118 BaseAddress,
119 Length,
120 &StartIndex,
121 &EndIndex
122 );
123 if (EFI_ERROR (Status)) {
124 return Status;
125 }
126
127 //
128 // Go through all related descriptors and set attributes accordingly
129 //
130 for (Index = StartIndex; Index <= EndIndex; Index++) {
131 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
132 continue;
133 }
134
135 //
136 // Calculate the start and end address of the overlapping range
137 //
138 if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {
139 RegionStart = BaseAddress;
140 } else {
141 RegionStart = MemorySpaceMap[Index].BaseAddress;
142 }
143
144 if ((BaseAddress + Length - 1) < (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length)) {
145 RegionLength = BaseAddress + Length - RegionStart;
146 } else {
147 RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;
148 }
149
150 // Always add RO, RP, and XP, as all memory is capable of supporting these types (they are software constructs,
151 // not hardware features) and they are critical to maintaining a security boundary.
152 Capabilities = MemorySpaceMap[Index].Capabilities | EFI_MEMORY_RO | EFI_MEMORY_RP | EFI_MEMORY_XP;
153
154 // Update GCD capabilities as these may have changed in the page table from the original GCD setting
155 // this follows the same pattern as x86 GCD and Page Table syncing
156 Status = gDS->SetMemorySpaceCapabilities (
157 RegionStart,
158 RegionLength,
159 Capabilities
160 );
161
162 if (EFI_ERROR (Status)) {
163 DEBUG ((
164 DEBUG_ERROR,
165 "%a - failed to update GCD capabilities: 0x%llx on memory region: 0x%llx length: 0x%llx Status: %r\n",
166 __func__,
167 Capabilities,
168 RegionStart,
169 RegionLength,
170 Status
171 ));
172
173 // If we fail to set capabilities, we should assert as this is a GCD internal error, but follow the previous
174 // behavior and try to set the attributes (which may or may not fail)
175 ASSERT_EFI_ERROR (Status);
176 }
177
178 //
179 // Set memory attributes according to page table attributes and the original attributes of descriptor
180 //
181 Status = gDS->SetMemorySpaceAttributes (
182 RegionStart,
183 RegionLength,
184 (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (Attributes & Capabilities)
185 );
186
187 if (EFI_ERROR (Status)) {
188 DEBUG ((
189 DEBUG_ERROR,
190 "%a - failed to update GCD attributes: 0x%llx on memory region: 0x%llx length: 0x%llx Status: %r\n",
191 __func__,
192 Attributes,
193 RegionStart,
194 RegionLength,
195 Status
196 ));
197
198 ASSERT_EFI_ERROR (Status);
199 }
200 }
201
202 return EFI_SUCCESS;
203}
204
227EFIAPI
230 IN EFI_PHYSICAL_ADDRESS BaseAddress,
231 IN UINT64 Length,
232 IN UINT64 EfiAttributes
233 )
234{
235 EFI_STATUS Status;
236 UINTN ArmAttributes;
237 UINTN RegionBaseAddress;
238 UINTN RegionLength;
239 UINTN RegionArmAttributes;
240
241 if (mIsFlushingGCD) {
242 return EFI_SUCCESS;
243 }
244
245 if ((BaseAddress & (SIZE_4KB - 1)) != 0) {
246 // Minimum granularity is SIZE_4KB (4KB on ARM)
247 DEBUG ((DEBUG_PAGE, "CpuSetMemoryAttributes(%lx, %lx, %lx): Minimum granularity is SIZE_4KB\n", BaseAddress, Length, EfiAttributes));
248 return EFI_UNSUPPORTED;
249 }
250
251 // Convert the 'Attribute' into ARM Attribute
252 ArmAttributes = EfiAttributeToArmAttribute (EfiAttributes);
253
254 // Get the region starting from 'BaseAddress' and its 'Attribute'
255 RegionBaseAddress = BaseAddress;
256 Status = GetMemoryRegion (&RegionBaseAddress, &RegionLength, &RegionArmAttributes);
257
258 // Data & Instruction Caches are flushed when we set new memory attributes.
259 // So, we only set the attributes if the new region is different.
260 if (EFI_ERROR (Status) || (RegionArmAttributes != ArmAttributes) ||
261 ((BaseAddress + Length) > (RegionBaseAddress + RegionLength)))
262 {
263 return ArmSetMemoryAttributes (BaseAddress, Length, EfiAttributes, 0);
264 } else {
265 return EFI_SUCCESS;
266 }
267}
UINT64 UINTN
EFI_STATUS ArmSetMemoryAttributes(IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes, IN UINT64 AttributeMask)
EFI_STATUS SetGcdMemorySpaceAttributes(IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap, IN UINTN NumberOfDescriptors, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes)
Definition: CpuMmuCommon.c:79
EFI_STATUS EFIAPI CpuSetMemoryAttributes(IN EFI_CPU_ARCH_PROTOCOL *This, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 EfiAttributes)
Definition: CpuMmuCommon.c:228
EFI_STATUS SearchGcdMemorySpaces(IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap, IN UINTN NumberOfDescriptors, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, OUT UINTN *StartIndex, OUT UINTN *EndIndex)
Definition: CpuMmuCommon.c:31
EFI_DXE_SERVICES * gDS
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
@ EfiGcdMemoryTypeNonExistent
Definition: PiDxeCis.h:26
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112