diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /arch/sparc/mm | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'arch/sparc/mm')
-rw-r--r-- | arch/sparc/mm/fault_32.c | 122 | ||||
-rw-r--r-- | arch/sparc/mm/fault_64.c | 71 | ||||
-rw-r--r-- | arch/sparc/mm/hugetlbpage.c | 1 | ||||
-rw-r--r-- | arch/sparc/mm/init_32.c | 1 | ||||
-rw-r--r-- | arch/sparc/mm/init_64.c | 7 | ||||
-rw-r--r-- | arch/sparc/mm/nosun4c.c | 2 | ||||
-rw-r--r-- | arch/sparc/mm/srmmu.c | 17 | ||||
-rw-r--r-- | arch/sparc/mm/sun4c.c | 24 | ||||
-rw-r--r-- | arch/sparc/mm/tsb.c | 1 |
9 files changed, 147 insertions, 99 deletions
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c index b99f81c4906f..bd8601601afa 100644 --- a/arch/sparc/mm/fault_32.c +++ b/arch/sparc/mm/fault_32.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/signal.h> | 18 | #include <linux/signal.h> |
19 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
20 | #include <linux/smp.h> | 20 | #include <linux/smp.h> |
21 | #include <linux/perf_event.h> | ||
21 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
22 | #include <linux/module.h> | 23 | #include <linux/module.h> |
23 | #include <linux/kdebug.h> | 24 | #include <linux/kdebug.h> |
@@ -34,6 +35,8 @@ | |||
34 | 35 | ||
35 | extern int prom_node_root; | 36 | extern int prom_node_root; |
36 | 37 | ||
38 | int show_unhandled_signals = 1; | ||
39 | |||
37 | /* At boot time we determine these two values necessary for setting | 40 | /* At boot time we determine these two values necessary for setting |
38 | * up the segment maps and page table entries (pte's). | 41 | * up the segment maps and page table entries (pte's). |
39 | */ | 42 | */ |
@@ -148,6 +151,45 @@ asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc, | |||
148 | return 0; | 151 | return 0; |
149 | } | 152 | } |
150 | 153 | ||
154 | static inline void | ||
155 | show_signal_msg(struct pt_regs *regs, int sig, int code, | ||
156 | unsigned long address, struct task_struct *tsk) | ||
157 | { | ||
158 | if (!unhandled_signal(tsk, sig)) | ||
159 | return; | ||
160 | |||
161 | if (!printk_ratelimit()) | ||
162 | return; | ||
163 | |||
164 | printk("%s%s[%d]: segfault at %lx ip %p (rpc %p) sp %p error %x", | ||
165 | task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, | ||
166 | tsk->comm, task_pid_nr(tsk), address, | ||
167 | (void *)regs->pc, (void *)regs->u_regs[UREG_I7], | ||
168 | (void *)regs->u_regs[UREG_FP], code); | ||
169 | |||
170 | print_vma_addr(KERN_CONT " in ", regs->pc); | ||
171 | |||
172 | printk(KERN_CONT "\n"); | ||
173 | } | ||
174 | |||
175 | static void __do_fault_siginfo(int code, int sig, struct pt_regs *regs, | ||
176 | unsigned long addr) | ||
177 | { | ||
178 | siginfo_t info; | ||
179 | |||
180 | info.si_signo = sig; | ||
181 | info.si_code = code; | ||
182 | info.si_errno = 0; | ||
183 | info.si_addr = (void __user *) addr; | ||
184 | info.si_trapno = 0; | ||
185 | |||
186 | if (unlikely(show_unhandled_signals)) | ||
187 | show_signal_msg(regs, sig, info.si_code, | ||
188 | addr, current); | ||
189 | |||
190 | force_sig_info (sig, &info, current); | ||
191 | } | ||
192 | |||
151 | extern unsigned long safe_compute_effective_address(struct pt_regs *, | 193 | extern unsigned long safe_compute_effective_address(struct pt_regs *, |
152 | unsigned int); | 194 | unsigned int); |
153 | 195 | ||
@@ -167,6 +209,14 @@ static unsigned long compute_si_addr(struct pt_regs *regs, int text_fault) | |||
167 | return safe_compute_effective_address(regs, insn); | 209 | return safe_compute_effective_address(regs, insn); |
168 | } | 210 | } |
169 | 211 | ||
212 | static noinline void do_fault_siginfo(int code, int sig, struct pt_regs *regs, | ||
213 | int text_fault) | ||
214 | { | ||
215 | unsigned long addr = compute_si_addr(regs, text_fault); | ||
216 | |||
217 | __do_fault_siginfo(code, sig, regs, addr); | ||
218 | } | ||
219 | |||
170 | asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, | 220 | asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, |
171 | unsigned long address) | 221 | unsigned long address) |
172 | { | 222 | { |
@@ -175,9 +225,8 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, | |||
175 | struct mm_struct *mm = tsk->mm; | 225 | struct mm_struct *mm = tsk->mm; |
176 | unsigned int fixup; | 226 | unsigned int fixup; |
177 | unsigned long g2; | 227 | unsigned long g2; |
178 | siginfo_t info; | ||
179 | int from_user = !(regs->psr & PSR_PS); | 228 | int from_user = !(regs->psr & PSR_PS); |
180 | int fault; | 229 | int fault, code; |
181 | 230 | ||
182 | if(text_fault) | 231 | if(text_fault) |
183 | address = regs->pc; | 232 | address = regs->pc; |
@@ -194,7 +243,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, | |||
194 | if (!ARCH_SUN4C && address >= TASK_SIZE) | 243 | if (!ARCH_SUN4C && address >= TASK_SIZE) |
195 | goto vmalloc_fault; | 244 | goto vmalloc_fault; |
196 | 245 | ||
197 | info.si_code = SEGV_MAPERR; | 246 | code = SEGV_MAPERR; |
198 | 247 | ||
199 | /* | 248 | /* |
200 | * If we're in an interrupt or have no user | 249 | * If we're in an interrupt or have no user |
@@ -203,6 +252,8 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, | |||
203 | if (in_atomic() || !mm) | 252 | if (in_atomic() || !mm) |
204 | goto no_context; | 253 | goto no_context; |
205 | 254 | ||
255 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address); | ||
256 | |||
206 | down_read(&mm->mmap_sem); | 257 | down_read(&mm->mmap_sem); |
207 | 258 | ||
208 | /* | 259 | /* |
@@ -226,7 +277,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, | |||
226 | * we can handle it.. | 277 | * we can handle it.. |
227 | */ | 278 | */ |
228 | good_area: | 279 | good_area: |
229 | info.si_code = SEGV_ACCERR; | 280 | code = SEGV_ACCERR; |
230 | if(write) { | 281 | if(write) { |
231 | if(!(vma->vm_flags & VM_WRITE)) | 282 | if(!(vma->vm_flags & VM_WRITE)) |
232 | goto bad_area; | 283 | goto bad_area; |
@@ -249,10 +300,15 @@ good_area: | |||
249 | goto do_sigbus; | 300 | goto do_sigbus; |
250 | BUG(); | 301 | BUG(); |
251 | } | 302 | } |
252 | if (fault & VM_FAULT_MAJOR) | 303 | if (fault & VM_FAULT_MAJOR) { |
253 | current->maj_flt++; | 304 | current->maj_flt++; |
254 | else | 305 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, |
306 | regs, address); | ||
307 | } else { | ||
255 | current->min_flt++; | 308 | current->min_flt++; |
309 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, | ||
310 | regs, address); | ||
311 | } | ||
256 | up_read(&mm->mmap_sem); | 312 | up_read(&mm->mmap_sem); |
257 | return; | 313 | return; |
258 | 314 | ||
@@ -265,18 +321,8 @@ bad_area: | |||
265 | 321 | ||
266 | bad_area_nosemaphore: | 322 | bad_area_nosemaphore: |
267 | /* User mode accesses just cause a SIGSEGV */ | 323 | /* User mode accesses just cause a SIGSEGV */ |
268 | if(from_user) { | 324 | if (from_user) { |
269 | #if 0 | 325 | do_fault_siginfo(code, SIGSEGV, regs, text_fault); |
270 | printk("Fault whee %s [%d]: segfaults at %08lx pc=%08lx\n", | ||
271 | tsk->comm, tsk->pid, address, regs->pc); | ||
272 | #endif | ||
273 | info.si_signo = SIGSEGV; | ||
274 | info.si_errno = 0; | ||
275 | /* info.si_code set above to make clear whether | ||
276 | this was a SEGV_MAPERR or SEGV_ACCERR fault. */ | ||
277 | info.si_addr = (void __user *)compute_si_addr(regs, text_fault); | ||
278 | info.si_trapno = 0; | ||
279 | force_sig_info (SIGSEGV, &info, tsk); | ||
280 | return; | 326 | return; |
281 | } | 327 | } |
282 | 328 | ||
@@ -327,12 +373,7 @@ out_of_memory: | |||
327 | 373 | ||
328 | do_sigbus: | 374 | do_sigbus: |
329 | up_read(&mm->mmap_sem); | 375 | up_read(&mm->mmap_sem); |
330 | info.si_signo = SIGBUS; | 376 | do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, text_fault); |
331 | info.si_errno = 0; | ||
332 | info.si_code = BUS_ADRERR; | ||
333 | info.si_addr = (void __user *) compute_si_addr(regs, text_fault); | ||
334 | info.si_trapno = 0; | ||
335 | force_sig_info (SIGBUS, &info, tsk); | ||
336 | if (!from_user) | 377 | if (!from_user) |
337 | goto no_context; | 378 | goto no_context; |
338 | 379 | ||
@@ -370,7 +411,7 @@ asmlinkage void do_sun4c_fault(struct pt_regs *regs, int text_fault, int write, | |||
370 | unsigned long address) | 411 | unsigned long address) |
371 | { | 412 | { |
372 | extern void sun4c_update_mmu_cache(struct vm_area_struct *, | 413 | extern void sun4c_update_mmu_cache(struct vm_area_struct *, |
373 | unsigned long,pte_t); | 414 | unsigned long,pte_t *); |
374 | extern pte_t *sun4c_pte_offset_kernel(pmd_t *,unsigned long); | 415 | extern pte_t *sun4c_pte_offset_kernel(pmd_t *,unsigned long); |
375 | struct task_struct *tsk = current; | 416 | struct task_struct *tsk = current; |
376 | struct mm_struct *mm = tsk->mm; | 417 | struct mm_struct *mm = tsk->mm; |
@@ -447,7 +488,7 @@ asmlinkage void do_sun4c_fault(struct pt_regs *regs, int text_fault, int write, | |||
447 | * on the CPU and doing a shrink_mmap() on this vma. | 488 | * on the CPU and doing a shrink_mmap() on this vma. |
448 | */ | 489 | */ |
449 | sun4c_update_mmu_cache (find_vma(current->mm, address), address, | 490 | sun4c_update_mmu_cache (find_vma(current->mm, address), address, |
450 | *ptep); | 491 | ptep); |
451 | else | 492 | else |
452 | do_sparc_fault(regs, text_fault, write, address); | 493 | do_sparc_fault(regs, text_fault, write, address); |
453 | } | 494 | } |
@@ -458,14 +499,10 @@ static void force_user_fault(unsigned long address, int write) | |||
458 | struct vm_area_struct *vma; | 499 | struct vm_area_struct *vma; |
459 | struct task_struct *tsk = current; | 500 | struct task_struct *tsk = current; |
460 | struct mm_struct *mm = tsk->mm; | 501 | struct mm_struct *mm = tsk->mm; |
461 | siginfo_t info; | 502 | int code; |
462 | 503 | ||
463 | info.si_code = SEGV_MAPERR; | 504 | code = SEGV_MAPERR; |
464 | 505 | ||
465 | #if 0 | ||
466 | printk("wf<pid=%d,wr=%d,addr=%08lx>\n", | ||
467 | tsk->pid, write, address); | ||
468 | #endif | ||
469 | down_read(&mm->mmap_sem); | 506 | down_read(&mm->mmap_sem); |
470 | vma = find_vma(mm, address); | 507 | vma = find_vma(mm, address); |
471 | if(!vma) | 508 | if(!vma) |
@@ -477,7 +514,7 @@ static void force_user_fault(unsigned long address, int write) | |||
477 | if(expand_stack(vma, address)) | 514 | if(expand_stack(vma, address)) |
478 | goto bad_area; | 515 | goto bad_area; |
479 | good_area: | 516 | good_area: |
480 | info.si_code = SEGV_ACCERR; | 517 | code = SEGV_ACCERR; |
481 | if(write) { | 518 | if(write) { |
482 | if(!(vma->vm_flags & VM_WRITE)) | 519 | if(!(vma->vm_flags & VM_WRITE)) |
483 | goto bad_area; | 520 | goto bad_area; |
@@ -494,27 +531,12 @@ good_area: | |||
494 | return; | 531 | return; |
495 | bad_area: | 532 | bad_area: |
496 | up_read(&mm->mmap_sem); | 533 | up_read(&mm->mmap_sem); |
497 | #if 0 | 534 | __do_fault_siginfo(code, SIGSEGV, tsk->thread.kregs, address); |
498 | printk("Window whee %s [%d]: segfaults at %08lx\n", | ||
499 | tsk->comm, tsk->pid, address); | ||
500 | #endif | ||
501 | info.si_signo = SIGSEGV; | ||
502 | info.si_errno = 0; | ||
503 | /* info.si_code set above to make clear whether | ||
504 | this was a SEGV_MAPERR or SEGV_ACCERR fault. */ | ||
505 | info.si_addr = (void __user *) address; | ||
506 | info.si_trapno = 0; | ||
507 | force_sig_info (SIGSEGV, &info, tsk); | ||
508 | return; | 535 | return; |
509 | 536 | ||
510 | do_sigbus: | 537 | do_sigbus: |
511 | up_read(&mm->mmap_sem); | 538 | up_read(&mm->mmap_sem); |
512 | info.si_signo = SIGBUS; | 539 | __do_fault_siginfo(BUS_ADRERR, SIGBUS, tsk->thread.kregs, address); |
513 | info.si_errno = 0; | ||
514 | info.si_code = BUS_ADRERR; | ||
515 | info.si_addr = (void __user *) address; | ||
516 | info.si_trapno = 0; | ||
517 | force_sig_info (SIGBUS, &info, tsk); | ||
518 | } | 540 | } |
519 | 541 | ||
520 | void window_overflow_fault(void) | 542 | void window_overflow_fault(void) |
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index 43b0da96a4fb..f92ce56a8b22 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/perf_event.h> | ||
19 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
20 | #include <linux/kprobes.h> | 21 | #include <linux/kprobes.h> |
21 | #include <linux/kdebug.h> | 22 | #include <linux/kdebug.h> |
@@ -31,13 +32,14 @@ | |||
31 | #include <asm/sections.h> | 32 | #include <asm/sections.h> |
32 | #include <asm/mmu_context.h> | 33 | #include <asm/mmu_context.h> |
33 | 34 | ||
34 | #ifdef CONFIG_KPROBES | 35 | int show_unhandled_signals = 1; |
35 | static inline int notify_page_fault(struct pt_regs *regs) | 36 | |
37 | static inline __kprobes int notify_page_fault(struct pt_regs *regs) | ||
36 | { | 38 | { |
37 | int ret = 0; | 39 | int ret = 0; |
38 | 40 | ||
39 | /* kprobe_running() needs smp_processor_id() */ | 41 | /* kprobe_running() needs smp_processor_id() */ |
40 | if (!user_mode(regs)) { | 42 | if (kprobes_built_in() && !user_mode(regs)) { |
41 | preempt_disable(); | 43 | preempt_disable(); |
42 | if (kprobe_running() && kprobe_fault_handler(regs, 0)) | 44 | if (kprobe_running() && kprobe_fault_handler(regs, 0)) |
43 | ret = 1; | 45 | ret = 1; |
@@ -45,12 +47,6 @@ static inline int notify_page_fault(struct pt_regs *regs) | |||
45 | } | 47 | } |
46 | return ret; | 48 | return ret; |
47 | } | 49 | } |
48 | #else | ||
49 | static inline int notify_page_fault(struct pt_regs *regs) | ||
50 | { | ||
51 | return 0; | ||
52 | } | ||
53 | #endif | ||
54 | 50 | ||
55 | static void __kprobes unhandled_fault(unsigned long address, | 51 | static void __kprobes unhandled_fault(unsigned long address, |
56 | struct task_struct *tsk, | 52 | struct task_struct *tsk, |
@@ -73,7 +69,7 @@ static void __kprobes unhandled_fault(unsigned long address, | |||
73 | die_if_kernel("Oops", regs); | 69 | die_if_kernel("Oops", regs); |
74 | } | 70 | } |
75 | 71 | ||
76 | static void bad_kernel_pc(struct pt_regs *regs, unsigned long vaddr) | 72 | static void __kprobes bad_kernel_pc(struct pt_regs *regs, unsigned long vaddr) |
77 | { | 73 | { |
78 | printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n", | 74 | printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n", |
79 | regs->tpc); | 75 | regs->tpc); |
@@ -134,22 +130,48 @@ outret: | |||
134 | return insn; | 130 | return insn; |
135 | } | 131 | } |
136 | 132 | ||
133 | static inline void | ||
134 | show_signal_msg(struct pt_regs *regs, int sig, int code, | ||
135 | unsigned long address, struct task_struct *tsk) | ||
136 | { | ||
137 | if (!unhandled_signal(tsk, sig)) | ||
138 | return; | ||
139 | |||
140 | if (!printk_ratelimit()) | ||
141 | return; | ||
142 | |||
143 | printk("%s%s[%d]: segfault at %lx ip %p (rpc %p) sp %p error %x", | ||
144 | task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, | ||
145 | tsk->comm, task_pid_nr(tsk), address, | ||
146 | (void *)regs->tpc, (void *)regs->u_regs[UREG_I7], | ||
147 | (void *)regs->u_regs[UREG_FP], code); | ||
148 | |||
149 | print_vma_addr(KERN_CONT " in ", regs->tpc); | ||
150 | |||
151 | printk(KERN_CONT "\n"); | ||
152 | } | ||
153 | |||
137 | extern unsigned long compute_effective_address(struct pt_regs *, unsigned int, unsigned int); | 154 | extern unsigned long compute_effective_address(struct pt_regs *, unsigned int, unsigned int); |
138 | 155 | ||
139 | static void do_fault_siginfo(int code, int sig, struct pt_regs *regs, | 156 | static void do_fault_siginfo(int code, int sig, struct pt_regs *regs, |
140 | unsigned int insn, int fault_code) | 157 | unsigned int insn, int fault_code) |
141 | { | 158 | { |
159 | unsigned long addr; | ||
142 | siginfo_t info; | 160 | siginfo_t info; |
143 | 161 | ||
144 | info.si_code = code; | 162 | info.si_code = code; |
145 | info.si_signo = sig; | 163 | info.si_signo = sig; |
146 | info.si_errno = 0; | 164 | info.si_errno = 0; |
147 | if (fault_code & FAULT_CODE_ITLB) | 165 | if (fault_code & FAULT_CODE_ITLB) |
148 | info.si_addr = (void __user *) regs->tpc; | 166 | addr = regs->tpc; |
149 | else | 167 | else |
150 | info.si_addr = (void __user *) | 168 | addr = compute_effective_address(regs, insn, 0); |
151 | compute_effective_address(regs, insn, 0); | 169 | info.si_addr = (void __user *) addr; |
152 | info.si_trapno = 0; | 170 | info.si_trapno = 0; |
171 | |||
172 | if (unlikely(show_unhandled_signals)) | ||
173 | show_signal_msg(regs, sig, code, addr, current); | ||
174 | |||
153 | force_sig_info(sig, &info, current); | 175 | force_sig_info(sig, &info, current); |
154 | } | 176 | } |
155 | 177 | ||
@@ -170,8 +192,9 @@ static unsigned int get_fault_insn(struct pt_regs *regs, unsigned int insn) | |||
170 | return insn; | 192 | return insn; |
171 | } | 193 | } |
172 | 194 | ||
173 | static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code, | 195 | static void __kprobes do_kernel_fault(struct pt_regs *regs, int si_code, |
174 | unsigned int insn, unsigned long address) | 196 | int fault_code, unsigned int insn, |
197 | unsigned long address) | ||
175 | { | 198 | { |
176 | unsigned char asi = ASI_P; | 199 | unsigned char asi = ASI_P; |
177 | 200 | ||
@@ -225,7 +248,7 @@ cannot_handle: | |||
225 | unhandled_fault (address, current, regs); | 248 | unhandled_fault (address, current, regs); |
226 | } | 249 | } |
227 | 250 | ||
228 | static void noinline bogus_32bit_fault_tpc(struct pt_regs *regs) | 251 | static void noinline __kprobes bogus_32bit_fault_tpc(struct pt_regs *regs) |
229 | { | 252 | { |
230 | static int times; | 253 | static int times; |
231 | 254 | ||
@@ -237,8 +260,8 @@ static void noinline bogus_32bit_fault_tpc(struct pt_regs *regs) | |||
237 | show_regs(regs); | 260 | show_regs(regs); |
238 | } | 261 | } |
239 | 262 | ||
240 | static void noinline bogus_32bit_fault_address(struct pt_regs *regs, | 263 | static void noinline __kprobes bogus_32bit_fault_address(struct pt_regs *regs, |
241 | unsigned long addr) | 264 | unsigned long addr) |
242 | { | 265 | { |
243 | static int times; | 266 | static int times; |
244 | 267 | ||
@@ -302,6 +325,8 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | |||
302 | if (in_atomic() || !mm) | 325 | if (in_atomic() || !mm) |
303 | goto intr_or_no_mm; | 326 | goto intr_or_no_mm; |
304 | 327 | ||
328 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address); | ||
329 | |||
305 | if (!down_read_trylock(&mm->mmap_sem)) { | 330 | if (!down_read_trylock(&mm->mmap_sem)) { |
306 | if ((regs->tstate & TSTATE_PRIV) && | 331 | if ((regs->tstate & TSTATE_PRIV) && |
307 | !search_exception_tables(regs->tpc)) { | 332 | !search_exception_tables(regs->tpc)) { |
@@ -406,11 +431,15 @@ good_area: | |||
406 | goto do_sigbus; | 431 | goto do_sigbus; |
407 | BUG(); | 432 | BUG(); |
408 | } | 433 | } |
409 | if (fault & VM_FAULT_MAJOR) | 434 | if (fault & VM_FAULT_MAJOR) { |
410 | current->maj_flt++; | 435 | current->maj_flt++; |
411 | else | 436 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, |
437 | regs, address); | ||
438 | } else { | ||
412 | current->min_flt++; | 439 | current->min_flt++; |
413 | 440 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, | |
441 | regs, address); | ||
442 | } | ||
414 | up_read(&mm->mmap_sem); | 443 | up_read(&mm->mmap_sem); |
415 | 444 | ||
416 | mm_rss = get_mm_rss(mm); | 445 | mm_rss = get_mm_rss(mm); |
diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c index f27d10369e0c..5fdddf134caa 100644 --- a/arch/sparc/mm/hugetlbpage.c +++ b/arch/sparc/mm/hugetlbpage.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
11 | #include <linux/hugetlb.h> | 11 | #include <linux/hugetlb.h> |
12 | #include <linux/pagemap.h> | 12 | #include <linux/pagemap.h> |
13 | #include <linux/slab.h> | ||
14 | #include <linux/sysctl.h> | 13 | #include <linux/sysctl.h> |
15 | 14 | ||
16 | #include <asm/mman.h> | 15 | #include <asm/mman.h> |
diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c index dc7c3b17a15f..6d0e02c4fe09 100644 --- a/arch/sparc/mm/init_32.c +++ b/arch/sparc/mm/init_32.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/bootmem.h> | 24 | #include <linux/bootmem.h> |
25 | #include <linux/pagemap.h> | 25 | #include <linux/pagemap.h> |
26 | #include <linux/poison.h> | 26 | #include <linux/poison.h> |
27 | #include <linux/gfp.h> | ||
27 | 28 | ||
28 | #include <asm/sections.h> | 29 | #include <asm/sections.h> |
29 | #include <asm/system.h> | 30 | #include <asm/system.h> |
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 1886d37d411b..b2831dc3c121 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/bootmem.h> | 13 | #include <linux/bootmem.h> |
14 | #include <linux/mm.h> | 14 | #include <linux/mm.h> |
15 | #include <linux/hugetlb.h> | 15 | #include <linux/hugetlb.h> |
16 | #include <linux/slab.h> | ||
17 | #include <linux/initrd.h> | 16 | #include <linux/initrd.h> |
18 | #include <linux/swap.h> | 17 | #include <linux/swap.h> |
19 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
@@ -26,6 +25,7 @@ | |||
26 | #include <linux/percpu.h> | 25 | #include <linux/percpu.h> |
27 | #include <linux/lmb.h> | 26 | #include <linux/lmb.h> |
28 | #include <linux/mmzone.h> | 27 | #include <linux/mmzone.h> |
28 | #include <linux/gfp.h> | ||
29 | 29 | ||
30 | #include <asm/head.h> | 30 | #include <asm/head.h> |
31 | #include <asm/system.h> | 31 | #include <asm/system.h> |
@@ -289,12 +289,13 @@ static void flush_dcache(unsigned long pfn) | |||
289 | } | 289 | } |
290 | } | 290 | } |
291 | 291 | ||
292 | void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) | 292 | void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) |
293 | { | 293 | { |
294 | struct mm_struct *mm; | 294 | struct mm_struct *mm; |
295 | struct tsb *tsb; | 295 | struct tsb *tsb; |
296 | unsigned long tag, flags; | 296 | unsigned long tag, flags; |
297 | unsigned long tsb_index, tsb_hash_shift; | 297 | unsigned long tsb_index, tsb_hash_shift; |
298 | pte_t pte = *ptep; | ||
298 | 299 | ||
299 | if (tlb_type != hypervisor) { | 300 | if (tlb_type != hypervisor) { |
300 | unsigned long pfn = pte_pfn(pte); | 301 | unsigned long pfn = pte_pfn(pte); |
@@ -2116,7 +2117,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) | |||
2116 | "node=%d entry=%lu/%lu\n", start, block, nr, | 2117 | "node=%d entry=%lu/%lu\n", start, block, nr, |
2117 | node, | 2118 | node, |
2118 | addr >> VMEMMAP_CHUNK_SHIFT, | 2119 | addr >> VMEMMAP_CHUNK_SHIFT, |
2119 | VMEMMAP_SIZE >> VMEMMAP_CHUNK_SHIFT); | 2120 | VMEMMAP_SIZE); |
2120 | } | 2121 | } |
2121 | } | 2122 | } |
2122 | return 0; | 2123 | return 0; |
diff --git a/arch/sparc/mm/nosun4c.c b/arch/sparc/mm/nosun4c.c index 196263f895b7..4e62c27147c4 100644 --- a/arch/sparc/mm/nosun4c.c +++ b/arch/sparc/mm/nosun4c.c | |||
@@ -62,7 +62,7 @@ pte_t *sun4c_pte_offset_kernel(pmd_t *dir, unsigned long address) | |||
62 | return NULL; | 62 | return NULL; |
63 | } | 63 | } |
64 | 64 | ||
65 | void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) | 65 | void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) |
66 | { | 66 | { |
67 | } | 67 | } |
68 | 68 | ||
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index 509b1ffeba66..f5f75a58e0b3 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c | |||
@@ -10,7 +10,6 @@ | |||
10 | 10 | ||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
13 | #include <linux/slab.h> | ||
14 | #include <linux/vmalloc.h> | 13 | #include <linux/vmalloc.h> |
15 | #include <linux/pagemap.h> | 14 | #include <linux/pagemap.h> |
16 | #include <linux/init.h> | 15 | #include <linux/init.h> |
@@ -20,6 +19,7 @@ | |||
20 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
21 | #include <linux/kdebug.h> | 20 | #include <linux/kdebug.h> |
22 | #include <linux/log2.h> | 21 | #include <linux/log2.h> |
22 | #include <linux/gfp.h> | ||
23 | 23 | ||
24 | #include <asm/bitext.h> | 24 | #include <asm/bitext.h> |
25 | #include <asm/page.h> | 25 | #include <asm/page.h> |
@@ -694,7 +694,7 @@ extern void tsunami_setup_blockops(void); | |||
694 | * The following code is a deadwood that may be necessary when | 694 | * The following code is a deadwood that may be necessary when |
695 | * we start to make precise page flushes again. --zaitcev | 695 | * we start to make precise page flushes again. --zaitcev |
696 | */ | 696 | */ |
697 | static void swift_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t pte) | 697 | static void swift_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t *ptep) |
698 | { | 698 | { |
699 | #if 0 | 699 | #if 0 |
700 | static unsigned long last; | 700 | static unsigned long last; |
@@ -703,10 +703,10 @@ static void swift_update_mmu_cache(struct vm_area_struct * vma, unsigned long ad | |||
703 | 703 | ||
704 | if (address == last) { | 704 | if (address == last) { |
705 | val = srmmu_hwprobe(address); | 705 | val = srmmu_hwprobe(address); |
706 | if (val != 0 && pte_val(pte) != val) { | 706 | if (val != 0 && pte_val(*ptep) != val) { |
707 | printk("swift_update_mmu_cache: " | 707 | printk("swift_update_mmu_cache: " |
708 | "addr %lx put %08x probed %08x from %p\n", | 708 | "addr %lx put %08x probed %08x from %p\n", |
709 | address, pte_val(pte), val, | 709 | address, pte_val(*ptep), val, |
710 | __builtin_return_address(0)); | 710 | __builtin_return_address(0)); |
711 | srmmu_flush_whole_tlb(); | 711 | srmmu_flush_whole_tlb(); |
712 | } | 712 | } |
@@ -1990,7 +1990,7 @@ void __init poke_leonsparc(void) | |||
1990 | void __init init_leon(void) | 1990 | void __init init_leon(void) |
1991 | { | 1991 | { |
1992 | 1992 | ||
1993 | srmmu_name = "Leon"; | 1993 | srmmu_name = "LEON"; |
1994 | 1994 | ||
1995 | BTFIXUPSET_CALL(flush_cache_all, leon_flush_cache_all, | 1995 | BTFIXUPSET_CALL(flush_cache_all, leon_flush_cache_all, |
1996 | BTFIXUPCALL_NORM); | 1996 | BTFIXUPCALL_NORM); |
@@ -2037,8 +2037,6 @@ static void __init get_srmmu_type(void) | |||
2037 | 2037 | ||
2038 | /* First, check for sparc-leon. */ | 2038 | /* First, check for sparc-leon. */ |
2039 | if (sparc_cpu_model == sparc_leon) { | 2039 | if (sparc_cpu_model == sparc_leon) { |
2040 | psr_typ = 0xf; /* hardcoded ids for older models/simulators */ | ||
2041 | psr_vers = 2; | ||
2042 | init_leon(); | 2040 | init_leon(); |
2043 | return; | 2041 | return; |
2044 | } | 2042 | } |
@@ -2301,7 +2299,8 @@ void __init ld_mmu_srmmu(void) | |||
2301 | BTFIXUPSET_CALL(flush_cache_mm, smp_flush_cache_mm, BTFIXUPCALL_NORM); | 2299 | BTFIXUPSET_CALL(flush_cache_mm, smp_flush_cache_mm, BTFIXUPCALL_NORM); |
2302 | BTFIXUPSET_CALL(flush_cache_range, smp_flush_cache_range, BTFIXUPCALL_NORM); | 2300 | BTFIXUPSET_CALL(flush_cache_range, smp_flush_cache_range, BTFIXUPCALL_NORM); |
2303 | BTFIXUPSET_CALL(flush_cache_page, smp_flush_cache_page, BTFIXUPCALL_NORM); | 2301 | BTFIXUPSET_CALL(flush_cache_page, smp_flush_cache_page, BTFIXUPCALL_NORM); |
2304 | if (sparc_cpu_model != sun4d) { | 2302 | if (sparc_cpu_model != sun4d && |
2303 | sparc_cpu_model != sparc_leon) { | ||
2305 | BTFIXUPSET_CALL(flush_tlb_all, smp_flush_tlb_all, BTFIXUPCALL_NORM); | 2304 | BTFIXUPSET_CALL(flush_tlb_all, smp_flush_tlb_all, BTFIXUPCALL_NORM); |
2306 | BTFIXUPSET_CALL(flush_tlb_mm, smp_flush_tlb_mm, BTFIXUPCALL_NORM); | 2305 | BTFIXUPSET_CALL(flush_tlb_mm, smp_flush_tlb_mm, BTFIXUPCALL_NORM); |
2307 | BTFIXUPSET_CALL(flush_tlb_range, smp_flush_tlb_range, BTFIXUPCALL_NORM); | 2306 | BTFIXUPSET_CALL(flush_tlb_range, smp_flush_tlb_range, BTFIXUPCALL_NORM); |
@@ -2330,6 +2329,8 @@ void __init ld_mmu_srmmu(void) | |||
2330 | #ifdef CONFIG_SMP | 2329 | #ifdef CONFIG_SMP |
2331 | if (sparc_cpu_model == sun4d) | 2330 | if (sparc_cpu_model == sun4d) |
2332 | sun4d_init_smp(); | 2331 | sun4d_init_smp(); |
2332 | else if (sparc_cpu_model == sparc_leon) | ||
2333 | leon_init_smp(); | ||
2333 | else | 2334 | else |
2334 | sun4m_init_smp(); | 2335 | sun4m_init_smp(); |
2335 | #endif | 2336 | #endif |
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index 2ffacd67c424..cf38846753dd 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c | |||
@@ -12,11 +12,13 @@ | |||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/mm.h> | 13 | #include <linux/mm.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/slab.h> | ||
15 | #include <linux/bootmem.h> | 16 | #include <linux/bootmem.h> |
16 | #include <linux/highmem.h> | 17 | #include <linux/highmem.h> |
17 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
18 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
19 | #include <linux/scatterlist.h> | 20 | #include <linux/scatterlist.h> |
21 | #include <linux/bitmap.h> | ||
20 | 22 | ||
21 | #include <asm/sections.h> | 23 | #include <asm/sections.h> |
22 | #include <asm/page.h> | 24 | #include <asm/page.h> |
@@ -1021,20 +1023,12 @@ static char *sun4c_lockarea(char *vaddr, unsigned long size) | |||
1021 | npages = (((unsigned long)vaddr & ~PAGE_MASK) + | 1023 | npages = (((unsigned long)vaddr & ~PAGE_MASK) + |
1022 | size + (PAGE_SIZE-1)) >> PAGE_SHIFT; | 1024 | size + (PAGE_SIZE-1)) >> PAGE_SHIFT; |
1023 | 1025 | ||
1024 | scan = 0; | ||
1025 | local_irq_save(flags); | 1026 | local_irq_save(flags); |
1026 | for (;;) { | 1027 | base = bitmap_find_next_zero_area(sun4c_iobuffer_map, iobuffer_map_size, |
1027 | scan = find_next_zero_bit(sun4c_iobuffer_map, | 1028 | 0, npages, 0); |
1028 | iobuffer_map_size, scan); | 1029 | if (base >= iobuffer_map_size) |
1029 | if ((base = scan) + npages > iobuffer_map_size) goto abend; | 1030 | goto abend; |
1030 | for (;;) { | ||
1031 | if (scan >= base + npages) goto found; | ||
1032 | if (test_bit(scan, sun4c_iobuffer_map)) break; | ||
1033 | scan++; | ||
1034 | } | ||
1035 | } | ||
1036 | 1031 | ||
1037 | found: | ||
1038 | high = ((base + npages) << PAGE_SHIFT) + sun4c_iobuffer_start; | 1032 | high = ((base + npages) << PAGE_SHIFT) + sun4c_iobuffer_start; |
1039 | high = SUN4C_REAL_PGDIR_ALIGN(high); | 1033 | high = SUN4C_REAL_PGDIR_ALIGN(high); |
1040 | while (high > sun4c_iobuffer_high) { | 1034 | while (high > sun4c_iobuffer_high) { |
@@ -1894,7 +1888,7 @@ static void sun4c_check_pgt_cache(int low, int high) | |||
1894 | /* An experiment, turn off by default for now... -DaveM */ | 1888 | /* An experiment, turn off by default for now... -DaveM */ |
1895 | #define SUN4C_PRELOAD_PSEG | 1889 | #define SUN4C_PRELOAD_PSEG |
1896 | 1890 | ||
1897 | void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) | 1891 | void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) |
1898 | { | 1892 | { |
1899 | unsigned long flags; | 1893 | unsigned long flags; |
1900 | int pseg; | 1894 | int pseg; |
@@ -1936,7 +1930,7 @@ void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, p | |||
1936 | start += PAGE_SIZE; | 1930 | start += PAGE_SIZE; |
1937 | } | 1931 | } |
1938 | #ifndef SUN4C_PRELOAD_PSEG | 1932 | #ifndef SUN4C_PRELOAD_PSEG |
1939 | sun4c_put_pte(address, pte_val(pte)); | 1933 | sun4c_put_pte(address, pte_val(*ptep)); |
1940 | #endif | 1934 | #endif |
1941 | local_irq_restore(flags); | 1935 | local_irq_restore(flags); |
1942 | return; | 1936 | return; |
@@ -1947,7 +1941,7 @@ void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, p | |||
1947 | add_lru(entry); | 1941 | add_lru(entry); |
1948 | } | 1942 | } |
1949 | 1943 | ||
1950 | sun4c_put_pte(address, pte_val(pte)); | 1944 | sun4c_put_pte(address, pte_val(*ptep)); |
1951 | local_irq_restore(flags); | 1945 | local_irq_restore(flags); |
1952 | } | 1946 | } |
1953 | 1947 | ||
diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c index 36a0813f9517..101d7c82870b 100644 --- a/arch/sparc/mm/tsb.c +++ b/arch/sparc/mm/tsb.c | |||
@@ -5,6 +5,7 @@ | |||
5 | 5 | ||
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
7 | #include <linux/preempt.h> | 7 | #include <linux/preempt.h> |
8 | #include <linux/slab.h> | ||
8 | #include <asm/system.h> | 9 | #include <asm/system.h> |
9 | #include <asm/page.h> | 10 | #include <asm/page.h> |
10 | #include <asm/tlbflush.h> | 11 | #include <asm/tlbflush.h> |