X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=arch%2Fsparc64%2Fmm%2Ffault.c;h=e2027f27c0fe73f2f43546aa838577e86fc6e3ba;hb=f10f114f199dbcb9e1d6b5a0b36a34acf93f6179;hp=55ae802dc0ad6ffd6c06b9bd12e860f9a777267b;hpb=0a7d5f8ce960e74fa22986bda4af488539796e49;p=linux-2.6 diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index 55ae802dc0..e2027f27c0 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -15,11 +15,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include @@ -29,40 +29,26 @@ #include #include #include -#include #include #ifdef CONFIG_KPROBES -ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); - -/* Hook to register for page fault notifications */ -int register_page_fault_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); -} - -int unregister_page_fault_notifier(struct notifier_block *nb) +static inline int notify_page_fault(struct pt_regs *regs) { - return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); -} - -static inline int notify_page_fault(enum die_val val, const char *str, - struct pt_regs *regs, long err, int trap, int sig) -{ - struct die_args args = { - .regs = regs, - .str = str, - .err = err, - .trapnr = trap, - .signr = sig - }; - return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); + int ret = 0; + + /* kprobe_running() needs smp_processor_id() */ + if (!user_mode(regs)) { + preempt_disable(); + if (kprobe_running() && kprobe_fault_handler(regs, 0)) + ret = 1; + preempt_enable(); + } + return ret; } #else -static inline int notify_page_fault(enum die_val val, const char *str, - struct pt_regs *regs, long err, int trap, int sig) +static inline int notify_page_fault(struct pt_regs *regs) { - return NOTIFY_DONE; + return 0; } #endif @@ -121,23 +107,17 @@ static void __kprobes unhandled_fault(unsigned long address, printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %016lx\n", (tsk->mm ? (unsigned long) tsk->mm->pgd : (unsigned long) tsk->active_mm->pgd)); - if (notify_die(DIE_GPF, "general protection fault", regs, - 0, 0, SIGSEGV) == NOTIFY_STOP) - return; die_if_kernel("Oops", regs); } static void bad_kernel_pc(struct pt_regs *regs, unsigned long vaddr) { - unsigned long *ksp; - printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n", regs->tpc); printk(KERN_CRIT "OOPS: RPC [%016lx]\n", regs->u_regs[15]); print_symbol("RPC: <%s>\n", regs->u_regs[15]); printk(KERN_CRIT "OOPS: Fault was to vaddr[%lx]\n", vaddr); - __asm__("mov %%sp, %0" : "=r" (ksp)); - show_stack(current, ksp); + dump_stack(); unhandled_fault(regs->tpc, current, regs); } @@ -295,13 +275,12 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) struct mm_struct *mm = current->mm; struct vm_area_struct *vma; unsigned int insn = 0; - int si_code, fault_code; + int si_code, fault_code, fault; unsigned long address, mm_rss; fault_code = get_thread_fault_code(); - if (notify_page_fault(DIE_PAGE_FAULT, "page_fault", regs, - fault_code, 0, SIGSEGV) == NOTIFY_STOP) + if (notify_page_fault(regs)) return; si_code = SEGV_MAPERR; @@ -433,20 +412,18 @@ good_area: goto bad_area; } - switch (handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE))) { - case VM_FAULT_MINOR: - current->min_flt++; - break; - case VM_FAULT_MAJOR: - current->maj_flt++; - break; - case VM_FAULT_SIGBUS: - goto do_sigbus; - case VM_FAULT_OOM: - goto out_of_memory; - default: + fault = handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE)); + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; BUG(); } + if (fault & VM_FAULT_MAJOR) + current->maj_flt++; + else + current->min_flt++; up_read(&mm->mmap_sem); @@ -486,7 +463,7 @@ out_of_memory: up_read(&mm->mmap_sem); printk("VM: killing process %s\n", current->comm); if (!(regs->tstate & TSTATE_PRIV)) - do_exit(SIGKILL); + do_group_exit(SIGKILL); goto handle_kernel_fault; intr_or_no_mm: