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