DxeRegisterCpuFeaturesLib.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /** @file
  2. CPU Register Table Library functions.
  3. Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <PiDxe.h>
  7. #include <Library/UefiBootServicesTableLib.h>
  8. #include <Library/UefiLib.h>
  9. #include "RegisterCpuFeatures.h"
  10. CPU_FEATURES_DATA mCpuFeaturesData = { 0 };
  11. /**
  12. Worker function to get CPU_FEATURES_DATA pointer.
  13. @return Pointer to CPU_FEATURES_DATA.
  14. **/
  15. CPU_FEATURES_DATA *
  16. GetCpuFeaturesData (
  17. VOID
  18. )
  19. {
  20. return &mCpuFeaturesData;
  21. }
  22. /**
  23. Worker function to get EFI_MP_SERVICES_PROTOCOL pointer.
  24. @return MP_SERVICES variable.
  25. **/
  26. MP_SERVICES
  27. GetMpService (
  28. VOID
  29. )
  30. {
  31. EFI_STATUS Status;
  32. MP_SERVICES MpService;
  33. //
  34. // Get MP Services Protocol
  35. //
  36. Status = gBS->LocateProtocol (
  37. &gEfiMpServiceProtocolGuid,
  38. NULL,
  39. (VOID **)&MpService.Protocol
  40. );
  41. ASSERT_EFI_ERROR (Status);
  42. return MpService;
  43. }
  44. /**
  45. Worker function to return processor index.
  46. @param CpuFeaturesData Cpu Feature Data structure.
  47. @return The processor index.
  48. **/
  49. UINTN
  50. GetProcessorIndex (
  51. IN CPU_FEATURES_DATA *CpuFeaturesData
  52. )
  53. {
  54. EFI_STATUS Status;
  55. UINTN ProcessorIndex;
  56. EFI_MP_SERVICES_PROTOCOL *MpServices;
  57. MpServices = CpuFeaturesData->MpService.Protocol;
  58. Status = MpServices->WhoAmI (MpServices, &ProcessorIndex);
  59. ASSERT_EFI_ERROR (Status);
  60. return ProcessorIndex;
  61. }
  62. /**
  63. Gets detailed MP-related information on the requested processor at the
  64. instant this call is made.
  65. @param[in] ProcessorNumber The handle number of processor.
  66. @param[out] ProcessorInfoBuffer A pointer to the buffer where information for
  67. the requested processor is deposited.
  68. @return Status of MpServices->GetProcessorInfo().
  69. **/
  70. EFI_STATUS
  71. GetProcessorInformation (
  72. IN UINTN ProcessorNumber,
  73. OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
  74. )
  75. {
  76. EFI_STATUS Status;
  77. EFI_MP_SERVICES_PROTOCOL *MpServices;
  78. CPU_FEATURES_DATA *CpuFeaturesData;
  79. CpuFeaturesData = GetCpuFeaturesData ();
  80. MpServices = CpuFeaturesData->MpService.Protocol;
  81. Status = MpServices->GetProcessorInfo (
  82. MpServices,
  83. ProcessorNumber,
  84. ProcessorInfoBuffer
  85. );
  86. return Status;
  87. }
  88. /**
  89. Worker function to execute a caller provided function on all enabled APs.
  90. @param[in] Procedure A pointer to the function to be run on
  91. enabled APs of the system.
  92. @param[in] MpEvent A pointer to the event to be used later
  93. to check whether procedure has done.
  94. **/
  95. VOID
  96. StartupAllAPsWorker (
  97. IN EFI_AP_PROCEDURE Procedure,
  98. IN EFI_EVENT MpEvent
  99. )
  100. {
  101. EFI_STATUS Status;
  102. EFI_MP_SERVICES_PROTOCOL *MpServices;
  103. CPU_FEATURES_DATA *CpuFeaturesData;
  104. CpuFeaturesData = GetCpuFeaturesData ();
  105. MpServices = CpuFeaturesData->MpService.Protocol;
  106. //
  107. // Wakeup all APs
  108. //
  109. Status = MpServices->StartupAllAPs (
  110. MpServices,
  111. Procedure,
  112. FALSE,
  113. MpEvent,
  114. 0,
  115. CpuFeaturesData,
  116. NULL
  117. );
  118. ASSERT_EFI_ERROR (Status);
  119. }
  120. /**
  121. Worker function to switch the requested AP to be the BSP from that point onward.
  122. @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
  123. **/
  124. VOID
  125. SwitchNewBsp (
  126. IN UINTN ProcessorNumber
  127. )
  128. {
  129. EFI_STATUS Status;
  130. EFI_MP_SERVICES_PROTOCOL *MpServices;
  131. CPU_FEATURES_DATA *CpuFeaturesData;
  132. CpuFeaturesData = GetCpuFeaturesData ();
  133. MpServices = CpuFeaturesData->MpService.Protocol;
  134. //
  135. // Wakeup all APs
  136. //
  137. Status = MpServices->SwitchBSP (
  138. MpServices,
  139. ProcessorNumber,
  140. TRUE
  141. );
  142. ASSERT_EFI_ERROR (Status);
  143. }
  144. /**
  145. Worker function to retrieve the number of logical processor in the platform.
  146. @param[out] NumberOfCpus Pointer to the total number of logical
  147. processors in the system, including the BSP
  148. and disabled APs.
  149. @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical
  150. processors that exist in system, including
  151. the BSP.
  152. **/
  153. VOID
  154. GetNumberOfProcessor (
  155. OUT UINTN *NumberOfCpus,
  156. OUT UINTN *NumberOfEnabledProcessors
  157. )
  158. {
  159. EFI_STATUS Status;
  160. EFI_MP_SERVICES_PROTOCOL *MpServices;
  161. CPU_FEATURES_DATA *CpuFeaturesData;
  162. CpuFeaturesData = GetCpuFeaturesData ();
  163. MpServices = CpuFeaturesData->MpService.Protocol;
  164. //
  165. // Get the number of CPUs
  166. //
  167. Status = MpServices->GetNumberOfProcessors (
  168. MpServices,
  169. NumberOfCpus,
  170. NumberOfEnabledProcessors
  171. );
  172. ASSERT_EFI_ERROR (Status);
  173. }
  174. /**
  175. Performs CPU features Initialization.
  176. This service will invoke MP service to perform CPU features
  177. initialization on BSP/APs per user configuration.
  178. @note This service could be called by BSP only.
  179. **/
  180. VOID
  181. EFIAPI
  182. CpuFeaturesInitialize (
  183. VOID
  184. )
  185. {
  186. CPU_FEATURES_DATA *CpuFeaturesData;
  187. UINTN OldBspNumber;
  188. EFI_EVENT MpEvent;
  189. EFI_STATUS Status;
  190. CpuFeaturesData = GetCpuFeaturesData ();
  191. OldBspNumber = GetProcessorIndex (CpuFeaturesData);
  192. CpuFeaturesData->BspNumber = OldBspNumber;
  193. //
  194. //
  195. // Initialize MpEvent to suppress incorrect compiler/analyzer warnings.
  196. //
  197. MpEvent = NULL;
  198. if (CpuFeaturesData->NumberOfCpus > 1) {
  199. Status = gBS->CreateEvent (
  200. EVT_NOTIFY_WAIT,
  201. TPL_CALLBACK,
  202. EfiEventEmptyFunction,
  203. NULL,
  204. &MpEvent
  205. );
  206. ASSERT_EFI_ERROR (Status);
  207. //
  208. // Wakeup all APs for programming.
  209. //
  210. StartupAllAPsWorker (SetProcessorRegister, MpEvent);
  211. }
  212. //
  213. // Programming BSP
  214. //
  215. SetProcessorRegister (CpuFeaturesData);
  216. if (CpuFeaturesData->NumberOfCpus > 1) {
  217. //
  218. // Wait all processors to finish the task.
  219. //
  220. do {
  221. Status = gBS->CheckEvent (MpEvent);
  222. } while (Status == EFI_NOT_READY);
  223. ASSERT_EFI_ERROR (Status);
  224. }
  225. //
  226. // Switch to new BSP if required
  227. //
  228. if (CpuFeaturesData->BspNumber != OldBspNumber) {
  229. SwitchNewBsp (CpuFeaturesData->BspNumber);
  230. }
  231. }