tsp_interrupt.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <inttypes.h>
  8. #include <platform_def.h>
  9. #include <arch_helpers.h>
  10. #include <bl32/tsp/tsp.h>
  11. #include <common/debug.h>
  12. #include <plat/common/platform.h>
  13. #include "tsp_private.h"
  14. /*******************************************************************************
  15. * This function updates the TSP statistics for S-EL1 interrupts handled
  16. * synchronously i.e the ones that have been handed over by the TSPD. It also
  17. * keeps count of the number of times control was passed back to the TSPD
  18. * after handling the interrupt. In the future it will be possible that the
  19. * TSPD hands over an S-EL1 interrupt to the TSP but does not expect it to
  20. * return execution. This statistic will be useful to distinguish between these
  21. * two models of synchronous S-EL1 interrupt handling. The 'elr_el3' parameter
  22. * contains the address of the instruction in normal world where this S-EL1
  23. * interrupt was generated.
  24. ******************************************************************************/
  25. void tsp_update_sync_sel1_intr_stats(uint32_t type, uint64_t elr_el3)
  26. {
  27. uint32_t linear_id = plat_my_core_pos();
  28. tsp_stats[linear_id].sync_sel1_intr_count++;
  29. if (type == TSP_HANDLE_SEL1_INTR_AND_RETURN)
  30. tsp_stats[linear_id].sync_sel1_intr_ret_count++;
  31. VERBOSE("TSP: cpu 0x%lx sync s-el1 interrupt request from 0x%" PRIx64 "\n",
  32. read_mpidr(), elr_el3);
  33. VERBOSE("TSP: cpu 0x%lx: %d sync s-el1 interrupt requests,"
  34. " %d sync s-el1 interrupt returns\n",
  35. read_mpidr(),
  36. tsp_stats[linear_id].sync_sel1_intr_count,
  37. tsp_stats[linear_id].sync_sel1_intr_ret_count);
  38. }
  39. /******************************************************************************
  40. * This function is invoked when a non S-EL1 interrupt is received and causes
  41. * the preemption of TSP. This function returns TSP_PREEMPTED and results
  42. * in the control being handed over to EL3 for handling the interrupt.
  43. *****************************************************************************/
  44. int32_t tsp_handle_preemption(void)
  45. {
  46. uint32_t linear_id = plat_my_core_pos();
  47. tsp_stats[linear_id].preempt_intr_count++;
  48. VERBOSE("TSP: cpu 0x%lx: %d preempt interrupt requests\n",
  49. read_mpidr(), tsp_stats[linear_id].preempt_intr_count);
  50. return TSP_PREEMPTED;
  51. }
  52. /*******************************************************************************
  53. * TSP interrupt handler is called as a part of both synchronous and
  54. * asynchronous handling of TSP interrupts. Currently the physical timer
  55. * interrupt is the only S-EL1 interrupt that this handler expects. It returns
  56. * 0 upon successfully handling the expected interrupt and all other
  57. * interrupts are treated as normal world or EL3 interrupts.
  58. ******************************************************************************/
  59. int32_t tsp_common_int_handler(void)
  60. {
  61. uint32_t linear_id = plat_my_core_pos(), id;
  62. /*
  63. * Get the highest priority pending interrupt id and see if it is the
  64. * secure physical generic timer interrupt in which case, handle it.
  65. * Otherwise throw this interrupt at the EL3 firmware.
  66. *
  67. * There is a small time window between reading the highest priority
  68. * pending interrupt and acknowledging it during which another
  69. * interrupt of higher priority could become the highest pending
  70. * interrupt. This is not expected to happen currently for TSP.
  71. */
  72. id = plat_ic_get_pending_interrupt_id();
  73. /* TSP can only handle the secure physical timer interrupt */
  74. if (id != TSP_IRQ_SEC_PHY_TIMER) {
  75. #if SPMC_AT_EL3
  76. /*
  77. * With the EL3 FF-A SPMC we expect only Timer secure interrupt to fire in
  78. * the TSP, so panic if any other interrupt does.
  79. */
  80. ERROR("Unexpected interrupt id %u\n", id);
  81. panic();
  82. #else
  83. return tsp_handle_preemption();
  84. #endif
  85. }
  86. /*
  87. * Acknowledge and handle the secure timer interrupt. Also sanity check
  88. * if it has been preempted by another interrupt through an assertion.
  89. */
  90. id = plat_ic_acknowledge_interrupt();
  91. assert(id == TSP_IRQ_SEC_PHY_TIMER);
  92. tsp_generic_timer_handler();
  93. plat_ic_end_of_interrupt(id);
  94. /* Update the statistics and print some messages */
  95. tsp_stats[linear_id].sel1_intr_count++;
  96. VERBOSE("TSP: cpu 0x%lx handled S-EL1 interrupt %d\n",
  97. read_mpidr(), id);
  98. VERBOSE("TSP: cpu 0x%lx: %d S-EL1 requests\n",
  99. read_mpidr(), tsp_stats[linear_id].sel1_intr_count);
  100. return 0;
  101. }