MainMPCore.c 5.4 KB

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