]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/StandaloneMmMmuLib/AArch64/ArmMmuStandaloneMmLib.c
ArmPkg: Correct small typos
[mirror_edk2.git] / ArmPkg / Library / StandaloneMmMmuLib / AArch64 / ArmMmuStandaloneMmLib.c
CommitLineData
eed947be 1/** @file\r
31eaefd4
SM
2 File managing the MMU for ARMv8 architecture in S-EL0\r
3\r
4 Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7 @par Reference(s):\r
8 - [1] SPM based on the MM interface.\r
9 (https://trustedfirmware-a.readthedocs.io/en/latest/components/\r
10 secure-partition-manager-mm.html)\r
11 - [2] Arm Firmware Framework for Armv8-A, DEN0077A, version 1.0\r
12 (https://developer.arm.com/documentation/den0077/a)\r
eed947be
AG
13**/\r
14\r
15#include <Uefi.h>\r
16#include <IndustryStandard/ArmMmSvc.h>\r
67f3f8b6 17#include <IndustryStandard/ArmFfaSvc.h>\r
eed947be
AG
18\r
19#include <Library/ArmLib.h>\r
20#include <Library/ArmMmuLib.h>\r
21#include <Library/ArmSvcLib.h>\r
22#include <Library/BaseLib.h>\r
0931171f 23#include <Library/BaseMemoryLib.h>\r
eed947be 24#include <Library/DebugLib.h>\r
0e43e02b 25#include <Library/PcdLib.h>\r
eed947be 26\r
31eaefd4
SM
27/** Send memory permission request to target.\r
28\r
29 @param [in, out] SvcArgs Pointer to SVC arguments to send. On\r
30 return it contains the response parameters.\r
31 @param [out] RetVal Pointer to return the response value.\r
32\r
33 @retval EFI_SUCCESS Request successfull.\r
34 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
35 @retval EFI_NOT_READY Callee is busy or not in a state to handle\r
36 this request.\r
37 @retval EFI_UNSUPPORTED This function is not implemented by the\r
38 callee.\r
39 @retval EFI_ABORTED Message target ran into an unexpected error\r
40 and has aborted.\r
41 @retval EFI_ACCESS_DENIED Access denied.\r
42 @retval EFI_OUT_OF_RESOURCES Out of memory to perform operation.\r
43**/\r
eed947be
AG
44STATIC\r
45EFI_STATUS\r
31eaefd4
SM
46SendMemoryPermissionRequest (\r
47 IN OUT ARM_SVC_ARGS *SvcArgs,\r
48 OUT INT32 *RetVal\r
eed947be
AG
49 )\r
50{\r
31eaefd4
SM
51 if ((SvcArgs == NULL) || (RetVal == NULL)) {\r
52 return EFI_INVALID_PARAMETER;\r
0e43e02b 53 }\r
eed947be 54\r
31eaefd4
SM
55 ArmCallSvc (SvcArgs);\r
56 if (FeaturePcdGet (PcdFfaEnable)) {\r
57 // Get/Set memory attributes is an atomic call, with\r
0e43e02b
AG
58 // StandaloneMm at S-EL0 being the caller and the SPM\r
59 // core being the callee. Thus there won't be a\r
60 // FFA_INTERRUPT or FFA_SUCCESS response to the Direct\r
61 // Request sent above. This will have to be considered\r
62 // for other Direct Request calls which are not atomic\r
63 // We therefore check only for Direct Response by the\r
64 // callee.\r
31eaefd4
SM
65 if (SvcArgs->Arg0 == ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64) {\r
66 // A Direct Response means FF-A success\r
67 // Now check the payload for errors\r
68 // The callee sends back the return value\r
69 // in Arg3\r
70 *RetVal = SvcArgs->Arg3;\r
71 } else {\r
0e43e02b
AG
72 // If Arg0 is not a Direct Response, that means we\r
73 // have an FF-A error. We need to check Arg2 for the\r
74 // FF-A error code.\r
31eaefd4
SM
75 // See [2], Table 10.8: FFA_ERROR encoding.\r
76 *RetVal = SvcArgs->Arg2;\r
77 switch (*RetVal) {\r
78 case ARM_FFA_SPM_RET_INVALID_PARAMETERS:\r
79 return EFI_INVALID_PARAMETER;\r
0e43e02b 80\r
31eaefd4
SM
81 case ARM_FFA_SPM_RET_DENIED:\r
82 return EFI_ACCESS_DENIED;\r
0e43e02b 83\r
31eaefd4
SM
84 case ARM_FFA_SPM_RET_NOT_SUPPORTED:\r
85 return EFI_UNSUPPORTED;\r
0e43e02b 86\r
31eaefd4
SM
87 case ARM_FFA_SPM_RET_BUSY:\r
88 return EFI_NOT_READY;\r
0e43e02b 89\r
31eaefd4
SM
90 case ARM_FFA_SPM_RET_ABORTED:\r
91 return EFI_ABORTED;\r
0e43e02b 92\r
31eaefd4
SM
93 default:\r
94 // Undefined error code received.\r
95 ASSERT (0);\r
96 return EFI_INVALID_PARAMETER;\r
0e43e02b 97 }\r
0e43e02b
AG
98 }\r
99 } else {\r
31eaefd4 100 *RetVal = SvcArgs->Arg0;\r
0e43e02b
AG
101 }\r
102\r
31eaefd4 103 // Check error response from Callee.\r
fd9cc205 104 if ((*RetVal & BIT31) != 0) {\r
b8de64be 105 // Bit 31 set means there is an error returned\r
31eaefd4
SM
106 // See [1], Section 13.5.5.1 MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 and\r
107 // Section 13.5.5.2 MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64.\r
108 switch (*RetVal) {\r
109 case ARM_SVC_SPM_RET_NOT_SUPPORTED:\r
110 return EFI_UNSUPPORTED;\r
111\r
112 case ARM_SVC_SPM_RET_INVALID_PARAMS:\r
113 return EFI_INVALID_PARAMETER;\r
114\r
115 case ARM_SVC_SPM_RET_DENIED:\r
116 return EFI_ACCESS_DENIED;\r
117\r
118 case ARM_SVC_SPM_RET_NO_MEMORY:\r
119 return EFI_OUT_OF_RESOURCES;\r
0e43e02b 120\r
31eaefd4
SM
121 default:\r
122 // Undefined error code received.\r
123 ASSERT (0);\r
124 return EFI_INVALID_PARAMETER;\r
0e43e02b 125 }\r
eed947be
AG
126 }\r
127\r
eed947be
AG
128 return EFI_SUCCESS;\r
129}\r
130\r
31eaefd4
SM
131/** Request the permission attributes of a memory region from S-EL0.\r
132\r
133 @param [in] BaseAddress Base address for the memory region.\r
134 @param [out] MemoryAttributes Pointer to return the memory attributes.\r
135\r
136 @retval EFI_SUCCESS Request successfull.\r
137 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
138 @retval EFI_NOT_READY Callee is busy or not in a state to handle\r
139 this request.\r
140 @retval EFI_UNSUPPORTED This function is not implemented by the\r
141 callee.\r
142 @retval EFI_ABORTED Message target ran into an unexpected error\r
143 and has aborted.\r
144 @retval EFI_ACCESS_DENIED Access denied.\r
145 @retval EFI_OUT_OF_RESOURCES Out of memory to perform operation.\r
146**/\r
eed947be
AG
147STATIC\r
148EFI_STATUS\r
31eaefd4 149GetMemoryPermissions (\r
eed947be 150 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
31eaefd4 151 OUT UINT32 *MemoryAttributes\r
eed947be
AG
152 )\r
153{\r
31eaefd4 154 EFI_STATUS Status;\r
9da5ee11 155 INT32 Ret;\r
31eaefd4 156 ARM_SVC_ARGS SvcArgs;\r
eed947be 157\r
31eaefd4
SM
158 if (MemoryAttributes == NULL) {\r
159 return EFI_INVALID_PARAMETER;\r
9da5ee11 160 }\r
eed947be 161\r
31eaefd4
SM
162 // Prepare the message parameters.\r
163 // See [1], Section 13.5.5.1 MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64.\r
164 ZeroMem (&SvcArgs, sizeof (ARM_SVC_ARGS));\r
165 if (FeaturePcdGet (PcdFfaEnable)) {\r
166 // See [2], Section 10.2 FFA_MSG_SEND_DIRECT_REQ.\r
167 SvcArgs.Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ_AARCH64;\r
168 SvcArgs.Arg1 = ARM_FFA_DESTINATION_ENDPOINT_ID;\r
169 SvcArgs.Arg2 = 0;\r
170 SvcArgs.Arg3 = ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES_AARCH64;\r
171 SvcArgs.Arg4 = BaseAddress;\r
9da5ee11 172 } else {\r
31eaefd4
SM
173 SvcArgs.Arg0 = ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES_AARCH64;\r
174 SvcArgs.Arg1 = BaseAddress;\r
175 SvcArgs.Arg2 = 0;\r
176 SvcArgs.Arg3 = 0;\r
9da5ee11 177 }\r
eed947be 178\r
31eaefd4
SM
179 Status = SendMemoryPermissionRequest (&SvcArgs, &Ret);\r
180 if (EFI_ERROR (Status)) {\r
181 *MemoryAttributes = 0;\r
182 return Status;\r
183 }\r
eed947be 184\r
31eaefd4
SM
185 *MemoryAttributes = Ret;\r
186 return Status;\r
187}\r
eed947be 188\r
31eaefd4
SM
189/** Set the permission attributes of a memory region from S-EL0.\r
190\r
191 @param [in] BaseAddress Base address for the memory region.\r
192 @param [in] Length Length of the memory region.\r
193 @param [in] Permissions Memory access controls attributes.\r
194\r
195 @retval EFI_SUCCESS Request successfull.\r
196 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
197 @retval EFI_NOT_READY Callee is busy or not in a state to handle\r
198 this request.\r
199 @retval EFI_UNSUPPORTED This function is not implemented by the\r
200 callee.\r
201 @retval EFI_ABORTED Message target ran into an unexpected error\r
202 and has aborted.\r
203 @retval EFI_ACCESS_DENIED Access denied.\r
204 @retval EFI_OUT_OF_RESOURCES Out of memory to perform operation.\r
205**/\r
206STATIC\r
207EFI_STATUS\r
208RequestMemoryPermissionChange (\r
209 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
210 IN UINT64 Length,\r
211 IN UINT32 Permissions\r
212 )\r
213{\r
214 INT32 Ret;\r
215 ARM_SVC_ARGS SvcArgs;\r
216\r
217 // Prepare the message parameters.\r
218 // See [1], Section 13.5.5.2 MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64.\r
219 ZeroMem (&SvcArgs, sizeof (ARM_SVC_ARGS));\r
220 if (FeaturePcdGet (PcdFfaEnable)) {\r
221 // See [2], Section 10.2 FFA_MSG_SEND_DIRECT_REQ.\r
222 SvcArgs.Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ_AARCH64;\r
223 SvcArgs.Arg1 = ARM_FFA_DESTINATION_ENDPOINT_ID;\r
224 SvcArgs.Arg2 = 0;\r
225 SvcArgs.Arg3 = ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES_AARCH64;\r
226 SvcArgs.Arg4 = BaseAddress;\r
227 SvcArgs.Arg5 = EFI_SIZE_TO_PAGES (Length);\r
228 SvcArgs.Arg6 = Permissions;\r
229 } else {\r
230 SvcArgs.Arg0 = ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES_AARCH64;\r
231 SvcArgs.Arg1 = BaseAddress;\r
232 SvcArgs.Arg2 = EFI_SIZE_TO_PAGES (Length);\r
233 SvcArgs.Arg3 = Permissions;\r
eed947be
AG
234 }\r
235\r
31eaefd4 236 return SendMemoryPermissionRequest (&SvcArgs, &Ret);\r
eed947be
AG
237}\r
238\r
239EFI_STATUS\r
240ArmSetMemoryRegionNoExec (\r
241 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
242 IN UINT64 Length\r
243 )\r
244{\r
245 EFI_STATUS Status;\r
246 UINT32 MemoryAttributes;\r
247 UINT32 CodePermission;\r
248\r
249 Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes);\r
31eaefd4 250 if (!EFI_ERROR (Status)) {\r
eed947be
AG
251 CodePermission = SET_MEM_ATTR_CODE_PERM_XN << SET_MEM_ATTR_CODE_PERM_SHIFT;\r
252 return RequestMemoryPermissionChange (\r
253 BaseAddress,\r
254 Length,\r
255 MemoryAttributes | CodePermission\r
256 );\r
257 }\r
31eaefd4 258 return Status;\r
eed947be
AG
259}\r
260\r
261EFI_STATUS\r
262ArmClearMemoryRegionNoExec (\r
263 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
264 IN UINT64 Length\r
265 )\r
266{\r
267 EFI_STATUS Status;\r
268 UINT32 MemoryAttributes;\r
269 UINT32 CodePermission;\r
270\r
271 Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes);\r
31eaefd4 272 if (!EFI_ERROR (Status)) {\r
eed947be
AG
273 CodePermission = SET_MEM_ATTR_CODE_PERM_XN << SET_MEM_ATTR_CODE_PERM_SHIFT;\r
274 return RequestMemoryPermissionChange (\r
275 BaseAddress,\r
276 Length,\r
277 MemoryAttributes & ~CodePermission\r
278 );\r
279 }\r
31eaefd4 280 return Status;\r
eed947be
AG
281}\r
282\r
283EFI_STATUS\r
284ArmSetMemoryRegionReadOnly (\r
285 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
286 IN UINT64 Length\r
287 )\r
288{\r
289 EFI_STATUS Status;\r
290 UINT32 MemoryAttributes;\r
291 UINT32 DataPermission;\r
292\r
293 Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes);\r
31eaefd4 294 if (!EFI_ERROR (Status)) {\r
eed947be
AG
295 DataPermission = SET_MEM_ATTR_DATA_PERM_RO << SET_MEM_ATTR_DATA_PERM_SHIFT;\r
296 return RequestMemoryPermissionChange (\r
297 BaseAddress,\r
298 Length,\r
299 MemoryAttributes | DataPermission\r
300 );\r
301 }\r
31eaefd4 302 return Status;\r
eed947be
AG
303}\r
304\r
305EFI_STATUS\r
306ArmClearMemoryRegionReadOnly (\r
307 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
308 IN UINT64 Length\r
309 )\r
310{\r
311 EFI_STATUS Status;\r
312 UINT32 MemoryAttributes;\r
313 UINT32 PermissionRequest;\r
314\r
315 Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes);\r
31eaefd4 316 if (!EFI_ERROR (Status)) {\r
eed947be
AG
317 PermissionRequest = SET_MEM_ATTR_MAKE_PERM_REQUEST (SET_MEM_ATTR_DATA_PERM_RW,\r
318 MemoryAttributes);\r
319 return RequestMemoryPermissionChange (\r
320 BaseAddress,\r
321 Length,\r
322 PermissionRequest\r
323 );\r
324 }\r
31eaefd4 325 return Status;\r
eed947be 326}\r