]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/StandaloneMmMmuLib/AArch64/ArmMmuStandaloneMmLib.c
ArmPkg: Allow FF-A calls to set memory region's attributes
[mirror_edk2.git] / ArmPkg / Library / StandaloneMmMmuLib / AArch64 / ArmMmuStandaloneMmLib.c
CommitLineData
eed947be
AG
1/** @file\r
2* File managing the MMU for ARMv8 architecture in S-EL0\r
3*\r
0931171f 4* Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>\r
eed947be 5*\r
4059386c 6* SPDX-License-Identifier: BSD-2-Clause-Patent\r
eed947be
AG
7*\r
8**/\r
9\r
10#include <Uefi.h>\r
11#include <IndustryStandard/ArmMmSvc.h>\r
67f3f8b6 12#include <IndustryStandard/ArmFfaSvc.h>\r
eed947be
AG
13\r
14#include <Library/ArmLib.h>\r
15#include <Library/ArmMmuLib.h>\r
16#include <Library/ArmSvcLib.h>\r
17#include <Library/BaseLib.h>\r
0931171f 18#include <Library/BaseMemoryLib.h>\r
eed947be 19#include <Library/DebugLib.h>\r
0e43e02b 20#include <Library/PcdLib.h>\r
eed947be
AG
21\r
22STATIC\r
23EFI_STATUS\r
24GetMemoryPermissions (\r
25 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
26 OUT UINT32 *MemoryAttributes\r
27 )\r
28{\r
0e43e02b 29 INT32 Ret;\r
0931171f 30 ARM_SVC_ARGS GetMemoryPermissionsSvcArgs;\r
0e43e02b 31 BOOLEAN FfaEnabled;\r
0931171f
PG
32\r
33 ZeroMem (&GetMemoryPermissionsSvcArgs, sizeof (ARM_SVC_ARGS));\r
eed947be 34\r
0e43e02b
AG
35 FfaEnabled = FeaturePcdGet (PcdFfaEnable);\r
36 if (FfaEnabled) {\r
37 GetMemoryPermissionsSvcArgs.Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ_AARCH64;\r
38 GetMemoryPermissionsSvcArgs.Arg1 = ARM_FFA_DESTINATION_ENDPOINT_ID;\r
39 GetMemoryPermissionsSvcArgs.Arg2 = 0;\r
40 GetMemoryPermissionsSvcArgs.Arg3 = ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES_AARCH64;\r
41 GetMemoryPermissionsSvcArgs.Arg4 = BaseAddress;\r
42 } else {\r
43 GetMemoryPermissionsSvcArgs.Arg0 = ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES_AARCH64;\r
44 GetMemoryPermissionsSvcArgs.Arg1 = BaseAddress;\r
45 GetMemoryPermissionsSvcArgs.Arg2 = 0;\r
46 GetMemoryPermissionsSvcArgs.Arg3 = 0;\r
47 }\r
eed947be 48\r
0e43e02b 49 *MemoryAttributes = 0;\r
eed947be 50 ArmCallSvc (&GetMemoryPermissionsSvcArgs);\r
0e43e02b
AG
51 if (FfaEnabled) {\r
52 // Getting memory attributes is an atomic call, with\r
53 // StandaloneMm at S-EL0 being the caller and the SPM\r
54 // core being the callee. Thus there won't be a\r
55 // FFA_INTERRUPT or FFA_SUCCESS response to the Direct\r
56 // Request sent above. This will have to be considered\r
57 // for other Direct Request calls which are not atomic\r
58 // We therefore check only for Direct Response by the\r
59 // callee.\r
60 if (GetMemoryPermissionsSvcArgs.Arg0 !=\r
61 ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64) {\r
62 // If Arg0 is not a Direct Response, that means we\r
63 // have an FF-A error. We need to check Arg2 for the\r
64 // FF-A error code.\r
65 Ret = GetMemoryPermissionsSvcArgs.Arg2;\r
66 switch (Ret) {\r
67 case ARM_FFA_SPM_RET_INVALID_PARAMETERS:\r
68\r
69 return EFI_INVALID_PARAMETER;\r
70\r
71 case ARM_FFA_SPM_RET_DENIED:\r
72 return EFI_NOT_READY;\r
73\r
74 case ARM_FFA_SPM_RET_NOT_SUPPORTED:\r
75 return EFI_UNSUPPORTED;\r
76\r
77 case ARM_FFA_SPM_RET_BUSY:\r
78 return EFI_NOT_READY;\r
79\r
80 case ARM_FFA_SPM_RET_ABORTED:\r
81 return EFI_ABORTED;\r
82 }\r
83 } else if (GetMemoryPermissionsSvcArgs.Arg0 ==\r
84 ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64) {\r
85 // A Direct Response means FF-A success\r
86 // Now check the payload for errors\r
87 // The callee sends back the return value\r
88 // in Arg3\r
89 Ret = GetMemoryPermissionsSvcArgs.Arg3;\r
90 }\r
91 } else {\r
92 Ret = GetMemoryPermissionsSvcArgs.Arg0;\r
93 }\r
94\r
95 if (Ret & BIT31) {\r
96 // Bit 31 set means there is an error retured\r
97 switch (Ret) {\r
98 case ARM_SVC_SPM_RET_INVALID_PARAMS:\r
99 return EFI_INVALID_PARAMETER;\r
100\r
101 case ARM_SVC_SPM_RET_NOT_SUPPORTED:\r
102 return EFI_UNSUPPORTED;\r
103 }\r
104 } else {\r
105 *MemoryAttributes = Ret;\r
eed947be
AG
106 }\r
107\r
eed947be
AG
108 return EFI_SUCCESS;\r
109}\r
110\r
111STATIC\r
112EFI_STATUS\r
113RequestMemoryPermissionChange (\r
114 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
115 IN UINT64 Length,\r
116 IN UINTN Permissions\r
117 )\r
118{\r
9da5ee11
AG
119 INT32 Ret;\r
120 BOOLEAN FfaEnabled;\r
0931171f
PG
121 ARM_SVC_ARGS ChangeMemoryPermissionsSvcArgs;\r
122\r
123 ZeroMem (&ChangeMemoryPermissionsSvcArgs, sizeof (ARM_SVC_ARGS));\r
eed947be 124\r
9da5ee11
AG
125 FfaEnabled = FeaturePcdGet (PcdFfaEnable);\r
126\r
127 if (FfaEnabled) {\r
128 ChangeMemoryPermissionsSvcArgs.Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ_AARCH64;\r
129 ChangeMemoryPermissionsSvcArgs.Arg1 = ARM_FFA_DESTINATION_ENDPOINT_ID;\r
130 ChangeMemoryPermissionsSvcArgs.Arg2 = 0;\r
131 ChangeMemoryPermissionsSvcArgs.Arg3 = ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES_AARCH64;\r
132 ChangeMemoryPermissionsSvcArgs.Arg4 = BaseAddress;\r
133 ChangeMemoryPermissionsSvcArgs.Arg5 = EFI_SIZE_TO_PAGES (Length);\r
134 ChangeMemoryPermissionsSvcArgs.Arg6 = Permissions;\r
135 } else {\r
136 ChangeMemoryPermissionsSvcArgs.Arg0 = ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES_AARCH64;\r
137 ChangeMemoryPermissionsSvcArgs.Arg1 = BaseAddress;\r
138 ChangeMemoryPermissionsSvcArgs.Arg2 = EFI_SIZE_TO_PAGES (Length);\r
139 ChangeMemoryPermissionsSvcArgs.Arg3 = Permissions;\r
140 }\r
eed947be
AG
141\r
142 ArmCallSvc (&ChangeMemoryPermissionsSvcArgs);\r
143\r
9da5ee11
AG
144 if (FfaEnabled) {\r
145 // Setting memory attributes is an atomic call, with\r
146 // StandaloneMm at S-EL0 being the caller and the SPM\r
147 // core being the callee. Thus there won't be a\r
148 // FFA_INTERRUPT or FFA_SUCCESS response to the Direct\r
149 // Request sent above. This will have to be considered\r
150 // for other Direct Request calls which are not atomic\r
151 // We therefore check only for Direct Response by the\r
152 // callee.\r
153 if (ChangeMemoryPermissionsSvcArgs.Arg0 !=\r
154 ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64) {\r
155 // If Arg0 is not a Direct Response, that means we\r
156 // have an FF-A error. We need to check Arg2 for the\r
157 // FF-A error code.\r
158 Ret = ChangeMemoryPermissionsSvcArgs.Arg2;\r
159 switch (Ret) {\r
160 case ARM_FFA_SPM_RET_INVALID_PARAMETERS:\r
161 return EFI_INVALID_PARAMETER;\r
eed947be 162\r
9da5ee11
AG
163 case ARM_FFA_SPM_RET_DENIED:\r
164 return EFI_NOT_READY;\r
165\r
166 case ARM_FFA_SPM_RET_NOT_SUPPORTED:\r
167 return EFI_UNSUPPORTED;\r
168\r
169 case ARM_FFA_SPM_RET_BUSY:\r
170 return EFI_NOT_READY;\r
171\r
172 case ARM_FFA_SPM_RET_ABORTED:\r
173 return EFI_ABORTED;\r
174 }\r
175 } else if (ChangeMemoryPermissionsSvcArgs.Arg0 ==\r
176 ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64) {\r
177 // A Direct Response means FF-A success\r
178 // Now check the payload for errors\r
179 // The callee sends back the return value\r
180 // in Arg3\r
181 Ret = ChangeMemoryPermissionsSvcArgs.Arg3;\r
182 }\r
183 } else {\r
184 Ret = ChangeMemoryPermissionsSvcArgs.Arg0;\r
185 }\r
eed947be 186\r
9da5ee11 187 switch (Ret) {\r
eed947be 188 case ARM_SVC_SPM_RET_NOT_SUPPORTED:\r
9da5ee11 189 return EFI_UNSUPPORTED;\r
eed947be
AG
190\r
191 case ARM_SVC_SPM_RET_INVALID_PARAMS:\r
9da5ee11 192 return EFI_INVALID_PARAMETER;\r
eed947be
AG
193\r
194 case ARM_SVC_SPM_RET_DENIED:\r
9da5ee11 195 return EFI_ACCESS_DENIED;\r
eed947be
AG
196\r
197 case ARM_SVC_SPM_RET_NO_MEMORY:\r
9da5ee11 198 return EFI_BAD_BUFFER_SIZE;\r
eed947be
AG
199 }\r
200\r
9da5ee11 201 return EFI_SUCCESS;\r
eed947be
AG
202}\r
203\r
204EFI_STATUS\r
205ArmSetMemoryRegionNoExec (\r
206 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
207 IN UINT64 Length\r
208 )\r
209{\r
210 EFI_STATUS Status;\r
211 UINT32 MemoryAttributes;\r
212 UINT32 CodePermission;\r
213\r
214 Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes);\r
215 if (Status != EFI_INVALID_PARAMETER) {\r
216 CodePermission = SET_MEM_ATTR_CODE_PERM_XN << SET_MEM_ATTR_CODE_PERM_SHIFT;\r
217 return RequestMemoryPermissionChange (\r
218 BaseAddress,\r
219 Length,\r
220 MemoryAttributes | CodePermission\r
221 );\r
222 }\r
223 return EFI_INVALID_PARAMETER;\r
224}\r
225\r
226EFI_STATUS\r
227ArmClearMemoryRegionNoExec (\r
228 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
229 IN UINT64 Length\r
230 )\r
231{\r
232 EFI_STATUS Status;\r
233 UINT32 MemoryAttributes;\r
234 UINT32 CodePermission;\r
235\r
236 Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes);\r
237 if (Status != EFI_INVALID_PARAMETER) {\r
238 CodePermission = SET_MEM_ATTR_CODE_PERM_XN << SET_MEM_ATTR_CODE_PERM_SHIFT;\r
239 return RequestMemoryPermissionChange (\r
240 BaseAddress,\r
241 Length,\r
242 MemoryAttributes & ~CodePermission\r
243 );\r
244 }\r
245 return EFI_INVALID_PARAMETER;\r
246}\r
247\r
248EFI_STATUS\r
249ArmSetMemoryRegionReadOnly (\r
250 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
251 IN UINT64 Length\r
252 )\r
253{\r
254 EFI_STATUS Status;\r
255 UINT32 MemoryAttributes;\r
256 UINT32 DataPermission;\r
257\r
258 Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes);\r
259 if (Status != EFI_INVALID_PARAMETER) {\r
260 DataPermission = SET_MEM_ATTR_DATA_PERM_RO << SET_MEM_ATTR_DATA_PERM_SHIFT;\r
261 return RequestMemoryPermissionChange (\r
262 BaseAddress,\r
263 Length,\r
264 MemoryAttributes | DataPermission\r
265 );\r
266 }\r
267 return EFI_INVALID_PARAMETER;\r
268}\r
269\r
270EFI_STATUS\r
271ArmClearMemoryRegionReadOnly (\r
272 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
273 IN UINT64 Length\r
274 )\r
275{\r
276 EFI_STATUS Status;\r
277 UINT32 MemoryAttributes;\r
278 UINT32 PermissionRequest;\r
279\r
280 Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes);\r
281 if (Status != EFI_INVALID_PARAMETER) {\r
282 PermissionRequest = SET_MEM_ATTR_MAKE_PERM_REQUEST (SET_MEM_ATTR_DATA_PERM_RW,\r
283 MemoryAttributes);\r
284 return RequestMemoryPermissionChange (\r
285 BaseAddress,\r
286 Length,\r
287 PermissionRequest\r
288 );\r
289 }\r
290 return EFI_INVALID_PARAMETER;\r
291}\r