aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sh/mm/Makefile_322
-rw-r--r--arch/sh/mm/Makefile_642
-rw-r--r--arch/sh/mm/fault_32.c (renamed from arch/sh/mm/fault.c)0
-rw-r--r--arch/sh/mm/fault_64.c (renamed from arch/sh64/mm/tlbmiss.c)146
4 files changed, 75 insertions, 75 deletions
diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32
index 9ea379303742..fc089c0cdbe9 100644
--- a/arch/sh/mm/Makefile_32
+++ b/arch/sh/mm/Makefile_32
@@ -12,7 +12,7 @@ obj-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o
12endif 12endif
13 13
14mmu-y := tlb-nommu.o pg-nommu.o 14mmu-y := tlb-nommu.o pg-nommu.o
15mmu-$(CONFIG_MMU) := fault.o clear_page.o copy_page.o tlb-flush_32.o \ 15mmu-$(CONFIG_MMU) := fault_32.o clear_page.o copy_page.o tlb-flush_32.o \
16 ioremap_32.o 16 ioremap_32.o
17 17
18obj-y += $(mmu-y) 18obj-y += $(mmu-y)
diff --git a/arch/sh/mm/Makefile_64 b/arch/sh/mm/Makefile_64
index ec8deaa17909..82fe9072fd5c 100644
--- a/arch/sh/mm/Makefile_64
+++ b/arch/sh/mm/Makefile_64
@@ -5,7 +5,7 @@
5obj-y := init.o extable_64.o consistent.o 5obj-y := init.o extable_64.o consistent.o
6 6
7mmu-y := tlb-nommu.o pg-nommu.o 7mmu-y := tlb-nommu.o pg-nommu.o
8mmu-$(CONFIG_MMU) := ioremap_64.o tlb-flush_64.o 8mmu-$(CONFIG_MMU) := fault_64.o ioremap_64.o tlb-flush_64.o
9 9
10obj-y += $(mmu-y) 10obj-y += $(mmu-y)
11 11
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault_32.c
index 60d74f793a1d..60d74f793a1d 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault_32.c
diff --git a/arch/sh64/mm/tlbmiss.c b/arch/sh/mm/fault_64.c
index b767d6cff72f..1469aa70bc78 100644
--- a/arch/sh64/mm/tlbmiss.c
+++ b/arch/sh/mm/fault_64.c
@@ -1,9 +1,5 @@
1/* 1/*
2 * This file is subject to the terms and conditions of the GNU General Public 2 * The SH64 TLB miss.
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * arch/sh64/mm/tlbmiss.c
7 * 3 *
8 * Original code from fault.c 4 * Original code from fault.c
9 * Copyright (C) 2000, 2001 Paolo Alberelli 5 * Copyright (C) 2000, 2001 Paolo Alberelli
@@ -12,16 +8,20 @@
12 * Copyright (C) 2003 Richard.Curnow@superh.com 8 * Copyright (C) 2003 Richard.Curnow@superh.com
13 * 9 *
14 * IMPORTANT NOTES : 10 * IMPORTANT NOTES :
15 * The do_fast_page_fault function is called from a context in entry.S where very few registers 11 * The do_fast_page_fault function is called from a context in entry.S
16 * have been saved. In particular, the code in this file must be compiled not to use ANY 12 * where very few registers have been saved. In particular, the code in
17 * caller-save registers that are not part of the restricted save set. Also, it means that 13 * this file must be compiled not to use ANY caller-save registers that
18 * code in this file must not make calls to functions elsewhere in the kernel, or else the 14 * are not part of the restricted save set. Also, it means that code in
19 * excepting context will see corruption in its caller-save registers. Plus, the entry.S save 15 * this file must not make calls to functions elsewhere in the kernel, or
20 * area is non-reentrant, so this code has to run with SR.BL==1, i.e. no interrupts taken inside 16 * else the excepting context will see corruption in its caller-save
21 * it and panic on any exception. 17 * registers. Plus, the entry.S save area is non-reentrant, so this code
18 * has to run with SR.BL==1, i.e. no interrupts taken inside it and panic
19 * on any exception.
22 * 20 *
21 * This file is subject to the terms and conditions of the GNU General Public
22 * License. See the file "COPYING" in the main directory of this archive
23 * for more details.
23 */ 24 */
24
25#include <linux/signal.h> 25#include <linux/signal.h>
26#include <linux/sched.h> 26#include <linux/sched.h>
27#include <linux/kernel.h> 27#include <linux/kernel.h>
@@ -33,14 +33,13 @@
33#include <linux/mm.h> 33#include <linux/mm.h>
34#include <linux/smp.h> 34#include <linux/smp.h>
35#include <linux/interrupt.h> 35#include <linux/interrupt.h>
36
37#include <asm/system.h> 36#include <asm/system.h>
38#include <asm/tlb.h> 37#include <asm/tlb.h>
39#include <asm/io.h> 38#include <asm/io.h>
40#include <asm/uaccess.h> 39#include <asm/uaccess.h>
41#include <asm/pgalloc.h> 40#include <asm/pgalloc.h>
42#include <asm/mmu_context.h> 41#include <asm/mmu_context.h>
43#include <asm/registers.h> /* required by inline asm statements */ 42#include <asm/cpu/registers.h>
44 43
45/* Callable from fault.c, so not static */ 44/* Callable from fault.c, so not static */
46inline void __do_tlb_refill(unsigned long address, 45inline void __do_tlb_refill(unsigned long address,
@@ -88,48 +87,47 @@ inline void __do_tlb_refill(unsigned long address,
88 87
89} 88}
90 89
91static int handle_vmalloc_fault(struct mm_struct *mm, unsigned long protection_flags, 90static int handle_vmalloc_fault(struct mm_struct *mm,
91 unsigned long protection_flags,
92 unsigned long long textaccess, 92 unsigned long long textaccess,
93 unsigned long address) 93 unsigned long address)
94{ 94{
95 pgd_t *dir; 95 pgd_t *dir;
96 pud_t *pud;
96 pmd_t *pmd; 97 pmd_t *pmd;
97 static pte_t *pte; 98 static pte_t *pte;
98 pte_t entry; 99 pte_t entry;
99 100
100 dir = pgd_offset_k(address); 101 dir = pgd_offset_k(address);
101 pmd = pmd_offset(dir, address);
102 102
103 if (pmd_none(*pmd)) { 103 pud = pud_offset(dir, address);
104 if (pud_none_or_clear_bad(pud))
104 return 0; 105 return 0;
105 }
106 106
107 if (pmd_bad(*pmd)) { 107 pmd = pmd_offset(pud, address);
108 pmd_clear(pmd); 108 if (pmd_none_or_clear_bad(pmd))
109 return 0; 109 return 0;
110 }
111 110
112 pte = pte_offset_kernel(pmd, address); 111 pte = pte_offset_kernel(pmd, address);
113 entry = *pte; 112 entry = *pte;
114 113
115 if (pte_none(entry) || !pte_present(entry)) { 114 if (pte_none(entry) || !pte_present(entry))
116 return 0; 115 return 0;
117 } 116 if ((pte_val(entry) & protection_flags) != protection_flags)
118
119 if ((pte_val(entry) & protection_flags) != protection_flags) {
120 return 0; 117 return 0;
121 }
122 118
123 __do_tlb_refill(address, textaccess, pte); 119 __do_tlb_refill(address, textaccess, pte);
124 120
125 return 1; 121 return 1;
126} 122}
127 123
128static int handle_tlbmiss(struct mm_struct *mm, unsigned long long protection_flags, 124static int handle_tlbmiss(struct mm_struct *mm,
129 unsigned long long textaccess, 125 unsigned long long protection_flags,
130 unsigned long address) 126 unsigned long long textaccess,
127 unsigned long address)
131{ 128{
132 pgd_t *dir; 129 pgd_t *dir;
130 pud_t *pud;
133 pmd_t *pmd; 131 pmd_t *pmd;
134 pte_t *pte; 132 pte_t *pte;
135 pte_t entry; 133 pte_t entry;
@@ -144,49 +142,49 @@ static int handle_tlbmiss(struct mm_struct *mm, unsigned long long protection_fl
144 142
145 See how mm->pgd is allocated and initialised in pgd_alloc to see why 143 See how mm->pgd is allocated and initialised in pgd_alloc to see why
146 the next test is necessary. - RPC */ 144 the next test is necessary. - RPC */
147 if (address >= (unsigned long) TASK_SIZE) { 145 if (address >= (unsigned long) TASK_SIZE)
148 /* upper half - never has page table entries. */ 146 /* upper half - never has page table entries. */
149 return 0; 147 return 0;
150 } 148
151 dir = pgd_offset(mm, address); 149 dir = pgd_offset(mm, address);
152 if (pgd_none(*dir)) { 150 if (pgd_none(*dir) || !pgd_present(*dir))
153 return 0; 151 return 0;
154 } 152 if (!pgd_present(*dir))
155 if (!pgd_present(*dir)) {
156 return 0; 153 return 0;
157 }
158 154
159 pmd = pmd_offset(dir, address); 155 pud = pud_offset(dir, address);
160 if (pmd_none(*pmd)) { 156 if (pud_none(*pud) || !pud_present(*pud))
161 return 0; 157 return 0;
162 } 158
163 if (!pmd_present(*pmd)) { 159 pmd = pmd_offset(pud, address);
160 if (pmd_none(*pmd) || !pmd_present(*pmd))
164 return 0; 161 return 0;
165 } 162
166 pte = pte_offset_kernel(pmd, address); 163 pte = pte_offset_kernel(pmd, address);
167 entry = *pte; 164 entry = *pte;
168 if (pte_none(entry)) { 165
169 return 0; 166 if (pte_none(entry) || !pte_present(entry))
170 }
171 if (!pte_present(entry)) {
172 return 0; 167 return 0;
173 }
174 168
175 /* If the page doesn't have sufficient protection bits set to service the 169 /*
176 kind of fault being handled, there's not much point doing the TLB refill. 170 * If the page doesn't have sufficient protection bits set to
177 Punt the fault to the general handler. */ 171 * service the kind of fault being handled, there's not much
178 if ((pte_val(entry) & protection_flags) != protection_flags) { 172 * point doing the TLB refill. Punt the fault to the general
173 * handler.
174 */
175 if ((pte_val(entry) & protection_flags) != protection_flags)
179 return 0; 176 return 0;
180 }
181 177
182 __do_tlb_refill(address, textaccess, pte); 178 __do_tlb_refill(address, textaccess, pte);
183 179
184 return 1; 180 return 1;
185} 181}
186 182
187/* Put all this information into one structure so that everything is just arithmetic 183/*
188 relative to a single base address. This reduces the number of movi/shori pairs needed 184 * Put all this information into one structure so that everything is just
189 just to load addresses of static data. */ 185 * arithmetic relative to a single base address. This reduces the number
186 * of movi/shori pairs needed just to load addresses of static data.
187 */
190struct expevt_lookup { 188struct expevt_lookup {
191 unsigned short protection_flags[8]; 189 unsigned short protection_flags[8];
192 unsigned char is_text_access[8]; 190 unsigned char is_text_access[8];
@@ -216,7 +214,8 @@ static struct expevt_lookup expevt_lookup_table = {
216 general fault handling in fault.c which deals with mapping file-backed 214 general fault handling in fault.c which deals with mapping file-backed
217 pages, stack growth, segmentation faults, swapping etc etc) 215 pages, stack growth, segmentation faults, swapping etc etc)
218 */ 216 */
219asmlinkage int do_fast_page_fault(unsigned long long ssr_md, unsigned long long expevt, 217asmlinkage int do_fast_page_fault(unsigned long long ssr_md,
218 unsigned long long expevt,
220 unsigned long address) 219 unsigned long address)
221{ 220{
222 struct task_struct *tsk; 221 struct task_struct *tsk;
@@ -226,17 +225,18 @@ asmlinkage int do_fast_page_fault(unsigned long long ssr_md, unsigned long long
226 unsigned long long index; 225 unsigned long long index;
227 unsigned long long expevt4; 226 unsigned long long expevt4;
228 227
229 /* The next few lines implement a way of hashing EXPEVT into a small array index 228 /* The next few lines implement a way of hashing EXPEVT into a
230 which can be used to lookup parameters specific to the type of TLBMISS being 229 * small array index which can be used to lookup parameters
231 handled. Note: 230 * specific to the type of TLBMISS being handled.
232 ITLBMISS has EXPEVT==0xa40 231 *
233 RTLBMISS has EXPEVT==0x040 232 * Note:
234 WTLBMISS has EXPEVT==0x060 233 * ITLBMISS has EXPEVT==0xa40
235 */ 234 * RTLBMISS has EXPEVT==0x040
236 235 * WTLBMISS has EXPEVT==0x060
236 */
237 expevt4 = (expevt >> 4); 237 expevt4 = (expevt >> 4);
238 /* TODO : xor ssr_md into this expression too. Then we can check that PRU is set 238 /* TODO : xor ssr_md into this expression too. Then we can check
239 when it needs to be. */ 239 * that PRU is set when it needs to be. */
240 index = expevt4 ^ (expevt4 >> 5); 240 index = expevt4 ^ (expevt4 >> 5);
241 index &= 7; 241 index &= 7;
242 protection_flags = expevt_lookup_table.protection_flags[index]; 242 protection_flags = expevt_lookup_table.protection_flags[index];
@@ -262,18 +262,18 @@ asmlinkage int do_fast_page_fault(unsigned long long ssr_md, unsigned long long
262 262
263 if ((address >= VMALLOC_START && address < VMALLOC_END) || 263 if ((address >= VMALLOC_START && address < VMALLOC_END) ||
264 (address >= IOBASE_VADDR && address < IOBASE_END)) { 264 (address >= IOBASE_VADDR && address < IOBASE_END)) {
265 if (ssr_md) { 265 if (ssr_md)
266 /* Process-contexts can never have this address range mapped */ 266 /*
267 if (handle_vmalloc_fault(mm, protection_flags, textaccess, address)) { 267 * Process-contexts can never have this address
268 * range mapped
269 */
270 if (handle_vmalloc_fault(mm, protection_flags,
271 textaccess, address))
268 return 1; 272 return 1;
269 }
270 }
271 } else if (!in_interrupt() && mm) { 273 } else if (!in_interrupt() && mm) {
272 if (handle_tlbmiss(mm, protection_flags, textaccess, address)) { 274 if (handle_tlbmiss(mm, protection_flags, textaccess, address))
273 return 1; 275 return 1;
274 }
275 } 276 }
276 277
277 return 0; 278 return 0;
278} 279}
279