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_SIGSEGV) 146 goto bad_area; 147 else if (fault & VM_FAULT_SIGBUS) 148 goto do_sigbus; 149 BUG(); 150 } 151 152 if (flags & FAULT_FLAG_ALLOW_RETRY) { 153 if (fault & VM_FAULT_MAJOR) 154 tsk->maj_flt++; 155 else 156 tsk->min_flt++; 157 if (fault & VM_FAULT_RETRY) { 158 flags &= ~FAULT_FLAG_ALLOW_RETRY; 159 flags |= FAULT_FLAG_TRIED; 160 161 /* 162 * No need to up_read(&mm->mmap_sem) as we would have 163 * already released it in __lock_page_or_retry() in 164 * mm/filemap.c. 165 */ 166 goto retry; 167 } 168 } 169 170 up_read(&mm->mmap_sem); 171 return; 172 173 /* 174 * Something tried to access memory that isn't in our memory 175 * map. Fix it, but check if it's kernel or user first... 176 */ 177bad_area: 178 up_read(&mm->mmap_sem); 179 180 if (user_mode(regs)) { 181 if (exception_trace && printk_ratelimit()) 182 printk("%s%s[%d]: segfault at %08lx pc %08lx " 183 "sp %08lx ecr %lu\n", 184 is_global_init(tsk) ? KERN_EMERG : KERN_INFO, 185 tsk->comm, tsk->pid, address, regs->pc, 186 regs->sp, ecr); 187 _exception(SIGSEGV, regs, code, address); 188 return; 189 } 190 191no_context: 192 /* Are we prepared to handle this kernel fault? */ 193 fixup = search_exception_tables(regs->pc); 194 if (fixup) { 195 regs->pc = fixup->fixup; 196 return; 197 } 198 199 /* 200 * Oops. The kernel tried to access some bad page. We'll have 201 * to terminate things with extreme prejudice. 202 */ 203 if (address < PAGE_SIZE) 204 printk(KERN_ALERT 205 "Unable to handle kernel NULL pointer dereference"); 206 else 207 printk(KERN_ALERT 208 "Unable to handle kernel paging request"); 209 printk(" at virtual address %08lx\n", address); 210 211 page = sysreg_read(PTBR); 212 printk(KERN_ALERT "ptbr = %08lx", page); 213 if (address >= TASK_SIZE) 214 page = (unsigned long)swapper_pg_dir; 215 if (page) { 216 page = ((unsigned long *)page)[address >> 22]; 217 printk(" pgd = %08lx", page); 218 if (page & _PAGE_PRESENT) { 219 page &= PAGE_MASK; 220 address &= 0x003ff000; 221 page = ((unsigned long *)__va(page))[address >> PAGE_SHIFT]; 222 printk(" pte = %08lx", page); 223 } 224 } 225 printk("\n"); 226 die("Kernel access of bad area", regs, signr); 227 return; 228 229 /* 230 * We ran out of memory, or some other thing happened to us 231 * that made us unable to handle the page fault gracefully. 232 */ 233out_of_memory: 234 up_read(&mm->mmap_sem); 235 if (!user_mode(regs)) 236 goto no_context; 237 pagefault_out_of_memory(); 238 return; 239 240do_sigbus: 241 up_read(&mm->mmap_sem); 242 243 /* Kernel mode? Handle exceptions or die */ 244 signr = SIGBUS; 245 code = BUS_ADRERR; 246 if (!user_mode(regs)) 247 goto no_context; 248 249 if (exception_trace) 250 printk("%s%s[%d]: bus error at %08lx pc %08lx " 251 "sp %08lx ecr %lu\n", 252 is_global_init(tsk) ? KERN_EMERG : KERN_INFO, 253 tsk->comm, tsk->pid, address, regs->pc, 254 regs->sp, ecr); 255 256 _exception(SIGBUS, regs, BUS_ADRERR, address); 257} 258 259asmlinkage void do_bus_error(unsigned long addr, int write_access, 260 struct pt_regs *regs) 261{ 262 printk(KERN_ALERT 263 "Bus error at physical address 0x%08lx (%s access)\n", 264 addr, write_access ? "write" : "read"); 265 printk(KERN_INFO "DTLB dump:\n"); 266 dump_dtlb(); 267 die("Bus Error", regs, SIGKILL); 268} 269