]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Library/StandaloneMmMmuLib/AArch64/ArmMmuStandaloneMmLib.c
14fe781630f597b83f675ba09a3852b7e4c95efd
[mirror_edk2.git] / ArmPkg / Library / StandaloneMmMmuLib / AArch64 / ArmMmuStandaloneMmLib.c
1 /** @file
2 * File managing the MMU for ARMv8 architecture in S-EL0
3 *
4 * Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
5 *
6 * SPDX-License-Identifier: BSD-2-Clause-Patent
7 *
8 **/
9
10 #include <Uefi.h>
11 #include <IndustryStandard/ArmMmSvc.h>
12 #include <IndustryStandard/ArmFfaSvc.h>
13
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>
21
22 STATIC
23 EFI_STATUS
24 GetMemoryPermissions (
25 IN EFI_PHYSICAL_ADDRESS BaseAddress,
26 OUT UINT32 *MemoryAttributes
27 )
28 {
29 INT32 Ret;
30 ARM_SVC_ARGS GetMemoryPermissionsSvcArgs;
31 BOOLEAN FfaEnabled;
32
33 ZeroMem (&GetMemoryPermissionsSvcArgs, sizeof (ARM_SVC_ARGS));
34
35 FfaEnabled = FeaturePcdGet (PcdFfaEnable);
36 if (FfaEnabled) {
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;
42 } else {
43 GetMemoryPermissionsSvcArgs.Arg0 = ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES_AARCH64;
44 GetMemoryPermissionsSvcArgs.Arg1 = BaseAddress;
45 GetMemoryPermissionsSvcArgs.Arg2 = 0;
46 GetMemoryPermissionsSvcArgs.Arg3 = 0;
47 }
48
49 *MemoryAttributes = 0;
50 ArmCallSvc (&GetMemoryPermissionsSvcArgs);
51 if (FfaEnabled) {
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
59 // callee.
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
64 // FF-A error code.
65 Ret = GetMemoryPermissionsSvcArgs.Arg2;
66 switch (Ret) {
67 case ARM_FFA_SPM_RET_INVALID_PARAMETERS:
68
69 return EFI_INVALID_PARAMETER;
70
71 case ARM_FFA_SPM_RET_DENIED:
72 return EFI_NOT_READY;
73
74 case ARM_FFA_SPM_RET_NOT_SUPPORTED:
75 return EFI_UNSUPPORTED;
76
77 case ARM_FFA_SPM_RET_BUSY:
78 return EFI_NOT_READY;
79
80 case ARM_FFA_SPM_RET_ABORTED:
81 return EFI_ABORTED;
82 }
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
88 // in Arg3
89 Ret = GetMemoryPermissionsSvcArgs.Arg3;
90 }
91 } else {
92 Ret = GetMemoryPermissionsSvcArgs.Arg0;
93 }
94
95 if (Ret & BIT31) {
96 // Bit 31 set means there is an error retured
97 switch (Ret) {
98 case ARM_SVC_SPM_RET_INVALID_PARAMS:
99 return EFI_INVALID_PARAMETER;
100
101 case ARM_SVC_SPM_RET_NOT_SUPPORTED:
102 return EFI_UNSUPPORTED;
103 }
104 } else {
105 *MemoryAttributes = Ret;
106 }
107
108 return EFI_SUCCESS;
109 }
110
111 STATIC
112 EFI_STATUS
113 RequestMemoryPermissionChange (
114 IN EFI_PHYSICAL_ADDRESS BaseAddress,
115 IN UINT64 Length,
116 IN UINTN Permissions
117 )
118 {
119 EFI_STATUS Status;
120 ARM_SVC_ARGS ChangeMemoryPermissionsSvcArgs;
121
122 ZeroMem (&ChangeMemoryPermissionsSvcArgs, sizeof (ARM_SVC_ARGS));
123
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;
128
129 ArmCallSvc (&ChangeMemoryPermissionsSvcArgs);
130
131 Status = ChangeMemoryPermissionsSvcArgs.Arg0;
132
133 switch (Status) {
134 case ARM_SVC_SPM_RET_SUCCESS:
135 Status = EFI_SUCCESS;
136 break;
137
138 case ARM_SVC_SPM_RET_NOT_SUPPORTED:
139 Status = EFI_UNSUPPORTED;
140 break;
141
142 case ARM_SVC_SPM_RET_INVALID_PARAMS:
143 Status = EFI_INVALID_PARAMETER;
144 break;
145
146 case ARM_SVC_SPM_RET_DENIED:
147 Status = EFI_ACCESS_DENIED;
148 break;
149
150 case ARM_SVC_SPM_RET_NO_MEMORY:
151 Status = EFI_BAD_BUFFER_SIZE;
152 break;
153
154 default:
155 Status = EFI_ACCESS_DENIED;
156 ASSERT (0);
157 }
158
159 return Status;
160 }
161
162 EFI_STATUS
163 ArmSetMemoryRegionNoExec (
164 IN EFI_PHYSICAL_ADDRESS BaseAddress,
165 IN UINT64 Length
166 )
167 {
168 EFI_STATUS Status;
169 UINT32 MemoryAttributes;
170 UINT32 CodePermission;
171
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 (
176 BaseAddress,
177 Length,
178 MemoryAttributes | CodePermission
179 );
180 }
181 return EFI_INVALID_PARAMETER;
182 }
183
184 EFI_STATUS
185 ArmClearMemoryRegionNoExec (
186 IN EFI_PHYSICAL_ADDRESS BaseAddress,
187 IN UINT64 Length
188 )
189 {
190 EFI_STATUS Status;
191 UINT32 MemoryAttributes;
192 UINT32 CodePermission;
193
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 (
198 BaseAddress,
199 Length,
200 MemoryAttributes & ~CodePermission
201 );
202 }
203 return EFI_INVALID_PARAMETER;
204 }
205
206 EFI_STATUS
207 ArmSetMemoryRegionReadOnly (
208 IN EFI_PHYSICAL_ADDRESS BaseAddress,
209 IN UINT64 Length
210 )
211 {
212 EFI_STATUS Status;
213 UINT32 MemoryAttributes;
214 UINT32 DataPermission;
215
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 (
220 BaseAddress,
221 Length,
222 MemoryAttributes | DataPermission
223 );
224 }
225 return EFI_INVALID_PARAMETER;
226 }
227
228 EFI_STATUS
229 ArmClearMemoryRegionReadOnly (
230 IN EFI_PHYSICAL_ADDRESS BaseAddress,
231 IN UINT64 Length
232 )
233 {
234 EFI_STATUS Status;
235 UINT32 MemoryAttributes;
236 UINT32 PermissionRequest;
237
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,
241 MemoryAttributes);
242 return RequestMemoryPermissionChange (
243 BaseAddress,
244 Length,
245 PermissionRequest
246 );
247 }
248 return EFI_INVALID_PARAMETER;
249 }