tsp_interrupt.c 4.4 KB

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