tlbflush.h 5.0 KB

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