xref: /openbmc/linux/arch/m68k/mm/fault.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  *  linux/arch/m68k/mm/fault.c
3*1da177e4SLinus Torvalds  *
4*1da177e4SLinus Torvalds  *  Copyright (C) 1995  Hamish Macdonald
5*1da177e4SLinus Torvalds  */
6*1da177e4SLinus Torvalds 
7*1da177e4SLinus Torvalds #include <linux/mman.h>
8*1da177e4SLinus Torvalds #include <linux/mm.h>
9*1da177e4SLinus Torvalds #include <linux/kernel.h>
10*1da177e4SLinus Torvalds #include <linux/ptrace.h>
11*1da177e4SLinus Torvalds #include <linux/interrupt.h>
12*1da177e4SLinus Torvalds #include <linux/module.h>
13*1da177e4SLinus Torvalds 
14*1da177e4SLinus Torvalds #include <asm/setup.h>
15*1da177e4SLinus Torvalds #include <asm/traps.h>
16*1da177e4SLinus Torvalds #include <asm/system.h>
17*1da177e4SLinus Torvalds #include <asm/uaccess.h>
18*1da177e4SLinus Torvalds #include <asm/pgalloc.h>
19*1da177e4SLinus Torvalds 
20*1da177e4SLinus Torvalds extern void die_if_kernel(char *, struct pt_regs *, long);
21*1da177e4SLinus Torvalds extern const int frame_extra_sizes[]; /* in m68k/kernel/signal.c */
22*1da177e4SLinus Torvalds 
23*1da177e4SLinus Torvalds int send_fault_sig(struct pt_regs *regs)
24*1da177e4SLinus Torvalds {
25*1da177e4SLinus Torvalds 	siginfo_t siginfo = { 0, 0, 0, };
26*1da177e4SLinus Torvalds 
27*1da177e4SLinus Torvalds 	siginfo.si_signo = current->thread.signo;
28*1da177e4SLinus Torvalds 	siginfo.si_code = current->thread.code;
29*1da177e4SLinus Torvalds 	siginfo.si_addr = (void *)current->thread.faddr;
30*1da177e4SLinus Torvalds #ifdef DEBUG
31*1da177e4SLinus Torvalds 	printk("send_fault_sig: %p,%d,%d\n", siginfo.si_addr, siginfo.si_signo, siginfo.si_code);
32*1da177e4SLinus Torvalds #endif
33*1da177e4SLinus Torvalds 
34*1da177e4SLinus Torvalds 	if (user_mode(regs)) {
35*1da177e4SLinus Torvalds 		force_sig_info(siginfo.si_signo,
36*1da177e4SLinus Torvalds 			       &siginfo, current);
37*1da177e4SLinus Torvalds 	} else {
38*1da177e4SLinus Torvalds 		const struct exception_table_entry *fixup;
39*1da177e4SLinus Torvalds 
40*1da177e4SLinus Torvalds 		/* Are we prepared to handle this kernel fault? */
41*1da177e4SLinus Torvalds 		if ((fixup = search_exception_tables(regs->pc))) {
42*1da177e4SLinus Torvalds 			struct pt_regs *tregs;
43*1da177e4SLinus Torvalds 			/* Create a new four word stack frame, discarding the old
44*1da177e4SLinus Torvalds 			   one.  */
45*1da177e4SLinus Torvalds 			regs->stkadj = frame_extra_sizes[regs->format];
46*1da177e4SLinus Torvalds 			tregs =	(struct pt_regs *)((ulong)regs + regs->stkadj);
47*1da177e4SLinus Torvalds 			tregs->vector = regs->vector;
48*1da177e4SLinus Torvalds 			tregs->format = 0;
49*1da177e4SLinus Torvalds 			tregs->pc = fixup->fixup;
50*1da177e4SLinus Torvalds 			tregs->sr = regs->sr;
51*1da177e4SLinus Torvalds 			return -1;
52*1da177e4SLinus Torvalds 		}
53*1da177e4SLinus Torvalds 
54*1da177e4SLinus Torvalds 		//if (siginfo.si_signo == SIGBUS)
55*1da177e4SLinus Torvalds 		//	force_sig_info(siginfo.si_signo,
56*1da177e4SLinus Torvalds 		//		       &siginfo, current);
57*1da177e4SLinus Torvalds 
58*1da177e4SLinus Torvalds 		/*
59*1da177e4SLinus Torvalds 		 * Oops. The kernel tried to access some bad page. We'll have to
60*1da177e4SLinus Torvalds 		 * terminate things with extreme prejudice.
61*1da177e4SLinus Torvalds 		 */
62*1da177e4SLinus Torvalds 		if ((unsigned long)siginfo.si_addr < PAGE_SIZE)
63*1da177e4SLinus Torvalds 			printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
64*1da177e4SLinus Torvalds 		else
65*1da177e4SLinus Torvalds 			printk(KERN_ALERT "Unable to handle kernel access");
66*1da177e4SLinus Torvalds 		printk(" at virtual address %p\n", siginfo.si_addr);
67*1da177e4SLinus Torvalds 		die_if_kernel("Oops", regs, 0 /*error_code*/);
68*1da177e4SLinus Torvalds 		do_exit(SIGKILL);
69*1da177e4SLinus Torvalds 	}
70*1da177e4SLinus Torvalds 
71*1da177e4SLinus Torvalds 	return 1;
72*1da177e4SLinus Torvalds }
73*1da177e4SLinus Torvalds 
74*1da177e4SLinus Torvalds /*
75*1da177e4SLinus Torvalds  * This routine handles page faults.  It determines the problem, and
76*1da177e4SLinus Torvalds  * then passes it off to one of the appropriate routines.
77*1da177e4SLinus Torvalds  *
78*1da177e4SLinus Torvalds  * error_code:
79*1da177e4SLinus Torvalds  *	bit 0 == 0 means no page found, 1 means protection fault
80*1da177e4SLinus Torvalds  *	bit 1 == 0 means read, 1 means write
81*1da177e4SLinus Torvalds  *
82*1da177e4SLinus Torvalds  * If this routine detects a bad access, it returns 1, otherwise it
83*1da177e4SLinus Torvalds  * returns 0.
84*1da177e4SLinus Torvalds  */
85*1da177e4SLinus Torvalds int do_page_fault(struct pt_regs *regs, unsigned long address,
86*1da177e4SLinus Torvalds 			      unsigned long error_code)
87*1da177e4SLinus Torvalds {
88*1da177e4SLinus Torvalds 	struct mm_struct *mm = current->mm;
89*1da177e4SLinus Torvalds 	struct vm_area_struct * vma;
90*1da177e4SLinus Torvalds 	int write, fault;
91*1da177e4SLinus Torvalds 
92*1da177e4SLinus Torvalds #ifdef DEBUG
93*1da177e4SLinus Torvalds 	printk ("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
94*1da177e4SLinus Torvalds 		regs->sr, regs->pc, address, error_code,
95*1da177e4SLinus Torvalds 		current->mm->pgd);
96*1da177e4SLinus Torvalds #endif
97*1da177e4SLinus Torvalds 
98*1da177e4SLinus Torvalds 	/*
99*1da177e4SLinus Torvalds 	 * If we're in an interrupt or have no user
100*1da177e4SLinus Torvalds 	 * context, we must not take the fault..
101*1da177e4SLinus Torvalds 	 */
102*1da177e4SLinus Torvalds 	if (in_interrupt() || !mm)
103*1da177e4SLinus Torvalds 		goto no_context;
104*1da177e4SLinus Torvalds 
105*1da177e4SLinus Torvalds 	down_read(&mm->mmap_sem);
106*1da177e4SLinus Torvalds 
107*1da177e4SLinus Torvalds 	vma = find_vma(mm, address);
108*1da177e4SLinus Torvalds 	if (!vma)
109*1da177e4SLinus Torvalds 		goto map_err;
110*1da177e4SLinus Torvalds 	if (vma->vm_flags & VM_IO)
111*1da177e4SLinus Torvalds 		goto acc_err;
112*1da177e4SLinus Torvalds 	if (vma->vm_start <= address)
113*1da177e4SLinus Torvalds 		goto good_area;
114*1da177e4SLinus Torvalds 	if (!(vma->vm_flags & VM_GROWSDOWN))
115*1da177e4SLinus Torvalds 		goto map_err;
116*1da177e4SLinus Torvalds 	if (user_mode(regs)) {
117*1da177e4SLinus Torvalds 		/* Accessing the stack below usp is always a bug.  The
118*1da177e4SLinus Torvalds 		   "+ 256" is there due to some instructions doing
119*1da177e4SLinus Torvalds 		   pre-decrement on the stack and that doesn't show up
120*1da177e4SLinus Torvalds 		   until later.  */
121*1da177e4SLinus Torvalds 		if (address + 256 < rdusp())
122*1da177e4SLinus Torvalds 			goto map_err;
123*1da177e4SLinus Torvalds 	}
124*1da177e4SLinus Torvalds 	if (expand_stack(vma, address))
125*1da177e4SLinus Torvalds 		goto map_err;
126*1da177e4SLinus Torvalds 
127*1da177e4SLinus Torvalds /*
128*1da177e4SLinus Torvalds  * Ok, we have a good vm_area for this memory access, so
129*1da177e4SLinus Torvalds  * we can handle it..
130*1da177e4SLinus Torvalds  */
131*1da177e4SLinus Torvalds good_area:
132*1da177e4SLinus Torvalds #ifdef DEBUG
133*1da177e4SLinus Torvalds 	printk("do_page_fault: good_area\n");
134*1da177e4SLinus Torvalds #endif
135*1da177e4SLinus Torvalds 	write = 0;
136*1da177e4SLinus Torvalds 	switch (error_code & 3) {
137*1da177e4SLinus Torvalds 		default:	/* 3: write, present */
138*1da177e4SLinus Torvalds 			/* fall through */
139*1da177e4SLinus Torvalds 		case 2:		/* write, not present */
140*1da177e4SLinus Torvalds 			if (!(vma->vm_flags & VM_WRITE))
141*1da177e4SLinus Torvalds 				goto acc_err;
142*1da177e4SLinus Torvalds 			write++;
143*1da177e4SLinus Torvalds 			break;
144*1da177e4SLinus Torvalds 		case 1:		/* read, present */
145*1da177e4SLinus Torvalds 			goto acc_err;
146*1da177e4SLinus Torvalds 		case 0:		/* read, not present */
147*1da177e4SLinus Torvalds 			if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
148*1da177e4SLinus Torvalds 				goto acc_err;
149*1da177e4SLinus Torvalds 	}
150*1da177e4SLinus Torvalds 
151*1da177e4SLinus Torvalds 	/*
152*1da177e4SLinus Torvalds 	 * If for any reason at all we couldn't handle the fault,
153*1da177e4SLinus Torvalds 	 * make sure we exit gracefully rather than endlessly redo
154*1da177e4SLinus Torvalds 	 * the fault.
155*1da177e4SLinus Torvalds 	 */
156*1da177e4SLinus Torvalds 
157*1da177e4SLinus Torvalds  survive:
158*1da177e4SLinus Torvalds 	fault = handle_mm_fault(mm, vma, address, write);
159*1da177e4SLinus Torvalds #ifdef DEBUG
160*1da177e4SLinus Torvalds 	printk("handle_mm_fault returns %d\n",fault);
161*1da177e4SLinus Torvalds #endif
162*1da177e4SLinus Torvalds 	switch (fault) {
163*1da177e4SLinus Torvalds 	case 1:
164*1da177e4SLinus Torvalds 		current->min_flt++;
165*1da177e4SLinus Torvalds 		break;
166*1da177e4SLinus Torvalds 	case 2:
167*1da177e4SLinus Torvalds 		current->maj_flt++;
168*1da177e4SLinus Torvalds 		break;
169*1da177e4SLinus Torvalds 	case 0:
170*1da177e4SLinus Torvalds 		goto bus_err;
171*1da177e4SLinus Torvalds 	default:
172*1da177e4SLinus Torvalds 		goto out_of_memory;
173*1da177e4SLinus Torvalds 	}
174*1da177e4SLinus Torvalds 
175*1da177e4SLinus Torvalds 	up_read(&mm->mmap_sem);
176*1da177e4SLinus Torvalds 	return 0;
177*1da177e4SLinus Torvalds 
178*1da177e4SLinus Torvalds /*
179*1da177e4SLinus Torvalds  * We ran out of memory, or some other thing happened to us that made
180*1da177e4SLinus Torvalds  * us unable to handle the page fault gracefully.
181*1da177e4SLinus Torvalds  */
182*1da177e4SLinus Torvalds out_of_memory:
183*1da177e4SLinus Torvalds 	up_read(&mm->mmap_sem);
184*1da177e4SLinus Torvalds 	if (current->pid == 1) {
185*1da177e4SLinus Torvalds 		yield();
186*1da177e4SLinus Torvalds 		down_read(&mm->mmap_sem);
187*1da177e4SLinus Torvalds 		goto survive;
188*1da177e4SLinus Torvalds 	}
189*1da177e4SLinus Torvalds 
190*1da177e4SLinus Torvalds 	printk("VM: killing process %s\n", current->comm);
191*1da177e4SLinus Torvalds 	if (user_mode(regs))
192*1da177e4SLinus Torvalds 		do_exit(SIGKILL);
193*1da177e4SLinus Torvalds 
194*1da177e4SLinus Torvalds no_context:
195*1da177e4SLinus Torvalds 	current->thread.signo = SIGBUS;
196*1da177e4SLinus Torvalds 	current->thread.faddr = address;
197*1da177e4SLinus Torvalds 	return send_fault_sig(regs);
198*1da177e4SLinus Torvalds 
199*1da177e4SLinus Torvalds bus_err:
200*1da177e4SLinus Torvalds 	current->thread.signo = SIGBUS;
201*1da177e4SLinus Torvalds 	current->thread.code = BUS_ADRERR;
202*1da177e4SLinus Torvalds 	current->thread.faddr = address;
203*1da177e4SLinus Torvalds 	goto send_sig;
204*1da177e4SLinus Torvalds 
205*1da177e4SLinus Torvalds map_err:
206*1da177e4SLinus Torvalds 	current->thread.signo = SIGSEGV;
207*1da177e4SLinus Torvalds 	current->thread.code = SEGV_MAPERR;
208*1da177e4SLinus Torvalds 	current->thread.faddr = address;
209*1da177e4SLinus Torvalds 	goto send_sig;
210*1da177e4SLinus Torvalds 
211*1da177e4SLinus Torvalds acc_err:
212*1da177e4SLinus Torvalds 	current->thread.signo = SIGSEGV;
213*1da177e4SLinus Torvalds 	current->thread.code = SEGV_ACCERR;
214*1da177e4SLinus Torvalds 	current->thread.faddr = address;
215*1da177e4SLinus Torvalds 
216*1da177e4SLinus Torvalds send_sig:
217*1da177e4SLinus Torvalds 	up_read(&mm->mmap_sem);
218*1da177e4SLinus Torvalds 	return send_fault_sig(regs);
219*1da177e4SLinus Torvalds }
220