entry.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #ifndef __BFIN_ENTRY_H
  2. #define __BFIN_ENTRY_H
  3. #include <asm/setup.h>
  4. #include <asm/page.h>
  5. #ifdef __ASSEMBLY__
  6. #define LFLUSH_I_AND_D 0x00000808
  7. #define LSIGTRAP 5
  8. /* process bits for task_struct.flags */
  9. #define PF_TRACESYS_OFF 3
  10. #define PF_TRACESYS_BIT 5
  11. #define PF_PTRACED_OFF 3
  12. #define PF_PTRACED_BIT 4
  13. #define PF_DTRACE_OFF 1
  14. #define PF_DTRACE_BIT 5
  15. /*
  16. * NOTE! The single-stepping code assumes that all interrupt handlers
  17. * start by saving SYSCFG on the stack with their first instruction.
  18. */
  19. /* This one is used for exceptions, emulation, and NMI. It doesn't push
  20. RETI and doesn't do cli. */
  21. #define SAVE_ALL_SYS save_context_no_interrupts
  22. /* This is used for all normal interrupts. It saves a minimum of registers
  23. to the stack, loads the IRQ number, and jumps to common code. */
  24. #ifdef CONFIG_IPIPE
  25. # define LOAD_IPIPE_IPEND \
  26. P0.l = lo(IPEND); \
  27. P0.h = hi(IPEND); \
  28. R1 = [P0];
  29. #else
  30. # define LOAD_IPIPE_IPEND
  31. #endif
  32. /*
  33. * Workaround for anomalies 05000283 and 05000315
  34. */
  35. #if ANOMALY_05000283 || ANOMALY_05000315
  36. # define ANOMALY_283_315_WORKAROUND(preg, dreg) \
  37. cc = dreg == dreg; \
  38. preg.h = HI(CHIPID); \
  39. preg.l = LO(CHIPID); \
  40. if cc jump 1f; \
  41. dreg.l = W[preg]; \
  42. 1:
  43. #else
  44. # define ANOMALY_283_315_WORKAROUND(preg, dreg)
  45. #endif /* ANOMALY_05000283 || ANOMALY_05000315 */
  46. #ifndef CONFIG_EXACT_HWERR
  47. /* As a debugging aid - we save IPEND when DEBUG_KERNEL is on,
  48. * otherwise it is a waste of cycles.
  49. */
  50. # ifndef CONFIG_DEBUG_KERNEL
  51. #define INTERRUPT_ENTRY(N) \
  52. [--sp] = SYSCFG; \
  53. [--sp] = P0; /*orig_p0*/ \
  54. [--sp] = R0; /*orig_r0*/ \
  55. [--sp] = (R7:0,P5:0); \
  56. R0 = (N); \
  57. LOAD_IPIPE_IPEND \
  58. jump __common_int_entry;
  59. # else /* CONFIG_DEBUG_KERNEL */
  60. #define INTERRUPT_ENTRY(N) \
  61. [--sp] = SYSCFG; \
  62. [--sp] = P0; /*orig_p0*/ \
  63. [--sp] = R0; /*orig_r0*/ \
  64. [--sp] = (R7:0,P5:0); \
  65. p0.l = lo(IPEND); \
  66. p0.h = hi(IPEND); \
  67. r1 = [p0]; \
  68. R0 = (N); \
  69. LOAD_IPIPE_IPEND \
  70. jump __common_int_entry;
  71. # endif /* CONFIG_DEBUG_KERNEL */
  72. /* For timer interrupts, we need to save IPEND, since the user_mode
  73. *macro accesses it to determine where to account time.
  74. */
  75. #define TIMER_INTERRUPT_ENTRY(N) \
  76. [--sp] = SYSCFG; \
  77. [--sp] = P0; /*orig_p0*/ \
  78. [--sp] = R0; /*orig_r0*/ \
  79. [--sp] = (R7:0,P5:0); \
  80. p0.l = lo(IPEND); \
  81. p0.h = hi(IPEND); \
  82. r1 = [p0]; \
  83. R0 = (N); \
  84. jump __common_int_entry;
  85. #else /* CONFIG_EXACT_HWERR is defined */
  86. /* if we want hardware error to be exact, we need to do a SSYNC (which forces
  87. * read/writes to complete to the memory controllers), and check to see that
  88. * caused a pending HW error condition. If so, we assume it was caused by user
  89. * space, by setting the same interrupt that we are in (so it goes off again)
  90. * and context restore, and a RTI (without servicing anything). This should
  91. * cause the pending HWERR to fire, and when that is done, this interrupt will
  92. * be re-serviced properly.
  93. * As you can see by the code - we actually need to do two SSYNCS - one to
  94. * make sure the read/writes complete, and another to make sure the hardware
  95. * error is recognized by the core.
  96. *
  97. * The extra nop before the SSYNC is to make sure we work around 05000244,
  98. * since the 283/315 workaround includes a branch to the end
  99. */
  100. #define INTERRUPT_ENTRY(N) \
  101. [--sp] = SYSCFG; \
  102. [--sp] = P0; /*orig_p0*/ \
  103. [--sp] = R0; /*orig_r0*/ \
  104. [--sp] = (R7:0,P5:0); \
  105. R1 = ASTAT; \
  106. ANOMALY_283_315_WORKAROUND(p0, r0) \
  107. P0.L = LO(ILAT); \
  108. P0.H = HI(ILAT); \
  109. NOP; \
  110. SSYNC; \
  111. SSYNC; \
  112. R0 = [P0]; \
  113. CC = BITTST(R0, EVT_IVHW_P); \
  114. IF CC JUMP 1f; \
  115. ASTAT = R1; \
  116. p0.l = lo(IPEND); \
  117. p0.h = hi(IPEND); \
  118. r1 = [p0]; \
  119. R0 = (N); \
  120. LOAD_IPIPE_IPEND \
  121. jump __common_int_entry; \
  122. 1: ASTAT = R1; \
  123. RAISE N; \
  124. (R7:0, P5:0) = [SP++]; \
  125. SP += 0x8; \
  126. SYSCFG = [SP++]; \
  127. CSYNC; \
  128. RTI;
  129. #define TIMER_INTERRUPT_ENTRY(N) \
  130. [--sp] = SYSCFG; \
  131. [--sp] = P0; /*orig_p0*/ \
  132. [--sp] = R0; /*orig_r0*/ \
  133. [--sp] = (R7:0,P5:0); \
  134. R1 = ASTAT; \
  135. ANOMALY_283_315_WORKAROUND(p0, r0) \
  136. P0.L = LO(ILAT); \
  137. P0.H = HI(ILAT); \
  138. NOP; \
  139. SSYNC; \
  140. SSYNC; \
  141. R0 = [P0]; \
  142. CC = BITTST(R0, EVT_IVHW_P); \
  143. IF CC JUMP 1f; \
  144. ASTAT = R1; \
  145. p0.l = lo(IPEND); \
  146. p0.h = hi(IPEND); \
  147. r1 = [p0]; \
  148. R0 = (N); \
  149. jump __common_int_entry; \
  150. 1: ASTAT = R1; \
  151. RAISE N; \
  152. (R7:0, P5:0) = [SP++]; \
  153. SP += 0x8; \
  154. SYSCFG = [SP++]; \
  155. CSYNC; \
  156. RTI;
  157. #endif /* CONFIG_EXACT_HWERR */
  158. /* This one pushes RETI without using CLI. Interrupts are enabled. */
  159. #define SAVE_CONTEXT_SYSCALL save_context_syscall
  160. #define SAVE_CONTEXT save_context_with_interrupts
  161. #define SAVE_CONTEXT_CPLB save_context_cplb
  162. #define RESTORE_ALL_SYS restore_context_no_interrupts
  163. #define RESTORE_CONTEXT restore_context_with_interrupts
  164. #define RESTORE_CONTEXT_CPLB restore_context_cplb
  165. #endif /* __ASSEMBLY__ */
  166. #endif /* __BFIN_ENTRY_H */