tlbflush.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. #ifndef _M68K_TLBFLUSH_H
  2. #define _M68K_TLBFLUSH_H
  3. #ifdef CONFIG_MMU
  4. #ifndef CONFIG_SUN3
  5. #include <asm/current.h>
  6. static inline void flush_tlb_kernel_page(void *addr)
  7. {
  8. if (CPU_IS_040_OR_060) {
  9. mm_segment_t old_fs = get_fs();
  10. set_fs(KERNEL_DS);
  11. __asm__ __volatile__(".chip 68040\n\t"
  12. "pflush (%0)\n\t"
  13. ".chip 68k"
  14. : : "a" (addr));
  15. set_fs(old_fs);
  16. } else if (CPU_IS_020_OR_030)
  17. __asm__ __volatile__("pflush #4,#4,(%0)" : : "a" (addr));
  18. }
  19. /*
  20. * flush all user-space atc entries.
  21. */
  22. static inline void __flush_tlb(void)
  23. {
  24. if (CPU_IS_040_OR_060)
  25. __asm__ __volatile__(".chip 68040\n\t"
  26. "pflushan\n\t"
  27. ".chip 68k");
  28. else if (CPU_IS_020_OR_030)
  29. __asm__ __volatile__("pflush #0,#4");
  30. }
  31. static inline void __flush_tlb040_one(unsigned long addr)
  32. {
  33. __asm__ __volatile__(".chip 68040\n\t"
  34. "pflush (%0)\n\t"
  35. ".chip 68k"
  36. : : "a" (addr));
  37. }
  38. static inline void __flush_tlb_one(unsigned long addr)
  39. {
  40. if (CPU_IS_040_OR_060)
  41. __flush_tlb040_one(addr);
  42. else if (CPU_IS_020_OR_030)
  43. __asm__ __volatile__("pflush #0,#4,(%0)" : : "a" (addr));
  44. }
  45. #define flush_tlb() __flush_tlb()
  46. /*
  47. * flush all atc entries (both kernel and user-space entries).
  48. */
  49. static inline void flush_tlb_all(void)
  50. {
  51. if (CPU_IS_040_OR_060)
  52. __asm__ __volatile__(".chip 68040\n\t"
  53. "pflusha\n\t"
  54. ".chip 68k");
  55. else if (CPU_IS_020_OR_030)
  56. __asm__ __volatile__("pflusha");
  57. }
  58. static inline void flush_tlb_mm(struct mm_struct *mm)
  59. {
  60. if (mm == current->active_mm)
  61. __flush_tlb();
  62. }
  63. static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
  64. {
  65. if (vma->vm_mm == current->active_mm) {
  66. mm_segment_t old_fs = get_fs();
  67. set_fs(USER_DS);
  68. __flush_tlb_one(addr);
  69. set_fs(old_fs);
  70. }
  71. }
  72. static inline void flush_tlb_range(struct vm_area_struct *vma,
  73. unsigned long start, unsigned long end)
  74. {
  75. if (vma->vm_mm == current->active_mm)
  76. __flush_tlb();
  77. }
  78. static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
  79. {
  80. flush_tlb_all();
  81. }
  82. #else
  83. /* Reserved PMEGs. */
  84. extern char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
  85. extern unsigned long pmeg_vaddr[SUN3_PMEGS_NUM];
  86. extern unsigned char pmeg_alloc[SUN3_PMEGS_NUM];
  87. extern unsigned char pmeg_ctx[SUN3_PMEGS_NUM];
  88. /* Flush all userspace mappings one by one... (why no flush command,
  89. sun?) */
  90. static inline void flush_tlb_all(void)
  91. {
  92. unsigned long addr;
  93. unsigned char ctx, oldctx;
  94. oldctx = sun3_get_context();
  95. for(addr = 0x00000000; addr < TASK_SIZE; addr += SUN3_PMEG_SIZE) {
  96. for(ctx = 0; ctx < 8; ctx++) {
  97. sun3_put_context(ctx);
  98. sun3_put_segmap(addr, SUN3_INVALID_PMEG);
  99. }
  100. }
  101. sun3_put_context(oldctx);
  102. /* erase all of the userspace pmeg maps, we've clobbered them
  103. all anyway */
  104. for(addr = 0; addr < SUN3_INVALID_PMEG; addr++) {
  105. if(pmeg_alloc[addr] == 1) {
  106. pmeg_alloc[addr] = 0;
  107. pmeg_ctx[addr] = 0;
  108. pmeg_vaddr[addr] = 0;
  109. }
  110. }
  111. }
  112. /* Clear user TLB entries within the context named in mm */
  113. static inline void flush_tlb_mm (struct mm_struct *mm)
  114. {
  115. unsigned char oldctx;
  116. unsigned char seg;
  117. unsigned long i;
  118. oldctx = sun3_get_context();
  119. sun3_put_context(mm->context);
  120. for(i = 0; i < TASK_SIZE; i += SUN3_PMEG_SIZE) {
  121. seg = sun3_get_segmap(i);
  122. if(seg == SUN3_INVALID_PMEG)
  123. continue;
  124. sun3_put_segmap(i, SUN3_INVALID_PMEG);
  125. pmeg_alloc[seg] = 0;
  126. pmeg_ctx[seg] = 0;
  127. pmeg_vaddr[seg] = 0;
  128. }
  129. sun3_put_context(oldctx);
  130. }
  131. /* Flush a single TLB page. In this case, we're limited to flushing a
  132. single PMEG */
  133. static inline void flush_tlb_page (struct vm_area_struct *vma,
  134. unsigned long addr)
  135. {
  136. unsigned char oldctx;
  137. unsigned char i;
  138. oldctx = sun3_get_context();
  139. sun3_put_context(vma->vm_mm->context);
  140. addr &= ~SUN3_PMEG_MASK;
  141. if((i = sun3_get_segmap(addr)) != SUN3_INVALID_PMEG)
  142. {
  143. pmeg_alloc[i] = 0;
  144. pmeg_ctx[i] = 0;
  145. pmeg_vaddr[i] = 0;
  146. sun3_put_segmap (addr, SUN3_INVALID_PMEG);
  147. }
  148. sun3_put_context(oldctx);
  149. }
  150. /* Flush a range of pages from TLB. */
  151. static inline void flush_tlb_range (struct vm_area_struct *vma,
  152. unsigned long start, unsigned long end)
  153. {
  154. struct mm_struct *mm = vma->vm_mm;
  155. unsigned char seg, oldctx;
  156. start &= ~SUN3_PMEG_MASK;
  157. oldctx = sun3_get_context();
  158. sun3_put_context(mm->context);
  159. while(start < end)
  160. {
  161. if((seg = sun3_get_segmap(start)) == SUN3_INVALID_PMEG)
  162. goto next;
  163. if(pmeg_ctx[seg] == mm->context) {
  164. pmeg_alloc[seg] = 0;
  165. pmeg_ctx[seg] = 0;
  166. pmeg_vaddr[seg] = 0;
  167. }
  168. sun3_put_segmap(start, SUN3_INVALID_PMEG);
  169. next:
  170. start += SUN3_PMEG_SIZE;
  171. }
  172. }
  173. static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
  174. {
  175. flush_tlb_all();
  176. }
  177. /* Flush kernel page from TLB. */
  178. static inline void flush_tlb_kernel_page (unsigned long addr)
  179. {
  180. sun3_put_segmap (addr & ~(SUN3_PMEG_SIZE - 1), SUN3_INVALID_PMEG);
  181. }
  182. #endif
  183. #else /* !CONFIG_MMU */
  184. /*
  185. * flush all user-space atc entries.
  186. */
  187. static inline void __flush_tlb(void)
  188. {
  189. BUG();
  190. }
  191. static inline void __flush_tlb_one(unsigned long addr)
  192. {
  193. BUG();
  194. }
  195. #define flush_tlb() __flush_tlb()
  196. /*
  197. * flush all atc entries (both kernel and user-space entries).
  198. */
  199. static inline void flush_tlb_all(void)
  200. {
  201. BUG();
  202. }
  203. static inline void flush_tlb_mm(struct mm_struct *mm)
  204. {
  205. BUG();
  206. }
  207. static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
  208. {
  209. BUG();
  210. }
  211. static inline void flush_tlb_range(struct mm_struct *mm,
  212. unsigned long start, unsigned long end)
  213. {
  214. BUG();
  215. }
  216. static inline void flush_tlb_kernel_page(unsigned long addr)
  217. {
  218. BUG();
  219. }
  220. #endif /* CONFIG_MMU */
  221. #endif /* _M68K_TLBFLUSH_H */