1/* 2 * linux/arch/frv/mm/fault.c 3 * 4 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. 5 * - Written by David Howells (dhowells@redhat.com) 6 * - Derived from arch/m68knommu/mm/fault.c 7 * - Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>, 8 * - Copyright (C) 2000 Lineo, Inc. (www.lineo.com) 9 * 10 * Based on: 11 * 12 * linux/arch/m68k/mm/fault.c 13 * 14 * Copyright (C) 1995 Hamish Macdonald 15 */ 16 17#include <linux/mman.h> 18#include <linux/mm.h> 19#include <linux/kernel.h> 20#include <linux/ptrace.h> 21#include <linux/hardirq.h> 22 23#include <asm/system.h> 24#include <asm/pgtable.h> 25#include <asm/uaccess.h> 26#include <asm/gdb-stub.h> 27 28/*****************************************************************************/ 29/* 30 * This routine handles page faults. It determines the problem, and 31 * then passes it off to one of the appropriate routines. 32 */ 33asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear0) 34{ 35 struct vm_area_struct *vma; 36 struct mm_struct *mm; 37 unsigned long _pme, lrai, lrad, fixup; 38 siginfo_t info; 39 pgd_t *pge; 40 pud_t *pue; 41 pte_t *pte; 42 int write; 43 int fault; 44 45 46 mm = current->mm; 47 48 /* 49 * We fault-in kernel-space virtual memory on-demand. The 50 * 'reference' page table is init_mm.pgd. 51 * 52 * NOTE! We MUST NOT take any locks for this case. We may 53 * be in an interrupt or a critical region, and should 54 * only copy the information from the master page table, 55 * nothing more. 56 * 57 * This verifies that the fault happens in kernel space 58 * and that the fault was a page not present (invalid) error 59 */ 60 if (!user_mode(__frame) && (esr0 & ESR0_ATXC) == ESR0_ATXC_AMRTLB_MISS) { 61 if (ear0 >= VMALLOC_START && ear0 < VMALLOC_END) 62 goto kernel_pte_fault; 63 if (ear0 >= PKMAP_BASE && ear0 < PKMAP_END) 64 goto kernel_pte_fault; 65 } 66 67 info.si_code = SEGV_MAPERR; 68 69 /* 70 * If we're in an interrupt or have no user 71 * context, we must not take the fault.. 72 */ 73 if (in_atomic() || !mm) 74 goto no_context; 75 76 down_read(&mm->mmap_sem); 77 78 vma = find_vma(mm, ear0); 79 if (!vma) 80 goto bad_area; 81 if (vma->vm_start <= ear0) 82 goto good_area; 83 if (!(vma->vm_flags & VM_GROWSDOWN)) 84 goto bad_area; 85 86 if (user_mode(__frame)) { 87 /* 88 * accessing the stack below %esp is always a bug. 89 * The "+ 32" is there due to some instructions (like 90 * pusha) doing post-decrement on the stack and that 91 * doesn't show up until later.. 92 */ 93 if ((ear0 & PAGE_MASK) + 2 * PAGE_SIZE < __frame->sp) { 94 goto bad_area; 95 } 96 } 97 98 if (expand_stack(vma, ear0)) 99 goto bad_area; 100 101/* 102 * Ok, we have a good vm_area for this memory access, so 103 * we can handle it.. 104 */ 105 good_area: 106 info.si_code = SEGV_ACCERR; 107 write = 0; 108 switch (esr0 & ESR0_ATXC) { 109 default: 110 /* handle write to write protected page */ 111 case ESR0_ATXC_WP_EXCEP: 112#ifdef TEST_VERIFY_AREA 113 if (!(user_mode(__frame))) 114 printk("WP fault at %08lx\n", __frame->pc); 115#endif 116 if (!(vma->vm_flags & VM_WRITE)) 117 goto bad_area; 118 write = 1; 119 break; 120 121 /* handle read from protected page */ 122 case ESR0_ATXC_PRIV_EXCEP: 123 goto bad_area; 124 125 /* handle read, write or exec on absent page 126 * - can't support write without permitting read 127 * - don't support execute without permitting read and vice-versa 128 */ 129 case ESR0_ATXC_AMRTLB_MISS: 130 if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC))) 131 goto bad_area; 132 break; 133 } 134 135 /* 136 * If for any reason at all we couldn't handle the fault, 137 * make sure we exit gracefully rather than endlessly redo 138 * the fault. 139 */ 140 fault = handle_mm_fault(mm, vma, ear0, write ? FAULT_FLAG_WRITE : 0); 141 if (unlikely(fault & VM_FAULT_ERROR)) { 142 if (fault & VM_FAULT_OOM) 143 goto out_of_memory; 144 else if (fault & VM_FAULT_SIGBUS) 145 goto do_sigbus; 146 BUG(); 147 } 148 if (fault & VM_FAULT_MAJOR) 149 current->maj_flt++; 150 else 151 current->min_flt++; 152 153 up_read(&mm->mmap_sem); 154 return; 155 156/* 157 * Something tried to access memory that isn't in our memory map.. 158 * Fix it, but check if it's kernel or user first.. 159 */ 160 bad_area: 161 up_read(&mm->mmap_sem); 162 163 /* User mode accesses just cause a SIGSEGV */ 164 if (user_mode(__frame)) { 165 info.si_signo = SIGSEGV; 166 info.si_errno = 0; 167 /* info.si_code has been set above */ 168 info.si_addr = (void *) ear0; 169 force_sig_info(SIGSEGV, &info, current); 170 return; 171 } 172 173 no_context: 174 /* are we prepared to handle this kernel fault? */ 175 if ((fixup = search_exception_table(__frame->pc)) != 0) { 176 __frame->pc = fixup; 177 return; 178 } 179 180/* 181 * Oops. The kernel tried to access some bad page. We'll have to 182 * terminate things with extreme prejudice. 183 */ 184 185 bust_spinlocks(1); 186 187 if (ear0 < PAGE_SIZE) 188 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); 189 else 190 printk(KERN_ALERT "Unable to handle kernel paging request"); 191 printk(" at virtual addr %08lx\n", ear0); 192 printk(" PC : %08lx\n", __frame->pc); 193 printk(" EXC : esr0=%08lx ear0=%08lx\n", esr0, ear0); 194 195 asm("lrai %1,%0,#1,#0,#0" : "=&r"(lrai) : "r"(ear0)); 196 asm("lrad %1,%0,#1,#0,#0" : "=&r"(lrad) : "r"(ear0)); 197 198 printk(KERN_ALERT " LRAI: %08lx\n", lrai); 199 printk(KERN_ALERT " LRAD: %08lx\n", lrad); 200 201 __break_hijack_kernel_event(); 202 203 pge = pgd_offset(current->mm, ear0); 204 pue = pud_offset(pge, ear0); 205 _pme = pue->pue[0].ste[0]; 206 207 printk(KERN_ALERT " PGE : %8p { PME %08lx }\n", pge, _pme); 208 209 if (_pme & xAMPRx_V) { 210 unsigned long dampr, damlr, val; 211 212 asm volatile("movsg dampr2,%0 ! movgs %2,dampr2 ! movsg damlr2,%1" 213 : "=&r"(dampr), "=r"(damlr) 214 : "r" (_pme | xAMPRx_L|xAMPRx_SS_16Kb|xAMPRx_S|xAMPRx_C|xAMPRx_V) 215 ); 216 217 pte = (pte_t *) damlr + __pte_index(ear0); 218 val = pte_val(*pte); 219 220 asm volatile("movgs %0,dampr2" :: "r" (dampr)); 221 222 printk(KERN_ALERT " PTE : %8p { %08lx }\n", pte, val); 223 } 224 225 die_if_kernel("Oops\n"); 226 do_exit(SIGKILL); 227 228/* 229 * We ran out of memory, or some other thing happened to us that made 230 * us unable to handle the page fault gracefully. 231 */ 232 out_of_memory: 233 up_read(&mm->mmap_sem); 234 if (!user_mode(__frame)) 235 goto no_context; 236 pagefault_out_of_memory(); 237 return; 238 239 do_sigbus: 240 up_read(&mm->mmap_sem); 241 242 /* 243 * Send a sigbus, regardless of whether we were in kernel 244 * or user mode. 245 */ 246 info.si_signo = SIGBUS; 247 info.si_errno = 0; 248 info.si_code = BUS_ADRERR; 249 info.si_addr = (void *) ear0; 250 force_sig_info(SIGBUS, &info, current); 251 252 /* Kernel mode? Handle exceptions or die */ 253 if (!user_mode(__frame)) 254 goto no_context; 255 return; 256 257/* 258 * The fault was caused by a kernel PTE (such as installed by vmalloc or kmap) 259 */ 260 kernel_pte_fault: 261 { 262 /* 263 * Synchronize this task's top level page-table 264 * with the 'reference' page table. 265 * 266 * Do _not_ use "tsk" here. We might be inside 267 * an interrupt in the middle of a task switch.. 268 */ 269 int index = pgd_index(ear0); 270 pgd_t *pgd, *pgd_k; 271 pud_t *pud, *pud_k; 272 pmd_t *pmd, *pmd_k; 273 pte_t *pte_k; 274 275 pgd = (pgd_t *) __get_TTBR(); 276 pgd = (pgd_t *)__va(pgd) + index; 277 pgd_k = ((pgd_t *)(init_mm.pgd)) + index; 278 279 if (!pgd_present(*pgd_k)) 280 goto no_context; 281 //set_pgd(pgd, *pgd_k); /////// gcc ICE's on this line 282 283 pud_k = pud_offset(pgd_k, ear0); 284 if (!pud_present(*pud_k)) 285 goto no_context; 286 287 pmd_k = pmd_offset(pud_k, ear0); 288 if (!pmd_present(*pmd_k)) 289 goto no_context; 290 291 pud = pud_offset(pgd, ear0); 292 pmd = pmd_offset(pud, ear0); 293 set_pmd(pmd, *pmd_k); 294 295 pte_k = pte_offset_kernel(pmd_k, ear0); 296 if (!pte_present(*pte_k)) 297 goto no_context; 298 return; 299 } 300} /* end do_page_fault() */ 301