1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * linux/arch/m68k/mm/fault.c 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (C) 1995 Hamish Macdonald 61da177e4SLinus Torvalds */ 71da177e4SLinus Torvalds 81da177e4SLinus Torvalds #include <linux/mman.h> 91da177e4SLinus Torvalds #include <linux/mm.h> 101da177e4SLinus Torvalds #include <linux/kernel.h> 111da177e4SLinus Torvalds #include <linux/ptrace.h> 121da177e4SLinus Torvalds #include <linux/interrupt.h> 131da177e4SLinus Torvalds #include <linux/module.h> 1470ffdb93SDavid Hildenbrand #include <linux/uaccess.h> 151da177e4SLinus Torvalds 161da177e4SLinus Torvalds #include <asm/setup.h> 171da177e4SLinus Torvalds #include <asm/traps.h> 181da177e4SLinus Torvalds #include <asm/pgalloc.h> 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds extern void die_if_kernel(char *, struct pt_regs *, long); 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds int send_fault_sig(struct pt_regs *regs) 231da177e4SLinus Torvalds { 243c67075dSEric W. Biederman int signo, si_code; 253c67075dSEric W. Biederman void __user *addr; 261da177e4SLinus Torvalds 273c67075dSEric W. Biederman signo = current->thread.signo; 283c67075dSEric W. Biederman si_code = current->thread.code; 293c67075dSEric W. Biederman addr = (void __user *)current->thread.faddr; 303c67075dSEric W. Biederman pr_debug("send_fault_sig: %p,%d,%d\n", addr, signo, si_code); 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds if (user_mode(regs)) { 332e1661d2SEric W. Biederman force_sig_fault(signo, si_code, addr); 341da177e4SLinus Torvalds } else { 3568acfdcbSAl Viro if (fixup_exception(regs)) 361da177e4SLinus Torvalds return -1; 371da177e4SLinus Torvalds 383c67075dSEric W. Biederman //if (signo == SIGBUS) 392e1661d2SEric W. Biederman // force_sig_fault(si_signo, si_code, addr); 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds /* 421da177e4SLinus Torvalds * Oops. The kernel tried to access some bad page. We'll have to 431da177e4SLinus Torvalds * terminate things with extreme prejudice. 441da177e4SLinus Torvalds */ 453c67075dSEric W. Biederman if ((unsigned long)addr < PAGE_SIZE) 468e398f63SGeert Uytterhoeven pr_alert("Unable to handle kernel NULL pointer dereference"); 471da177e4SLinus Torvalds else 488e398f63SGeert Uytterhoeven pr_alert("Unable to handle kernel access"); 493c67075dSEric W. Biederman pr_cont(" at virtual address %p\n", addr); 501da177e4SLinus Torvalds die_if_kernel("Oops", regs, 0 /*error_code*/); 511da177e4SLinus Torvalds do_exit(SIGKILL); 521da177e4SLinus Torvalds } 531da177e4SLinus Torvalds 541da177e4SLinus Torvalds return 1; 551da177e4SLinus Torvalds } 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds /* 581da177e4SLinus Torvalds * This routine handles page faults. It determines the problem, and 591da177e4SLinus Torvalds * then passes it off to one of the appropriate routines. 601da177e4SLinus Torvalds * 611da177e4SLinus Torvalds * error_code: 621da177e4SLinus Torvalds * bit 0 == 0 means no page found, 1 means protection fault 631da177e4SLinus Torvalds * bit 1 == 0 means read, 1 means write 641da177e4SLinus Torvalds * 651da177e4SLinus Torvalds * If this routine detects a bad access, it returns 1, otherwise it 661da177e4SLinus Torvalds * returns 0. 671da177e4SLinus Torvalds */ 681da177e4SLinus Torvalds int do_page_fault(struct pt_regs *regs, unsigned long address, 691da177e4SLinus Torvalds unsigned long error_code) 701da177e4SLinus Torvalds { 711da177e4SLinus Torvalds struct mm_struct *mm = current->mm; 721da177e4SLinus Torvalds struct vm_area_struct * vma; 7350a7ca3cSSouptick Joarder vm_fault_t fault; 74dde16072SPeter Xu unsigned int flags = FAULT_FLAG_DEFAULT; 751da177e4SLinus Torvalds 768e398f63SGeert Uytterhoeven pr_debug("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n", 774e25c0e9SGeert Uytterhoeven regs->sr, regs->pc, address, error_code, mm ? mm->pgd : NULL); 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds /* 801da177e4SLinus Torvalds * If we're in an interrupt or have no user 811da177e4SLinus Torvalds * context, we must not take the fault.. 821da177e4SLinus Torvalds */ 8370ffdb93SDavid Hildenbrand if (faulthandler_disabled() || !mm) 841da177e4SLinus Torvalds goto no_context; 851da177e4SLinus Torvalds 86759496baSJohannes Weiner if (user_mode(regs)) 87759496baSJohannes Weiner flags |= FAULT_FLAG_USER; 88b637a6b1SKautuk Consul retry: 89d8ed45c5SMichel Lespinasse mmap_read_lock(mm); 901da177e4SLinus Torvalds 911da177e4SLinus Torvalds vma = find_vma(mm, address); 921da177e4SLinus Torvalds if (!vma) 931da177e4SLinus Torvalds goto map_err; 941da177e4SLinus Torvalds if (vma->vm_flags & VM_IO) 951da177e4SLinus Torvalds goto acc_err; 961da177e4SLinus Torvalds if (vma->vm_start <= address) 971da177e4SLinus Torvalds goto good_area; 981da177e4SLinus Torvalds if (!(vma->vm_flags & VM_GROWSDOWN)) 991da177e4SLinus Torvalds goto map_err; 1001da177e4SLinus Torvalds if (user_mode(regs)) { 1011da177e4SLinus Torvalds /* Accessing the stack below usp is always a bug. The 1021da177e4SLinus Torvalds "+ 256" is there due to some instructions doing 1031da177e4SLinus Torvalds pre-decrement on the stack and that doesn't show up 1041da177e4SLinus Torvalds until later. */ 1051da177e4SLinus Torvalds if (address + 256 < rdusp()) 1061da177e4SLinus Torvalds goto map_err; 1071da177e4SLinus Torvalds } 1081da177e4SLinus Torvalds if (expand_stack(vma, address)) 1091da177e4SLinus Torvalds goto map_err; 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds /* 1121da177e4SLinus Torvalds * Ok, we have a good vm_area for this memory access, so 1131da177e4SLinus Torvalds * we can handle it.. 1141da177e4SLinus Torvalds */ 1151da177e4SLinus Torvalds good_area: 1168e398f63SGeert Uytterhoeven pr_debug("do_page_fault: good_area\n"); 1171da177e4SLinus Torvalds switch (error_code & 3) { 1181da177e4SLinus Torvalds default: /* 3: write, present */ 1191da177e4SLinus Torvalds /* fall through */ 1201da177e4SLinus Torvalds case 2: /* write, not present */ 1211da177e4SLinus Torvalds if (!(vma->vm_flags & VM_WRITE)) 1221da177e4SLinus Torvalds goto acc_err; 123b637a6b1SKautuk Consul flags |= FAULT_FLAG_WRITE; 1241da177e4SLinus Torvalds break; 1251da177e4SLinus Torvalds case 1: /* read, present */ 1261da177e4SLinus Torvalds goto acc_err; 1271da177e4SLinus Torvalds case 0: /* read, not present */ 1285093c587SAnshuman Khandual if (unlikely(!vma_is_accessible(vma))) 1291da177e4SLinus Torvalds goto acc_err; 1301da177e4SLinus Torvalds } 1311da177e4SLinus Torvalds 1321da177e4SLinus Torvalds /* 1331da177e4SLinus Torvalds * If for any reason at all we couldn't handle the fault, 1341da177e4SLinus Torvalds * make sure we exit gracefully rather than endlessly redo 1351da177e4SLinus Torvalds * the fault. 1361da177e4SLinus Torvalds */ 1371da177e4SLinus Torvalds 138dcddffd4SKirill A. Shutemov fault = handle_mm_fault(vma, address, flags); 13950a7ca3cSSouptick Joarder pr_debug("handle_mm_fault returns %x\n", fault); 140b637a6b1SKautuk Consul 1414ef87322SPeter Xu if (fault_signal_pending(fault, regs)) 142b637a6b1SKautuk Consul return 0; 143b637a6b1SKautuk Consul 14483c54070SNick Piggin if (unlikely(fault & VM_FAULT_ERROR)) { 14583c54070SNick Piggin if (fault & VM_FAULT_OOM) 1461da177e4SLinus Torvalds goto out_of_memory; 14733692f27SLinus Torvalds else if (fault & VM_FAULT_SIGSEGV) 14833692f27SLinus Torvalds goto map_err; 14983c54070SNick Piggin else if (fault & VM_FAULT_SIGBUS) 15083c54070SNick Piggin goto bus_err; 15183c54070SNick Piggin BUG(); 1521da177e4SLinus Torvalds } 153b637a6b1SKautuk Consul 154b637a6b1SKautuk Consul /* 155b637a6b1SKautuk Consul * Major/minor page fault accounting is only done on the 156b637a6b1SKautuk Consul * initial attempt. If we go through a retry, it is extremely 157b637a6b1SKautuk Consul * likely that the page will be found in page cache at that point. 158b637a6b1SKautuk Consul */ 159b637a6b1SKautuk Consul if (flags & FAULT_FLAG_ALLOW_RETRY) { 16083c54070SNick Piggin if (fault & VM_FAULT_MAJOR) 16183c54070SNick Piggin current->maj_flt++; 16283c54070SNick Piggin else 16383c54070SNick Piggin current->min_flt++; 164b637a6b1SKautuk Consul if (fault & VM_FAULT_RETRY) { 16545cac65bSShaohua Li flags |= FAULT_FLAG_TRIED; 166b637a6b1SKautuk Consul 167b637a6b1SKautuk Consul /* 168*3e4e28c5SMichel Lespinasse * No need to mmap_read_unlock(mm) as we would 169b637a6b1SKautuk Consul * have already released it in __lock_page_or_retry 170b637a6b1SKautuk Consul * in mm/filemap.c. 171b637a6b1SKautuk Consul */ 172b637a6b1SKautuk Consul 173b637a6b1SKautuk Consul goto retry; 174b637a6b1SKautuk Consul } 175b637a6b1SKautuk Consul } 1761da177e4SLinus Torvalds 177d8ed45c5SMichel Lespinasse mmap_read_unlock(mm); 1781da177e4SLinus Torvalds return 0; 1791da177e4SLinus Torvalds 1801da177e4SLinus Torvalds /* 1811da177e4SLinus Torvalds * We ran out of memory, or some other thing happened to us that made 1821da177e4SLinus Torvalds * us unable to handle the page fault gracefully. 1831da177e4SLinus Torvalds */ 1841da177e4SLinus Torvalds out_of_memory: 185d8ed45c5SMichel Lespinasse mmap_read_unlock(mm); 186adbf6e69SNick Piggin if (!user_mode(regs)) 187adbf6e69SNick Piggin goto no_context; 188adbf6e69SNick Piggin pagefault_out_of_memory(); 189adbf6e69SNick Piggin return 0; 1901da177e4SLinus Torvalds 1911da177e4SLinus Torvalds no_context: 1921da177e4SLinus Torvalds current->thread.signo = SIGBUS; 1931da177e4SLinus Torvalds current->thread.faddr = address; 1941da177e4SLinus Torvalds return send_fault_sig(regs); 1951da177e4SLinus Torvalds 1961da177e4SLinus Torvalds bus_err: 1971da177e4SLinus Torvalds current->thread.signo = SIGBUS; 1981da177e4SLinus Torvalds current->thread.code = BUS_ADRERR; 1991da177e4SLinus Torvalds current->thread.faddr = address; 2001da177e4SLinus Torvalds goto send_sig; 2011da177e4SLinus Torvalds 2021da177e4SLinus Torvalds map_err: 2031da177e4SLinus Torvalds current->thread.signo = SIGSEGV; 2041da177e4SLinus Torvalds current->thread.code = SEGV_MAPERR; 2051da177e4SLinus Torvalds current->thread.faddr = address; 2061da177e4SLinus Torvalds goto send_sig; 2071da177e4SLinus Torvalds 2081da177e4SLinus Torvalds acc_err: 2091da177e4SLinus Torvalds current->thread.signo = SIGSEGV; 2101da177e4SLinus Torvalds current->thread.code = SEGV_ACCERR; 2111da177e4SLinus Torvalds current->thread.faddr = address; 2121da177e4SLinus Torvalds 2131da177e4SLinus Torvalds send_sig: 214d8ed45c5SMichel Lespinasse mmap_read_unlock(mm); 2151da177e4SLinus Torvalds return send_fault_sig(regs); 2161da177e4SLinus Torvalds } 217