TianoCore EDK2 master
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
94 DEBUG ((
95 DEBUG_GCD,
96 "SetGcdMemorySpaceAttributes[0x%lX; 0x%lX] = 0x%lX\n",
97 BaseAddress,
98 BaseAddress + Length,
99 Attributes
100 ));
101
102 // We do not support a smaller granularity than 4KB on ARM Architecture
103 if ((Length & EFI_PAGE_MASK) != 0) {
104 DEBUG ((
105 DEBUG_WARN,
106 "Warning: We do not support smaller granularity than 4KB on ARM Architecture (passed length: 0x%lX).\n",
107 Length
108 ));
109 }
110
111 //
112 // Get all memory descriptors covered by the memory range
113 //
114 Status = SearchGcdMemorySpaces (
115 MemorySpaceMap,
116 NumberOfDescriptors,
117 BaseAddress,
118 Length,
119 &StartIndex,
120 &EndIndex
121 );
122 if (EFI_ERROR (Status)) {
123 return Status;
124 }
125
126 //
127 // Go through all related descriptors and set attributes accordingly
128 //
129 for (Index = StartIndex; Index <= EndIndex; Index++) {
130 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
131 continue;
132 }
133
134 //
135 // Calculate the start and end address of the overlapping range
136 //
137 if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {
138 RegionStart = BaseAddress;
139 } else {
140 RegionStart = MemorySpaceMap[Index].BaseAddress;
141 }
142
143 if ((BaseAddress + Length - 1) < (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length)) {
144 RegionLength = BaseAddress + Length - RegionStart;
145 } else {
146 RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;
147 }
148
149 //
150 // Set memory attributes according to MTRR attribute and the original attribute of descriptor
151 //
152 gDS->SetMemorySpaceAttributes (
153 RegionStart,
154 RegionLength,
155 (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)
156 );
157 }
158
159 return EFI_SUCCESS;
160}
161
184EFIAPI
187 IN EFI_PHYSICAL_ADDRESS BaseAddress,
188 IN UINT64 Length,
189 IN UINT64 EfiAttributes
190 )
191{
192 EFI_STATUS Status;
193 UINTN ArmAttributes;
194 UINTN RegionBaseAddress;
195 UINTN RegionLength;
196 UINTN RegionArmAttributes;
197
198 if (mIsFlushingGCD) {
199 return EFI_SUCCESS;
200 }
201
202 if ((BaseAddress & (SIZE_4KB - 1)) != 0) {
203 // Minimum granularity is SIZE_4KB (4KB on ARM)
204 DEBUG ((DEBUG_PAGE, "CpuSetMemoryAttributes(%lx, %lx, %lx): Minimum granularity is SIZE_4KB\n", BaseAddress, Length, EfiAttributes));
205 return EFI_UNSUPPORTED;
206 }
207
208 // Convert the 'Attribute' into ARM Attribute
209 ArmAttributes = EfiAttributeToArmAttribute (EfiAttributes);
210
211 // Get the region starting from 'BaseAddress' and its 'Attribute'
212 RegionBaseAddress = BaseAddress;
213 Status = GetMemoryRegion (&RegionBaseAddress, &RegionLength, &RegionArmAttributes);
214
215 // Data & Instruction Caches are flushed when we set new memory attributes.
216 // So, we only set the attributes if the new region is different.
217 if (EFI_ERROR (Status) || (RegionArmAttributes != ArmAttributes) ||
218 ((BaseAddress + Length) > (RegionBaseAddress + RegionLength)))
219 {
220 return ArmSetMemoryAttributes (BaseAddress, Length, EfiAttributes);
221 } else {
222 return EFI_SUCCESS;
223 }
224}
UINT64 UINTN
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
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:185
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
#define DEBUG(Expression)
Definition: DebugLib.h:417
EFI_DXE_SERVICES * gDS
@ EfiGcdMemoryTypeNonExistent
Definition: PiDxeCis.h:26
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:49
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:28
#define EFI_SUCCESS
Definition: UefiBaseType.h:111