root/arch/sh/mm/tlbflush_32.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. local_flush_tlb_page
  2. local_flush_tlb_range
  3. local_flush_tlb_kernel_range
  4. local_flush_tlb_mm
  5. __flush_tlb_global

   1 /*
   2  * TLB flushing operations for SH with an MMU.
   3  *
   4  *  Copyright (C) 1999  Niibe Yutaka
   5  *  Copyright (C) 2003  Paul Mundt
   6  *
   7  * This file is subject to the terms and conditions of the GNU General Public
   8  * License.  See the file "COPYING" in the main directory of this archive
   9  * for more details.
  10  */
  11 #include <linux/mm.h>
  12 #include <asm/mmu_context.h>
  13 #include <asm/tlbflush.h>
  14 
  15 void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
  16 {
  17         unsigned int cpu = smp_processor_id();
  18 
  19         if (vma->vm_mm && cpu_context(cpu, vma->vm_mm) != NO_CONTEXT) {
  20                 unsigned long flags;
  21                 unsigned long asid;
  22                 unsigned long saved_asid = MMU_NO_ASID;
  23 
  24                 asid = cpu_asid(cpu, vma->vm_mm);
  25                 page &= PAGE_MASK;
  26 
  27                 local_irq_save(flags);
  28                 if (vma->vm_mm != current->mm) {
  29                         saved_asid = get_asid();
  30                         set_asid(asid);
  31                 }
  32                 local_flush_tlb_one(asid, page);
  33                 if (saved_asid != MMU_NO_ASID)
  34                         set_asid(saved_asid);
  35                 local_irq_restore(flags);
  36         }
  37 }
  38 
  39 void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
  40                            unsigned long end)
  41 {
  42         struct mm_struct *mm = vma->vm_mm;
  43         unsigned int cpu = smp_processor_id();
  44 
  45         if (cpu_context(cpu, mm) != NO_CONTEXT) {
  46                 unsigned long flags;
  47                 int size;
  48 
  49                 local_irq_save(flags);
  50                 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
  51                 if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
  52                         cpu_context(cpu, mm) = NO_CONTEXT;
  53                         if (mm == current->mm)
  54                                 activate_context(mm, cpu);
  55                 } else {
  56                         unsigned long asid;
  57                         unsigned long saved_asid = MMU_NO_ASID;
  58 
  59                         asid = cpu_asid(cpu, mm);
  60                         start &= PAGE_MASK;
  61                         end += (PAGE_SIZE - 1);
  62                         end &= PAGE_MASK;
  63                         if (mm != current->mm) {
  64                                 saved_asid = get_asid();
  65                                 set_asid(asid);
  66                         }
  67                         while (start < end) {
  68                                 local_flush_tlb_one(asid, start);
  69                                 start += PAGE_SIZE;
  70                         }
  71                         if (saved_asid != MMU_NO_ASID)
  72                                 set_asid(saved_asid);
  73                 }
  74                 local_irq_restore(flags);
  75         }
  76 }
  77 
  78 void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
  79 {
  80         unsigned int cpu = smp_processor_id();
  81         unsigned long flags;
  82         int size;
  83 
  84         local_irq_save(flags);
  85         size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
  86         if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
  87                 local_flush_tlb_all();
  88         } else {
  89                 unsigned long asid;
  90                 unsigned long saved_asid = get_asid();
  91 
  92                 asid = cpu_asid(cpu, &init_mm);
  93                 start &= PAGE_MASK;
  94                 end += (PAGE_SIZE - 1);
  95                 end &= PAGE_MASK;
  96                 set_asid(asid);
  97                 while (start < end) {
  98                         local_flush_tlb_one(asid, start);
  99                         start += PAGE_SIZE;
 100                 }
 101                 set_asid(saved_asid);
 102         }
 103         local_irq_restore(flags);
 104 }
 105 
 106 void local_flush_tlb_mm(struct mm_struct *mm)
 107 {
 108         unsigned int cpu = smp_processor_id();
 109 
 110         /* Invalidate all TLB of this process. */
 111         /* Instead of invalidating each TLB, we get new MMU context. */
 112         if (cpu_context(cpu, mm) != NO_CONTEXT) {
 113                 unsigned long flags;
 114 
 115                 local_irq_save(flags);
 116                 cpu_context(cpu, mm) = NO_CONTEXT;
 117                 if (mm == current->mm)
 118                         activate_context(mm, cpu);
 119                 local_irq_restore(flags);
 120         }
 121 }
 122 
 123 void __flush_tlb_global(void)
 124 {
 125         unsigned long flags;
 126 
 127         local_irq_save(flags);
 128 
 129         /*
 130          * This is the most destructive of the TLB flushing options,
 131          * and will tear down all of the UTLB/ITLB mappings, including
 132          * wired entries.
 133          */
 134         __raw_writel(__raw_readl(MMUCR) | MMUCR_TI, MMUCR);
 135 
 136         local_irq_restore(flags);
 137 }

/* [<][>][^][v][top][bottom][index][help] */