SmmMp.c 19 KB

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