irqflags.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 by Ralf Baechle
  7. * Copyright (C) 1996 by Paul M. Antoine
  8. * Copyright (C) 1999 Silicon Graphics
  9. * Copyright (C) 2000 MIPS Technologies, Inc.
  10. */
  11. #ifndef _ASM_IRQFLAGS_H
  12. #define _ASM_IRQFLAGS_H
  13. #ifndef __ASSEMBLY__
  14. #include <asm/hazards.h>
  15. __asm__ (
  16. " .macro raw_local_irq_enable \n"
  17. " .set push \n"
  18. " .set reorder \n"
  19. " .set noat \n"
  20. #ifdef CONFIG_MIPS_MT_SMTC
  21. " mfc0 $1, $2, 1 # SMTC - clear TCStatus.IXMT \n"
  22. " ori $1, 0x400 \n"
  23. " xori $1, 0x400 \n"
  24. " mtc0 $1, $2, 1 \n"
  25. #elif defined(CONFIG_CPU_MIPSR2)
  26. " ei \n"
  27. #else
  28. " mfc0 $1,$12 \n"
  29. " ori $1,0x1f \n"
  30. " xori $1,0x1e \n"
  31. " mtc0 $1,$12 \n"
  32. #endif
  33. " irq_enable_hazard \n"
  34. " .set pop \n"
  35. " .endm");
  36. static inline void raw_local_irq_enable(void)
  37. {
  38. __asm__ __volatile__(
  39. "raw_local_irq_enable"
  40. : /* no outputs */
  41. : /* no inputs */
  42. : "memory");
  43. }
  44. /*
  45. * For cli() we have to insert nops to make sure that the new value
  46. * has actually arrived in the status register before the end of this
  47. * macro.
  48. * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
  49. * no nops at all.
  50. */
  51. /*
  52. * For TX49, operating only IE bit is not enough.
  53. *
  54. * If mfc0 $12 follows store and the mfc0 is last instruction of a
  55. * page and fetching the next instruction causes TLB miss, the result
  56. * of the mfc0 might wrongly contain EXL bit.
  57. *
  58. * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
  59. *
  60. * Workaround: mask EXL bit of the result or place a nop before mfc0.
  61. */
  62. __asm__ (
  63. " .macro raw_local_irq_disable\n"
  64. " .set push \n"
  65. " .set noat \n"
  66. #ifdef CONFIG_MIPS_MT_SMTC
  67. " mfc0 $1, $2, 1 \n"
  68. " ori $1, 0x400 \n"
  69. " .set noreorder \n"
  70. " mtc0 $1, $2, 1 \n"
  71. #elif defined(CONFIG_CPU_MIPSR2)
  72. " di \n"
  73. #else
  74. " mfc0 $1,$12 \n"
  75. " ori $1,0x1f \n"
  76. " xori $1,0x1f \n"
  77. " .set noreorder \n"
  78. " mtc0 $1,$12 \n"
  79. #endif
  80. " irq_disable_hazard \n"
  81. " .set pop \n"
  82. " .endm \n");
  83. static inline void raw_local_irq_disable(void)
  84. {
  85. __asm__ __volatile__(
  86. "raw_local_irq_disable"
  87. : /* no outputs */
  88. : /* no inputs */
  89. : "memory");
  90. }
  91. __asm__ (
  92. " .macro raw_local_save_flags flags \n"
  93. " .set push \n"
  94. " .set reorder \n"
  95. #ifdef CONFIG_MIPS_MT_SMTC
  96. " mfc0 \\flags, $2, 1 \n"
  97. #else
  98. " mfc0 \\flags, $12 \n"
  99. #endif
  100. " .set pop \n"
  101. " .endm \n");
  102. #define raw_local_save_flags(x) \
  103. __asm__ __volatile__( \
  104. "raw_local_save_flags %0" \
  105. : "=r" (x))
  106. __asm__ (
  107. " .macro raw_local_irq_save result \n"
  108. " .set push \n"
  109. " .set reorder \n"
  110. " .set noat \n"
  111. #ifdef CONFIG_MIPS_MT_SMTC
  112. " mfc0 \\result, $2, 1 \n"
  113. " ori $1, \\result, 0x400 \n"
  114. " .set noreorder \n"
  115. " mtc0 $1, $2, 1 \n"
  116. " andi \\result, \\result, 0x400 \n"
  117. #elif defined(CONFIG_CPU_MIPSR2)
  118. " di \\result \n"
  119. " andi \\result, 1 \n"
  120. #else
  121. " mfc0 \\result, $12 \n"
  122. " ori $1, \\result, 0x1f \n"
  123. " xori $1, 0x1f \n"
  124. " .set noreorder \n"
  125. " mtc0 $1, $12 \n"
  126. #endif
  127. " irq_disable_hazard \n"
  128. " .set pop \n"
  129. " .endm \n");
  130. #define raw_local_irq_save(x) \
  131. __asm__ __volatile__( \
  132. "raw_local_irq_save\t%0" \
  133. : "=r" (x) \
  134. : /* no inputs */ \
  135. : "memory")
  136. __asm__ (
  137. " .macro raw_local_irq_restore flags \n"
  138. " .set push \n"
  139. " .set noreorder \n"
  140. " .set noat \n"
  141. #ifdef CONFIG_MIPS_MT_SMTC
  142. "mfc0 $1, $2, 1 \n"
  143. "andi \\flags, 0x400 \n"
  144. "ori $1, 0x400 \n"
  145. "xori $1, 0x400 \n"
  146. "or \\flags, $1 \n"
  147. "mtc0 \\flags, $2, 1 \n"
  148. #elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
  149. /*
  150. * Slow, but doesn't suffer from a relativly unlikely race
  151. * condition we're having since days 1.
  152. */
  153. " beqz \\flags, 1f \n"
  154. " di \n"
  155. " ei \n"
  156. "1: \n"
  157. #elif defined(CONFIG_CPU_MIPSR2)
  158. /*
  159. * Fast, dangerous. Life is fun, life is good.
  160. */
  161. " mfc0 $1, $12 \n"
  162. " ins $1, \\flags, 0, 1 \n"
  163. " mtc0 $1, $12 \n"
  164. #else
  165. " mfc0 $1, $12 \n"
  166. " andi \\flags, 1 \n"
  167. " ori $1, 0x1f \n"
  168. " xori $1, 0x1f \n"
  169. " or \\flags, $1 \n"
  170. " mtc0 \\flags, $12 \n"
  171. #endif
  172. " irq_disable_hazard \n"
  173. " .set pop \n"
  174. " .endm \n");
  175. #define raw_local_irq_restore(flags) \
  176. do { \
  177. unsigned long __tmp1; \
  178. \
  179. __asm__ __volatile__( \
  180. "raw_local_irq_restore\t%0" \
  181. : "=r" (__tmp1) \
  182. : "0" (flags) \
  183. : "memory"); \
  184. } while(0)
  185. static inline int raw_irqs_disabled_flags(unsigned long flags)
  186. {
  187. #ifdef CONFIG_MIPS_MT_SMTC
  188. /*
  189. * SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU
  190. */
  191. return flags & 0x400;
  192. #else
  193. return !(flags & 1);
  194. #endif
  195. }
  196. #endif
  197. /*
  198. * Do the CPU's IRQ-state tracing from assembly code.
  199. */
  200. #ifdef CONFIG_TRACE_IRQFLAGS
  201. # define TRACE_IRQS_ON \
  202. jal trace_hardirqs_on
  203. # define TRACE_IRQS_OFF \
  204. jal trace_hardirqs_off
  205. #else
  206. # define TRACE_IRQS_ON
  207. # define TRACE_IRQS_OFF
  208. #endif
  209. #endif /* _ASM_IRQFLAGS_H */