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
,
120 ARM_SVC_ARGS ChangeMemoryPermissionsSvcArgs
;
122 ZeroMem (&ChangeMemoryPermissionsSvcArgs
, sizeof (ARM_SVC_ARGS
));
124 ChangeMemoryPermissionsSvcArgs
.Arg0
= ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES_AARCH64
;
125 ChangeMemoryPermissionsSvcArgs
.Arg1
= BaseAddress
;
126 ChangeMemoryPermissionsSvcArgs
.Arg2
= EFI_SIZE_TO_PAGES(Length
);
127 ChangeMemoryPermissionsSvcArgs
.Arg3
= Permissions
;
129 ArmCallSvc (&ChangeMemoryPermissionsSvcArgs
);
131 Status
= ChangeMemoryPermissionsSvcArgs
.Arg0
;
134 case ARM_SVC_SPM_RET_SUCCESS
:
135 Status
= EFI_SUCCESS
;
138 case ARM_SVC_SPM_RET_NOT_SUPPORTED
:
139 Status
= EFI_UNSUPPORTED
;
142 case ARM_SVC_SPM_RET_INVALID_PARAMS
:
143 Status
= EFI_INVALID_PARAMETER
;
146 case ARM_SVC_SPM_RET_DENIED
:
147 Status
= EFI_ACCESS_DENIED
;
150 case ARM_SVC_SPM_RET_NO_MEMORY
:
151 Status
= EFI_BAD_BUFFER_SIZE
;
155 Status
= EFI_ACCESS_DENIED
;
163 ArmSetMemoryRegionNoExec (
164 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
169 UINT32 MemoryAttributes
;
170 UINT32 CodePermission
;
172 Status
= GetMemoryPermissions (BaseAddress
, &MemoryAttributes
);
173 if (Status
!= EFI_INVALID_PARAMETER
) {
174 CodePermission
= SET_MEM_ATTR_CODE_PERM_XN
<< SET_MEM_ATTR_CODE_PERM_SHIFT
;
175 return RequestMemoryPermissionChange (
178 MemoryAttributes
| CodePermission
181 return EFI_INVALID_PARAMETER
;
185 ArmClearMemoryRegionNoExec (
186 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
191 UINT32 MemoryAttributes
;
192 UINT32 CodePermission
;
194 Status
= GetMemoryPermissions (BaseAddress
, &MemoryAttributes
);
195 if (Status
!= EFI_INVALID_PARAMETER
) {
196 CodePermission
= SET_MEM_ATTR_CODE_PERM_XN
<< SET_MEM_ATTR_CODE_PERM_SHIFT
;
197 return RequestMemoryPermissionChange (
200 MemoryAttributes
& ~CodePermission
203 return EFI_INVALID_PARAMETER
;
207 ArmSetMemoryRegionReadOnly (
208 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
213 UINT32 MemoryAttributes
;
214 UINT32 DataPermission
;
216 Status
= GetMemoryPermissions (BaseAddress
, &MemoryAttributes
);
217 if (Status
!= EFI_INVALID_PARAMETER
) {
218 DataPermission
= SET_MEM_ATTR_DATA_PERM_RO
<< SET_MEM_ATTR_DATA_PERM_SHIFT
;
219 return RequestMemoryPermissionChange (
222 MemoryAttributes
| DataPermission
225 return EFI_INVALID_PARAMETER
;
229 ArmClearMemoryRegionReadOnly (
230 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
235 UINT32 MemoryAttributes
;
236 UINT32 PermissionRequest
;
238 Status
= GetMemoryPermissions (BaseAddress
, &MemoryAttributes
);
239 if (Status
!= EFI_INVALID_PARAMETER
) {
240 PermissionRequest
= SET_MEM_ATTR_MAKE_PERM_REQUEST (SET_MEM_ATTR_DATA_PERM_RW
,
242 return RequestMemoryPermissionChange (
248 return EFI_INVALID_PARAMETER
;