MainMPCore.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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 "PrePi.h"
  9. #include <Library/ArmGicLib.h>
  10. #include <Ppi/ArmMpCoreInfo.h>
  11. VOID
  12. PrimaryMain (
  13. IN UINTN UefiMemoryBase,
  14. IN UINTN StacksBase,
  15. IN UINT64 StartTimeStamp
  16. )
  17. {
  18. // Enable the GIC Distributor
  19. ArmGicEnableDistributor(PcdGet64(PcdGicDistributorBase));
  20. // In some cases, the secondary cores are waiting for an SGI from the next stage boot loader to resume their initialization
  21. if (!FixedPcdGet32(PcdSendSgiToBringUpSecondaryCores)) {
  22. // Sending SGI to all the Secondary CPU interfaces
  23. ArmGicSendSgiTo (PcdGet64(PcdGicDistributorBase), ARM_GIC_ICDSGIR_FILTER_EVERYONEELSE, 0x0E, PcdGet32 (PcdGicSgiIntId));
  24. }
  25. PrePiMain (UefiMemoryBase, StacksBase, StartTimeStamp);
  26. // We must never return
  27. ASSERT(FALSE);
  28. }
  29. VOID
  30. SecondaryMain (
  31. IN UINTN MpId
  32. )
  33. {
  34. EFI_STATUS Status;
  35. ARM_MP_CORE_INFO_PPI *ArmMpCoreInfoPpi;
  36. UINTN Index;
  37. UINTN ArmCoreCount;
  38. ARM_CORE_INFO *ArmCoreInfoTable;
  39. UINT32 ClusterId;
  40. UINT32 CoreId;
  41. VOID (*SecondaryStart)(VOID);
  42. UINTN SecondaryEntryAddr;
  43. UINTN AcknowledgeInterrupt;
  44. UINTN InterruptId;
  45. ClusterId = GET_CLUSTER_ID(MpId);
  46. CoreId = GET_CORE_ID(MpId);
  47. // On MP Core Platform we must implement the ARM MP Core Info PPI (gArmMpCoreInfoPpiGuid)
  48. Status = GetPlatformPpi (&gArmMpCoreInfoPpiGuid, (VOID**)&ArmMpCoreInfoPpi);
  49. ASSERT_EFI_ERROR (Status);
  50. ArmCoreCount = 0;
  51. Status = ArmMpCoreInfoPpi->GetMpCoreInfo (&ArmCoreCount, &ArmCoreInfoTable);
  52. ASSERT_EFI_ERROR (Status);
  53. // Find the core in the ArmCoreTable
  54. for (Index = 0; Index < ArmCoreCount; Index++) {
  55. if ((ArmCoreInfoTable[Index].ClusterId == ClusterId) && (ArmCoreInfoTable[Index].CoreId == CoreId)) {
  56. break;
  57. }
  58. }
  59. // The ARM Core Info Table must define every core
  60. ASSERT (Index != ArmCoreCount);
  61. // Clear Secondary cores MailBox
  62. MmioWrite32 (ArmCoreInfoTable[Index].MailboxClearAddress, ArmCoreInfoTable[Index].MailboxClearValue);
  63. do {
  64. ArmCallWFI ();
  65. // Read the Mailbox
  66. SecondaryEntryAddr = MmioRead32 (ArmCoreInfoTable[Index].MailboxGetAddress);
  67. // Acknowledge the interrupt and send End of Interrupt signal.
  68. AcknowledgeInterrupt = ArmGicAcknowledgeInterrupt (PcdGet64 (PcdGicInterruptInterfaceBase), &InterruptId);
  69. // Check if it is a valid interrupt ID
  70. if (InterruptId < ArmGicGetMaxNumInterrupts (PcdGet64 (PcdGicDistributorBase))) {
  71. // Got a valid SGI number hence signal End of Interrupt
  72. ArmGicEndOfInterrupt (PcdGet64 (PcdGicInterruptInterfaceBase), AcknowledgeInterrupt);
  73. }
  74. } while (SecondaryEntryAddr == 0);
  75. // Jump to secondary core entry point.
  76. SecondaryStart = (VOID (*)())SecondaryEntryAddr;
  77. SecondaryStart();
  78. // The secondaries shouldn't reach here
  79. ASSERT(FALSE);
  80. }