1/* arch/sparc64/mm/tlb.c 2 * 3 * Copyright (C) 2004 David S. Miller <davem@redhat.com> 4 */ 5 6#include <linux/kernel.h> 7#include <linux/init.h> 8#include <linux/percpu.h> 9#include <linux/mm.h> 10#include <linux/swap.h> 11#include <linux/preempt.h> 12 13#include <asm/pgtable.h> 14#include <asm/pgalloc.h> 15#include <asm/tlbflush.h> 16#include <asm/cacheflush.h> 17#include <asm/mmu_context.h> 18#include <asm/tlb.h> 19 20/* Heavily inspired by the ppc64 code. */ 21 22DEFINE_PER_CPU(struct mmu_gather, mmu_gathers) = { 0, }; 23 24void flush_tlb_pending(void) 25{ 26 struct mmu_gather *mp = &__get_cpu_var(mmu_gathers); 27 28 preempt_disable(); 29 30 if (mp->tlb_nr) { 31 flush_tsb_user(mp); 32 33 if (CTX_VALID(mp->mm->context)) { 34#ifdef CONFIG_SMP 35 smp_flush_tlb_pending(mp->mm, mp->tlb_nr, 36 &mp->vaddrs[0]); 37#else 38 __flush_tlb_pending(CTX_HWBITS(mp->mm->context), 39 mp->tlb_nr, &mp->vaddrs[0]); 40#endif 41 } 42 mp->tlb_nr = 0; 43 } 44 45 preempt_enable(); 46} 47 48void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig) 49{ 50 struct mmu_gather *mp = &__get_cpu_var(mmu_gathers); 51 unsigned long nr; 52 53 vaddr &= PAGE_MASK; 54 if (pte_exec(orig)) 55 vaddr |= 0x1UL; 56 57 if (tlb_type != hypervisor && 58 pte_dirty(orig)) { 59 unsigned long paddr, pfn = pte_pfn(orig); 60 struct address_space *mapping; 61 struct page *page; 62 63 if (!pfn_valid(pfn)) 64 goto no_cache_flush; 65 66 page = pfn_to_page(pfn); 67 if (PageReserved(page)) 68 goto no_cache_flush; 69 70 /* A real file page? */ 71 mapping = page_mapping(page); 72 if (!mapping) 73 goto no_cache_flush; 74 75 paddr = (unsigned long) page_address(page); 76 if ((paddr ^ vaddr) & (1 << 13)) 77 flush_dcache_page_all(mm, page); 78 } 79 80no_cache_flush: 81 82 if (mp->fullmm) 83 return; 84 85 nr = mp->tlb_nr; 86 87 if (unlikely(nr != 0 && mm != mp->mm)) { 88 flush_tlb_pending(); 89 nr = 0; 90 } 91 92 if (nr == 0) 93 mp->mm = mm; 94 95 mp->vaddrs[nr] = vaddr; 96 mp->tlb_nr = ++nr; 97 if (nr >= TLB_BATCH_NR) 98 flush_tlb_pending(); 99} 100