]>
Commit | Line | Data |
---|---|---|
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 |
22 | STATIC\r | |
23 | EFI_STATUS\r | |
24 | GetMemoryPermissions (\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 | |
111 | STATIC\r | |
112 | EFI_STATUS\r | |
113 | RequestMemoryPermissionChange (\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 | |
204 | EFI_STATUS\r | |
205 | ArmSetMemoryRegionNoExec (\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 | |
226 | EFI_STATUS\r | |
227 | ArmClearMemoryRegionNoExec (\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 | |
248 | EFI_STATUS\r | |
249 | ArmSetMemoryRegionReadOnly (\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 | |
270 | EFI_STATUS\r | |
271 | ArmClearMemoryRegionReadOnly (\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 |