]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/PiSmmCpuDxeSmm/SmmMp.c
UefiCpuPkg/PiSmmCpuDxeSmm: Enable MM MP Protocol
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / SmmMp.c
1 /** @file
2 SMM MP protocol implementation
3
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "PiSmmCpuDxeSmm.h"
11 #include "SmmMp.h"
12
13 ///
14 /// SMM MP Protocol instance
15 ///
16 EFI_MM_MP_PROTOCOL mSmmMp = {
17 EFI_MM_MP_PROTOCOL_REVISION,
18 0,
19 SmmMpGetNumberOfProcessors,
20 SmmMpDispatchProcedure,
21 SmmMpBroadcastProcedure,
22 SmmMpSetStartupProcedure,
23 SmmMpCheckForProcedure,
24 SmmMpWaitForProcedure
25 };
26
27 /**
28 Service to retrieves the number of logical processor in the platform.
29
30 @param[in] This The EFI_MM_MP_PROTOCOL instance.
31 @param[out] NumberOfProcessors Pointer to the total number of logical processors in the system,
32 including the BSP and all APs.
33
34 @retval EFI_SUCCESS The number of processors was retrieved successfully
35 @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL
36 **/
37 EFI_STATUS
38 EFIAPI
39 SmmMpGetNumberOfProcessors (
40 IN CONST EFI_MM_MP_PROTOCOL *This,
41 OUT UINTN *NumberOfProcessors
42 )
43 {
44 if (NumberOfProcessors == NULL) {
45 return EFI_INVALID_PARAMETER;
46 }
47
48 *NumberOfProcessors = gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;
49
50 return EFI_SUCCESS;
51 }
52
53 /**
54 This service allows the caller to invoke a procedure one of the application processors (AP). This
55 function uses an optional token parameter to support blocking and non-blocking modes. If the token
56 is passed into the call, the function will operate in a non-blocking fashion and the caller can
57 check for completion with CheckOnProcedure or WaitForProcedure.
58
59 @param[in] This The EFI_MM_MP_PROTOCOL instance.
60 @param[in] Procedure A pointer to the procedure to be run on the designated target
61 AP of the system. Type EFI_AP_PROCEDURE2 is defined below in
62 related definitions.
63 @param[in] CpuNumber The zero-based index of the processor number of the target
64 AP, on which the code stream is supposed to run. If the number
65 points to the calling processor then it will not run the
66 supplied code.
67 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for this AP to
68 finish execution of Procedure, either for blocking or
69 non-blocking mode. Zero means infinity. If the timeout
70 expires before this AP returns from Procedure, then Procedure
71 on the AP is terminated. If the timeout expires in blocking
72 mode, the call returns EFI_TIMEOUT. If the timeout expires
73 in non-blocking mode, the timeout determined can be through
74 CheckOnProcedure or WaitForProcedure.
75 Note that timeout support is optional. Whether an
76 implementation supports this feature, can be determined via
77 the Attributes data member.
78 @param[in,out] ProcedureArguments Allows the caller to pass a list of parameters to the code
79 that is run by the AP. It is an optional common mailbox
80 between APs and the caller to share information.
81 @param[in,out] Token This is parameter is broken into two components:
82 1.Token->Completion is an optional parameter that allows the
83 caller to execute the procedure in a blocking or non-blocking
84 fashion. If it is NULL the call is blocking, and the call will
85 not return until the AP has completed the procedure. If the
86 token is not NULL, the call will return immediately. The caller
87 can check whether the procedure has completed with
88 CheckOnProcedure or WaitForProcedure.
89 2.Token->Status The implementation updates the address pointed
90 at by this variable with the status code returned by Procedure
91 when it completes execution on the target AP, or with EFI_TIMEOUT
92 if the Procedure fails to complete within the optional timeout.
93 The implementation will update this variable with EFI_NOT_READY
94 prior to starting Procedure on the target AP
95 @param[in,out] CPUStatus This optional pointer may be used to get the status code returned
96 by Procedure when it completes execution on the target AP, or with
97 EFI_TIMEOUT if the Procedure fails to complete within the optional
98 timeout. The implementation will update this variable with
99 EFI_NOT_READY prior to starting Procedure on the target AP.
100
101 @retval EFI_SUCCESS In the blocking case, this indicates that Procedure has completed
102 execution on the target AP.
103 In the non-blocking case this indicates that the procedure has
104 been successfully scheduled for execution on the target AP.
105 @retval EFI_INVALID_PARAMETER The input arguments are out of range. Either the target AP is the
106 caller of the function, or the Procedure or Token is NULL
107 @retval EFI_NOT_READY If the target AP is busy executing another procedure
108 @retval EFI_ALREADY_STARTED Token is already in use for another procedure
109 @retval EFI_TIMEOUT In blocking mode, the timeout expired before the specified AP
110 has finished
111 @retval EFI_OUT_OF_RESOURCES Could not allocate a required resource.
112
113 **/
114 EFI_STATUS
115 EFIAPI
116 SmmMpDispatchProcedure (
117 IN CONST EFI_MM_MP_PROTOCOL *This,
118 IN EFI_AP_PROCEDURE2 Procedure,
119 IN UINTN CpuNumber,
120 IN UINTN TimeoutInMicroseconds,
121 IN OUT VOID *ProcedureArguments OPTIONAL,
122 IN OUT MM_COMPLETION *Token,
123 IN OUT EFI_STATUS *CPUStatus
124 )
125 {
126 return InternalSmmStartupThisAp (
127 Procedure,
128 CpuNumber,
129 ProcedureArguments,
130 Token,
131 TimeoutInMicroseconds,
132 CPUStatus
133 );
134 }
135
136 /**
137 This service allows the caller to invoke a procedure on all running application processors (AP)
138 except the caller. This function uses an optional token parameter to support blocking and
139 nonblocking modes. If the token is passed into the call, the function will operate in a non-blocking
140 fashion and the caller can check for completion with CheckOnProcedure or WaitForProcedure.
141
142 It is not necessary for the implementation to run the procedure on every processor on the platform.
143 Processors that are powered down in such a way that they cannot respond to interrupts, may be
144 excluded from the broadcast.
145
146
147 @param[in] This The EFI_MM_MP_PROTOCOL instance.
148 @param[in] Procedure A pointer to the code stream to be run on the APs that have
149 entered MM. Type EFI_AP_PROCEDURE is defined below in related
150 definitions.
151 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for the APs to finish
152 execution of Procedure, either for blocking or non-blocking mode.
153 Zero means infinity. If the timeout expires before all APs return
154 from Procedure, then Procedure on the failed APs is terminated. If
155 the timeout expires in blocking mode, the call returns EFI_TIMEOUT.
156 If the timeout expires in non-blocking mode, the timeout determined
157 can be through CheckOnProcedure or WaitForProcedure.
158 Note that timeout support is optional. Whether an implementation
159 supports this feature can be determined via the Attributes data
160 member.
161 @param[in,out] ProcedureArguments Allows the caller to pass a list of parameters to the code
162 that is run by the AP. It is an optional common mailbox
163 between APs and the caller to share information.
164 @param[in,out] Token This is parameter is broken into two components:
165 1.Token->Completion is an optional parameter that allows the
166 caller to execute the procedure in a blocking or non-blocking
167 fashion. If it is NULL the call is blocking, and the call will
168 not return until the AP has completed the procedure. If the
169 token is not NULL, the call will return immediately. The caller
170 can check whether the procedure has completed with
171 CheckOnProcedure or WaitForProcedure.
172 2.Token->Status The implementation updates the address pointed
173 at by this variable with the status code returned by Procedure
174 when it completes execution on the target AP, or with EFI_TIMEOUT
175 if the Procedure fails to complete within the optional timeout.
176 The implementation will update this variable with EFI_NOT_READY
177 prior to starting Procedure on the target AP
178 @param[in,out] CPUStatus This optional pointer may be used to get the individual status
179 returned by every AP that participated in the broadcast. This
180 parameter if used provides the base address of an array to hold
181 the EFI_STATUS value of each AP in the system. The size of the
182 array can be ascertained by the GetNumberOfProcessors function.
183 As mentioned above, the broadcast may not include every processor
184 in the system. Some implementations may exclude processors that
185 have been powered down in such a way that they are not responsive
186 to interrupts. Additionally the broadcast excludes the processor
187 which is making the BroadcastProcedure call. For every excluded
188 processor, the array entry must contain a value of EFI_NOT_STARTED
189
190 @retval EFI_SUCCESS In the blocking case, this indicates that Procedure has completed
191 execution on the APs.
192 In the non-blocking case this indicates that the procedure has
193 been successfully scheduled for execution on the APs.
194 @retval EFI_INVALID_PARAMETER The Procedure or Token is NULL
195 @retval EFI_NOT_READY If the target AP is busy executing another procedure
196 @retval EFI_ALREADY_STARTED Token is already in use for another procedure
197 @retval EFI_TIMEOUT In blocking mode, the timeout expired before the specified AP
198 has finished.
199 @retval EFI_OUT_OF_RESOURCES Could not allocate a required resource.
200
201 **/
202 EFI_STATUS
203 EFIAPI
204 SmmMpBroadcastProcedure (
205 IN CONST EFI_MM_MP_PROTOCOL *This,
206 IN EFI_AP_PROCEDURE2 Procedure,
207 IN UINTN TimeoutInMicroseconds,
208 IN OUT VOID *ProcedureArguments OPTIONAL,
209 IN OUT MM_COMPLETION *Token,
210 IN OUT EFI_STATUS *CPUStatus
211 )
212 {
213 return InternalSmmStartupAllAPs(
214 Procedure,
215 TimeoutInMicroseconds,
216 ProcedureArguments,
217 Token,
218 CPUStatus
219 );
220 }
221
222 /**
223 This service allows the caller to set a startup procedure that will be executed when an AP powers
224 up from a state where core configuration and context is lost. The procedure is execution has the
225 following properties:
226 1. The procedure executes before the processor is handed over to the operating system.
227 2. All processors execute the same startup procedure.
228 3. The procedure may run in parallel with other procedures invoked through the functions in this
229 protocol, or with processors that are executing an MM handler or running in the operating system.
230
231
232 @param[in] This The EFI_MM_MP_PROTOCOL instance.
233 @param[in] Procedure A pointer to the code stream to be run on the designated target AP
234 of the system. Type EFI_AP_PROCEDURE is defined below in Volume 2
235 with the related definitions of
236 EFI_MP_SERVICES_PROTOCOL.StartupAllAPs.
237 If caller may pass a value of NULL to deregister any existing
238 startup procedure.
239 @param[in,out] ProcedureArguments Allows the caller to pass a list of parameters to the code that is
240 run by the AP. It is an optional common mailbox between APs and
241 the caller to share information
242
243 @retval EFI_SUCCESS The Procedure has been set successfully.
244 @retval EFI_INVALID_PARAMETER The Procedure is NULL but ProcedureArguments not NULL.
245
246 **/
247 EFI_STATUS
248 EFIAPI
249 SmmMpSetStartupProcedure (
250 IN CONST EFI_MM_MP_PROTOCOL *This,
251 IN EFI_AP_PROCEDURE Procedure,
252 IN OUT VOID *ProcedureArguments OPTIONAL
253 )
254 {
255 return RegisterStartupProcedure (Procedure, ProcedureArguments);
256 }
257
258 /**
259 When non-blocking execution of a procedure on an AP is invoked with DispatchProcedure,
260 via the use of a token, this function can be used to check for completion of the procedure on the AP.
261 The function takes the token that was passed into the DispatchProcedure call. If the procedure
262 is complete, and therefore it is now possible to run another procedure on the same AP, this function
263 returns EFI_SUCESS. In this case the status returned by the procedure that executed on the AP is
264 returned in the token's Status field. If the procedure has not yet completed, then this function
265 returns EFI_NOT_READY.
266
267 When a non-blocking execution of a procedure is invoked with BroadcastProcedure, via the
268 use of a token, this function can be used to check for completion of the procedure on all the
269 broadcast APs. The function takes the token that was passed into the BroadcastProcedure
270 call. If the procedure is complete on all broadcast APs this function returns EFI_SUCESS. In this
271 case the Status field in the token passed into the function reflects the overall result of the
272 invocation, which may be EFI_SUCCESS, if all executions succeeded, or the first observed failure.
273 If the procedure has not yet completed on the broadcast APs, the function returns
274 EFI_NOT_READY.
275
276 @param[in] This The EFI_MM_MP_PROTOCOL instance.
277 @param[in] Token This parameter describes the token that was passed into
278 DispatchProcedure or BroadcastProcedure.
279
280 @retval EFI_SUCCESS Procedure has completed.
281 @retval EFI_NOT_READY The Procedure has not completed.
282 @retval EFI_INVALID_PARAMETER Token or Token->Completion is NULL
283 @retval EFI_NOT_FOUND Token is not currently in use for a non-blocking call
284
285 **/
286 EFI_STATUS
287 EFIAPI
288 SmmMpCheckForProcedure (
289 IN CONST EFI_MM_MP_PROTOCOL *This,
290 IN MM_COMPLETION Token
291 )
292 {
293 if (Token == NULL) {
294 return EFI_INVALID_PARAMETER;
295 }
296
297 if (!IsTokenInUse ((SPIN_LOCK *)Token)) {
298 return EFI_NOT_FOUND;
299 }
300
301 return IsApReady ((SPIN_LOCK *)Token);
302 }
303
304 /**
305 When a non-blocking execution of a procedure on an AP is invoked via DispatchProcedure,
306 this function will block the caller until the remote procedure has completed on the designated AP.
307 The non-blocking procedure invocation is identified by the Token parameter, which must match the
308 token that used when DispatchProcedure was called. Upon completion the status returned by
309 the procedure that executed on the AP is used to update the token's Status field.
310
311 When a non-blocking execution of a procedure on an AP is invoked via BroadcastProcedure
312 this function will block the caller until the remote procedure has completed on all of the APs that
313 entered MM. The non-blocking procedure invocation is identified by the Token parameter, which
314 must match the token that used when BroadcastProcedure was called. Upon completion the
315 overall status returned by the procedures that executed on the broadcast AP is used to update the
316 token's Status field. The overall status may be EFI_SUCCESS, if all executions succeeded, or the
317 first observed failure.
318
319
320 @param[in] This The EFI_MM_MP_PROTOCOL instance.
321 @param[in] Token This parameter describes the token that was passed into
322 DispatchProcedure or BroadcastProcedure.
323
324 @retval EFI_SUCCESS Procedure has completed.
325 @retval EFI_INVALID_PARAMETER Token or Token->Completion is NULL
326 @retval EFI_NOT_FOUND Token is not currently in use for a non-blocking call
327
328 **/
329 EFI_STATUS
330 EFIAPI
331 SmmMpWaitForProcedure (
332 IN CONST EFI_MM_MP_PROTOCOL *This,
333 IN MM_COMPLETION Token
334 )
335 {
336 EFI_STATUS Status;
337
338 do {
339 Status = SmmMpCheckForProcedure (This, Token);
340 } while (Status == EFI_NOT_READY);
341
342 return Status;
343 }
344