2 * TLB flushing operations for SH with an MMU.
4 * Copyright (C) 1999 Niibe Yutaka
5 * Copyright (C) 2003 Paul Mundt
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
12 #include <asm/mmu_context.h>
13 #include <asm/tlbflush.h>
15 void local_flush_tlb_page(struct vm_area_struct
*vma
, unsigned long page
)
17 unsigned int cpu
= smp_processor_id();
19 if (vma
->vm_mm
&& cpu_context(cpu
, vma
->vm_mm
) != NO_CONTEXT
) {
22 unsigned long saved_asid
= MMU_NO_ASID
;
24 asid
= cpu_asid(cpu
, vma
->vm_mm
);
27 local_irq_save(flags
);
28 if (vma
->vm_mm
!= current
->mm
) {
29 saved_asid
= get_asid();
32 local_flush_tlb_one(asid
, page
);
33 if (saved_asid
!= MMU_NO_ASID
)
35 local_irq_restore(flags
);
39 void local_flush_tlb_range(struct vm_area_struct
*vma
, unsigned long start
,
42 struct mm_struct
*mm
= vma
->vm_mm
;
43 unsigned int cpu
= smp_processor_id();
45 if (cpu_context(cpu
, mm
) != NO_CONTEXT
) {
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
);
57 unsigned long saved_asid
= MMU_NO_ASID
;
59 asid
= cpu_asid(cpu
, mm
);
61 end
+= (PAGE_SIZE
- 1);
63 if (mm
!= current
->mm
) {
64 saved_asid
= get_asid();
68 local_flush_tlb_one(asid
, start
);
71 if (saved_asid
!= MMU_NO_ASID
)
74 local_irq_restore(flags
);
78 void local_flush_tlb_kernel_range(unsigned long start
, unsigned long end
)
80 unsigned int cpu
= smp_processor_id();
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();
90 unsigned long saved_asid
= get_asid();
92 asid
= cpu_asid(cpu
, &init_mm
);
94 end
+= (PAGE_SIZE
- 1);
98 local_flush_tlb_one(asid
, start
);
101 set_asid(saved_asid
);
103 local_irq_restore(flags
);
106 void local_flush_tlb_mm(struct mm_struct
*mm
)
108 unsigned int cpu
= smp_processor_id();
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
) {
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
);
123 void local_flush_tlb_all(void)
125 unsigned long flags
, status
;
130 * Write to the MMU control register's bit:
131 * TF-bit for SH-3, TI-bit for SH-4.
132 * It's same position, bit #2.
134 local_irq_save(flags
);
135 status
= ctrl_inl(MMUCR
);
137 ctrl_outl(status
, MMUCR
);
139 local_irq_restore(flags
);