1*4882a593Smuzhiyun // TODO VM_EXEC flag work-around, cache aliasing
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * arch/xtensa/mm/fault.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * This file is subject to the terms and conditions of the GNU General Public
6*4882a593Smuzhiyun * License. See the file "COPYING" in the main directory of this archive
7*4882a593Smuzhiyun * for more details.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * Copyright (C) 2001 - 2010 Tensilica Inc.
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * Chris Zankel <chris@zankel.net>
12*4882a593Smuzhiyun * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include <linux/mm.h>
16*4882a593Smuzhiyun #include <linux/extable.h>
17*4882a593Smuzhiyun #include <linux/hardirq.h>
18*4882a593Smuzhiyun #include <linux/perf_event.h>
19*4882a593Smuzhiyun #include <linux/uaccess.h>
20*4882a593Smuzhiyun #include <asm/mmu_context.h>
21*4882a593Smuzhiyun #include <asm/cacheflush.h>
22*4882a593Smuzhiyun #include <asm/hardirq.h>
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun DEFINE_PER_CPU(unsigned long, asid_cache) = ASID_USER_FIRST;
25*4882a593Smuzhiyun void bad_page_fault(struct pt_regs*, unsigned long, int);
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun /*
28*4882a593Smuzhiyun * This routine handles page faults. It determines the address,
29*4882a593Smuzhiyun * and the problem, and then passes it off to one of the appropriate
30*4882a593Smuzhiyun * routines.
31*4882a593Smuzhiyun *
32*4882a593Smuzhiyun * Note: does not handle Miss and MultiHit.
33*4882a593Smuzhiyun */
34*4882a593Smuzhiyun
do_page_fault(struct pt_regs * regs)35*4882a593Smuzhiyun void do_page_fault(struct pt_regs *regs)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun struct vm_area_struct * vma;
38*4882a593Smuzhiyun struct mm_struct *mm = current->mm;
39*4882a593Smuzhiyun unsigned int exccause = regs->exccause;
40*4882a593Smuzhiyun unsigned int address = regs->excvaddr;
41*4882a593Smuzhiyun int code;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun int is_write, is_exec;
44*4882a593Smuzhiyun vm_fault_t fault;
45*4882a593Smuzhiyun unsigned int flags = FAULT_FLAG_DEFAULT;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun code = SEGV_MAPERR;
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun /* We fault-in kernel-space virtual memory on-demand. The
50*4882a593Smuzhiyun * 'reference' page table is init_mm.pgd.
51*4882a593Smuzhiyun */
52*4882a593Smuzhiyun if (address >= TASK_SIZE && !user_mode(regs))
53*4882a593Smuzhiyun goto vmalloc_fault;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun /* If we're in an interrupt or have no user
56*4882a593Smuzhiyun * context, we must not take the fault..
57*4882a593Smuzhiyun */
58*4882a593Smuzhiyun if (faulthandler_disabled() || !mm) {
59*4882a593Smuzhiyun bad_page_fault(regs, address, SIGSEGV);
60*4882a593Smuzhiyun return;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun is_write = (exccause == EXCCAUSE_STORE_CACHE_ATTRIBUTE) ? 1 : 0;
64*4882a593Smuzhiyun is_exec = (exccause == EXCCAUSE_ITLB_PRIVILEGE ||
65*4882a593Smuzhiyun exccause == EXCCAUSE_ITLB_MISS ||
66*4882a593Smuzhiyun exccause == EXCCAUSE_FETCH_CACHE_ATTRIBUTE) ? 1 : 0;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun pr_debug("[%s:%d:%08x:%d:%08lx:%s%s]\n",
69*4882a593Smuzhiyun current->comm, current->pid,
70*4882a593Smuzhiyun address, exccause, regs->pc,
71*4882a593Smuzhiyun is_write ? "w" : "", is_exec ? "x" : "");
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun if (user_mode(regs))
74*4882a593Smuzhiyun flags |= FAULT_FLAG_USER;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun retry:
79*4882a593Smuzhiyun mmap_read_lock(mm);
80*4882a593Smuzhiyun vma = find_vma(mm, address);
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun if (!vma)
83*4882a593Smuzhiyun goto bad_area;
84*4882a593Smuzhiyun if (vma->vm_start <= address)
85*4882a593Smuzhiyun goto good_area;
86*4882a593Smuzhiyun if (!(vma->vm_flags & VM_GROWSDOWN))
87*4882a593Smuzhiyun goto bad_area;
88*4882a593Smuzhiyun if (expand_stack(vma, address))
89*4882a593Smuzhiyun goto bad_area;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun /* Ok, we have a good vm_area for this memory access, so
92*4882a593Smuzhiyun * we can handle it..
93*4882a593Smuzhiyun */
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun good_area:
96*4882a593Smuzhiyun code = SEGV_ACCERR;
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun if (is_write) {
99*4882a593Smuzhiyun if (!(vma->vm_flags & VM_WRITE))
100*4882a593Smuzhiyun goto bad_area;
101*4882a593Smuzhiyun flags |= FAULT_FLAG_WRITE;
102*4882a593Smuzhiyun } else if (is_exec) {
103*4882a593Smuzhiyun if (!(vma->vm_flags & VM_EXEC))
104*4882a593Smuzhiyun goto bad_area;
105*4882a593Smuzhiyun } else /* Allow read even from write-only pages. */
106*4882a593Smuzhiyun if (!(vma->vm_flags & (VM_READ | VM_WRITE)))
107*4882a593Smuzhiyun goto bad_area;
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun /* If for any reason at all we couldn't handle the fault,
110*4882a593Smuzhiyun * make sure we exit gracefully rather than endlessly redo
111*4882a593Smuzhiyun * the fault.
112*4882a593Smuzhiyun */
113*4882a593Smuzhiyun fault = handle_mm_fault(vma, address, flags, regs);
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun if (fault_signal_pending(fault, regs)) {
116*4882a593Smuzhiyun if (!user_mode(regs))
117*4882a593Smuzhiyun goto bad_page_fault;
118*4882a593Smuzhiyun return;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun if (unlikely(fault & VM_FAULT_ERROR)) {
122*4882a593Smuzhiyun if (fault & VM_FAULT_OOM)
123*4882a593Smuzhiyun goto out_of_memory;
124*4882a593Smuzhiyun else if (fault & VM_FAULT_SIGSEGV)
125*4882a593Smuzhiyun goto bad_area;
126*4882a593Smuzhiyun else if (fault & VM_FAULT_SIGBUS)
127*4882a593Smuzhiyun goto do_sigbus;
128*4882a593Smuzhiyun BUG();
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun if (flags & FAULT_FLAG_ALLOW_RETRY) {
131*4882a593Smuzhiyun if (fault & VM_FAULT_RETRY) {
132*4882a593Smuzhiyun flags |= FAULT_FLAG_TRIED;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun /* No need to mmap_read_unlock(mm) as we would
135*4882a593Smuzhiyun * have already released it in __lock_page_or_retry
136*4882a593Smuzhiyun * in mm/filemap.c.
137*4882a593Smuzhiyun */
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun goto retry;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun mmap_read_unlock(mm);
144*4882a593Smuzhiyun return;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun /* Something tried to access memory that isn't in our memory map..
147*4882a593Smuzhiyun * Fix it, but check if it's kernel or user first..
148*4882a593Smuzhiyun */
149*4882a593Smuzhiyun bad_area:
150*4882a593Smuzhiyun mmap_read_unlock(mm);
151*4882a593Smuzhiyun if (user_mode(regs)) {
152*4882a593Smuzhiyun current->thread.bad_vaddr = address;
153*4882a593Smuzhiyun current->thread.error_code = is_write;
154*4882a593Smuzhiyun force_sig_fault(SIGSEGV, code, (void *) address);
155*4882a593Smuzhiyun return;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun bad_page_fault(regs, address, SIGSEGV);
158*4882a593Smuzhiyun return;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun /* We ran out of memory, or some other thing happened to us that made
162*4882a593Smuzhiyun * us unable to handle the page fault gracefully.
163*4882a593Smuzhiyun */
164*4882a593Smuzhiyun out_of_memory:
165*4882a593Smuzhiyun mmap_read_unlock(mm);
166*4882a593Smuzhiyun if (!user_mode(regs))
167*4882a593Smuzhiyun bad_page_fault(regs, address, SIGKILL);
168*4882a593Smuzhiyun else
169*4882a593Smuzhiyun pagefault_out_of_memory();
170*4882a593Smuzhiyun return;
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun do_sigbus:
173*4882a593Smuzhiyun mmap_read_unlock(mm);
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun /* Send a sigbus, regardless of whether we were in kernel
176*4882a593Smuzhiyun * or user mode.
177*4882a593Smuzhiyun */
178*4882a593Smuzhiyun current->thread.bad_vaddr = address;
179*4882a593Smuzhiyun force_sig_fault(SIGBUS, BUS_ADRERR, (void *) address);
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun /* Kernel mode? Handle exceptions or die */
182*4882a593Smuzhiyun if (!user_mode(regs))
183*4882a593Smuzhiyun bad_page_fault(regs, address, SIGBUS);
184*4882a593Smuzhiyun return;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun vmalloc_fault:
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun /* Synchronize this task's top level page-table
189*4882a593Smuzhiyun * with the 'reference' page table.
190*4882a593Smuzhiyun */
191*4882a593Smuzhiyun struct mm_struct *act_mm = current->active_mm;
192*4882a593Smuzhiyun int index = pgd_index(address);
193*4882a593Smuzhiyun pgd_t *pgd, *pgd_k;
194*4882a593Smuzhiyun p4d_t *p4d, *p4d_k;
195*4882a593Smuzhiyun pud_t *pud, *pud_k;
196*4882a593Smuzhiyun pmd_t *pmd, *pmd_k;
197*4882a593Smuzhiyun pte_t *pte_k;
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun if (act_mm == NULL)
200*4882a593Smuzhiyun goto bad_page_fault;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun pgd = act_mm->pgd + index;
203*4882a593Smuzhiyun pgd_k = init_mm.pgd + index;
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun if (!pgd_present(*pgd_k))
206*4882a593Smuzhiyun goto bad_page_fault;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun pgd_val(*pgd) = pgd_val(*pgd_k);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun p4d = p4d_offset(pgd, address);
211*4882a593Smuzhiyun p4d_k = p4d_offset(pgd_k, address);
212*4882a593Smuzhiyun if (!p4d_present(*p4d) || !p4d_present(*p4d_k))
213*4882a593Smuzhiyun goto bad_page_fault;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun pud = pud_offset(p4d, address);
216*4882a593Smuzhiyun pud_k = pud_offset(p4d_k, address);
217*4882a593Smuzhiyun if (!pud_present(*pud) || !pud_present(*pud_k))
218*4882a593Smuzhiyun goto bad_page_fault;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun pmd = pmd_offset(pud, address);
221*4882a593Smuzhiyun pmd_k = pmd_offset(pud_k, address);
222*4882a593Smuzhiyun if (!pmd_present(*pmd) || !pmd_present(*pmd_k))
223*4882a593Smuzhiyun goto bad_page_fault;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun pmd_val(*pmd) = pmd_val(*pmd_k);
226*4882a593Smuzhiyun pte_k = pte_offset_kernel(pmd_k, address);
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun if (!pte_present(*pte_k))
229*4882a593Smuzhiyun goto bad_page_fault;
230*4882a593Smuzhiyun return;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun bad_page_fault:
233*4882a593Smuzhiyun bad_page_fault(regs, address, SIGKILL);
234*4882a593Smuzhiyun return;
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun void
bad_page_fault(struct pt_regs * regs,unsigned long address,int sig)239*4882a593Smuzhiyun bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun extern void die(const char*, struct pt_regs*, long);
242*4882a593Smuzhiyun const struct exception_table_entry *entry;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun /* Are we prepared to handle this kernel fault? */
245*4882a593Smuzhiyun if ((entry = search_exception_tables(regs->pc)) != NULL) {
246*4882a593Smuzhiyun pr_debug("%s: Exception at pc=%#010lx (%lx)\n",
247*4882a593Smuzhiyun current->comm, regs->pc, entry->fixup);
248*4882a593Smuzhiyun current->thread.bad_uaddr = address;
249*4882a593Smuzhiyun regs->pc = entry->fixup;
250*4882a593Smuzhiyun return;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun /* Oops. The kernel tried to access some bad page. We'll have to
254*4882a593Smuzhiyun * terminate things with extreme prejudice.
255*4882a593Smuzhiyun */
256*4882a593Smuzhiyun pr_alert("Unable to handle kernel paging request at virtual "
257*4882a593Smuzhiyun "address %08lx\n pc = %08lx, ra = %08lx\n",
258*4882a593Smuzhiyun address, regs->pc, regs->areg[0]);
259*4882a593Smuzhiyun die("Oops", regs, sig);
260*4882a593Smuzhiyun do_exit(sig);
261*4882a593Smuzhiyun }
262