File: /usr/src/linux/arch/sparc/mm/fault.c

1     /* $Id: fault.c,v 1.120 2001/07/18 13:40:05 anton Exp $
2      * fault.c:  Page fault handlers for the Sparc.
3      *
4      * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
5      * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
6      * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
7      */
8     
9     #include <asm/head.h>
10     
11     #include <linux/string.h>
12     #include <linux/types.h>
13     #include <linux/ptrace.h>
14     #include <linux/mman.h>
15     #include <linux/threads.h>
16     #include <linux/kernel.h>
17     #include <linux/signal.h>
18     #include <linux/mm.h>
19     #include <linux/smp.h>
20     #include <linux/smp_lock.h>
21     #include <linux/interrupt.h>
22     
23     #include <asm/system.h>
24     #include <asm/segment.h>
25     #include <asm/page.h>
26     #include <asm/pgtable.h>
27     #include <asm/memreg.h>
28     #include <asm/openprom.h>
29     #include <asm/oplib.h>
30     #include <asm/smp.h>
31     #include <asm/traps.h>
32     #include <asm/kdebug.h>
33     #include <asm/uaccess.h>
34     
35     #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0]))
36     
37     extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
38     extern int prom_node_root;
39     
40     /* At boot time we determine these two values necessary for setting
41      * up the segment maps and page table entries (pte's).
42      */
43     
44     int num_segmaps, num_contexts;
45     int invalid_segment;
46     
47     /* various Virtual Address Cache parameters we find at boot time... */
48     
49     int vac_size, vac_linesize, vac_do_hw_vac_flushes;
50     int vac_entries_per_context, vac_entries_per_segment;
51     int vac_entries_per_page;
52     
53     /* Nice, simple, prom library does all the sweating for us. ;) */
54     int prom_probe_memory (void)
55     {
56     	register struct linux_mlist_v0 *mlist;
57     	register unsigned long bytes, base_paddr, tally;
58     	register int i;
59     
60     	i = 0;
61     	mlist= *prom_meminfo()->v0_available;
62     	bytes = tally = mlist->num_bytes;
63     	base_paddr = (unsigned long) mlist->start_adr;
64       
65     	sp_banks[0].base_addr = base_paddr;
66     	sp_banks[0].num_bytes = bytes;
67     
68     	while (mlist->theres_more != (void *) 0){
69     		i++;
70     		mlist = mlist->theres_more;
71     		bytes = mlist->num_bytes;
72     		tally += bytes;
73     		if (i >= SPARC_PHYS_BANKS-1) {
74     			printk ("The machine has more banks than "
75     				"this kernel can support\n"
76     				"Increase the SPARC_PHYS_BANKS "
77     				"setting (currently %d)\n",
78     				SPARC_PHYS_BANKS);
79     			i = SPARC_PHYS_BANKS-1;
80     			break;
81     		}
82         
83     		sp_banks[i].base_addr = (unsigned long) mlist->start_adr;
84     		sp_banks[i].num_bytes = mlist->num_bytes;
85     	}
86     
87     	i++;
88     	sp_banks[i].base_addr = 0xdeadbeef;
89     	sp_banks[i].num_bytes = 0;
90     
91     	/* Now mask all bank sizes on a page boundary, it is all we can
92     	 * use anyways.
93     	 */
94     	for(i=0; sp_banks[i].num_bytes != 0; i++)
95     		sp_banks[i].num_bytes &= PAGE_MASK;
96     
97     	return tally;
98     }
99     
100     /* Traverse the memory lists in the prom to see how much physical we
101      * have.
102      */
103     unsigned long
104     probe_memory(void)
105     {
106     	int total;
107     
108     	total = prom_probe_memory();
109     
110     	/* Oh man, much nicer, keep the dirt in promlib. */
111     	return total;
112     }
113     
114     extern void sun4c_complete_all_stores(void);
115     
116     /* Whee, a level 15 NMI interrupt memory error.  Let's have fun... */
117     asmlinkage void sparc_lvl15_nmi(struct pt_regs *regs, unsigned long serr,
118     				unsigned long svaddr, unsigned long aerr,
119     				unsigned long avaddr)
120     {
121     	sun4c_complete_all_stores();
122     	printk("FAULT: NMI received\n");
123     	printk("SREGS: Synchronous Error %08lx\n", serr);
124     	printk("       Synchronous Vaddr %08lx\n", svaddr);
125     	printk("      Asynchronous Error %08lx\n", aerr);
126     	printk("      Asynchronous Vaddr %08lx\n", avaddr);
127     	if (sun4c_memerr_reg)
128     		printk("     Memory Parity Error %08lx\n", *sun4c_memerr_reg);
129     	printk("REGISTER DUMP:\n");
130     	show_regs(regs);
131     	prom_halt();
132     }
133     
134     static void unhandled_fault(unsigned long, struct task_struct *,
135     		struct pt_regs *) __attribute__ ((noreturn));
136     
137     static void unhandled_fault(unsigned long address, struct task_struct *tsk,
138                          struct pt_regs *regs)
139     {
140     	if((unsigned long) address < PAGE_SIZE) {
141     		printk(KERN_ALERT "Unable to handle kernel NULL "
142     		       "pointer dereference");
143     	} else {
144     		printk(KERN_ALERT "Unable to handle kernel paging request "
145     		       "at virtual address %08lx\n", address);
146     	}
147     	printk(KERN_ALERT "tsk->{mm,active_mm}->context = %08lx\n",
148     		(tsk->mm ? tsk->mm->context : tsk->active_mm->context));
149     	printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %08lx\n",
150     		(tsk->mm ? (unsigned long) tsk->mm->pgd :
151     		 	(unsigned long) tsk->active_mm->pgd));
152     	die_if_kernel("Oops", regs);
153     }
154     
155     asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc, 
156     			    unsigned long address)
157     {
158     	unsigned long g2;
159     	int i;
160     	unsigned insn;
161     	struct pt_regs regs;
162     	
163     	i = search_exception_table (ret_pc, &g2);
164     	switch (i) {
165     	/* load & store will be handled by fixup */
166     	case 3: return 3;
167     	/* store will be handled by fixup, load will bump out */
168     	/* for _to_ macros */
169     	case 1: insn = (unsigned)pc; if ((insn >> 21) & 1) return 1; break;
170     	/* load will be handled by fixup, store will bump out */
171     	/* for _from_ macros */
172     	case 2: insn = (unsigned)pc; 
173     		if (!((insn >> 21) & 1) || ((insn>>19)&0x3f) == 15) return 2; 
174     		break; 
175     	default: break;
176     	}
177     	memset (&regs, 0, sizeof (regs));
178     	regs.pc = pc;
179     	regs.npc = pc + 4;
180     	__asm__ __volatile__ ("
181     		rd %%psr, %0
182     		nop
183     		nop
184     		nop" : "=r" (regs.psr));
185     	unhandled_fault (address, current, &regs);
186     	/* Not reached */
187     	return 0;
188     }
189     
190     asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
191     			       unsigned long address)
192     {
193     	struct vm_area_struct *vma;
194     	struct task_struct *tsk = current;
195     	struct mm_struct *mm = tsk->mm;
196     	unsigned int fixup;
197     	unsigned long g2;
198     	siginfo_t info;
199     	int from_user = !(regs->psr & PSR_PS);
200     
201     	if(text_fault)
202     		address = regs->pc;
203     
204     	/*
205     	 * We fault-in kernel-space virtual memory on-demand. The
206     	 * 'reference' page table is init_mm.pgd.
207     	 *
208     	 * NOTE! We MUST NOT take any locks for this case. We may
209     	 * be in an interrupt or a critical region, and should
210     	 * only copy the information from the master page table,
211     	 * nothing more.
212     	 */
213     	if (!ARCH_SUN4C_SUN4 && address >= TASK_SIZE)
214     		goto vmalloc_fault;
215     
216     	info.si_code = SEGV_MAPERR;
217     
218     	/*
219     	 * If we're in an interrupt or have no user
220     	 * context, we must not take the fault..
221     	 */
222             if (in_interrupt() || !mm)
223                     goto no_context;
224     
225     	down_read(&mm->mmap_sem);
226     
227     	/*
228     	 * The kernel referencing a bad kernel pointer can lock up
229     	 * a sun4c machine completely, so we must attempt recovery.
230     	 */
231     	if(!from_user && address >= PAGE_OFFSET)
232     		goto bad_area;
233     
234     	vma = find_vma(mm, address);
235     	if(!vma)
236     		goto bad_area;
237     	if(vma->vm_start <= address)
238     		goto good_area;
239     	if(!(vma->vm_flags & VM_GROWSDOWN))
240     		goto bad_area;
241     	if(expand_stack(vma, address))
242     		goto bad_area;
243     	/*
244     	 * Ok, we have a good vm_area for this memory access, so
245     	 * we can handle it..
246     	 */
247     good_area:
248     	info.si_code = SEGV_ACCERR;
249     	if(write) {
250     		if(!(vma->vm_flags & VM_WRITE))
251     			goto bad_area;
252     	} else {
253     		/* Allow reads even for write-only mappings */
254     		if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
255     			goto bad_area;
256     	}
257     
258     	/*
259     	 * If for any reason at all we couldn't handle the fault,
260     	 * make sure we exit gracefully rather than endlessly redo
261     	 * the fault.
262     	 */
263     	switch (handle_mm_fault(mm, vma, address, write)) {
264     	case 1:
265     		current->min_flt++;
266     		break;
267     	case 2:
268     		current->maj_flt++;
269     		break;
270     	case 0:
271     		goto do_sigbus;
272     	default:
273     		goto out_of_memory;
274     	}
275     	up_read(&mm->mmap_sem);
276     	return;
277     
278     	/*
279     	 * Something tried to access memory that isn't in our memory map..
280     	 * Fix it, but check if it's kernel or user first..
281     	 */
282     bad_area:
283     	up_read(&mm->mmap_sem);
284     
285     bad_area_nosemaphore:
286     	/* User mode accesses just cause a SIGSEGV */
287     	if(from_user) {
288     #if 0
289     		printk("Fault whee %s [%d]: segfaults at %08lx pc=%08lx\n",
290     		       tsk->comm, tsk->pid, address, regs->pc);
291     #endif
292     		info.si_signo = SIGSEGV;
293     		info.si_errno = 0;
294     		/* info.si_code set above to make clear whether
295     		   this was a SEGV_MAPERR or SEGV_ACCERR fault.  */
296     		info.si_addr = (void *)address;
297     		info.si_trapno = 0;
298     		force_sig_info (SIGSEGV, &info, tsk);
299     		return;
300     	}
301     
302     	/* Is this in ex_table? */
303     no_context:
304     	g2 = regs->u_regs[UREG_G2];
305     	if (!from_user && (fixup = search_exception_table (regs->pc, &g2))) {
306     		if (fixup > 10) { /* Values below are reserved for other things */
307     			extern const unsigned __memset_start[];
308     			extern const unsigned __memset_end[];
309     			extern const unsigned __csum_partial_copy_start[];
310     			extern const unsigned __csum_partial_copy_end[];
311     
312     #ifdef DEBUG_EXCEPTIONS
313     			printk("Exception: PC<%08lx> faddr<%08lx>\n", regs->pc, address);
314     			printk("EX_TABLE: insn<%08lx> fixup<%08x> g2<%08lx>\n",
315     				regs->pc, fixup, g2);
316     #endif
317     			if ((regs->pc >= (unsigned long)__memset_start &&
318     			     regs->pc < (unsigned long)__memset_end) ||
319     			    (regs->pc >= (unsigned long)__csum_partial_copy_start &&
320     			     regs->pc < (unsigned long)__csum_partial_copy_end)) {
321     			        regs->u_regs[UREG_I4] = address;
322     				regs->u_regs[UREG_I5] = regs->pc;
323     			}
324     			regs->u_regs[UREG_G2] = g2;
325     			regs->pc = fixup;
326     			regs->npc = regs->pc + 4;
327     			return;
328     		}
329     	}
330     	
331     	unhandled_fault (address, tsk, regs);
332     	do_exit(SIGKILL);
333     
334     /*
335      * We ran out of memory, or some other thing happened to us that made
336      * us unable to handle the page fault gracefully.
337      */
338     out_of_memory:
339     	up_read(&mm->mmap_sem);
340     	printk("VM: killing process %s\n", tsk->comm);
341     	if (from_user)
342     		do_exit(SIGKILL);
343     	goto no_context;
344     
345     do_sigbus:
346     	up_read(&mm->mmap_sem);
347     	info.si_signo = SIGBUS;
348     	info.si_errno = 0;
349     	info.si_code = BUS_ADRERR;
350     	info.si_addr = (void *)address;
351     	info.si_trapno = 0;
352     	force_sig_info (SIGBUS, &info, tsk);
353     	if (!from_user)
354     		goto no_context;
355     
356     vmalloc_fault:
357     	{
358     		/*
359     		 * Synchronize this task's top level page-table
360     		 * with the 'reference' page table.
361     		 */
362     		int offset = pgd_index(address);
363     		pgd_t *pgd, *pgd_k;
364     		pmd_t *pmd, *pmd_k;
365     
366     		pgd = tsk->active_mm->pgd + offset;
367     		pgd_k = init_mm.pgd + offset;
368     
369     		if (!pgd_present(*pgd)) {
370     			if (!pgd_present(*pgd_k))
371     				goto bad_area_nosemaphore;
372     			pgd_val(*pgd) = pgd_val(*pgd_k);
373     			return;
374     		}
375     
376     		pmd = pmd_offset(pgd, address);
377     		pmd_k = pmd_offset(pgd_k, address);
378     
379     		if (pmd_present(*pmd) || !pmd_present(*pmd_k))
380     			goto bad_area_nosemaphore;
381     		pmd_val(*pmd) = pmd_val(*pmd_k);
382     		return;
383     	}
384     }
385     
386     asmlinkage void do_sun4c_fault(struct pt_regs *regs, int text_fault, int write,
387     			       unsigned long address)
388     {
389     	extern void sun4c_update_mmu_cache(struct vm_area_struct *,
390     					   unsigned long,pte_t);
391     	extern pte_t *sun4c_pte_offset(pmd_t *,unsigned long);
392     	struct task_struct *tsk = current;
393     	struct mm_struct *mm = tsk->mm;
394     	pgd_t *pgdp;
395     	pte_t *ptep;
396     
397     	if (text_fault) {
398     		address = regs->pc;
399     	} else if (!write &&
400     		   !(regs->psr & PSR_PS)) {
401     		unsigned int insn, *ip;
402     
403     		ip = (unsigned int *)regs->pc;
404     		if (! get_user(insn, ip)) {
405     			if ((insn & 0xc1680000) == 0xc0680000)
406     				write = 1;
407     		}
408     	}
409     
410     	pgdp = pgd_offset(mm, address);
411     	ptep = sun4c_pte_offset((pmd_t *) pgdp, address);
412     
413     	if (pgd_val(*pgdp)) {
414     	    if (write) {
415     		if ((pte_val(*ptep) & (_SUN4C_PAGE_WRITE|_SUN4C_PAGE_PRESENT))
416     				   == (_SUN4C_PAGE_WRITE|_SUN4C_PAGE_PRESENT)) {
417     			unsigned long flags;
418     
419     			*ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_ACCESSED |
420     				      _SUN4C_PAGE_MODIFIED |
421     				      _SUN4C_PAGE_VALID |
422     				      _SUN4C_PAGE_DIRTY);
423     
424     			save_and_cli(flags);
425     			if (sun4c_get_segmap(address) != invalid_segment) {
426     				sun4c_put_pte(address, pte_val(*ptep));
427     				restore_flags(flags);
428     				return;
429     			}
430     			restore_flags(flags);
431     		}
432     	    } else {
433     		if ((pte_val(*ptep) & (_SUN4C_PAGE_READ|_SUN4C_PAGE_PRESENT))
434     				   == (_SUN4C_PAGE_READ|_SUN4C_PAGE_PRESENT)) {
435     			unsigned long flags;
436     
437     			*ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_ACCESSED |
438     				      _SUN4C_PAGE_VALID);
439     
440     			save_and_cli(flags);
441     			if (sun4c_get_segmap(address) != invalid_segment) {
442     				sun4c_put_pte(address, pte_val(*ptep));
443     				restore_flags(flags);
444     				return;
445     			}
446     			restore_flags(flags);
447     		}
448     	    }
449     	}
450     
451     	/* This conditional is 'interesting'. */
452     	if (pgd_val(*pgdp) && !(write && !(pte_val(*ptep) & _SUN4C_PAGE_WRITE))
453     	    && (pte_val(*ptep) & _SUN4C_PAGE_VALID))
454     		/* Note: It is safe to not grab the MMAP semaphore here because
455     		 *       we know that update_mmu_cache() will not sleep for
456     		 *       any reason (at least not in the current implementation)
457     		 *       and therefore there is no danger of another thread getting
458     		 *       on the CPU and doing a shrink_mmap() on this vma.
459     		 */
460     		sun4c_update_mmu_cache (find_vma(current->mm, address), address,
461     					*ptep);
462     	else
463     		do_sparc_fault(regs, text_fault, write, address);
464     }
465     
466     /* This always deals with user addresses. */
467     inline void force_user_fault(unsigned long address, int write)
468     {
469     	struct vm_area_struct *vma;
470     	struct task_struct *tsk = current;
471     	struct mm_struct *mm = tsk->mm;
472     	siginfo_t info;
473     
474     	info.si_code = SEGV_MAPERR;
475     
476     #if 0
477     	printk("wf<pid=%d,wr=%d,addr=%08lx>\n",
478     	       tsk->pid, write, address);
479     #endif
480     	down_read(&mm->mmap_sem);
481     	vma = find_vma(mm, address);
482     	if(!vma)
483     		goto bad_area;
484     	if(vma->vm_start <= address)
485     		goto good_area;
486     	if(!(vma->vm_flags & VM_GROWSDOWN))
487     		goto bad_area;
488     	if(expand_stack(vma, address))
489     		goto bad_area;
490     good_area:
491     	info.si_code = SEGV_ACCERR;
492     	if(write) {
493     		if(!(vma->vm_flags & VM_WRITE))
494     			goto bad_area;
495     	} else {
496     		if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
497     			goto bad_area;
498     	}
499     	if (!handle_mm_fault(mm, vma, address, write))
500     		goto do_sigbus;
501     	up_read(&mm->mmap_sem);
502     	return;
503     bad_area:
504     	up_read(&mm->mmap_sem);
505     #if 0
506     	printk("Window whee %s [%d]: segfaults at %08lx\n",
507     	       tsk->comm, tsk->pid, address);
508     #endif
509     	info.si_signo = SIGSEGV;
510     	info.si_errno = 0;
511     	/* info.si_code set above to make clear whether
512     	   this was a SEGV_MAPERR or SEGV_ACCERR fault.  */
513     	info.si_addr = (void *)address;
514     	info.si_trapno = 0;
515     	force_sig_info (SIGSEGV, &info, tsk);
516     	return;
517     
518     do_sigbus:
519     	up_read(&mm->mmap_sem);
520     	info.si_signo = SIGBUS;
521     	info.si_errno = 0;
522     	info.si_code = BUS_ADRERR;
523     	info.si_addr = (void *)address;
524     	info.si_trapno = 0;
525     	force_sig_info (SIGBUS, &info, tsk);
526     }
527     
528     void window_overflow_fault(void)
529     {
530     	unsigned long sp;
531     
532     	sp = current->thread.rwbuf_stkptrs[0];
533     	if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
534     		force_user_fault(sp + 0x38, 1);
535     	force_user_fault(sp, 1);
536     }
537     
538     void window_underflow_fault(unsigned long sp)
539     {
540     	if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
541     		force_user_fault(sp + 0x38, 0);
542     	force_user_fault(sp, 0);
543     }
544     
545     void window_ret_fault(struct pt_regs *regs)
546     {
547     	unsigned long sp;
548     
549     	sp = regs->u_regs[UREG_FP];
550     	if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
551     		force_user_fault(sp + 0x38, 0);
552     	force_user_fault(sp, 0);
553     }
554