aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/mm/tlb-flush.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2006-09-27 02:13:36 -0400
committerPaul Mundt <lethal@linux-sh.org>2006-09-27 02:13:36 -0400
commit26ff6c11ef38e08990c1e417c299246e6ab18ff7 (patch)
treeebd37fd0270b7c7dfe8474a046663db78fcdb1ab /arch/sh/mm/tlb-flush.c
parent9359e757709a211040e4b0151eae69248e7c6eca (diff)
sh: page table alloc cleanups and page fault optimizations.
Cleanup of page table allocators, using generic folded PMD and PUD helpers. TLB flushing operations are moved to a more sensible spot. The page fault handler is also optimized slightly, we no longer waste cycles on IRQ disabling for flushing of the page from the ITLB, since we're already under CLI protection by the initial exception handler. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/mm/tlb-flush.c')
-rw-r--r--arch/sh/mm/tlb-flush.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/arch/sh/mm/tlb-flush.c b/arch/sh/mm/tlb-flush.c
new file mode 100644
index 000000000000..fd7e42bcaa40
--- /dev/null
+++ b/arch/sh/mm/tlb-flush.c
@@ -0,0 +1,132 @@
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
15void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
16{
17 if (vma->vm_mm && vma->vm_mm->context != NO_CONTEXT) {
18 unsigned long flags;
19 unsigned long asid;
20 unsigned long saved_asid = MMU_NO_ASID;
21
22 asid = vma->vm_mm->context & MMU_CONTEXT_ASID_MASK;
23 page &= PAGE_MASK;
24
25 local_irq_save(flags);
26 if (vma->vm_mm != current->mm) {
27 saved_asid = get_asid();
28 set_asid(asid);
29 }
30 __flush_tlb_page(asid, page);
31 if (saved_asid != MMU_NO_ASID)
32 set_asid(saved_asid);
33 local_irq_restore(flags);
34 }
35}
36
37void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
38 unsigned long end)
39{
40 struct mm_struct *mm = vma->vm_mm;
41
42 if (mm->context != NO_CONTEXT) {
43 unsigned long flags;
44 int size;
45
46 local_irq_save(flags);
47 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
48 if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
49 mm->context = NO_CONTEXT;
50 if (mm == current->mm)
51 activate_context(mm);
52 } else {
53 unsigned long asid = mm->context&MMU_CONTEXT_ASID_MASK;
54 unsigned long saved_asid = MMU_NO_ASID;
55
56 start &= PAGE_MASK;
57 end += (PAGE_SIZE - 1);
58 end &= PAGE_MASK;
59 if (mm != current->mm) {
60 saved_asid = get_asid();
61 set_asid(asid);
62 }
63 while (start < end) {
64 __flush_tlb_page(asid, start);
65 start += PAGE_SIZE;
66 }
67 if (saved_asid != MMU_NO_ASID)
68 set_asid(saved_asid);
69 }
70 local_irq_restore(flags);
71 }
72}
73
74void flush_tlb_kernel_range(unsigned long start, unsigned long end)
75{
76 unsigned long flags;
77 int size;
78
79 local_irq_save(flags);
80 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
81 if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */
82 flush_tlb_all();
83 } else {
84 unsigned long asid = init_mm.context&MMU_CONTEXT_ASID_MASK;
85 unsigned long saved_asid = get_asid();
86
87 start &= PAGE_MASK;
88 end += (PAGE_SIZE - 1);
89 end &= PAGE_MASK;
90 set_asid(asid);
91 while (start < end) {
92 __flush_tlb_page(asid, start);
93 start += PAGE_SIZE;
94 }
95 set_asid(saved_asid);
96 }
97 local_irq_restore(flags);
98}
99
100void flush_tlb_mm(struct mm_struct *mm)
101{
102 /* Invalidate all TLB of this process. */
103 /* Instead of invalidating each TLB, we get new MMU context. */
104 if (mm->context != NO_CONTEXT) {
105 unsigned long flags;
106
107 local_irq_save(flags);
108 mm->context = NO_CONTEXT;
109 if (mm == current->mm)
110 activate_context(mm);
111 local_irq_restore(flags);
112 }
113}
114
115void flush_tlb_all(void)
116{
117 unsigned long flags, status;
118
119 /*
120 * Flush all the TLB.
121 *
122 * Write to the MMU control register's bit:
123 * TF-bit for SH-3, TI-bit for SH-4.
124 * It's same position, bit #2.
125 */
126 local_irq_save(flags);
127 status = ctrl_inl(MMUCR);
128 status |= 0x04;
129 ctrl_outl(status, MMUCR);
130 ctrl_barrier();
131 local_irq_restore(flags);
132}