ArmVirtGicArchLib.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /** @file
  2. ArmGicArchLib library class implementation for DT based virt platforms
  3. Copyright (c) 2015 - 2016, Linaro Ltd. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Base.h>
  7. #include <Uefi.h>
  8. #include <Library/ArmGicLib.h>
  9. #include <Library/ArmGicArchLib.h>
  10. #include <Library/BaseLib.h>
  11. #include <Library/DebugLib.h>
  12. #include <Library/PcdLib.h>
  13. #include <Library/UefiBootServicesTableLib.h>
  14. #include <Protocol/FdtClient.h>
  15. STATIC ARM_GIC_ARCH_REVISION mGicArchRevision;
  16. RETURN_STATUS
  17. EFIAPI
  18. ArmVirtGicArchLibConstructor (
  19. VOID
  20. )
  21. {
  22. UINT32 IccSre;
  23. FDT_CLIENT_PROTOCOL *FdtClient;
  24. CONST UINT64 *Reg;
  25. UINT32 RegSize;
  26. UINTN AddressCells, SizeCells;
  27. UINTN GicRevision;
  28. EFI_STATUS Status;
  29. UINT64 DistBase, CpuBase, RedistBase;
  30. RETURN_STATUS PcdStatus;
  31. Status = gBS->LocateProtocol (
  32. &gFdtClientProtocolGuid,
  33. NULL,
  34. (VOID **)&FdtClient
  35. );
  36. ASSERT_EFI_ERROR (Status);
  37. GicRevision = 2;
  38. Status = FdtClient->FindCompatibleNodeReg (
  39. FdtClient,
  40. "arm,cortex-a15-gic",
  41. (CONST VOID **)&Reg,
  42. &AddressCells,
  43. &SizeCells,
  44. &RegSize
  45. );
  46. if (Status == EFI_NOT_FOUND) {
  47. GicRevision = 3;
  48. Status = FdtClient->FindCompatibleNodeReg (
  49. FdtClient,
  50. "arm,gic-v3",
  51. (CONST VOID **)&Reg,
  52. &AddressCells,
  53. &SizeCells,
  54. &RegSize
  55. );
  56. }
  57. if (EFI_ERROR (Status)) {
  58. return Status;
  59. }
  60. switch (GicRevision) {
  61. case 3:
  62. //
  63. // The GIC v3 DT binding describes a series of at least 3 physical (base
  64. // addresses, size) pairs: the distributor interface (GICD), at least one
  65. // redistributor region (GICR) containing dedicated redistributor
  66. // interfaces for all individual CPUs, and the CPU interface (GICC).
  67. // Under virtualization, we assume that the first redistributor region
  68. // listed covers the boot CPU. Also, our GICv3 driver only supports the
  69. // system register CPU interface, so we can safely ignore the MMIO version
  70. // which is listed after the sequence of redistributor interfaces.
  71. // This means we are only interested in the first two memory regions
  72. // supplied, and ignore everything else.
  73. //
  74. ASSERT (RegSize >= 32);
  75. // RegProp[0..1] == { GICD base, GICD size }
  76. DistBase = SwapBytes64 (Reg[0]);
  77. ASSERT (DistBase < MAX_UINTN);
  78. // RegProp[2..3] == { GICR base, GICR size }
  79. RedistBase = SwapBytes64 (Reg[2]);
  80. ASSERT (RedistBase < MAX_UINTN);
  81. PcdStatus = PcdSet64S (PcdGicDistributorBase, DistBase);
  82. ASSERT_RETURN_ERROR (PcdStatus);
  83. PcdStatus = PcdSet64S (PcdGicRedistributorsBase, RedistBase);
  84. ASSERT_RETURN_ERROR (PcdStatus);
  85. DEBUG ((
  86. DEBUG_INFO,
  87. "Found GIC v3 (re)distributor @ 0x%Lx (0x%Lx)\n",
  88. DistBase,
  89. RedistBase
  90. ));
  91. //
  92. // The default implementation of ArmGicArchLib is responsible for enabling
  93. // the system register interface on the GICv3 if one is found. So let's do
  94. // the same here.
  95. //
  96. IccSre = ArmGicV3GetControlSystemRegisterEnable ();
  97. if (!(IccSre & ICC_SRE_EL2_SRE)) {
  98. ArmGicV3SetControlSystemRegisterEnable (IccSre | ICC_SRE_EL2_SRE);
  99. IccSre = ArmGicV3GetControlSystemRegisterEnable ();
  100. }
  101. //
  102. // Unlike the default implementation, there is no fall through to GICv2
  103. // mode if this GICv3 cannot be driven in native mode due to the fact
  104. // that the System Register interface is unavailable.
  105. //
  106. ASSERT (IccSre & ICC_SRE_EL2_SRE);
  107. mGicArchRevision = ARM_GIC_ARCH_REVISION_3;
  108. break;
  109. case 2:
  110. //
  111. // When the GICv2 is emulated with virtualization=on, it adds a virtual
  112. // set of control registers. This means the register property can be
  113. // either 32 or 64 bytes in size.
  114. //
  115. ASSERT ((RegSize == 32) || (RegSize == 64));
  116. DistBase = SwapBytes64 (Reg[0]);
  117. CpuBase = SwapBytes64 (Reg[2]);
  118. ASSERT (DistBase < MAX_UINTN);
  119. ASSERT (CpuBase < MAX_UINTN);
  120. PcdStatus = PcdSet64S (PcdGicDistributorBase, DistBase);
  121. ASSERT_RETURN_ERROR (PcdStatus);
  122. PcdStatus = PcdSet64S (PcdGicInterruptInterfaceBase, CpuBase);
  123. ASSERT_RETURN_ERROR (PcdStatus);
  124. DEBUG ((DEBUG_INFO, "Found GIC @ 0x%Lx/0x%Lx\n", DistBase, CpuBase));
  125. mGicArchRevision = ARM_GIC_ARCH_REVISION_2;
  126. break;
  127. default:
  128. DEBUG ((DEBUG_ERROR, "%a: No GIC revision specified!\n", __FUNCTION__));
  129. return RETURN_NOT_FOUND;
  130. }
  131. return RETURN_SUCCESS;
  132. }
  133. ARM_GIC_ARCH_REVISION
  134. EFIAPI
  135. ArmGicGetSupportedArchRevision (
  136. VOID
  137. )
  138. {
  139. return mGicArchRevision;
  140. }