sdei_state.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <stdbool.h>
  8. #include <lib/cassert.h>
  9. #include "sdei_private.h"
  10. /* Aliases for SDEI handler states: 'R'unning, 'E'nabled, and re'G'istered */
  11. #define r_ 0U
  12. #define R_ (1u << SDEI_STATF_RUNNING)
  13. #define e_ 0U
  14. #define E_ (1u << SDEI_STATF_ENABLED)
  15. #define g_ 0U
  16. #define G_ (1u << SDEI_STATF_REGISTERED)
  17. /* All possible composite handler states */
  18. #define reg_ (r_ | e_ | g_)
  19. #define reG_ (r_ | e_ | G_)
  20. #define rEg_ (r_ | E_ | g_)
  21. #define rEG_ (r_ | E_ | G_)
  22. #define Reg_ (R_ | e_ | g_)
  23. #define ReG_ (R_ | e_ | G_)
  24. #define REg_ (R_ | E_ | g_)
  25. #define REG_ (R_ | E_ | G_)
  26. #define MAX_STATES (REG_ + 1u)
  27. /* Invalid state */
  28. #define SDEI_STATE_INVALID ((sdei_state_t) (-1))
  29. /* No change in state */
  30. #define SDEI_STATE_NOP ((sdei_state_t) (-2))
  31. #define X___ SDEI_STATE_INVALID
  32. #define NOP_ SDEI_STATE_NOP
  33. /* Ensure special states don't overlap with valid ones */
  34. CASSERT(X___ > REG_, sdei_state_overlap_invalid);
  35. CASSERT(NOP_ > REG_, sdei_state_overlap_nop);
  36. /*
  37. * SDEI handler state machine: refer to sections 6.1 and 6.1.2 of the SDEI v1.0
  38. * specification (ARM DEN0054A).
  39. *
  40. * Not all calls contribute to handler state transition. This table is also used
  41. * to validate whether a call is permissible at a given handler state:
  42. *
  43. * - X___ denotes a forbidden transition;
  44. * - NOP_ denotes a permitted transition, but there's no change in state;
  45. * - Otherwise, XXX_ gives the new state.
  46. *
  47. * DISP[atch] is a transition added for the implementation, but is not mentioned
  48. * in the spec.
  49. *
  50. * Those calls that the spec mentions as can be made any time don't picture in
  51. * this table.
  52. */
  53. static const sdei_state_t sdei_state_table[MAX_STATES][DO_MAX] = {
  54. /*
  55. * Action: REG REL ENA DISA UREG ROUT CTX COMP COMPR DISP
  56. * Notes: [3] [1] [3] [3][4] [2]
  57. */
  58. /* Handler unregistered, disabled, and not running. This is the default state. */
  59. /* 0 */ [reg_] = { reG_, NOP_, X___, X___, X___, X___, X___, X___, X___, X___, },
  60. /* Handler unregistered and running */
  61. /* 4 */ [Reg_] = { X___, X___, X___, X___, X___, X___, NOP_, reg_, reg_, X___, },
  62. /* Handler registered */
  63. /* 1 */ [reG_] = { X___, X___, rEG_, NOP_, reg_, NOP_, X___, X___, X___, X___, },
  64. /* Handler registered and running */
  65. /* 5 */ [ReG_] = { X___, X___, REG_, NOP_, Reg_, X___, NOP_, reG_, reG_, X___, },
  66. /* Handler registered and enabled */
  67. /* 3 */ [rEG_] = { X___, X___, NOP_, reG_, reg_, X___, X___, X___, X___, REG_, },
  68. /* Handler registered, enabled, and running */
  69. /* 7 */ [REG_] = { X___, X___, NOP_, ReG_, Reg_, X___, NOP_, rEG_, rEG_, X___, },
  70. /*
  71. * Invalid states: no valid transition would leave the handler in these
  72. * states; and no transition from these states is possible either.
  73. */
  74. /*
  75. * Handler can't be enabled without being registered. I.e., XEg is
  76. * impossible.
  77. */
  78. /* 2 */ [rEg_] = { X___, X___, X___, X___, X___, X___, X___, X___, X___, X___, },
  79. /* 6 */ [REg_] = { X___, X___, X___, X___, X___, X___, X___, X___, X___, X___, },
  80. };
  81. /*
  82. * [1] Unregister will always also disable the event, so the new state will have
  83. * Xeg.
  84. * [2] Event is considered for dispatch only when it's both registered and
  85. * enabled.
  86. * [3] Never causes change in state.
  87. * [4] Only allowed when running.
  88. */
  89. /*
  90. * Given an action, transition the state of an event by looking up the state
  91. * table above:
  92. *
  93. * - Return false for invalid transition;
  94. * - Return true for valid transition that causes no change in state;
  95. * - Otherwise, update state and return true.
  96. *
  97. * This function assumes that the caller holds necessary locks. If the
  98. * transition has constrains other than the state table describes, the caller is
  99. * expected to restore the previous state. See sdei_event_register() for
  100. * example.
  101. */
  102. bool can_sdei_state_trans(sdei_entry_t *se, sdei_action_t act)
  103. {
  104. sdei_state_t next;
  105. assert(act < DO_MAX);
  106. if (se->state >= MAX_STATES) {
  107. WARN(" event state invalid: %x\n", se->state);
  108. return false;
  109. }
  110. next = sdei_state_table[se->state][act];
  111. switch (next) {
  112. case SDEI_STATE_INVALID:
  113. return false;
  114. case SDEI_STATE_NOP:
  115. return true;
  116. default:
  117. /* Valid transition. Update state. */
  118. SDEI_LOG(" event state 0x%x => 0x%x\n", se->state, next);
  119. se->state = next;
  120. return true;
  121. }
  122. }