plat_gicv2.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
  3. * Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: BSD-3-Clause
  6. */
  7. #include <assert.h>
  8. #include <stdbool.h>
  9. #include <bl31/interrupt_mgmt.h>
  10. #include <drivers/arm/gic_common.h>
  11. #include <drivers/arm/gicv2.h>
  12. #include <plat/common/platform.h>
  13. /*
  14. * The following platform GIC functions are weakly defined. They
  15. * provide typical implementations that may be re-used by multiple
  16. * platforms but may also be overridden by a platform if required.
  17. */
  18. #pragma weak plat_ic_get_pending_interrupt_id
  19. #pragma weak plat_ic_get_pending_interrupt_type
  20. #pragma weak plat_ic_acknowledge_interrupt
  21. #pragma weak plat_ic_get_interrupt_type
  22. #pragma weak plat_ic_end_of_interrupt
  23. #pragma weak plat_interrupt_type_to_line
  24. #pragma weak plat_ic_get_running_priority
  25. #pragma weak plat_ic_is_spi
  26. #pragma weak plat_ic_is_ppi
  27. #pragma weak plat_ic_is_sgi
  28. #pragma weak plat_ic_get_interrupt_active
  29. #pragma weak plat_ic_enable_interrupt
  30. #pragma weak plat_ic_disable_interrupt
  31. #pragma weak plat_ic_set_interrupt_priority
  32. #pragma weak plat_ic_set_interrupt_type
  33. #pragma weak plat_ic_raise_el3_sgi
  34. #pragma weak plat_ic_raise_ns_sgi
  35. #pragma weak plat_ic_raise_s_el1_sgi
  36. #pragma weak plat_ic_set_spi_routing
  37. /*
  38. * This function returns the highest priority pending interrupt at
  39. * the Interrupt controller
  40. */
  41. uint32_t plat_ic_get_pending_interrupt_id(void)
  42. {
  43. unsigned int id;
  44. id = gicv2_get_pending_interrupt_id();
  45. if (id == GIC_SPURIOUS_INTERRUPT)
  46. return INTR_ID_UNAVAILABLE;
  47. return id;
  48. }
  49. /*
  50. * This function returns the type of the highest priority pending interrupt
  51. * at the Interrupt controller. In the case of GICv2, the Highest Priority
  52. * Pending interrupt register (`GICC_HPPIR`) is read to determine the id of
  53. * the pending interrupt. The type of interrupt depends upon the id value
  54. * as follows.
  55. * 1. id < PENDING_G1_INTID (1022) is reported as a S-EL1 interrupt
  56. * 2. id = PENDING_G1_INTID (1022) is reported as a Non-secure interrupt.
  57. * 3. id = GIC_SPURIOUS_INTERRUPT (1023) is reported as an invalid interrupt
  58. * type.
  59. */
  60. uint32_t plat_ic_get_pending_interrupt_type(void)
  61. {
  62. unsigned int id;
  63. id = gicv2_get_pending_interrupt_type();
  64. /* Assume that all secure interrupts are S-EL1 interrupts */
  65. if (id < PENDING_G1_INTID) {
  66. #if GICV2_G0_FOR_EL3
  67. return INTR_TYPE_EL3;
  68. #else
  69. return INTR_TYPE_S_EL1;
  70. #endif
  71. }
  72. if (id == GIC_SPURIOUS_INTERRUPT)
  73. return INTR_TYPE_INVAL;
  74. return INTR_TYPE_NS;
  75. }
  76. /*
  77. * This function returns the highest priority pending interrupt at
  78. * the Interrupt controller and indicates to the Interrupt controller
  79. * that the interrupt processing has started.
  80. */
  81. uint32_t plat_ic_acknowledge_interrupt(void)
  82. {
  83. return gicv2_acknowledge_interrupt();
  84. }
  85. /*
  86. * This function returns the type of the interrupt `id`, depending on how
  87. * the interrupt has been configured in the interrupt controller
  88. */
  89. uint32_t plat_ic_get_interrupt_type(uint32_t id)
  90. {
  91. unsigned int type;
  92. type = gicv2_get_interrupt_group(id);
  93. /* Assume that all secure interrupts are S-EL1 interrupts */
  94. return (type == GICV2_INTR_GROUP1) ? INTR_TYPE_NS :
  95. #if GICV2_G0_FOR_EL3
  96. INTR_TYPE_EL3;
  97. #else
  98. INTR_TYPE_S_EL1;
  99. #endif
  100. }
  101. /*
  102. * This functions is used to indicate to the interrupt controller that
  103. * the processing of the interrupt corresponding to the `id` has
  104. * finished.
  105. */
  106. void plat_ic_end_of_interrupt(uint32_t id)
  107. {
  108. gicv2_end_of_interrupt(id);
  109. }
  110. /*
  111. * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins.
  112. * The interrupt controller knows which pin/line it uses to signal a type of
  113. * interrupt. It lets the interrupt management framework determine
  114. * for a type of interrupt and security state, which line should be used in the
  115. * SCR_EL3 to control its routing to EL3. The interrupt line is represented
  116. * as the bit position of the IRQ or FIQ bit in the SCR_EL3.
  117. */
  118. uint32_t plat_interrupt_type_to_line(uint32_t type,
  119. uint32_t security_state)
  120. {
  121. assert((type == INTR_TYPE_S_EL1) || (type == INTR_TYPE_EL3) ||
  122. (type == INTR_TYPE_NS));
  123. assert(sec_state_is_valid(security_state));
  124. /* Non-secure interrupts are signaled on the IRQ line always */
  125. if (type == INTR_TYPE_NS)
  126. return __builtin_ctz(SCR_IRQ_BIT);
  127. /*
  128. * Secure interrupts are signaled using the IRQ line if the FIQ is
  129. * not enabled else they are signaled using the FIQ line.
  130. */
  131. return ((gicv2_is_fiq_enabled() != 0U) ? __builtin_ctz(SCR_FIQ_BIT) :
  132. __builtin_ctz(SCR_IRQ_BIT));
  133. }
  134. unsigned int plat_ic_get_running_priority(void)
  135. {
  136. return gicv2_get_running_priority();
  137. }
  138. int plat_ic_is_spi(unsigned int id)
  139. {
  140. return (id >= MIN_SPI_ID) && (id <= MAX_SPI_ID);
  141. }
  142. int plat_ic_is_ppi(unsigned int id)
  143. {
  144. return (id >= MIN_PPI_ID) && (id < MIN_SPI_ID);
  145. }
  146. int plat_ic_is_sgi(unsigned int id)
  147. {
  148. return (id >= MIN_SGI_ID) && (id < MIN_PPI_ID);
  149. }
  150. unsigned int plat_ic_get_interrupt_active(unsigned int id)
  151. {
  152. return gicv2_get_interrupt_active(id);
  153. }
  154. void plat_ic_enable_interrupt(unsigned int id)
  155. {
  156. gicv2_enable_interrupt(id);
  157. }
  158. void plat_ic_disable_interrupt(unsigned int id)
  159. {
  160. gicv2_disable_interrupt(id);
  161. }
  162. void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority)
  163. {
  164. gicv2_set_interrupt_priority(id, priority);
  165. }
  166. bool plat_ic_has_interrupt_type(unsigned int type)
  167. {
  168. bool has_interrupt_type = false;
  169. switch (type) {
  170. #if GICV2_G0_FOR_EL3
  171. case INTR_TYPE_EL3:
  172. #else
  173. case INTR_TYPE_S_EL1:
  174. #endif
  175. case INTR_TYPE_NS:
  176. has_interrupt_type = true;
  177. break;
  178. default:
  179. /* Do nothing in default case */
  180. break;
  181. }
  182. return has_interrupt_type;
  183. }
  184. void plat_ic_set_interrupt_type(unsigned int id, unsigned int type)
  185. {
  186. unsigned int gicv2_group = 0U;
  187. /* Map canonical interrupt type to GICv2 type */
  188. switch (type) {
  189. #if GICV2_G0_FOR_EL3
  190. case INTR_TYPE_EL3:
  191. #else
  192. case INTR_TYPE_S_EL1:
  193. #endif
  194. gicv2_group = GICV2_INTR_GROUP0;
  195. break;
  196. case INTR_TYPE_NS:
  197. gicv2_group = GICV2_INTR_GROUP1;
  198. break;
  199. default:
  200. assert(false); /* Unreachable */
  201. break;
  202. }
  203. gicv2_set_interrupt_group(id, gicv2_group);
  204. }
  205. void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target)
  206. {
  207. #if GICV2_G0_FOR_EL3
  208. int id;
  209. /* Target must be a valid MPIDR in the system */
  210. id = plat_core_pos_by_mpidr(target);
  211. assert(id >= 0);
  212. /* Verify that this is a secure SGI */
  213. assert(plat_ic_get_interrupt_type(sgi_num) == INTR_TYPE_EL3);
  214. gicv2_raise_sgi(sgi_num, false, id);
  215. #else
  216. assert(false);
  217. #endif
  218. }
  219. void plat_ic_raise_ns_sgi(int sgi_num, u_register_t target)
  220. {
  221. int id;
  222. /* Target must be a valid MPIDR in the system */
  223. id = plat_core_pos_by_mpidr(target);
  224. assert(id >= 0);
  225. /* Verify that this is a non-secure SGI */
  226. assert(plat_ic_get_interrupt_type(sgi_num) == INTR_TYPE_NS);
  227. gicv2_raise_sgi(sgi_num, true, id);
  228. }
  229. void plat_ic_raise_s_el1_sgi(int sgi_num, u_register_t target)
  230. {
  231. #if GICV2_G0_FOR_EL3
  232. assert(false);
  233. #else
  234. int id;
  235. /* Target must be a valid MPIDR in the system */
  236. id = plat_core_pos_by_mpidr(target);
  237. assert(id >= 0);
  238. /* Verify that this is a secure EL1 SGI */
  239. assert(plat_ic_get_interrupt_type(sgi_num) == INTR_TYPE_S_EL1);
  240. gicv2_raise_sgi(sgi_num, false, id);
  241. #endif
  242. }
  243. void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode,
  244. u_register_t mpidr)
  245. {
  246. int proc_num = 0;
  247. switch (routing_mode) {
  248. case INTR_ROUTING_MODE_PE:
  249. proc_num = plat_core_pos_by_mpidr(mpidr);
  250. assert(proc_num >= 0);
  251. break;
  252. case INTR_ROUTING_MODE_ANY:
  253. /* Bit mask selecting all 8 CPUs as candidates */
  254. proc_num = -1;
  255. break;
  256. default:
  257. assert(0); /* Unreachable */
  258. break;
  259. }
  260. gicv2_set_spi_routing(id, proc_num);
  261. }
  262. void plat_ic_set_interrupt_pending(unsigned int id)
  263. {
  264. gicv2_set_interrupt_pending(id);
  265. }
  266. void plat_ic_clear_interrupt_pending(unsigned int id)
  267. {
  268. gicv2_clear_interrupt_pending(id);
  269. }
  270. unsigned int plat_ic_set_priority_mask(unsigned int mask)
  271. {
  272. return gicv2_set_pmr(mask);
  273. }
  274. unsigned int plat_ic_get_interrupt_id(unsigned int raw)
  275. {
  276. unsigned int id = (raw & INT_ID_MASK);
  277. if (id == GIC_SPURIOUS_INTERRUPT)
  278. id = INTR_ID_UNAVAILABLE;
  279. return id;
  280. }