| 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_KPROBESstatic 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;}#elsestatic 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",
 |