Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.31 326 lines 8.2 kB view raw
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#if 0 46 const char *atxc[16] = { 47 [0x0] = "mmu-miss", [0x8] = "multi-dat", [0x9] = "multi-sat", 48 [0xa] = "tlb-miss", [0xc] = "privilege", [0xd] = "write-prot", 49 }; 50 51 printk("do_page_fault(%d,%lx [%s],%lx)\n", 52 datammu, esr0, atxc[esr0 >> 20 & 0xf], ear0); 53#endif 54 55 mm = current->mm; 56 57 /* 58 * We fault-in kernel-space virtual memory on-demand. The 59 * 'reference' page table is init_mm.pgd. 60 * 61 * NOTE! We MUST NOT take any locks for this case. We may 62 * be in an interrupt or a critical region, and should 63 * only copy the information from the master page table, 64 * nothing more. 65 * 66 * This verifies that the fault happens in kernel space 67 * and that the fault was a page not present (invalid) error 68 */ 69 if (!user_mode(__frame) && (esr0 & ESR0_ATXC) == ESR0_ATXC_AMRTLB_MISS) { 70 if (ear0 >= VMALLOC_START && ear0 < VMALLOC_END) 71 goto kernel_pte_fault; 72 if (ear0 >= PKMAP_BASE && ear0 < PKMAP_END) 73 goto kernel_pte_fault; 74 } 75 76 info.si_code = SEGV_MAPERR; 77 78 /* 79 * If we're in an interrupt or have no user 80 * context, we must not take the fault.. 81 */ 82 if (in_atomic() || !mm) 83 goto no_context; 84 85 down_read(&mm->mmap_sem); 86 87 vma = find_vma(mm, ear0); 88 if (!vma) 89 goto bad_area; 90 if (vma->vm_start <= ear0) 91 goto good_area; 92 if (!(vma->vm_flags & VM_GROWSDOWN)) 93 goto bad_area; 94 95 if (user_mode(__frame)) { 96 /* 97 * accessing the stack below %esp is always a bug. 98 * The "+ 32" is there due to some instructions (like 99 * pusha) doing post-decrement on the stack and that 100 * doesn't show up until later.. 101 */ 102 if ((ear0 & PAGE_MASK) + 2 * PAGE_SIZE < __frame->sp) { 103#if 0 104 printk("[%d] ### Access below stack @%lx (sp=%lx)\n", 105 current->pid, ear0, __frame->sp); 106 show_registers(__frame); 107 printk("[%d] ### Code: [%08lx] %02x %02x %02x %02x %02x %02x %02x %02x\n", 108 current->pid, 109 __frame->pc, 110 ((u8*)__frame->pc)[0], 111 ((u8*)__frame->pc)[1], 112 ((u8*)__frame->pc)[2], 113 ((u8*)__frame->pc)[3], 114 ((u8*)__frame->pc)[4], 115 ((u8*)__frame->pc)[5], 116 ((u8*)__frame->pc)[6], 117 ((u8*)__frame->pc)[7] 118 ); 119#endif 120 goto bad_area; 121 } 122 } 123 124 if (expand_stack(vma, ear0)) 125 goto bad_area; 126 127/* 128 * Ok, we have a good vm_area for this memory access, so 129 * we can handle it.. 130 */ 131 good_area: 132 info.si_code = SEGV_ACCERR; 133 write = 0; 134 switch (esr0 & ESR0_ATXC) { 135 default: 136 /* handle write to write protected page */ 137 case ESR0_ATXC_WP_EXCEP: 138#ifdef TEST_VERIFY_AREA 139 if (!(user_mode(__frame))) 140 printk("WP fault at %08lx\n", __frame->pc); 141#endif 142 if (!(vma->vm_flags & VM_WRITE)) 143 goto bad_area; 144 write = 1; 145 break; 146 147 /* handle read from protected page */ 148 case ESR0_ATXC_PRIV_EXCEP: 149 goto bad_area; 150 151 /* handle read, write or exec on absent page 152 * - can't support write without permitting read 153 * - don't support execute without permitting read and vice-versa 154 */ 155 case ESR0_ATXC_AMRTLB_MISS: 156 if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC))) 157 goto bad_area; 158 break; 159 } 160 161 /* 162 * If for any reason at all we couldn't handle the fault, 163 * make sure we exit gracefully rather than endlessly redo 164 * the fault. 165 */ 166 fault = handle_mm_fault(mm, vma, ear0, write ? FAULT_FLAG_WRITE : 0); 167 if (unlikely(fault & VM_FAULT_ERROR)) { 168 if (fault & VM_FAULT_OOM) 169 goto out_of_memory; 170 else if (fault & VM_FAULT_SIGBUS) 171 goto do_sigbus; 172 BUG(); 173 } 174 if (fault & VM_FAULT_MAJOR) 175 current->maj_flt++; 176 else 177 current->min_flt++; 178 179 up_read(&mm->mmap_sem); 180 return; 181 182/* 183 * Something tried to access memory that isn't in our memory map.. 184 * Fix it, but check if it's kernel or user first.. 185 */ 186 bad_area: 187 up_read(&mm->mmap_sem); 188 189 /* User mode accesses just cause a SIGSEGV */ 190 if (user_mode(__frame)) { 191 info.si_signo = SIGSEGV; 192 info.si_errno = 0; 193 /* info.si_code has been set above */ 194 info.si_addr = (void *) ear0; 195 force_sig_info(SIGSEGV, &info, current); 196 return; 197 } 198 199 no_context: 200 /* are we prepared to handle this kernel fault? */ 201 if ((fixup = search_exception_table(__frame->pc)) != 0) { 202 __frame->pc = fixup; 203 return; 204 } 205 206/* 207 * Oops. The kernel tried to access some bad page. We'll have to 208 * terminate things with extreme prejudice. 209 */ 210 211 bust_spinlocks(1); 212 213 if (ear0 < PAGE_SIZE) 214 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); 215 else 216 printk(KERN_ALERT "Unable to handle kernel paging request"); 217 printk(" at virtual addr %08lx\n", ear0); 218 printk(" PC : %08lx\n", __frame->pc); 219 printk(" EXC : esr0=%08lx ear0=%08lx\n", esr0, ear0); 220 221 asm("lrai %1,%0,#1,#0,#0" : "=&r"(lrai) : "r"(ear0)); 222 asm("lrad %1,%0,#1,#0,#0" : "=&r"(lrad) : "r"(ear0)); 223 224 printk(KERN_ALERT " LRAI: %08lx\n", lrai); 225 printk(KERN_ALERT " LRAD: %08lx\n", lrad); 226 227 __break_hijack_kernel_event(); 228 229 pge = pgd_offset(current->mm, ear0); 230 pue = pud_offset(pge, ear0); 231 _pme = pue->pue[0].ste[0]; 232 233 printk(KERN_ALERT " PGE : %8p { PME %08lx }\n", pge, _pme); 234 235 if (_pme & xAMPRx_V) { 236 unsigned long dampr, damlr, val; 237 238 asm volatile("movsg dampr2,%0 ! movgs %2,dampr2 ! movsg damlr2,%1" 239 : "=&r"(dampr), "=r"(damlr) 240 : "r" (_pme | xAMPRx_L|xAMPRx_SS_16Kb|xAMPRx_S|xAMPRx_C|xAMPRx_V) 241 ); 242 243 pte = (pte_t *) damlr + __pte_index(ear0); 244 val = pte_val(*pte); 245 246 asm volatile("movgs %0,dampr2" :: "r" (dampr)); 247 248 printk(KERN_ALERT " PTE : %8p { %08lx }\n", pte, val); 249 } 250 251 die_if_kernel("Oops\n"); 252 do_exit(SIGKILL); 253 254/* 255 * We ran out of memory, or some other thing happened to us that made 256 * us unable to handle the page fault gracefully. 257 */ 258 out_of_memory: 259 up_read(&mm->mmap_sem); 260 printk("VM: killing process %s\n", current->comm); 261 if (user_mode(__frame)) 262 do_group_exit(SIGKILL); 263 goto no_context; 264 265 do_sigbus: 266 up_read(&mm->mmap_sem); 267 268 /* 269 * Send a sigbus, regardless of whether we were in kernel 270 * or user mode. 271 */ 272 info.si_signo = SIGBUS; 273 info.si_errno = 0; 274 info.si_code = BUS_ADRERR; 275 info.si_addr = (void *) ear0; 276 force_sig_info(SIGBUS, &info, current); 277 278 /* Kernel mode? Handle exceptions or die */ 279 if (!user_mode(__frame)) 280 goto no_context; 281 return; 282 283/* 284 * The fault was caused by a kernel PTE (such as installed by vmalloc or kmap) 285 */ 286 kernel_pte_fault: 287 { 288 /* 289 * Synchronize this task's top level page-table 290 * with the 'reference' page table. 291 * 292 * Do _not_ use "tsk" here. We might be inside 293 * an interrupt in the middle of a task switch.. 294 */ 295 int index = pgd_index(ear0); 296 pgd_t *pgd, *pgd_k; 297 pud_t *pud, *pud_k; 298 pmd_t *pmd, *pmd_k; 299 pte_t *pte_k; 300 301 pgd = (pgd_t *) __get_TTBR(); 302 pgd = (pgd_t *)__va(pgd) + index; 303 pgd_k = ((pgd_t *)(init_mm.pgd)) + index; 304 305 if (!pgd_present(*pgd_k)) 306 goto no_context; 307 //set_pgd(pgd, *pgd_k); /////// gcc ICE's on this line 308 309 pud_k = pud_offset(pgd_k, ear0); 310 if (!pud_present(*pud_k)) 311 goto no_context; 312 313 pmd_k = pmd_offset(pud_k, ear0); 314 if (!pmd_present(*pmd_k)) 315 goto no_context; 316 317 pud = pud_offset(pgd, ear0); 318 pmd = pmd_offset(pud, ear0); 319 set_pmd(pmd, *pmd_k); 320 321 pte_k = pte_offset_kernel(pmd_k, ear0); 322 if (!pte_present(*pte_k)) 323 goto no_context; 324 return; 325 } 326} /* end do_page_fault() */