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