Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.28 219 lines 5.0 kB view raw
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 if (CPU_IS_020_OR_030) 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 if (CPU_IS_020_OR_030) 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 if (CPU_IS_020_OR_030) 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 if (CPU_IS_020_OR_030) 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 95#else 96 97 98/* Reserved PMEGs. */ 99extern char sun3_reserved_pmeg[SUN3_PMEGS_NUM]; 100extern unsigned long pmeg_vaddr[SUN3_PMEGS_NUM]; 101extern unsigned char pmeg_alloc[SUN3_PMEGS_NUM]; 102extern unsigned char pmeg_ctx[SUN3_PMEGS_NUM]; 103 104/* Flush all userspace mappings one by one... (why no flush command, 105 sun?) */ 106static inline void flush_tlb_all(void) 107{ 108 unsigned long addr; 109 unsigned char ctx, oldctx; 110 111 oldctx = sun3_get_context(); 112 for(addr = 0x00000000; addr < TASK_SIZE; addr += SUN3_PMEG_SIZE) { 113 for(ctx = 0; ctx < 8; ctx++) { 114 sun3_put_context(ctx); 115 sun3_put_segmap(addr, SUN3_INVALID_PMEG); 116 } 117 } 118 119 sun3_put_context(oldctx); 120 /* erase all of the userspace pmeg maps, we've clobbered them 121 all anyway */ 122 for(addr = 0; addr < SUN3_INVALID_PMEG; addr++) { 123 if(pmeg_alloc[addr] == 1) { 124 pmeg_alloc[addr] = 0; 125 pmeg_ctx[addr] = 0; 126 pmeg_vaddr[addr] = 0; 127 } 128 } 129 130} 131 132/* Clear user TLB entries within the context named in mm */ 133static inline void flush_tlb_mm (struct mm_struct *mm) 134{ 135 unsigned char oldctx; 136 unsigned char seg; 137 unsigned long i; 138 139 oldctx = sun3_get_context(); 140 sun3_put_context(mm->context); 141 142 for(i = 0; i < TASK_SIZE; i += SUN3_PMEG_SIZE) { 143 seg = sun3_get_segmap(i); 144 if(seg == SUN3_INVALID_PMEG) 145 continue; 146 147 sun3_put_segmap(i, SUN3_INVALID_PMEG); 148 pmeg_alloc[seg] = 0; 149 pmeg_ctx[seg] = 0; 150 pmeg_vaddr[seg] = 0; 151 } 152 153 sun3_put_context(oldctx); 154 155} 156 157/* Flush a single TLB page. In this case, we're limited to flushing a 158 single PMEG */ 159static inline void flush_tlb_page (struct vm_area_struct *vma, 160 unsigned long addr) 161{ 162 unsigned char oldctx; 163 unsigned char i; 164 165 oldctx = sun3_get_context(); 166 sun3_put_context(vma->vm_mm->context); 167 addr &= ~SUN3_PMEG_MASK; 168 if((i = sun3_get_segmap(addr)) != SUN3_INVALID_PMEG) 169 { 170 pmeg_alloc[i] = 0; 171 pmeg_ctx[i] = 0; 172 pmeg_vaddr[i] = 0; 173 sun3_put_segmap (addr, SUN3_INVALID_PMEG); 174 } 175 sun3_put_context(oldctx); 176 177} 178/* Flush a range of pages from TLB. */ 179 180static inline void flush_tlb_range (struct vm_area_struct *vma, 181 unsigned long start, unsigned long end) 182{ 183 struct mm_struct *mm = vma->vm_mm; 184 unsigned char seg, oldctx; 185 186 start &= ~SUN3_PMEG_MASK; 187 188 oldctx = sun3_get_context(); 189 sun3_put_context(mm->context); 190 191 while(start < end) 192 { 193 if((seg = sun3_get_segmap(start)) == SUN3_INVALID_PMEG) 194 goto next; 195 if(pmeg_ctx[seg] == mm->context) { 196 pmeg_alloc[seg] = 0; 197 pmeg_ctx[seg] = 0; 198 pmeg_vaddr[seg] = 0; 199 } 200 sun3_put_segmap(start, SUN3_INVALID_PMEG); 201 next: 202 start += SUN3_PMEG_SIZE; 203 } 204} 205 206static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end) 207{ 208 flush_tlb_all(); 209} 210 211/* Flush kernel page from TLB. */ 212static inline void flush_tlb_kernel_page (unsigned long addr) 213{ 214 sun3_put_segmap (addr & ~(SUN3_PMEG_SIZE - 1), SUN3_INVALID_PMEG); 215} 216 217#endif 218 219#endif /* _M68K_TLBFLUSH_H */