2 * File managing the MMU for ARMv8 architecture in S-EL0
4 * Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
6 * SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <IndustryStandard/ArmMmSvc.h>
12 #include <IndustryStandard/ArmFfaSvc.h>
14 #include <Library/ArmLib.h>
15 #include <Library/ArmMmuLib.h>
16 #include <Library/ArmSvcLib.h>
17 #include <Library/BaseLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/PcdLib.h>
24 GetMemoryPermissions (
25 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
26 OUT UINT32
*MemoryAttributes
30 ARM_SVC_ARGS GetMemoryPermissionsSvcArgs
;
33 ZeroMem (&GetMemoryPermissionsSvcArgs
, sizeof (ARM_SVC_ARGS
));
35 FfaEnabled
= FeaturePcdGet (PcdFfaEnable
);
37 GetMemoryPermissionsSvcArgs
.Arg0
= ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ_AARCH64
;
38 GetMemoryPermissionsSvcArgs
.Arg1
= ARM_FFA_DESTINATION_ENDPOINT_ID
;
39 GetMemoryPermissionsSvcArgs
.Arg2
= 0;
40 GetMemoryPermissionsSvcArgs
.Arg3
= ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES_AARCH64
;
41 GetMemoryPermissionsSvcArgs
.Arg4
= BaseAddress
;
43 GetMemoryPermissionsSvcArgs
.Arg0
= ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES_AARCH64
;
44 GetMemoryPermissionsSvcArgs
.Arg1
= BaseAddress
;
45 GetMemoryPermissionsSvcArgs
.Arg2
= 0;
46 GetMemoryPermissionsSvcArgs
.Arg3
= 0;
49 *MemoryAttributes
= 0;
50 ArmCallSvc (&GetMemoryPermissionsSvcArgs
);
52 // Getting memory attributes is an atomic call, with
53 // StandaloneMm at S-EL0 being the caller and the SPM
54 // core being the callee. Thus there won't be a
55 // FFA_INTERRUPT or FFA_SUCCESS response to the Direct
56 // Request sent above. This will have to be considered
57 // for other Direct Request calls which are not atomic
58 // We therefore check only for Direct Response by the
60 if (GetMemoryPermissionsSvcArgs
.Arg0
!=
61 ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64
) {
62 // If Arg0 is not a Direct Response, that means we
63 // have an FF-A error. We need to check Arg2 for the
65 Ret
= GetMemoryPermissionsSvcArgs
.Arg2
;
67 case ARM_FFA_SPM_RET_INVALID_PARAMETERS
:
69 return EFI_INVALID_PARAMETER
;
71 case ARM_FFA_SPM_RET_DENIED
:
74 case ARM_FFA_SPM_RET_NOT_SUPPORTED
:
75 return EFI_UNSUPPORTED
;
77 case ARM_FFA_SPM_RET_BUSY
:
80 case ARM_FFA_SPM_RET_ABORTED
:
83 } else if (GetMemoryPermissionsSvcArgs
.Arg0
==
84 ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64
) {
85 // A Direct Response means FF-A success
86 // Now check the payload for errors
87 // The callee sends back the return value
89 Ret
= GetMemoryPermissionsSvcArgs
.Arg3
;
92 Ret
= GetMemoryPermissionsSvcArgs
.Arg0
;
96 // Bit 31 set means there is an error retured
98 case ARM_SVC_SPM_RET_INVALID_PARAMS
:
99 return EFI_INVALID_PARAMETER
;
101 case ARM_SVC_SPM_RET_NOT_SUPPORTED
:
102 return EFI_UNSUPPORTED
;
105 *MemoryAttributes
= Ret
;
113 RequestMemoryPermissionChange (
114 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
121 ARM_SVC_ARGS ChangeMemoryPermissionsSvcArgs
;
123 ZeroMem (&ChangeMemoryPermissionsSvcArgs
, sizeof (ARM_SVC_ARGS
));
125 FfaEnabled
= FeaturePcdGet (PcdFfaEnable
);
128 ChangeMemoryPermissionsSvcArgs
.Arg0
= ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ_AARCH64
;
129 ChangeMemoryPermissionsSvcArgs
.Arg1
= ARM_FFA_DESTINATION_ENDPOINT_ID
;
130 ChangeMemoryPermissionsSvcArgs
.Arg2
= 0;
131 ChangeMemoryPermissionsSvcArgs
.Arg3
= ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES_AARCH64
;
132 ChangeMemoryPermissionsSvcArgs
.Arg4
= BaseAddress
;
133 ChangeMemoryPermissionsSvcArgs
.Arg5
= EFI_SIZE_TO_PAGES (Length
);
134 ChangeMemoryPermissionsSvcArgs
.Arg6
= Permissions
;
136 ChangeMemoryPermissionsSvcArgs
.Arg0
= ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES_AARCH64
;
137 ChangeMemoryPermissionsSvcArgs
.Arg1
= BaseAddress
;
138 ChangeMemoryPermissionsSvcArgs
.Arg2
= EFI_SIZE_TO_PAGES (Length
);
139 ChangeMemoryPermissionsSvcArgs
.Arg3
= Permissions
;
142 ArmCallSvc (&ChangeMemoryPermissionsSvcArgs
);
145 // Setting memory attributes is an atomic call, with
146 // StandaloneMm at S-EL0 being the caller and the SPM
147 // core being the callee. Thus there won't be a
148 // FFA_INTERRUPT or FFA_SUCCESS response to the Direct
149 // Request sent above. This will have to be considered
150 // for other Direct Request calls which are not atomic
151 // We therefore check only for Direct Response by the
153 if (ChangeMemoryPermissionsSvcArgs
.Arg0
!=
154 ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64
) {
155 // If Arg0 is not a Direct Response, that means we
156 // have an FF-A error. We need to check Arg2 for the
158 Ret
= ChangeMemoryPermissionsSvcArgs
.Arg2
;
160 case ARM_FFA_SPM_RET_INVALID_PARAMETERS
:
161 return EFI_INVALID_PARAMETER
;
163 case ARM_FFA_SPM_RET_DENIED
:
164 return EFI_NOT_READY
;
166 case ARM_FFA_SPM_RET_NOT_SUPPORTED
:
167 return EFI_UNSUPPORTED
;
169 case ARM_FFA_SPM_RET_BUSY
:
170 return EFI_NOT_READY
;
172 case ARM_FFA_SPM_RET_ABORTED
:
175 } else if (ChangeMemoryPermissionsSvcArgs
.Arg0
==
176 ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64
) {
177 // A Direct Response means FF-A success
178 // Now check the payload for errors
179 // The callee sends back the return value
181 Ret
= ChangeMemoryPermissionsSvcArgs
.Arg3
;
184 Ret
= ChangeMemoryPermissionsSvcArgs
.Arg0
;
188 case ARM_SVC_SPM_RET_NOT_SUPPORTED
:
189 return EFI_UNSUPPORTED
;
191 case ARM_SVC_SPM_RET_INVALID_PARAMS
:
192 return EFI_INVALID_PARAMETER
;
194 case ARM_SVC_SPM_RET_DENIED
:
195 return EFI_ACCESS_DENIED
;
197 case ARM_SVC_SPM_RET_NO_MEMORY
:
198 return EFI_BAD_BUFFER_SIZE
;
205 ArmSetMemoryRegionNoExec (
206 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
211 UINT32 MemoryAttributes
;
212 UINT32 CodePermission
;
214 Status
= GetMemoryPermissions (BaseAddress
, &MemoryAttributes
);
215 if (Status
!= EFI_INVALID_PARAMETER
) {
216 CodePermission
= SET_MEM_ATTR_CODE_PERM_XN
<< SET_MEM_ATTR_CODE_PERM_SHIFT
;
217 return RequestMemoryPermissionChange (
220 MemoryAttributes
| CodePermission
223 return EFI_INVALID_PARAMETER
;
227 ArmClearMemoryRegionNoExec (
228 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
233 UINT32 MemoryAttributes
;
234 UINT32 CodePermission
;
236 Status
= GetMemoryPermissions (BaseAddress
, &MemoryAttributes
);
237 if (Status
!= EFI_INVALID_PARAMETER
) {
238 CodePermission
= SET_MEM_ATTR_CODE_PERM_XN
<< SET_MEM_ATTR_CODE_PERM_SHIFT
;
239 return RequestMemoryPermissionChange (
242 MemoryAttributes
& ~CodePermission
245 return EFI_INVALID_PARAMETER
;
249 ArmSetMemoryRegionReadOnly (
250 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
255 UINT32 MemoryAttributes
;
256 UINT32 DataPermission
;
258 Status
= GetMemoryPermissions (BaseAddress
, &MemoryAttributes
);
259 if (Status
!= EFI_INVALID_PARAMETER
) {
260 DataPermission
= SET_MEM_ATTR_DATA_PERM_RO
<< SET_MEM_ATTR_DATA_PERM_SHIFT
;
261 return RequestMemoryPermissionChange (
264 MemoryAttributes
| DataPermission
267 return EFI_INVALID_PARAMETER
;
271 ArmClearMemoryRegionReadOnly (
272 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
277 UINT32 MemoryAttributes
;
278 UINT32 PermissionRequest
;
280 Status
= GetMemoryPermissions (BaseAddress
, &MemoryAttributes
);
281 if (Status
!= EFI_INVALID_PARAMETER
) {
282 PermissionRequest
= SET_MEM_ATTR_MAKE_PERM_REQUEST (SET_MEM_ATTR_DATA_PERM_RW
,
284 return RequestMemoryPermissionChange (
290 return EFI_INVALID_PARAMETER
;