PeiRegisterCpuFeaturesLib.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /** @file
  2. CPU Register Table Library functions.
  3. Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <PiPei.h>
  7. #include <Library/HobLib.h>
  8. #include <Library/PeiServicesLib.h>
  9. #include <Library/PeiServicesTablePointerLib.h>
  10. #include <Ppi/MpServices2.h>
  11. #include "RegisterCpuFeatures.h"
  12. #define REGISTER_CPU_FEATURES_GUID \
  13. { \
  14. 0xa694c467, 0x697a, 0x446b, { 0xb9, 0x29, 0x5b, 0x14, 0xa0, 0xcf, 0x39, 0xf } \
  15. }
  16. EFI_GUID mRegisterCpuFeaturesHobGuid = REGISTER_CPU_FEATURES_GUID;
  17. /**
  18. Worker function to get CPU_FEATURES_DATA pointer.
  19. @return Pointer to CPU_FEATURES_DATA.
  20. **/
  21. CPU_FEATURES_DATA *
  22. GetCpuFeaturesData (
  23. VOID
  24. )
  25. {
  26. CPU_FEATURES_DATA *CpuInitData;
  27. EFI_HOB_GUID_TYPE *GuidHob;
  28. VOID *DataInHob;
  29. UINT64 Data64;
  30. CpuInitData = NULL;
  31. GuidHob = GetFirstGuidHob (&mRegisterCpuFeaturesHobGuid);
  32. if (GuidHob != NULL) {
  33. DataInHob = GET_GUID_HOB_DATA (GuidHob);
  34. CpuInitData = (CPU_FEATURES_DATA *)(*(UINTN *)DataInHob);
  35. ASSERT (CpuInitData != NULL);
  36. } else {
  37. CpuInitData = AllocateZeroPool (sizeof (CPU_FEATURES_DATA));
  38. ASSERT (CpuInitData != NULL);
  39. //
  40. // Build location of CPU MP DATA buffer in HOB
  41. //
  42. Data64 = (UINT64)(UINTN)CpuInitData;
  43. BuildGuidDataHob (
  44. &mRegisterCpuFeaturesHobGuid,
  45. (VOID *)&Data64,
  46. sizeof (UINT64)
  47. );
  48. }
  49. return CpuInitData;
  50. }
  51. /**
  52. Worker function to get MP PPI service pointer.
  53. @return MP_SERVICES variable.
  54. **/
  55. MP_SERVICES
  56. GetMpService (
  57. VOID
  58. )
  59. {
  60. EFI_STATUS Status;
  61. MP_SERVICES MpService;
  62. //
  63. // Get MP Services2 Ppi
  64. //
  65. Status = PeiServicesLocatePpi (
  66. &gEdkiiPeiMpServices2PpiGuid,
  67. 0,
  68. NULL,
  69. (VOID **)&MpService.Ppi
  70. );
  71. ASSERT_EFI_ERROR (Status);
  72. return MpService;
  73. }
  74. /**
  75. Worker function to return processor index.
  76. @param CpuFeaturesData Cpu Feature Data structure.
  77. @return The processor index.
  78. **/
  79. UINTN
  80. GetProcessorIndex (
  81. IN CPU_FEATURES_DATA *CpuFeaturesData
  82. )
  83. {
  84. EFI_STATUS Status;
  85. EDKII_PEI_MP_SERVICES2_PPI *CpuMp2Ppi;
  86. UINTN ProcessorIndex;
  87. CpuMp2Ppi = CpuFeaturesData->MpService.Ppi;
  88. //
  89. // For two reasons which use NULL for WhoAmI:
  90. // 1. This function will be called by APs and AP should not use PeiServices Table
  91. // 2. Check WhoAmI implementation, this parameter will not be used.
  92. //
  93. Status = CpuMp2Ppi->WhoAmI (CpuMp2Ppi, &ProcessorIndex);
  94. ASSERT_EFI_ERROR (Status);
  95. return ProcessorIndex;
  96. }
  97. /**
  98. Worker function to MP-related information on the requested processor at the
  99. instant this call is made.
  100. @param[in] ProcessorNumber The handle number of processor.
  101. @param[out] ProcessorInfoBuffer A pointer to the buffer where information for
  102. the requested processor is deposited.
  103. @return Status of MpServices->GetProcessorInfo().
  104. **/
  105. EFI_STATUS
  106. GetProcessorInformation (
  107. IN UINTN ProcessorNumber,
  108. OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
  109. )
  110. {
  111. EDKII_PEI_MP_SERVICES2_PPI *CpuMp2Ppi;
  112. EFI_STATUS Status;
  113. CPU_FEATURES_DATA *CpuFeaturesData;
  114. CpuFeaturesData = GetCpuFeaturesData ();
  115. CpuMp2Ppi = CpuFeaturesData->MpService.Ppi;
  116. Status = CpuMp2Ppi->GetProcessorInfo (
  117. CpuMp2Ppi,
  118. ProcessorNumber,
  119. ProcessorInfoBuffer
  120. );
  121. return Status;
  122. }
  123. /**
  124. Worker function to execute a caller provided function on all enabled APs.
  125. @param[in] Procedure A pointer to the function to be run on
  126. enabled APs of the system.
  127. @param[in] MpEvent The Event used to sync the result.
  128. **/
  129. VOID
  130. StartupAllAPsWorker (
  131. IN EFI_AP_PROCEDURE Procedure,
  132. IN EFI_EVENT MpEvent
  133. )
  134. {
  135. EFI_STATUS Status;
  136. EDKII_PEI_MP_SERVICES2_PPI *CpuMp2Ppi;
  137. CPU_FEATURES_DATA *CpuFeaturesData;
  138. CpuFeaturesData = GetCpuFeaturesData ();
  139. CpuMp2Ppi = CpuFeaturesData->MpService.Ppi;
  140. //
  141. // Wakeup all APs for data collection.
  142. //
  143. Status = CpuMp2Ppi->StartupAllAPs (
  144. CpuMp2Ppi,
  145. Procedure,
  146. FALSE,
  147. 0,
  148. CpuFeaturesData
  149. );
  150. ASSERT_EFI_ERROR (Status);
  151. }
  152. /**
  153. Worker function to execute a caller provided function on all enabled CPUs.
  154. @param[in] Procedure A pointer to the function to be run on
  155. enabled CPUs of the system.
  156. **/
  157. VOID
  158. StartupAllCPUsWorker (
  159. IN EFI_AP_PROCEDURE Procedure
  160. )
  161. {
  162. EFI_STATUS Status;
  163. EDKII_PEI_MP_SERVICES2_PPI *CpuMp2Ppi;
  164. CPU_FEATURES_DATA *CpuFeaturesData;
  165. CpuFeaturesData = GetCpuFeaturesData ();
  166. //
  167. // Get MP Services2 Ppi
  168. //
  169. CpuMp2Ppi = CpuFeaturesData->MpService.Ppi;
  170. Status = CpuMp2Ppi->StartupAllCPUs (
  171. CpuMp2Ppi,
  172. Procedure,
  173. 0,
  174. CpuFeaturesData
  175. );
  176. ASSERT_EFI_ERROR (Status);
  177. }
  178. /**
  179. Worker function to switch the requested AP to be the BSP from that point onward.
  180. @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
  181. **/
  182. VOID
  183. SwitchNewBsp (
  184. IN UINTN ProcessorNumber
  185. )
  186. {
  187. EFI_STATUS Status;
  188. EDKII_PEI_MP_SERVICES2_PPI *CpuMp2Ppi;
  189. CPU_FEATURES_DATA *CpuFeaturesData;
  190. CpuFeaturesData = GetCpuFeaturesData ();
  191. CpuMp2Ppi = CpuFeaturesData->MpService.Ppi;
  192. //
  193. // Wakeup all APs for data collection.
  194. //
  195. Status = CpuMp2Ppi->SwitchBSP (
  196. CpuMp2Ppi,
  197. ProcessorNumber,
  198. TRUE
  199. );
  200. ASSERT_EFI_ERROR (Status);
  201. }
  202. /**
  203. Worker function to retrieve the number of logical processor in the platform.
  204. @param[out] NumberOfCpus Pointer to the total number of logical
  205. processors in the system, including the BSP
  206. and disabled APs.
  207. @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical
  208. processors that exist in system, including
  209. the BSP.
  210. **/
  211. VOID
  212. GetNumberOfProcessor (
  213. OUT UINTN *NumberOfCpus,
  214. OUT UINTN *NumberOfEnabledProcessors
  215. )
  216. {
  217. EFI_STATUS Status;
  218. EDKII_PEI_MP_SERVICES2_PPI *CpuMp2Ppi;
  219. CPU_FEATURES_DATA *CpuFeaturesData;
  220. CpuFeaturesData = GetCpuFeaturesData ();
  221. CpuMp2Ppi = CpuFeaturesData->MpService.Ppi;
  222. //
  223. // Get the number of CPUs
  224. //
  225. Status = CpuMp2Ppi->GetNumberOfProcessors (
  226. CpuMp2Ppi,
  227. NumberOfCpus,
  228. NumberOfEnabledProcessors
  229. );
  230. ASSERT_EFI_ERROR (Status);
  231. }
  232. /**
  233. Performs CPU features Initialization.
  234. This service will invoke MP service to perform CPU features
  235. initialization on BSP/APs per user configuration.
  236. @note This service could be called by BSP only.
  237. **/
  238. VOID
  239. EFIAPI
  240. CpuFeaturesInitialize (
  241. VOID
  242. )
  243. {
  244. CPU_FEATURES_DATA *CpuFeaturesData;
  245. UINTN OldBspNumber;
  246. CpuFeaturesData = GetCpuFeaturesData ();
  247. OldBspNumber = GetProcessorIndex (CpuFeaturesData);
  248. CpuFeaturesData->BspNumber = OldBspNumber;
  249. //
  250. // Start to program register for all CPUs.
  251. //
  252. StartupAllCPUsWorker (SetProcessorRegister);
  253. //
  254. // Switch to new BSP if required
  255. //
  256. if (CpuFeaturesData->BspNumber != OldBspNumber) {
  257. SwitchNewBsp (CpuFeaturesData->BspNumber);
  258. }
  259. }