MainMPCore.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /** @file
  2. Copyright (c) 2011-2014, ARM Limited. All rights reserved.
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. #include <Library/ArmGicLib.h>
  6. #include <Ppi/ArmMpCoreInfo.h>
  7. #include "PrePeiCore.h"
  8. /*
  9. * This is the main function for secondary cores. They loop around until a non Null value is written to
  10. * SYS_FLAGS register.The SYS_FLAGS register is platform specific.
  11. * Note:The secondary cores, while executing secondary_main, assumes that:
  12. * : SGI 0 is configured as Non-secure interrupt
  13. * : Priority Mask is configured to allow SGI 0
  14. * : Interrupt Distributor and CPU interfaces are enabled
  15. *
  16. */
  17. VOID
  18. EFIAPI
  19. SecondaryMain (
  20. IN UINTN MpId
  21. )
  22. {
  23. EFI_STATUS Status;
  24. UINTN PpiListSize;
  25. UINTN PpiListCount;
  26. EFI_PEI_PPI_DESCRIPTOR *PpiList;
  27. ARM_MP_CORE_INFO_PPI *ArmMpCoreInfoPpi;
  28. UINTN Index;
  29. UINTN ArmCoreCount;
  30. ARM_CORE_INFO *ArmCoreInfoTable;
  31. UINT32 ClusterId;
  32. UINT32 CoreId;
  33. VOID (*SecondaryStart)(
  34. VOID
  35. );
  36. UINTN SecondaryEntryAddr;
  37. UINTN AcknowledgeInterrupt;
  38. UINTN InterruptId;
  39. ClusterId = GET_CLUSTER_ID (MpId);
  40. CoreId = GET_CORE_ID (MpId);
  41. // Get the gArmMpCoreInfoPpiGuid
  42. PpiListSize = 0;
  43. ArmPlatformGetPlatformPpiList (&PpiListSize, &PpiList);
  44. PpiListCount = PpiListSize / sizeof (EFI_PEI_PPI_DESCRIPTOR);
  45. for (Index = 0; Index < PpiListCount; Index++, PpiList++) {
  46. if (CompareGuid (PpiList->Guid, &gArmMpCoreInfoPpiGuid) == TRUE) {
  47. break;
  48. }
  49. }
  50. // On MP Core Platform we must implement the ARM MP Core Info PPI
  51. ASSERT (Index != PpiListCount);
  52. ArmMpCoreInfoPpi = PpiList->Ppi;
  53. ArmCoreCount = 0;
  54. Status = ArmMpCoreInfoPpi->GetMpCoreInfo (&ArmCoreCount, &ArmCoreInfoTable);
  55. ASSERT_EFI_ERROR (Status);
  56. // Find the core in the ArmCoreTable
  57. for (Index = 0; Index < ArmCoreCount; Index++) {
  58. if ((GET_MPIDR_AFF1 (ArmCoreInfoTable[Index].Mpidr) == ClusterId) &&
  59. (GET_MPIDR_AFF0 (ArmCoreInfoTable[Index].Mpidr) == CoreId))
  60. {
  61. break;
  62. }
  63. }
  64. // The ARM Core Info Table must define every core
  65. ASSERT (Index != ArmCoreCount);
  66. // Clear Secondary cores MailBox
  67. MmioWrite32 (ArmCoreInfoTable[Index].MailboxClearAddress, ArmCoreInfoTable[Index].MailboxClearValue);
  68. do {
  69. ArmCallWFI ();
  70. // Read the Mailbox
  71. SecondaryEntryAddr = MmioRead32 (ArmCoreInfoTable[Index].MailboxGetAddress);
  72. // Acknowledge the interrupt and send End of Interrupt signal.
  73. AcknowledgeInterrupt = ArmGicAcknowledgeInterrupt (PcdGet64 (PcdGicInterruptInterfaceBase), &InterruptId);
  74. // Check if it is a valid interrupt ID
  75. if (InterruptId < ArmGicGetMaxNumInterrupts (PcdGet64 (PcdGicDistributorBase))) {
  76. // Got a valid SGI number hence signal End of Interrupt
  77. ArmGicEndOfInterrupt (PcdGet64 (PcdGicInterruptInterfaceBase), AcknowledgeInterrupt);
  78. }
  79. } while (SecondaryEntryAddr == 0);
  80. // Jump to secondary core entry point.
  81. SecondaryStart = (VOID (*)()) SecondaryEntryAddr;
  82. SecondaryStart ();
  83. // The secondaries shouldn't reach here
  84. ASSERT (FALSE);
  85. }
  86. VOID
  87. EFIAPI
  88. PrimaryMain (
  89. IN EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint
  90. )
  91. {
  92. EFI_SEC_PEI_HAND_OFF SecCoreData;
  93. UINTN PpiListSize;
  94. EFI_PEI_PPI_DESCRIPTOR *PpiList;
  95. UINTN TemporaryRamBase;
  96. UINTN TemporaryRamSize;
  97. CreatePpiList (&PpiListSize, &PpiList);
  98. // Enable the GIC Distributor
  99. ArmGicEnableDistributor (PcdGet64 (PcdGicDistributorBase));
  100. // If ArmVe has not been built as Standalone then we need to wake up the secondary cores
  101. if (FeaturePcdGet (PcdSendSgiToBringUpSecondaryCores)) {
  102. // Sending SGI to all the Secondary CPU interfaces
  103. ArmGicSendSgiTo (PcdGet64 (PcdGicDistributorBase), ARM_GIC_ICDSGIR_FILTER_EVERYONEELSE, 0x0E, PcdGet32 (PcdGicSgiIntId));
  104. }
  105. // Adjust the Temporary Ram as the new Ppi List (Common + Platform Ppi Lists) is created at
  106. // the base of the primary core stack
  107. PpiListSize = ALIGN_VALUE (PpiListSize, CPU_STACK_ALIGNMENT);
  108. TemporaryRamBase = (UINTN)PcdGet64 (PcdCPUCoresStackBase) + PpiListSize;
  109. TemporaryRamSize = (UINTN)PcdGet32 (PcdCPUCorePrimaryStackSize) - PpiListSize;
  110. //
  111. // Bind this information into the SEC hand-off state
  112. // Note: this must be in sync with the stuff in the asm file
  113. // Note also: HOBs (pei temp ram) MUST be above stack
  114. //
  115. SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);
  116. SecCoreData.BootFirmwareVolumeBase = (VOID *)(UINTN)PcdGet64 (PcdFvBaseAddress);
  117. SecCoreData.BootFirmwareVolumeSize = PcdGet32 (PcdFvSize);
  118. SecCoreData.TemporaryRamBase = (VOID *)TemporaryRamBase; // We run on the primary core (and so we use the first stack)
  119. SecCoreData.TemporaryRamSize = TemporaryRamSize;
  120. SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
  121. SecCoreData.PeiTemporaryRamSize = ALIGN_VALUE (SecCoreData.TemporaryRamSize / 2, CPU_STACK_ALIGNMENT);
  122. SecCoreData.StackBase = (VOID *)((UINTN)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize);
  123. SecCoreData.StackSize = (TemporaryRamBase + TemporaryRamSize) - (UINTN)SecCoreData.StackBase;
  124. // Jump to PEI core entry point
  125. PeiCoreEntryPoint (&SecCoreData, PpiList);
  126. }