aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/kernel/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc/kernel/cache.c')
-rw-r--r--arch/parisc/kernel/cache.c88
1 files changed, 58 insertions, 30 deletions
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index 19c0c141bc3f..e3b45546d589 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -465,10 +465,10 @@ EXPORT_SYMBOL(copy_user_page);
465int __flush_tlb_range(unsigned long sid, unsigned long start, 465int __flush_tlb_range(unsigned long sid, unsigned long start,
466 unsigned long end) 466 unsigned long end)
467{ 467{
468 unsigned long flags, size; 468 unsigned long flags;
469 469
470 size = (end - start); 470 if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
471 if (size >= parisc_tlb_flush_threshold) { 471 end - start >= parisc_tlb_flush_threshold) {
472 flush_tlb_all(); 472 flush_tlb_all();
473 return 1; 473 return 1;
474 } 474 }
@@ -539,13 +539,12 @@ void flush_cache_mm(struct mm_struct *mm)
539 struct vm_area_struct *vma; 539 struct vm_area_struct *vma;
540 pgd_t *pgd; 540 pgd_t *pgd;
541 541
542 /* Flush the TLB to avoid speculation if coherency is required. */
543 if (parisc_requires_coherency())
544 flush_tlb_all();
545
546 /* Flushing the whole cache on each cpu takes forever on 542 /* Flushing the whole cache on each cpu takes forever on
547 rp3440, etc. So, avoid it if the mm isn't too big. */ 543 rp3440, etc. So, avoid it if the mm isn't too big. */
548 if (mm_total_size(mm) >= parisc_cache_flush_threshold) { 544 if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
545 mm_total_size(mm) >= parisc_cache_flush_threshold) {
546 if (mm->context)
547 flush_tlb_all();
549 flush_cache_all(); 548 flush_cache_all();
550 return; 549 return;
551 } 550 }
@@ -553,9 +552,9 @@ void flush_cache_mm(struct mm_struct *mm)
553 if (mm->context == mfsp(3)) { 552 if (mm->context == mfsp(3)) {
554 for (vma = mm->mmap; vma; vma = vma->vm_next) { 553 for (vma = mm->mmap; vma; vma = vma->vm_next) {
555 flush_user_dcache_range_asm(vma->vm_start, vma->vm_end); 554 flush_user_dcache_range_asm(vma->vm_start, vma->vm_end);
556 if ((vma->vm_flags & VM_EXEC) == 0) 555 if (vma->vm_flags & VM_EXEC)
557 continue; 556 flush_user_icache_range_asm(vma->vm_start, vma->vm_end);
558 flush_user_icache_range_asm(vma->vm_start, vma->vm_end); 557 flush_tlb_range(vma, vma->vm_start, vma->vm_end);
559 } 558 }
560 return; 559 return;
561 } 560 }
@@ -573,6 +572,8 @@ void flush_cache_mm(struct mm_struct *mm)
573 pfn = pte_pfn(*ptep); 572 pfn = pte_pfn(*ptep);
574 if (!pfn_valid(pfn)) 573 if (!pfn_valid(pfn))
575 continue; 574 continue;
575 if (unlikely(mm->context))
576 flush_tlb_page(vma, addr);
576 __flush_cache_page(vma, addr, PFN_PHYS(pfn)); 577 __flush_cache_page(vma, addr, PFN_PHYS(pfn));
577 } 578 }
578 } 579 }
@@ -581,30 +582,45 @@ void flush_cache_mm(struct mm_struct *mm)
581void flush_cache_range(struct vm_area_struct *vma, 582void flush_cache_range(struct vm_area_struct *vma,
582 unsigned long start, unsigned long end) 583 unsigned long start, unsigned long end)
583{ 584{
584 BUG_ON(!vma->vm_mm->context); 585 pgd_t *pgd;
585 586 unsigned long addr;
586 /* Flush the TLB to avoid speculation if coherency is required. */
587 if (parisc_requires_coherency())
588 flush_tlb_range(vma, start, end);
589 587
590 if ((end - start) >= parisc_cache_flush_threshold 588 if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
591 || vma->vm_mm->context != mfsp(3)) { 589 end - start >= parisc_cache_flush_threshold) {
590 if (vma->vm_mm->context)
591 flush_tlb_range(vma, start, end);
592 flush_cache_all(); 592 flush_cache_all();
593 return; 593 return;
594 } 594 }
595 595
596 flush_user_dcache_range_asm(start, end); 596 if (vma->vm_mm->context == mfsp(3)) {
597 if (vma->vm_flags & VM_EXEC) 597 flush_user_dcache_range_asm(start, end);
598 flush_user_icache_range_asm(start, end); 598 if (vma->vm_flags & VM_EXEC)
599 flush_user_icache_range_asm(start, end);
600 flush_tlb_range(vma, start, end);
601 return;
602 }
603
604 pgd = vma->vm_mm->pgd;
605 for (addr = vma->vm_start; addr < vma->vm_end; addr += PAGE_SIZE) {
606 unsigned long pfn;
607 pte_t *ptep = get_ptep(pgd, addr);
608 if (!ptep)
609 continue;
610 pfn = pte_pfn(*ptep);
611 if (pfn_valid(pfn)) {
612 if (unlikely(vma->vm_mm->context))
613 flush_tlb_page(vma, addr);
614 __flush_cache_page(vma, addr, PFN_PHYS(pfn));
615 }
616 }
599} 617}
600 618
601void 619void
602flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn) 620flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
603{ 621{
604 BUG_ON(!vma->vm_mm->context);
605
606 if (pfn_valid(pfn)) { 622 if (pfn_valid(pfn)) {
607 if (parisc_requires_coherency()) 623 if (likely(vma->vm_mm->context))
608 flush_tlb_page(vma, vmaddr); 624 flush_tlb_page(vma, vmaddr);
609 __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn)); 625 __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
610 } 626 }
@@ -613,21 +629,33 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
613void flush_kernel_vmap_range(void *vaddr, int size) 629void flush_kernel_vmap_range(void *vaddr, int size)
614{ 630{
615 unsigned long start = (unsigned long)vaddr; 631 unsigned long start = (unsigned long)vaddr;
632 unsigned long end = start + size;
616 633
617 if ((unsigned long)size > parisc_cache_flush_threshold) 634 if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
635 (unsigned long)size >= parisc_cache_flush_threshold) {
636 flush_tlb_kernel_range(start, end);
618 flush_data_cache(); 637 flush_data_cache();
619 else 638 return;
620 flush_kernel_dcache_range_asm(start, start + size); 639 }
640
641 flush_kernel_dcache_range_asm(start, end);
642 flush_tlb_kernel_range(start, end);
621} 643}
622EXPORT_SYMBOL(flush_kernel_vmap_range); 644EXPORT_SYMBOL(flush_kernel_vmap_range);
623 645
624void invalidate_kernel_vmap_range(void *vaddr, int size) 646void invalidate_kernel_vmap_range(void *vaddr, int size)
625{ 647{
626 unsigned long start = (unsigned long)vaddr; 648 unsigned long start = (unsigned long)vaddr;
649 unsigned long end = start + size;
627 650
628 if ((unsigned long)size > parisc_cache_flush_threshold) 651 if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
652 (unsigned long)size >= parisc_cache_flush_threshold) {
653 flush_tlb_kernel_range(start, end);
629 flush_data_cache(); 654 flush_data_cache();
630 else 655 return;
631 flush_kernel_dcache_range_asm(start, start + size); 656 }
657
658 purge_kernel_dcache_range_asm(start, end);
659 flush_tlb_kernel_range(start, end);
632} 660}
633EXPORT_SYMBOL(invalidate_kernel_vmap_range); 661EXPORT_SYMBOL(invalidate_kernel_vmap_range);