at v5.0 348 lines 8.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2// Copyright (C) 2005-2017 Andes Technology Corporation 3 4#include <linux/mm.h> 5#include <linux/sched.h> 6#include <linux/fs.h> 7#include <linux/pagemap.h> 8#include <linux/module.h> 9#include <asm/cacheflush.h> 10#include <asm/proc-fns.h> 11#include <asm/shmparam.h> 12#include <asm/cache_info.h> 13 14extern struct cache_info L1_cache_info[2]; 15 16void flush_icache_range(unsigned long start, unsigned long end) 17{ 18 unsigned long line_size, flags; 19 line_size = L1_cache_info[DCACHE].line_size; 20 start = start & ~(line_size - 1); 21 end = (end + line_size - 1) & ~(line_size - 1); 22 local_irq_save(flags); 23 cpu_cache_wbinval_range(start, end, 1); 24 local_irq_restore(flags); 25} 26EXPORT_SYMBOL(flush_icache_range); 27 28void flush_icache_page(struct vm_area_struct *vma, struct page *page) 29{ 30 unsigned long flags; 31 unsigned long kaddr; 32 local_irq_save(flags); 33 kaddr = (unsigned long)kmap_atomic(page); 34 cpu_cache_wbinval_page(kaddr, vma->vm_flags & VM_EXEC); 35 kunmap_atomic((void *)kaddr); 36 local_irq_restore(flags); 37} 38EXPORT_SYMBOL(flush_icache_page); 39 40void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, 41 unsigned long addr, int len) 42{ 43 unsigned long kaddr; 44 kaddr = (unsigned long)kmap_atomic(page) + (addr & ~PAGE_MASK); 45 flush_icache_range(kaddr, kaddr + len); 46 kunmap_atomic((void *)kaddr); 47} 48 49void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, 50 pte_t * pte) 51{ 52 struct page *page; 53 unsigned long pfn = pte_pfn(*pte); 54 unsigned long flags; 55 56 if (!pfn_valid(pfn)) 57 return; 58 59 if (vma->vm_mm == current->active_mm) { 60 local_irq_save(flags); 61 __nds32__mtsr_dsb(addr, NDS32_SR_TLB_VPN); 62 __nds32__tlbop_rwr(*pte); 63 __nds32__isb(); 64 local_irq_restore(flags); 65 } 66 page = pfn_to_page(pfn); 67 68 if ((test_and_clear_bit(PG_dcache_dirty, &page->flags)) || 69 (vma->vm_flags & VM_EXEC)) { 70 unsigned long kaddr; 71 local_irq_save(flags); 72 kaddr = (unsigned long)kmap_atomic(page); 73 cpu_cache_wbinval_page(kaddr, vma->vm_flags & VM_EXEC); 74 kunmap_atomic((void *)kaddr); 75 local_irq_restore(flags); 76 } 77} 78#ifdef CONFIG_CPU_CACHE_ALIASING 79extern pte_t va_present(struct mm_struct *mm, unsigned long addr); 80 81static inline unsigned long aliasing(unsigned long addr, unsigned long page) 82{ 83 return ((addr & PAGE_MASK) ^ page) & (SHMLBA - 1); 84} 85 86static inline unsigned long kremap0(unsigned long uaddr, unsigned long pa) 87{ 88 unsigned long kaddr, pte; 89 90#define BASE_ADDR0 0xffffc000 91 kaddr = BASE_ADDR0 | (uaddr & L1_cache_info[DCACHE].aliasing_mask); 92 pte = (pa | PAGE_KERNEL); 93 __nds32__mtsr_dsb(kaddr, NDS32_SR_TLB_VPN); 94 __nds32__tlbop_rwlk(pte); 95 __nds32__isb(); 96 return kaddr; 97} 98 99static inline void kunmap01(unsigned long kaddr) 100{ 101 __nds32__tlbop_unlk(kaddr); 102 __nds32__tlbop_inv(kaddr); 103 __nds32__isb(); 104} 105 106static inline unsigned long kremap1(unsigned long uaddr, unsigned long pa) 107{ 108 unsigned long kaddr, pte; 109 110#define BASE_ADDR1 0xffff8000 111 kaddr = BASE_ADDR1 | (uaddr & L1_cache_info[DCACHE].aliasing_mask); 112 pte = (pa | PAGE_KERNEL); 113 __nds32__mtsr_dsb(kaddr, NDS32_SR_TLB_VPN); 114 __nds32__tlbop_rwlk(pte); 115 __nds32__isb(); 116 return kaddr; 117} 118 119void flush_cache_mm(struct mm_struct *mm) 120{ 121 unsigned long flags; 122 123 local_irq_save(flags); 124 cpu_dcache_wbinval_all(); 125 cpu_icache_inval_all(); 126 local_irq_restore(flags); 127} 128 129void flush_cache_dup_mm(struct mm_struct *mm) 130{ 131} 132 133void flush_cache_range(struct vm_area_struct *vma, 134 unsigned long start, unsigned long end) 135{ 136 unsigned long flags; 137 138 if ((end - start) > 8 * PAGE_SIZE) { 139 cpu_dcache_wbinval_all(); 140 if (vma->vm_flags & VM_EXEC) 141 cpu_icache_inval_all(); 142 return; 143 } 144 local_irq_save(flags); 145 while (start < end) { 146 if (va_present(vma->vm_mm, start)) 147 cpu_cache_wbinval_page(start, vma->vm_flags & VM_EXEC); 148 start += PAGE_SIZE; 149 } 150 local_irq_restore(flags); 151 return; 152} 153 154void flush_cache_page(struct vm_area_struct *vma, 155 unsigned long addr, unsigned long pfn) 156{ 157 unsigned long vto, flags; 158 159 local_irq_save(flags); 160 vto = kremap0(addr, pfn << PAGE_SHIFT); 161 cpu_cache_wbinval_page(vto, vma->vm_flags & VM_EXEC); 162 kunmap01(vto); 163 local_irq_restore(flags); 164} 165 166void flush_cache_vmap(unsigned long start, unsigned long end) 167{ 168 cpu_dcache_wbinval_all(); 169 cpu_icache_inval_all(); 170} 171 172void flush_cache_vunmap(unsigned long start, unsigned long end) 173{ 174 cpu_dcache_wbinval_all(); 175 cpu_icache_inval_all(); 176} 177 178void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, 179 struct page *to) 180{ 181 cpu_dcache_wbinval_page((unsigned long)vaddr); 182 cpu_icache_inval_page((unsigned long)vaddr); 183 copy_page(vto, vfrom); 184 cpu_dcache_wbinval_page((unsigned long)vto); 185 cpu_icache_inval_page((unsigned long)vto); 186} 187 188void clear_user_page(void *addr, unsigned long vaddr, struct page *page) 189{ 190 cpu_dcache_wbinval_page((unsigned long)vaddr); 191 cpu_icache_inval_page((unsigned long)vaddr); 192 clear_page(addr); 193 cpu_dcache_wbinval_page((unsigned long)addr); 194 cpu_icache_inval_page((unsigned long)addr); 195} 196 197void copy_user_highpage(struct page *to, struct page *from, 198 unsigned long vaddr, struct vm_area_struct *vma) 199{ 200 unsigned long vto, vfrom, flags, kto, kfrom, pfrom, pto; 201 kto = ((unsigned long)page_address(to) & PAGE_MASK); 202 kfrom = ((unsigned long)page_address(from) & PAGE_MASK); 203 pto = page_to_phys(to); 204 pfrom = page_to_phys(from); 205 206 local_irq_save(flags); 207 if (aliasing(vaddr, (unsigned long)kfrom)) 208 cpu_dcache_wb_page((unsigned long)kfrom); 209 vto = kremap0(vaddr, pto); 210 vfrom = kremap1(vaddr, pfrom); 211 copy_page((void *)vto, (void *)vfrom); 212 kunmap01(vfrom); 213 kunmap01(vto); 214 local_irq_restore(flags); 215} 216 217EXPORT_SYMBOL(copy_user_highpage); 218 219void clear_user_highpage(struct page *page, unsigned long vaddr) 220{ 221 unsigned long vto, flags, kto; 222 223 kto = ((unsigned long)page_address(page) & PAGE_MASK); 224 225 local_irq_save(flags); 226 if (aliasing(kto, vaddr) && kto != 0) { 227 cpu_dcache_inval_page(kto); 228 cpu_icache_inval_page(kto); 229 } 230 vto = kremap0(vaddr, page_to_phys(page)); 231 clear_page((void *)vto); 232 kunmap01(vto); 233 local_irq_restore(flags); 234} 235 236EXPORT_SYMBOL(clear_user_highpage); 237 238void flush_dcache_page(struct page *page) 239{ 240 struct address_space *mapping; 241 242 mapping = page_mapping(page); 243 if (mapping && !mapping_mapped(mapping)) 244 set_bit(PG_dcache_dirty, &page->flags); 245 else { 246 unsigned long kaddr, flags; 247 248 kaddr = (unsigned long)page_address(page); 249 local_irq_save(flags); 250 cpu_dcache_wbinval_page(kaddr); 251 if (mapping) { 252 unsigned long vaddr, kto; 253 254 vaddr = page->index << PAGE_SHIFT; 255 if (aliasing(vaddr, kaddr)) { 256 kto = kremap0(vaddr, page_to_phys(page)); 257 cpu_dcache_wbinval_page(kto); 258 kunmap01(kto); 259 } 260 } 261 local_irq_restore(flags); 262 } 263} 264EXPORT_SYMBOL(flush_dcache_page); 265 266void copy_to_user_page(struct vm_area_struct *vma, struct page *page, 267 unsigned long vaddr, void *dst, void *src, int len) 268{ 269 unsigned long line_size, start, end, vto, flags; 270 271 local_irq_save(flags); 272 vto = kremap0(vaddr, page_to_phys(page)); 273 dst = (void *)(vto | (vaddr & (PAGE_SIZE - 1))); 274 memcpy(dst, src, len); 275 if (vma->vm_flags & VM_EXEC) { 276 line_size = L1_cache_info[DCACHE].line_size; 277 start = (unsigned long)dst & ~(line_size - 1); 278 end = 279 ((unsigned long)dst + len + line_size - 1) & ~(line_size - 280 1); 281 cpu_cache_wbinval_range(start, end, 1); 282 } 283 kunmap01(vto); 284 local_irq_restore(flags); 285} 286 287void copy_from_user_page(struct vm_area_struct *vma, struct page *page, 288 unsigned long vaddr, void *dst, void *src, int len) 289{ 290 unsigned long vto, flags; 291 292 local_irq_save(flags); 293 vto = kremap0(vaddr, page_to_phys(page)); 294 src = (void *)(vto | (vaddr & (PAGE_SIZE - 1))); 295 memcpy(dst, src, len); 296 kunmap01(vto); 297 local_irq_restore(flags); 298} 299 300void flush_anon_page(struct vm_area_struct *vma, 301 struct page *page, unsigned long vaddr) 302{ 303 unsigned long kaddr, flags, ktmp; 304 if (!PageAnon(page)) 305 return; 306 307 if (vma->vm_mm != current->active_mm) 308 return; 309 310 local_irq_save(flags); 311 if (vma->vm_flags & VM_EXEC) 312 cpu_icache_inval_page(vaddr & PAGE_MASK); 313 kaddr = (unsigned long)page_address(page); 314 if (aliasing(vaddr, kaddr)) { 315 ktmp = kremap0(vaddr, page_to_phys(page)); 316 cpu_dcache_wbinval_page(ktmp); 317 kunmap01(ktmp); 318 } 319 local_irq_restore(flags); 320} 321 322void flush_kernel_dcache_page(struct page *page) 323{ 324 unsigned long flags; 325 local_irq_save(flags); 326 cpu_dcache_wbinval_page((unsigned long)page_address(page)); 327 local_irq_restore(flags); 328} 329EXPORT_SYMBOL(flush_kernel_dcache_page); 330 331void flush_kernel_vmap_range(void *addr, int size) 332{ 333 unsigned long flags; 334 local_irq_save(flags); 335 cpu_dcache_wb_range((unsigned long)addr, (unsigned long)addr + size); 336 local_irq_restore(flags); 337} 338EXPORT_SYMBOL(flush_kernel_vmap_range); 339 340void invalidate_kernel_vmap_range(void *addr, int size) 341{ 342 unsigned long flags; 343 local_irq_save(flags); 344 cpu_dcache_inval_range((unsigned long)addr, (unsigned long)addr + size); 345 local_irq_restore(flags); 346} 347EXPORT_SYMBOL(invalidate_kernel_vmap_range); 348#endif