1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * Based on linux/arch/sh/mm/fault.c:
5 *   Copyright (C) 1999  Niibe Yutaka
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/mm.h>
13#include <linux/module.h>
14#include <linux/pagemap.h>
15#include <linux/kdebug.h>
16#include <linux/kprobes.h>
17
18#include <asm/mmu_context.h>
19#include <asm/sysreg.h>
20#include <asm/tlb.h>
21#include <asm/uaccess.h>
22
23#ifdef CONFIG_KPROBES
24static inline int notify_page_fault(struct pt_regs *regs, int trap)
25{
26	int ret = 0;
27
28	if (!user_mode(regs)) {
29		if (kprobe_running() && kprobe_fault_handler(regs, trap))
30			ret = 1;
31	}
32
33	return ret;
34}
35#else
36static inline int notify_page_fault(struct pt_regs *regs, int trap)
37{
38	return 0;
39}
40#endif
41
42int exception_trace = 1;
43
44/*
45 * This routine handles page faults. It determines the address and the
46 * problem, and then passes it off to one of the appropriate routines.
47 *
48 * ecr is the Exception Cause Register. Possible values are:
49 *   6:  Protection fault (instruction access)
50 *   15: Protection fault (read access)
51 *   16: Protection fault (write access)
52 *   20: Page not found (instruction access)
53 *   24: Page not found (read access)
54 *   28: Page not found (write access)
55 */
56asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
57{
58	struct task_struct *tsk;
59	struct mm_struct *mm;
60	struct vm_area_struct *vma;
61	const struct exception_table_entry *fixup;
62	unsigned long address;
63	unsigned long page;
64	long signr;
65	int code;
66	int fault;
67	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
68
69	if (notify_page_fault(regs, ecr))
70		return;
71
72	address = sysreg_read(TLBEAR);
73
74	tsk = current;
75	mm = tsk->mm;
76
77	signr = SIGSEGV;
78	code = SEGV_MAPERR;
79
80	/*
81	 * If we're in an interrupt or have no user context, we must
82	 * not take the fault...
83	 */
84	if (in_atomic() || !mm || regs->sr & SYSREG_BIT(GM))
85		goto no_context;
86
87	local_irq_enable();
88
89	if (user_mode(regs))
90		flags |= FAULT_FLAG_USER;
91retry:
92	down_read(&mm->mmap_sem);
93
94	vma = find_vma(mm, address);
95	if (!vma)
96		goto bad_area;
97	if (vma->vm_start <= address)
98		goto good_area;
99	if (!(vma->vm_flags & VM_GROWSDOWN))
100		goto bad_area;
101	if (expand_stack(vma, address))
102		goto bad_area;
103
104	/*
105	 * Ok, we have a good vm_area for this memory access, so we
106	 * can handle it...
107	 */
108good_area:
109	code = SEGV_ACCERR;
110
111	switch (ecr) {
112	case ECR_PROTECTION_X:
113	case ECR_TLB_MISS_X:
114		if (!(vma->vm_flags & VM_EXEC))
115			goto bad_area;
116		break;
117	case ECR_PROTECTION_R:
118	case ECR_TLB_MISS_R:
119		if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
120			goto bad_area;
121		break;
122	case ECR_PROTECTION_W:
123	case ECR_TLB_MISS_W:
124		if (!(vma->vm_flags & VM_WRITE))
125			goto bad_area;
126		flags |= FAULT_FLAG_WRITE;
127		break;
128	default:
129		panic("Unhandled case %lu in do_page_fault!", ecr);
130	}
131
132	/*
133	 * If for any reason at all we couldn't handle the fault, make
134	 * sure we exit gracefully rather than endlessly redo the
135	 * fault.
136	 */
137	fault = handle_mm_fault(mm, vma, address, flags);
138
139	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
140		return;
141
142	if (unlikely(fault & VM_FAULT_ERROR)) {
143		if (fault & VM_FAULT_OOM)
144			goto out_of_memory;
145		else if (fault & VM_FAULT_SIGBUS)
146			goto do_sigbus;
147		BUG();
148	}
149
150	if (flags & FAULT_FLAG_ALLOW_RETRY) {
151		if (fault & VM_FAULT_MAJOR)
152			tsk->maj_flt++;
153		else
154			tsk->min_flt++;
155		if (fault & VM_FAULT_RETRY) {
156			flags &= ~FAULT_FLAG_ALLOW_RETRY;
157			flags |= FAULT_FLAG_TRIED;
158
159			/*
160			 * No need to up_read(&mm->mmap_sem) as we would have
161			 * already released it in __lock_page_or_retry() in
162			 * mm/filemap.c.
163			 */
164			goto retry;
165		}
166	}
167
168	up_read(&mm->mmap_sem);
169	return;
170
171	/*
172	 * Something tried to access memory that isn't in our memory
173	 * map. Fix it, but check if it's kernel or user first...
174	 */
175bad_area:
176	up_read(&mm->mmap_sem);
177
178	if (user_mode(regs)) {
179		if (exception_trace && printk_ratelimit())
180			printk("%s%s[%d]: segfault at %08lx pc %08lx "
181			       "sp %08lx ecr %lu\n",
182			       is_global_init(tsk) ? KERN_EMERG : KERN_INFO,
183			       tsk->comm, tsk->pid, address, regs->pc,
184			       regs->sp, ecr);
185		_exception(SIGSEGV, regs, code, address);
186		return;
187	}
188
189no_context:
190	/* Are we prepared to handle this kernel fault? */
191	fixup = search_exception_tables(regs->pc);
192	if (fixup) {
193		regs->pc = fixup->fixup;
194		return;
195	}
196
197	/*
198	 * Oops. The kernel tried to access some bad page. We'll have
199	 * to terminate things with extreme prejudice.
200	 */
201	if (address < PAGE_SIZE)
202		printk(KERN_ALERT
203		       "Unable to handle kernel NULL pointer dereference");
204	else
205		printk(KERN_ALERT
206		       "Unable to handle kernel paging request");
207	printk(" at virtual address %08lx\n", address);
208
209	page = sysreg_read(PTBR);
210	printk(KERN_ALERT "ptbr = %08lx", page);
211	if (address >= TASK_SIZE)
212		page = (unsigned long)swapper_pg_dir;
213	if (page) {
214		page = ((unsigned long *)page)[address >> 22];
215		printk(" pgd = %08lx", page);
216		if (page & _PAGE_PRESENT) {
217			page &= PAGE_MASK;
218			address &= 0x003ff000;
219			page = ((unsigned long *)__va(page))[address >> PAGE_SHIFT];
220			printk(" pte = %08lx", page);
221		}
222	}
223	printk("\n");
224	die("Kernel access of bad area", regs, signr);
225	return;
226
227	/*
228	 * We ran out of memory, or some other thing happened to us
229	 * that made us unable to handle the page fault gracefully.
230	 */
231out_of_memory:
232	up_read(&mm->mmap_sem);
233	if (!user_mode(regs))
234		goto no_context;
235	pagefault_out_of_memory();
236	return;
237
238do_sigbus:
239	up_read(&mm->mmap_sem);
240
241	/* Kernel mode? Handle exceptions or die */
242	signr = SIGBUS;
243	code = BUS_ADRERR;
244	if (!user_mode(regs))
245		goto no_context;
246
247	if (exception_trace)
248		printk("%s%s[%d]: bus error at %08lx pc %08lx "
249		       "sp %08lx ecr %lu\n",
250		       is_global_init(tsk) ? KERN_EMERG : KERN_INFO,
251		       tsk->comm, tsk->pid, address, regs->pc,
252		       regs->sp, ecr);
253
254	_exception(SIGBUS, regs, BUS_ADRERR, address);
255}
256
257asmlinkage void do_bus_error(unsigned long addr, int write_access,
258			     struct pt_regs *regs)
259{
260	printk(KERN_ALERT
261	       "Bus error at physical address 0x%08lx (%s access)\n",
262	       addr, write_access ? "write" : "read");
263	printk(KERN_INFO "DTLB dump:\n");
264	dump_dtlb();
265	die("Bus Error", regs, SIGKILL);
266}
267