123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- /*
- * linux/arch/arm/mm/fault.c
- *
- * Copyright (C) 1995 Linus Torvalds
- * Modifications for ARM processor (c) 1995-2004 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
- #include <linux/module.h>
- #include <linux/signal.h>
- #include <linux/mm.h>
- #include <linux/hardirq.h>
- #include <linux/init.h>
- #include <linux/kprobes.h>
- #include <linux/uaccess.h>
- #include <linux/page-flags.h>
- #include <linux/sched.h>
- #include <linux/highmem.h>
- #include <linux/perf_event.h>
- #include <asm/exception.h>
- #include <asm/pgtable.h>
- #include <asm/system_misc.h>
- #include <asm/system_info.h>
- #include <asm/tlbflush.h>
- #include "fault.h"
- #ifdef CONFIG_MMU
- #ifdef CONFIG_KPROBES
- static inline int notify_page_fault(struct pt_regs *regs, unsigned int fsr)
- {
- int ret = 0;
- if (!user_mode(regs)) {
- /* kprobe_running() needs smp_processor_id() */
- preempt_disable();
- if (kprobe_running() && kprobe_fault_handler(regs, fsr))
- ret = 1;
- preempt_enable();
- }
- return ret;
- }
- #else
- static inline int notify_page_fault(struct pt_regs *regs, unsigned int fsr)
- {
- return 0;
- }
- #endif
- /*
- * This is useful to dump out the page tables associated with
- * 'addr' in mm 'mm'.
- */
- void show_pte(struct mm_struct *mm, unsigned long addr)
- {
- pgd_t *pgd;
- if (!mm)
- mm = &init_mm;
- printk(KERN_ALERT "pgd = %p\n", mm->pgd);
- pgd = pgd_offset(mm, addr);
- printk(KERN_ALERT "[%08lx] *pgd=%08llx",
- addr, (long long)pgd_val(*pgd));
- do {
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- if (pgd_none(*pgd))
- break;
- if (pgd_bad(*pgd)) {
- printk("(bad)");
- break;
- }
- pud = pud_offset(pgd, addr);
- if (PTRS_PER_PUD != 1)
- printk(", *pud=%08llx", (long long)pud_val(*pud));
- if (pud_none(*pud))
- break;
- if (pud_bad(*pud)) {
- printk("(bad)");
- break;
- }
- pmd = pmd_offset(pud, addr);
- if (PTRS_PER_PMD != 1)
- printk(", *pmd=%08llx", (long long)pmd_val(*pmd));
- if (pmd_none(*pmd))
- break;
- if (pmd_bad(*pmd)) {
- printk("(bad)");
- break;
- }
- /* We must not map this if we have highmem enabled */
- if (PageHighMem(pfn_to_page(pmd_val(*pmd) >> PAGE_SHIFT)))
- break;
- pte = pte_offset_map(pmd, addr);
- printk(", *pte=%08llx", (long long)pte_val(*pte));
- #ifndef CONFIG_ARM_LPAE
- printk(", *ppte=%08llx",
|