/* * Something tried to access memory that isn't in our memory map. User mode * accesses just cause a SIGSEGV */ static void __do_user_fault(struct task_struct *tsk, unsigned long addr, unsigned int esr, unsigned int sig, int code, struct pt_regs *regs) { struct siginfo si; trace_user_fault(tsk, addr, esr); if (show_unhandled_signals && unhandled_signal(tsk, sig) && printk_ratelimit()) { pr_info("%s[%d]: unhandled %s (%d) at 0x%08lx, esr 0x%03x\n", tsk->comm, task_pid_nr(tsk), fault_name(esr), sig, addr, esr); show_pte(tsk->mm, addr); show_regs(regs); } tsk->thread.fault_address = addr; tsk->thread.fault_code = esr; si.si_signo = sig; si.si_errno = 0; si.si_code = code; si.si_addr = (void __user *)addr; force_sig_info(sig, &si, tsk); }
/* * The kernel tried to access some page that wasn't present. */ static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int esr, struct pt_regs *regs) { #if defined(CONFIG_HTC_DEBUG_RTB) static int enable_logk_die = 1; #endif /* * Are we prepared to handle this kernel fault? */ if (fixup_exception(regs)) return; #if defined(CONFIG_HTC_DEBUG_RTB) if (enable_logk_die) { uncached_logk(LOGK_DIE, (void *)regs->pc); uncached_logk(LOGK_DIE, (void *)regs->regs[30]); uncached_logk(LOGK_DIE, (void *)addr); /* Disable RTB here to avoid weird recursive spinlock/printk behaviors */ msm_rtb_disable(); enable_logk_die = 0; } #endif /* * No handler, we'll have to terminate things with extreme prejudice. */ bust_spinlocks(1); pr_alert("Unable to handle kernel %s at virtual address %08lx\n", (addr < PAGE_SIZE) ? "NULL pointer dereference" : "paging request", addr); show_pte(mm, addr); die("Oops", regs, esr); bust_spinlocks(0); do_exit(SIGKILL); }
/* * Oops. The kernel tried to access some page that wasn't present. */ static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr, struct pt_regs *regs) { unsigned long fixup; /* * Are we prepared to handle this kernel fault? */ if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) { #ifdef DEBUG printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n", current->comm, regs->ARM_pc, addr, fixup); #endif regs->ARM_pc = fixup; return; } /* * No handler, we'll have to terminate things with extreme prejudice. */ printk(KERN_ALERT "Unable to handle kernel %s at virtual address %08lx\n", (addr < PAGE_SIZE) ? "NULL pointer dereference" : "paging request", addr); show_pte(mm, addr); die("Oops", regs, fsr); do_exit(SIGKILL); }
static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int esr, struct pt_regs *regs) { #if defined(CONFIG_HTC_DEBUG_RTB) static int enable_logk_die = 1; #endif if (fixup_exception(regs)) return; #if defined(CONFIG_HTC_DEBUG_RTB) if (enable_logk_die) { uncached_logk(LOGK_DIE, (void *)regs->pc); uncached_logk(LOGK_DIE, (void *)regs->regs[30]); uncached_logk(LOGK_DIE, (void *)addr); msm_rtb_disable(); enable_logk_die = 0; } #endif bust_spinlocks(1); pr_alert("Unable to handle kernel %s at virtual address %08lx\n", (addr < PAGE_SIZE) ? "NULL pointer dereference" : "paging request", addr); show_pte(mm, addr); die("Oops", regs, esr); bust_spinlocks(0); do_exit(SIGKILL); }
/* * Currently dropped down to debug level */ asmlinkage void do_DataAbort(unsigned long addr, int error_code, struct pt_regs *regs, int fsr) { const struct fsr_info *inf = fsr_info + (fsr & 15); if (!inf->fn(addr, error_code, regs)) return; force_sig(inf->sig, current); printk(KERN_ALERT "Unhandled fault: %s (%X) at 0x%08lx\n", inf->name, fsr, addr); show_pte(current->mm, addr); die_if_kernel("Oops", regs, 0); return; }
/* * The kernel tried to access some page that wasn't present. */ static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int esr, struct pt_regs *regs) { /* * Are we prepared to handle this kernel fault? */ if (fixup_exception(regs)) return; /* * No handler, we'll have to terminate things with extreme prejudice. */ bust_spinlocks(1); pr_alert("Unable to handle kernel %s at virtual address %08lx\n", (addr < PAGE_SIZE) ? "NULL pointer dereference" : "paging request", addr); show_pte(mm, addr); die("Oops", regs, esr); bust_spinlocks(0); do_exit(SIGKILL); }
static int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs) { struct task_struct *tsk; struct mm_struct *mm; unsigned long fixup; int fault; tsk = current; mm = tsk->mm; /* * We fault-in kernel-space virtual memory on-demand. The * 'reference' page table is init_mm.pgd. * * NOTE! We MUST NOT take any locks for this case. We may * be in an interrupt or a critical region, and should * only copy the information from the master page table, * nothing more. */ if (addr >= TASK_SIZE) goto vmalloc_fault; /* * If we're in an interrupt or have no user * context, we must not take the fault.. */ if (in_interrupt() || !mm) goto no_context; down(&mm->mmap_sem); fault = __do_page_fault(mm, addr, mode, tsk); up(&mm->mmap_sem); ret: /* * Handle the "normal" case first */ if (fault > 0) return 0; /* * We had some memory, but were unable to * successfully fix up this page fault. */ if (fault == 0) goto do_sigbus; /* * If we are in kernel mode at this point, we * have no context to handle this fault with. */ if (!user_mode(regs)) goto no_context; if (fault == -3) { /* * We ran out of memory, or some other thing happened to * us that made us unable to handle the page fault gracefully. */ printk("VM: killing process %s\n", tsk->comm); do_exit(SIGKILL); } else { /* * Something tried to access memory that isn't in our memory map.. * User mode accesses just cause a SIGSEGV */ struct siginfo si; #ifdef CONFIG_DEBUG_USER printk(KERN_DEBUG "%s: unhandled page fault at pc=0x%08lx, " "lr=0x%08lx (bad address=0x%08lx, code %d)\n", tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode); #endif tsk->thread.address = addr; tsk->thread.error_code = mode; tsk->thread.trap_no = 14; si.si_signo = SIGSEGV; si.si_errno = 0; si.si_code = fault == -1 ? SEGV_ACCERR : SEGV_MAPERR; si.si_addr = (void *)addr; force_sig_info(SIGSEGV, &si, tsk); } return 0; /* * We ran out of memory, or some other thing happened to us that made * us unable to handle the page fault gracefully. */ do_sigbus: /* * Send a sigbus, regardless of whether we were in kernel * or user mode. */ tsk->thread.address = addr; tsk->thread.error_code = mode; tsk->thread.trap_no = 14; force_sig(SIGBUS, tsk); /* Kernel mode? Handle exceptions or die */ if (user_mode(regs)) return 0; no_context: /* Are we prepared to handle this kernel fault? */ if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) { #ifdef DEBUG printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n", tsk->comm, regs->ARM_pc, addr, fixup); #endif regs->ARM_pc = fixup; return 0; } /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ printk(KERN_ALERT "Unable to handle kernel %s at virtual address %08lx\n", (addr < PAGE_SIZE) ? "NULL pointer dereference" : "paging request", addr); show_pte(mm, addr); die("Oops", regs, mode); do_exit(SIGKILL); return 0; vmalloc_fault: fault = __do_vmalloc_fault(addr, mm); goto ret; }